changeset 16943:f8e60d11c0ec

Merge
author Stefan Anzinger <stefan.anzinger@oracle.com>
date Mon, 25 Aug 2014 21:15:59 -0700
parents ae0f235469db (current diff) 87a40fe1ba0c (diff)
children a04d9cbc149f 4feac7e51f42
files graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionHandle.java graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionInterface.java graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionPointer.java graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeLibraryHandle.java graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/nfi/NativeFunctionInterfaceTest.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/HostBackend.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/InputType.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInfo.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/DonorThreadPool.java graal/com.oracle.graal.hotspot.jdk8.test/src/com/oracle/graal/hotspot/jdk8/test/CRC32UpdateByteBufferSubstitutionTest.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveCurrentStackFrameOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/BytecodeVerificationTest.java graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/GraalClassLoaderTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/GuardsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SlowPathTest.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Generic.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/PolymorphicLimit.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/ExtensionContext.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableAnnotationMirror.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableElementFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableExecutableElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableVariableElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeAnnotationMirror.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeAnnotationValue.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeCompilationUnit.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeElementScanner.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeExecutableElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeImport.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeNames.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTree.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeBuilder.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeKind.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTypeElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTypeMirror.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeVariableElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/GeneratedElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/AbstractCodeWriter.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/FixWarningsVisitor.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/GenerateOverrideVisitor.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/OrganizedImports.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/AbstractCompiler.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/Compiler.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/CompilerFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JDTCompiler.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JavaCCompiler.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeChildData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeExecutionData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeFieldData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGuardData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationThrowsData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ClassElementFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/CodeElementFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/CompilationUnitFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MethodSpec.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ParameterSpec.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/Template.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemCodeGenerator.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTProber.java
diffstat 903 files changed, 33020 insertions(+), 21715 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Mon Aug 25 14:42:42 2014 -0700
+++ b/.hgignore	Mon Aug 25 21:15:59 2014 -0700
@@ -71,13 +71,13 @@
 .idea/
 ^cscope.out
 ^tags
-graal.src.zip*
-graal-loader.src.zip*
 syntax: glob
 *.bgv
 core.*
 *.jar
 *.jar.*
+*.zip
+*.zip.*
 eclipse-build.xml
 rebuild-launch.out
 coverage
--- a/.hgtags	Mon Aug 25 14:42:42 2014 -0700
+++ b/.hgtags	Mon Aug 25 21:15:59 2014 -0700
@@ -406,3 +406,4 @@
 b124e22eb772806c13d942cc110de38da0108147 graal-0.1
 483d05bf77a7c2a762aca1e06c4191bc06647176 graal-0.2
 9535eccd2a115f6c6f0b15efb508b11ff74cc0d3 graal-0.3
+7d4f630172a16e983212d46c0f1ad6cdb826dfce graal-0.4
--- a/CHANGELOG.md	Mon Aug 25 14:42:42 2014 -0700
+++ b/CHANGELOG.md	Mon Aug 25 21:15:59 2014 -0700
@@ -2,26 +2,35 @@
 
 ## `tip`
 ### Graal
+* ...
+
+### Truffle
+* ...
+
+## Version 0.4
+19-Aug-2014, [Repository Revision](http://hg.openjdk.java.net/graal/graal/rev/graal-0.4)
+### Graal
 * Made initialization of Graal runtime lazy in hosted mode.
-* Added supported for new 'jrelibrary' dependency type in mx/projects.
-* Java projects with compliance level higher than the JDKs specified by JAVA_HOME and EXTRA_JAVA_HOMES are ignored once mx/projects has been processed.
-* ResolvedJavaType.resolveMethod now takes a context type used to perform access checks. It now works correctly regarding default methods.
-* Removed Java based compilation queue (CompilationQueue.java).
-* Enabled use of separate class loader (via -XX:+UseGraalClassLoader) for classes loaded from graal.jar to hide them from application classes.
+* Added supported for new `jrelibrary` dependency type in `mx/projects`.
+* Java projects with compliance level higher than the JDKs specified by `JAVA_HOME` and `EXTRA_JAVA_HOMES` are ignored once `mx/projects` has been processed.
+* `ResolvedJavaType.resolveMethod` now takes a context type used to perform access checks. It now works correctly regarding default methods.
+* Removed Java based compilation queue (`CompilationQueue.java`).
+* Enabled use of separate class loader (via `-XX:+UseGraalClassLoader`) for classes loaded from `graal.jar` to hide them from application classes.
 
 ### Truffle
 * Change API for stack walking to a visitor: `TruffleRuntime#iterateFrames` replaces `TruffleRuntime#getStackTrace`
-* New flag -G:+TraceTruffleCompilationCallTree to print the tree of inlined calls before compilation.
+* New flag `-G:+TraceTruffleCompilationCallTree` to print the tree of inlined calls before compilation.
 * `truffle.jar`: strip out build-time only dependency into a seperated JAR file (`truffle-dsl-processor.jar`)
-* New flag -G:+TraceTruffleCompilationAST to print the AST before compilation.
-* New experimental TypedObject interface added.
-* Renamed flag -G:+TruffleSplittingEnabled to -G:+TruffleSplitting
-* New flag -G:+TruffleSplittingNew to enable the experimental splitting mode based on function arguments.
-* New flag -G:+TruffleSplittingTypedInstanceStamps to enable splitting for TypedObject instances.
-* New flag -G:+TruffleSplittingClassInstanceStamps to enable splitting for Java object instances except TypedObject.
-* New flag -G:TruffleSplittingStartCallCount=3 which sets the number of minimal calls until splitting is performed.
-* New flag -G:-TruffleSplittingAggressive if enabled splits every function call.
-* ...
+* New flag `-G:+TraceTruffleCompilationAST` to print the AST before compilation.
+* New experimental `TypedObject` interface added.
+* Renamed flag `-G:+TruffleSplittingEnabled` to `-G:+TruffleSplitting`
+* New flag `-G:+TruffleSplittingNew` to enable the experimental splitting mode based on function arguments.
+* New flag `-G:+TruffleSplittingTypedInstanceStamps` to enable splitting for `TypedObject` instances.
+* New flag `-G:+TruffleSplittingClassInstanceStamps` to enable splitting for Java object instances except `TypedObject`.
+* New flag `-G:TruffleSplittingStartCallCount=3` which sets the number of minimal calls until splitting is performed.
+* New flag `-G:-TruffleSplittingAggressive` if enabled splits every function call.
+* Added `isVisited` method for `BranchProfile`.
+* Added new `ConditionProfile`, `BinaryConditionProfile` and `CountingConditionProfile` utility classes to profile if conditions.
 
 ## Version 0.3
 9-May-2014, [Repository Revision](http://hg.openjdk.java.net/graal/graal/rev/graal-0.3)
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java	Mon Aug 25 21:15:59 2014 -0700
@@ -161,6 +161,9 @@
      * because of Word type rewriting and alternative backends that can't be done.
      */
     public boolean validateFormat() {
+        if (caller() != null) {
+            caller().validateFormat();
+        }
         for (int i = 0; i < numLocals + numStack; i++) {
             if (values[i] != null) {
                 Kind kind = values[i].getKind();
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionHandle.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +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.api.code;
-
-/**
- * A handle that can be used to {@linkplain #call(Object[]) call} a native function.
- */
-public interface NativeFunctionHandle {
-
-    /**
-     * Calls the native function.
-     * <p>
-     * The caller is responsible for ensuring {@code args} comply with the platform ABI (e.g. <a
-     * href="http://www.uclibc.org/docs/psABI-x86_64.pdf"> Unix AMD64 ABI</a>). If the library
-     * function has struct parameters, the fields of the struct must be passed as individual
-     * arguments.
-     * 
-     * @param args the arguments that will be passed to the native function
-     * @return boxed return value of the function call
-     */
-    Object call(Object... args);
-
-    /**
-     * Returns the installed code of the call stub for the native function call.
-     * 
-     * @return the installed code of the native call stub
-     */
-    InstalledCode getCallStub();
-}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionInterface.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +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.api.code;
-
-/**
- * Interface to get a {@linkplain NativeFunctionHandle handle} or {@linkplain NativeFunctionPointer
- * pointer} to a native function or a {@linkplain NativeLibraryHandle handle} to an open native
- * library.
- */
-public interface NativeFunctionInterface {
-
-    /**
-     * Resolves and returns a handle to an open native library. This method will open the library
-     * only if it is not already open.
-     *
-     * @param libPath the absolute path to the library
-     * @return the resolved library handle
-     * @throws UnsatisfiedLinkError if the library could not be found or opened
-     */
-    NativeLibraryHandle getLibraryHandle(String libPath);
-
-    /**
-     * Determines if the underlying platform/runtime supports the notion of a default library search
-     * path. For example, on *nix systems, this is typically defined by the {@code LD_LIBRARY_PATH}
-     * environment variable.
-     */
-    boolean isDefaultLibrarySearchSupported();
-
-    /**
-     * Resolves the function pointer {@code NativeFunctionPointer} of a native function.
-     *
-     * @param libraries the ordered list of libraries to search for the function
-     * @param name the name of the function to be resolved
-     * @return a pointer to the native function
-     * @throws UnsatisfiedLinkError if the function could not be resolved
-     */
-    NativeFunctionPointer getFunctionPointer(NativeLibraryHandle[] libraries, String name);
-
-    /**
-     * Resolves a function name to a {@linkplain NativeFunctionHandle handle} that can be called
-     * with a given signature. The signature contains the types of the arguments that will be passed
-     * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}.
-     *
-     * @param library the handle to a resolved library
-     * @param name the name of the function to be resolved
-     * @param returnType the type of the return value
-     * @param argumentTypes the types of the arguments
-     * @return the function handle of the native function
-     * @throws UnsatisfiedLinkError if the function handle could not be resolved
-     */
-    NativeFunctionHandle getFunctionHandle(NativeLibraryHandle library, String name, Class<?> returnType, Class<?>... argumentTypes);
-
-    /**
-     * Resolves a function pointer to a {@linkplain NativeFunctionHandle handle} that can be called
-     * with a given signature. The signature contains the types of the arguments that will be passed
-     * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}.
-     *
-     * @param functionPointer a function pointer
-     * @param returnType the type of the return value
-     * @param argumentTypes the types of the arguments
-     * @return the function handle of the native function
-     * @throws UnsatisfiedLinkError the function handle could not be created
-     */
-    NativeFunctionHandle getFunctionHandle(NativeFunctionPointer functionPointer, Class<?> returnType, Class<?>... argumentTypes);
-
-    /**
-     * Resolves a function name to a {@linkplain NativeFunctionHandle handle} that can be called
-     * with a given signature. The signature contains the types of the arguments that will be passed
-     * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}.
-     *
-     * @param libraries the ordered list of libraries to search for the function
-     * @param name the name of the function to be resolved
-     * @param returnType the type of the return value
-     * @param argumentTypes the types of the arguments
-     * @return the function handle of the native function
-     * @throws UnsatisfiedLinkError if the function handle could not be created
-     */
-    NativeFunctionHandle getFunctionHandle(NativeLibraryHandle[] libraries, String name, Class<?> returnType, Class<?>... argumentTypes);
-
-    /**
-     * Resolves a function name to a {@linkplain NativeFunctionHandle handle} that can be called
-     * with a given signature. The signature contains the types of the arguments that will be passed
-     * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}.
-     *
-     * @param name the name of the function to be resolved
-     * @param returnType the type of the return value
-     * @param argumentTypes the types of the arguments
-     * @return the function handle of the native function
-     * @throws UnsatisfiedLinkError if default library searching is not
-     *             {@linkplain #isDefaultLibrarySearchSupported() supported} or if the function
-     *             could not be resolved
-     */
-    NativeFunctionHandle getFunctionHandle(String name, Class<?> returnType, Class<?>... argumentTypes);
-
-    /**
-     * Creates a {@link NativeFunctionPointer} from a raw value.
-     *
-     * @param rawValue raw function pointer
-     * @return {@code NativeFunctionPointer} for {@code rawValue}
-     */
-    NativeFunctionPointer getNativeFunctionPointerFromRawValue(long rawValue);
-}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionPointer.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +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.api.code;
-
-/**
- * An opaque representation of a native function pointer.
- * <p>
- * Use {@code NativeFunctionInterface#getFunctionHandle(NativeFunctionPointer, Class, Class...)} to
- * get a handle enabling the native function to be {@linkplain NativeFunctionHandle#call(Object...)
- * called}.
- */
-public interface NativeFunctionPointer {
-
-    /**
-     * Returns the name of the function.
-     * 
-     * @return name of the function
-     */
-    String getName();
-
-}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeLibraryHandle.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +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.api.code;
-
-/**
- * An opaque representation of a native library handle. A handle is obtained via
- * {@link NativeFunctionInterface#getLibraryHandle(String)}. A handle is used to resolve a string to
- * a {@linkplain NativeFunctionInterface#getFunctionHandle(String, Class, Class...) handle} or
- * {@linkplain NativeFunctionInterface#getFunctionPointer(NativeLibraryHandle[], String) pointer}.
- */
-public interface NativeLibraryHandle {
-    /**
-     * Gets a name for this library. This may be the path for the file from which the library was
-     * loaded.
-     */
-    String getName();
-}
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaType.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaType.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,11 +24,6 @@
 
 import static org.junit.Assert.*;
 
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import java.util.stream.*;
-
 import org.junit.*;
 
 import com.oracle.graal.api.meta.*;
@@ -50,91 +45,4 @@
             assertEquals(expected, actual);
         }
     }
-
-    static class A {
-        A or(A other) {
-            return other;
-        }
-    }
-
-    @Test
-    public void testResolve() throws ClassNotFoundException {
-        String classPath = System.getProperty("java.class.path");
-        String[] parts = classPath.split(File.pathSeparator);
-        URL[] urls = Arrays.asList(parts).stream().map(e -> asURL(e)).collect(Collectors.toList()).toArray(new URL[parts.length]);
-        URLClassLoader clOne = newClassLoader(urls);
-        URLClassLoader clTwo = newClassLoader(urls);
-
-        String className = getClass().getName() + "$A";
-        Class<?> aClassOne = Class.forName(className, true, clOne);
-        Class<?> aClassTwo = Class.forName(getClass().getName() + "$A", true, clTwo);
-
-        assertNotEquals(aClassOne, aClassTwo);
-        assertNotEquals(aClassOne.getClassLoader(), aClassTwo.getClassLoader());
-
-        ResolvedJavaType aTypeOne = metaAccess.lookupJavaType(aClassOne);
-        ResolvedJavaType aTypeTwo = metaAccess.lookupJavaType(aClassTwo);
-
-        assertNotEquals(aTypeOne, aTypeTwo);
-
-        checkResolveWithoutAccessingClass(aTypeOne);
-        checkResolveWithoutAccessingClass(aTypeTwo);
-
-        assertEquals(aTypeOne.resolve(aTypeOne), aTypeOne);
-        assertNotEquals(aTypeOne.resolve(aTypeTwo), aTypeOne);
-        assertEquals(aTypeOne.resolve(aTypeTwo), aTypeTwo);
-
-        assertEquals(aTypeTwo.resolve(aTypeTwo), aTypeTwo);
-        assertNotEquals(aTypeTwo.resolve(aTypeOne), aTypeTwo);
-        assertEquals(aTypeTwo.resolve(aTypeOne), aTypeOne);
-
-        ResolvedJavaMethod m = ResolvedJavaTypeResolveMethodTest.getMethod(aTypeOne, "or");
-        JavaType resolvedTypeOne = m.getSignature().getParameterType(0, aTypeOne);
-        JavaType resolvedTypeTwo = m.getSignature().getReturnType(aTypeOne);
-        JavaType unresolvedTypeOne = m.getSignature().getParameterType(0, null);
-        JavaType unresolvedTypeTwo = m.getSignature().getReturnType(null);
-
-        assertTrue(resolvedTypeOne instanceof ResolvedJavaType);
-        assertTrue(resolvedTypeTwo instanceof ResolvedJavaType);
-        assertFalse(unresolvedTypeOne instanceof ResolvedJavaType);
-        assertFalse(unresolvedTypeTwo instanceof ResolvedJavaType);
-
-        assertEquals(resolvedTypeOne.resolve(aTypeOne), aTypeOne);
-        assertEquals(resolvedTypeOne.resolve(aTypeTwo), aTypeTwo);
-        assertEquals(resolvedTypeTwo.resolve(aTypeOne), aTypeOne);
-        assertEquals(resolvedTypeTwo.resolve(aTypeTwo), aTypeTwo);
-
-        checkResolveWithoutAccessingClass(unresolvedTypeOne);
-        checkResolveWithoutAccessingClass(unresolvedTypeTwo);
-
-        assertEquals(unresolvedTypeOne.resolve(aTypeOne), aTypeOne);
-        assertEquals(unresolvedTypeOne.resolve(aTypeTwo), aTypeTwo);
-    }
-
-    private static void checkResolveWithoutAccessingClass(JavaType type) {
-        try {
-            type.resolve(null);
-            fail();
-        } catch (NullPointerException e) {
-        }
-    }
-
-    private static URLClassLoader newClassLoader(URL[] urls) {
-        URLClassLoader cl = new URLClassLoader(urls) {
-            @Override
-            protected java.lang.Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
-                boolean callSuper = name.startsWith("java/") || name.startsWith("java.");
-                return callSuper ? super.loadClass(name, resolve) : super.findClass(name);
-            }
-        };
-        return cl;
-    }
-
-    private static URL asURL(String e) {
-        try {
-            return new File(e).toURI().toURL();
-        } catch (MalformedURLException e1) {
-            throw new RuntimeException(e1);
-        }
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ExcludeFromIdentityComparisonVerification.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, 2014, 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.annotation.*;
+
+/**
+ * This annotation denotes methods which are allowed to use identity checks (==/!=) on restricted
+ * types.
+ *
+ * @see CheckGraalInvariants
+ */
+@SuppressWarnings("javadoc")
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface ExcludeFromIdentityComparisonVerification {
+
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,7 +23,6 @@
 package com.oracle.graal.api.meta;
 
 import java.io.*;
-import java.lang.annotation.*;
 import java.util.*;
 
 /**
@@ -289,34 +288,28 @@
             base = base.substring(base.length() - 2);
         }
 
-        if (className.equals("boolean")) {
-            return prefix + "Z";
-        }
-        if (className.equals("byte")) {
-            return prefix + "B";
-        }
-        if (className.equals("short")) {
-            return prefix + "S";
-        }
-        if (className.equals("char")) {
-            return prefix + "C";
+        switch (className) {
+            case "boolean":
+                return prefix + "Z";
+            case "byte":
+                return prefix + "B";
+            case "short":
+                return prefix + "S";
+            case "char":
+                return prefix + "C";
+            case "int":
+                return prefix + "I";
+            case "float":
+                return prefix + "F";
+            case "long":
+                return prefix + "J";
+            case "double":
+                return prefix + "D";
+            case "void":
+                return prefix + "V";
+            default:
+                return prefix + "L" + className.replace('.', '/') + ";";
         }
-        if (className.equals("int")) {
-            return prefix + "I";
-        }
-        if (className.equals("float")) {
-            return prefix + "F";
-        }
-        if (className.equals("long")) {
-            return prefix + "J";
-        }
-        if (className.equals("double")) {
-            return prefix + "D";
-        }
-        if (className.equals("void")) {
-            return prefix + "V";
-        }
-        return prefix + "L" + className.replace('.', '/') + ";";
     }
 
     /**
@@ -333,78 +326,4 @@
         }
         return indentation + lines.replace(newLine, newLine + indentation);
     }
-
-    // The methods below here will be soon removed. They exist to simplify updating
-    // clients of the old API to switch to using the default methods that replace
-    // these utility methods. In Eclipse will show calls to these methods as warnings.
-
-    @Deprecated
-    public static boolean isJavaLangObject(ResolvedJavaType type) {
-        return type.isJavaLangObject();
-    }
-
-    @Deprecated
-    public static ResolvedJavaType[] lookupJavaTypes(MetaAccessProvider metaAccess, Class<?>[] classes) {
-        return metaAccess.lookupJavaTypes(classes);
-    }
-
-    @Deprecated
-    public static ResolvedJavaType getElementalType(ResolvedJavaType type) {
-        return type.getElementalType();
-    }
-
-    @Deprecated
-    public static String toJavaName(JavaType type, boolean qualified) {
-        return type.toJavaName(qualified);
-    }
-
-    @Deprecated
-    public static String toJavaName(JavaType type) {
-        return type.toJavaName();
-    }
-
-    @Deprecated
-    public static String toClassName(JavaType type) {
-        return type.toClassName();
-    }
-
-    @Deprecated
-    public static String format(String format, JavaMethod method) throws IllegalFormatException {
-        return method.format(format);
-    }
-
-    @Deprecated
-    public static String format(String format, JavaField field) throws IllegalFormatException {
-        return field.format(format);
-    }
-
-    @Deprecated
-    public static <T extends Annotation> T[] getParameterAnnotations(Class<T> annotationClass, ResolvedJavaMethod method) {
-        return method.getParameterAnnotations(annotationClass);
-    }
-
-    @Deprecated
-    public static <T extends Annotation> T getParameterAnnotation(Class<T> annotationClass, int parameterIndex, ResolvedJavaMethod method) {
-        return method.getParameterAnnotation(annotationClass, parameterIndex);
-    }
-
-    @Deprecated
-    public static JavaType[] signatureToTypes(Signature signature, JavaType receiverType) {
-        return signature.toParameterTypes(receiverType);
-    }
-
-    @Deprecated
-    public static JavaType[] signatureToTypes(ResolvedJavaMethod method) {
-        return method.toParameterTypes();
-    }
-
-    @Deprecated
-    public static String signatureToMethodDescriptor(Signature sig) {
-        return sig.toMethodDescriptor();
-    }
-
-    @Deprecated
-    public static String profileToString(ProfilingInfo info, ResolvedJavaMethod method, String sep) {
-        return info.toString(method, sep);
-    }
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java	Mon Aug 25 21:15:59 2014 -0700
@@ -96,4 +96,15 @@
         }
         return false;
     }
+
+    /**
+     * Checks if this value is identical to {@code other}.
+     *
+     * Warning: Use with caution! Usually equivalence {@link #equals(Object)} is sufficient and
+     * should be used.
+     */
+    @ExcludeFromIdentityComparisonVerification
+    public final boolean identityEquals(Value other) {
+        return this == other;
+    }
 }
--- a/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/Services.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/Services.java	Mon Aug 25 21:15:59 2014 -0700
@@ -56,7 +56,7 @@
                 // Fall back to standard SerivceLoader
             }
         }
-        return ServiceLoader.loadInstalled(service);
+        return ServiceLoader.load(service, Services.class.getClassLoader());
     }
 
     private static native <S> S[] getServiceImpls(Class<?> service);
--- a/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Mon Aug 25 21:15:59 2014 -0700
@@ -88,12 +88,30 @@
      */
     public abstract void mov(Register a, Constant src);
 
+    private static String getBitTypeFromKind(Kind kind) {
+        switch (kind) {
+            case Boolean:
+            case Byte:
+            case Short:
+            case Char:
+            case Int:
+            case Float:
+                return "b32";
+            case Long:
+            case Double:
+            case Object:
+                return "b64";
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
     public final void emitMov(Kind kind, Value dst, Value src) {
         if (isRegister(dst) && isConstant(src) && kind.getStackKind() == Kind.Object) {
             mov(asRegister(dst), asConstant(src));
         } else {
-            String argtype = getArgTypeFromKind(kind).substring(1);
-            emitString("mov_b" + argtype + " " + mapRegOrConstToString(dst) + ", " + mapRegOrConstToString(src) + ";");
+            String argtype = getBitTypeFromKind(kind);
+            emitString("mov_" + argtype + " " + mapRegOrConstToString(dst) + ", " + mapRegOrConstToString(src) + ";");
         }
     }
 
@@ -324,7 +342,11 @@
     }
 
     public static String mapAddress(HSAILAddress addr) {
-        return "[$d" + addr.getBase().encoding() + " + " + addr.getDisplacement() + "]";
+        if (addr.getBase().encoding() < 0) {
+            return "[0x" + Long.toHexString(addr.getDisplacement()) + "]";
+        } else {
+            return "[$d" + addr.getBase().encoding() + " + " + addr.getDisplacement() + "]";
+        }
     }
 
     private static String doubleToString(double dval) {
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Mon Aug 25 21:15:59 2014 -0700
@@ -400,20 +400,7 @@
             return;
         }
 
-        double probability = profilingInfo.getBranchTakenProbability(bci());
-        if (probability < 0) {
-            assert probability == -1 : "invalid probability";
-            Debug.log("missing probability in %s at bci %d", method, bci());
-            probability = 0.5;
-        }
-
-        if (!optimisticOpts.removeNeverExecutedCode()) {
-            if (probability == 0) {
-                probability = 0.0000001;
-            } else if (probability == 1) {
-                probability = 0.999999;
-            }
-        }
+        double probability = branchProbability();
 
         LabelRef trueDestination = getSuccessor(0);
         LabelRef falseDestination = getSuccessor(1);
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java	Mon Aug 25 21:15:59 2014 -0700
@@ -275,63 +275,63 @@
 
     protected AMD64Arithmetic getOp(ValueNode operation, Access access) {
         Kind memoryKind = getMemoryKind(access);
-        if (operation.getClass() == IntegerAddNode.class) {
+        if (operation.getClass() == IntegerAddNode.getGenClass()) {
             switch (memoryKind) {
                 case Int:
                     return IADD;
                 case Long:
                     return LADD;
             }
-        } else if (operation.getClass() == FloatAddNode.class) {
+        } else if (operation.getClass() == FloatAddNode.getGenClass()) {
             switch (memoryKind) {
                 case Float:
                     return FADD;
                 case Double:
                     return DADD;
             }
-        } else if (operation.getClass() == AndNode.class) {
+        } else if (operation.getClass() == AndNode.getGenClass()) {
             switch (memoryKind) {
                 case Int:
                     return IAND;
                 case Long:
                     return LAND;
             }
-        } else if (operation.getClass() == OrNode.class) {
+        } else if (operation.getClass() == OrNode.getGenClass()) {
             switch (memoryKind) {
                 case Int:
                     return IOR;
                 case Long:
                     return LOR;
             }
-        } else if (operation.getClass() == XorNode.class) {
+        } else if (operation.getClass() == XorNode.getGenClass()) {
             switch (memoryKind) {
                 case Int:
                     return IXOR;
                 case Long:
                     return LXOR;
             }
-        } else if (operation.getClass() == IntegerSubNode.class) {
+        } else if (operation.getClass() == IntegerSubNode.getGenClass()) {
             switch (memoryKind) {
                 case Int:
                     return ISUB;
                 case Long:
                     return LSUB;
             }
-        } else if (operation.getClass() == FloatSubNode.class) {
+        } else if (operation.getClass() == FloatSubNode.getGenClass()) {
             switch (memoryKind) {
                 case Float:
                     return FSUB;
                 case Double:
                     return DSUB;
             }
-        } else if (operation.getClass() == IntegerMulNode.class) {
+        } else if (operation.getClass() == IntegerMulNode.getGenClass()) {
             switch (memoryKind) {
                 case Int:
                     return IMUL;
                 case Long:
                     return LMUL;
             }
-        } else if (operation.getClass() == FloatMulNode.class) {
+        } else if (operation.getClass() == FloatMulNode.getGenClass()) {
             switch (memoryKind) {
                 case Float:
                     return FMUL;
--- a/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java	Mon Aug 25 21:15:59 2014 -0700
@@ -131,6 +131,13 @@
     }
 
     /**
+     * Determines if we are running CQE tests (via a -D flag)
+     */
+    public boolean runningCQETests() {
+        return Boolean.getBoolean("com.amd.CQE");
+    }
+
+    /**
      * Determines if the JVM supports the required typeProfileWidth.
      */
     public boolean typeProfileWidthAtLeast(int val) {
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleCosTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleCosTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -38,6 +38,12 @@
         });
     }
 
+    // internally allocates a Rempiostruct, escape analysis not catching it
+    @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canHandleObjectAllocation());
+    }
+
     @Test
     public void testUsingLambdaMethod() {
         testGeneratedHsailUsingLambdaMethod();
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleNextAfterTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleNextAfterTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -39,6 +39,11 @@
         });
     }
 
+    @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (runningOnSimulator() || runningCQETests());
+    }
+
     @Test
     public void testUsingLambdaMethod() {
         testGeneratedHsailUsingLambdaMethod();
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleNextUpTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleNextUpTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -38,6 +38,11 @@
         });
     }
 
+    @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (runningOnSimulator() || runningCQETests());
+    }
+
     @Test
     public void testUsingLambdaMethod() {
         testGeneratedHsailUsingLambdaMethod();
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleSinTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleSinTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -38,6 +38,12 @@
         });
     }
 
+    // internally allocates a Rempiostruct, escape analysis not catching it
+    @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canHandleObjectAllocation());
+    }
+
     @Test
     public void testUsingLambdaMethod() {
         testGeneratedHsailUsingLambdaMethod();
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleTanTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleTanTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -38,6 +38,12 @@
         });
     }
 
+    // internally allocates a Rempiostruct, escape analysis not catching it
+    @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canHandleObjectAllocation());
+    }
+
     @Test
     public void testUsingLambdaMethod() {
         testGeneratedHsailUsingLambdaMethod();
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatCosTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatCosTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -38,6 +38,12 @@
         });
     }
 
+    // internally allocates a Rempiostruct, escape analysis not catching it
+    @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canHandleObjectAllocation());
+    }
+
     @Test
     public void testUsingLambdaMethod() {
         testGeneratedHsailUsingLambdaMethod();
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatNextAfterTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatNextAfterTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -39,6 +39,11 @@
         });
     }
 
+    @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (runningOnSimulator() || runningCQETests());
+    }
+
     @Test
     public void testUsingLambdaMethod() {
         testGeneratedHsailUsingLambdaMethod();
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatNextUpTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatNextUpTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -38,6 +38,11 @@
         });
     }
 
+    @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (runningOnSimulator() || runningCQETests());
+    }
+
     @Test
     public void testUsingLambdaMethod() {
         testGeneratedHsailUsingLambdaMethod();
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatSinTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatSinTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -38,6 +38,12 @@
         });
     }
 
+    // internally allocates a Rempiostruct, escape analysis not catching it
+    @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canHandleObjectAllocation());
+    }
+
     @Test
     public void testUsingLambdaMethod() {
         testGeneratedHsailUsingLambdaMethod();
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatTanTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatTanTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -38,6 +38,12 @@
         });
     }
 
+    // internally allocates a Rempiostruct, escape analysis not catching it
+    @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canHandleObjectAllocation());
+    }
+
     @Test
     public void testUsingLambdaMethod() {
         testGeneratedHsailUsingLambdaMethod();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/MoreThanEightArgsTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2014, 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.hsail.test.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+
+import org.junit.*;
+
+public class MoreThanEightArgsTest extends GraalKernelTester {
+
+    int[] makeIntArray(int size) {
+        int[] out = new int[size];
+
+        for (int i = 0; i < size; i++) {
+            out[i] = 1;
+        }
+        return out;
+    }
+
+    final int rows = 4096;
+    final int cols = 4096;
+    final int loops = 2;
+
+    @Result int[] result;
+
+    void innerTest(int[] res, int[] a, int[] b, int[] c, int[] d, int base, int stride) {
+        final int resCols = a.length;
+        final int resRows = res.length;
+        final int limit = resCols - stride;
+
+        dispatchLambdaKernel(resRows, (row) -> {
+            res[row] = 0;
+            if (a != null) {
+                for (int col = base; col < limit; col += 4) {
+                    int p0 = 0;
+                    int p1 = 0;
+                    int p2 = 0;
+                    int p3 = 0;
+                    p0 = a[col] + b[col] + c[col] + d[col] + stride;
+                    p1 = a[col + 1] + b[col + 1] + c[col + 1] + d[col + 1];
+                    p2 = a[col + 2] + b[col + 2] + c[col + 2] + d[col + 2];
+                    p3 = a[col + 3] + b[col + 3] + c[col + 3] + d[col + 3];
+                    res[row] += p0 + p1 + p2 + p3;
+                }
+            }
+        });
+    }
+
+    @Override
+    public void runTest() {
+        int[] a;
+        int[] b;
+        int[] c;
+        int[] d;
+
+        result = makeIntArray(rows);
+        a = makeIntArray(cols);
+        b = makeIntArray(cols);
+        c = makeIntArray(cols);
+        d = makeIntArray(cols);
+        for (int i = 0; i < loops; i++) {
+            innerTest(result, a, b, c, d, 0, 4);
+        }
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringBuilderTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringBuilderTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -47,7 +47,7 @@
 
     @Override
     protected boolean supportsRequiredCapabilities() {
-        return (canHandleObjectAllocation());
+        return (canHandleObjectAllocation() && (runningOnSimulator() || runningCQETests()));
     }
 
     @Test
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Aug 25 21:15:59 2014 -0700
@@ -243,8 +243,6 @@
     @Override
     public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability) {
         append(new BranchOp(ConditionFlag.CarrySet, overflow, noOverflow, Kind.Long));
-        // append(new BranchOp(negated ? ConditionFlag.NoOverflow : ConditionFlag.Overflow, label));
-// throw GraalInternalError.unimplemented();
     }
 
     @Override
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/AllocSpy.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/AllocSpy.java	Mon Aug 25 21:15:59 2014 -0700
@@ -51,7 +51,7 @@
  * @see #BarSize
  * @see #NumberSize
  */
-final class AllocSpy implements AutoCloseable {
+public final class AllocSpy implements AutoCloseable {
 
     static ThreadLocal<AllocSpy> current = new ThreadLocal<>();
 
@@ -70,6 +70,10 @@
         }
     }
 
+    public static boolean isEnabled() {
+        return ENABLED;
+    }
+
     static String prop(String sfx) {
         return AllocSpy.class.getSimpleName() + "." + sfx;
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -305,7 +305,7 @@
     }
 
     private void processMethod(final String snippet) {
-        graph = parse(snippet);
+        graph = parseEager(snippet);
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
         new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
@@ -317,7 +317,7 @@
     }
 
     private void compareGraphs(final String snippet, final String referenceSnippet, final boolean loopPeeling, final boolean excludeVirtual) {
-        graph = parse(snippet);
+        graph = parseEager(snippet);
 
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
@@ -334,7 +334,7 @@
         new DeadCodeEliminationPhase().apply(graph);
         canonicalizer.apply(graph, context);
 
-        StructuredGraph referenceGraph = parse(referenceSnippet);
+        StructuredGraph referenceGraph = parseEager(referenceSnippet);
         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/CheckGraalInvariants.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java	Mon Aug 25 21:15:59 2014 -0700
@@ -38,7 +38,9 @@
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.CompilerThreadFactory.DebugConfigAccess;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.java.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.VerifyPhase.VerificationError;
@@ -113,17 +115,28 @@
         for (String className : classNames) {
             try {
                 Class<?> c = Class.forName(className, false, CheckGraalInvariants.class.getClassLoader());
+                executor.execute(() -> {
+                    try {
+                        checkClass(c, metaAccess);
+                    } catch (Throwable e) {
+                        errors.add(String.format("Error while checking %s:%n%s", className, printStackTraceToString(e)));
+                    }
+                });
+
                 for (Method m : c.getDeclaredMethods()) {
                     if (Modifier.isNative(m.getModifiers()) || Modifier.isAbstract(m.getModifiers())) {
                         // ignore
                     } else {
                         String methodName = className + "." + m.getName();
+                        boolean verifyEquals = !m.isAnnotationPresent(ExcludeFromIdentityComparisonVerification.class);
                         if (matches(filters, methodName)) {
                             executor.execute(() -> {
                                 StructuredGraph graph = new StructuredGraph(metaAccess.lookupJavaMethod(m));
                                 try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) {
                                     graphBuilderSuite.apply(graph, context);
-                                    checkGraph(context, graph);
+                                    // update phi stamps
+                                    graph.getNodes().filter(PhiNode.class).forEach(PhiNode::inferStamp);
+                                    checkGraph(context, graph, verifyEquals);
                                 } catch (VerificationError e) {
                                     errors.add(e.getMessage());
                                 } catch (LinkageError e) {
@@ -132,9 +145,7 @@
                                     // Graal bail outs on certain patterns in Java bytecode (e.g.,
                                     // unbalanced monitors introduced by jacoco).
                                 } catch (Throwable e) {
-                                    StringWriter sw = new StringWriter();
-                                    e.printStackTrace(new PrintWriter(sw));
-                                    errors.add(String.format("Error while checking %s:%n%s", methodName, sw));
+                                    errors.add(String.format("Error while checking %s:%n%s", methodName, printStackTraceToString(e)));
                                 }
                             });
                         }
@@ -166,15 +177,41 @@
     }
 
     /**
+     * @param metaAccess
+     */
+    private static void checkClass(Class<?> c, MetaAccessProvider metaAccess) {
+        if (Node.class.isAssignableFrom(c)) {
+            if (c.getAnnotation(GeneratedNode.class) == null) {
+                if (Modifier.isFinal(c.getModifiers())) {
+                    throw new AssertionError(String.format("Node subclass %s must not be final", c.getName()));
+                }
+                if (c.getAnnotation(NodeInfo.class) == null) {
+                    throw new AssertionError(String.format("Node subclass %s requires %s annotation", c.getName(), NodeClass.class.getSimpleName()));
+                }
+                if (!Modifier.isAbstract(c.getModifiers())) {
+                    try {
+                        Class.forName(c.getName().replace('$', '_') + "Gen");
+                    } catch (ClassNotFoundException e) {
+                        throw new AssertionError(String.format("Missing generated Node class %s", c.getName() + "Gen"));
+                    }
+                }
+            }
+        }
+    }
+
+    /**
      * Checks the invariants for a single graph.
      */
-    private static void checkGraph(HighTierContext context, StructuredGraph graph) {
-        new VerifyUsageWithEquals(Value.class).apply(graph, context);
-        new VerifyUsageWithEquals(Register.class).apply(graph, context);
-        new VerifyUsageWithEquals(JavaType.class).apply(graph, context);
-        new VerifyUsageWithEquals(JavaMethod.class).apply(graph, context);
-        new VerifyUsageWithEquals(JavaField.class).apply(graph, context);
-        new VerifyUsageWithEquals(LIRKind.class).apply(graph, context);
+    private static void checkGraph(HighTierContext context, StructuredGraph graph, boolean verifyEquals) {
+        if (verifyEquals) {
+            new VerifyNoNodeClassLiteralIdentityTests().apply(graph, context);
+            new VerifyUsageWithEquals(Value.class).apply(graph, context);
+            new VerifyUsageWithEquals(Register.class).apply(graph, context);
+            new VerifyUsageWithEquals(JavaType.class).apply(graph, context);
+            new VerifyUsageWithEquals(JavaMethod.class).apply(graph, context);
+            new VerifyUsageWithEquals(JavaField.class).apply(graph, context);
+            new VerifyUsageWithEquals(LIRKind.class).apply(graph, context);
+        }
         new VerifyDebugUsage().apply(graph, context);
     }
 
@@ -189,4 +226,10 @@
         }
         return false;
     }
+
+    private static String printStackTraceToString(Throwable t) {
+        StringWriter sw = new StringWriter();
+        t.printStackTrace(new PrintWriter(sw));
+        return sw.toString();
+    }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -35,7 +35,7 @@
 public class CompareCanonicalizerTest extends GraalCompilerTest {
 
     private StructuredGraph getCanonicalizedGraph(String name) {
-        StructuredGraph graph = parse(name);
+        StructuredGraph graph = parseEager(name);
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
         return graph;
     }
@@ -48,9 +48,9 @@
 
     @Test
     public void testCanonicalComparison() {
-        StructuredGraph referenceGraph = parse("referenceCanonicalComparison");
+        StructuredGraph referenceGraph = parseEager("referenceCanonicalComparison");
         for (int i = 1; i < 4; i++) {
-            StructuredGraph graph = parse("canonicalCompare" + i);
+            StructuredGraph graph = parseEager("canonicalCompare" + i);
             assertEquals(referenceGraph, graph);
         }
         Assumptions assumptions = new Assumptions(false);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -90,7 +90,7 @@
 
     @Test
     public void testRedundantCompares() {
-        StructuredGraph graph = parse("testRedundantComparesSnippet");
+        StructuredGraph graph = parseEager("testRedundantComparesSnippet");
         CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
         PhaseContext context = new PhaseContext(getProviders(), null);
 
@@ -113,7 +113,7 @@
     @Test
     @Ignore
     public void testInstanceOfCheckCastLowered() {
-        StructuredGraph graph = parse("testInstanceOfCheckCastSnippet");
+        StructuredGraph graph = parseEager("testInstanceOfCheckCastSnippet");
 
         CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
         PhaseContext context = new PhaseContext(getProviders(), null);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -81,12 +81,12 @@
 
     private void test(final String snippet) {
         try (Scope s = Debug.scope("DegeneratedLoopsTest", new DebugDumpScope(snippet))) {
-            StructuredGraph graph = parse(snippet);
+            StructuredGraph graph = parseEager(snippet);
             HighTierContext context = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
             new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
             new CanonicalizerPhase(true).apply(graph, context);
             Debug.dump(graph, "Graph");
-            StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
+            StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET);
             Debug.dump(referenceGraph, "ReferenceGraph");
             assertEquals(referenceGraph, graph);
         } catch (Throwable e) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -106,7 +106,7 @@
     }
 
     private StructuredGraph compileSnippet(final String snippet, final int checkcasts, final int afterCanon) {
-        final StructuredGraph graph = parse(snippet);
+        final StructuredGraph graph = parseEager(snippet);
         try (Scope s = Debug.scope("NestedCheckCastsTest", graph)) {
             Debug.dump(graph, "After parsing: " + snippet);
             Assert.assertEquals(checkcasts, graph.getNodes().filter(CheckCastNode.class).count());
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -58,7 +58,7 @@
     private void test(final String snippet) {
         try (Scope s = Debug.scope("FloatingReadTest", new DebugDumpScope(snippet))) {
 
-            StructuredGraph graph = parse(snippet);
+            StructuredGraph graph = parseEager(snippet);
             PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false));
             new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
             new FloatingReadPhase().apply(graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,25 +22,21 @@
  */
 package com.oracle.graal.compiler.test;
 
-import com.oracle.graal.debug.Debug;
-import com.oracle.graal.debug.DebugConfig;
-import com.oracle.graal.debug.DebugConfigScope;
-import com.oracle.graal.debug.internal.DebugScope;
-import com.oracle.graal.graph.Node;
-import com.oracle.graal.nodes.calc.ObjectEqualsNode;
-import com.oracle.graal.nodes.util.GraphUtil;
-import com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase;
+import java.util.*;
 
 import org.junit.*;
 
+import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.internal.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.common.cfs.*;
 import com.oracle.graal.phases.tiers.*;
 
-import java.util.Iterator;
-import java.util.List;
-
 /**
  * Tests whether {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase} actually
  * performs some graph rewritings that it's supposed to perform.
@@ -376,7 +372,7 @@
     }
 
     public StructuredGraph afterFlowSensitiveReduce(String snippet) {
-        StructuredGraph before = canonicalize(parse(snippet));
+        StructuredGraph before = canonicalize(parseEager(snippet));
         // visualize(before, snippet + "-before");
         StructuredGraph result = flowSensitiveReduce(before);
         // visualize(result, snippet + "-after");
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSensitiveReductionTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSensitiveReductionTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,16 +26,15 @@
 import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
 import static org.junit.Assert.*;
 
-import com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase;
-
 import org.junit.*;
 
+import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.common.cfs.*;
 import com.oracle.graal.phases.tiers.*;
 
 /**
@@ -144,7 +143,7 @@
         test("testNullnessSnippet", new Object(), null);
         test("testNullnessSnippet", new Object(), new Object());
 
-        StructuredGraph graph = parse("testNullnessSnippet");
+        StructuredGraph graph = parseEager("testNullnessSnippet");
         PhaseContext context = new PhaseContext(getProviders(), null);
         new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context);
         new CanonicalizerPhase(true).apply(graph, context);
@@ -172,14 +171,14 @@
 
     @Test
     public void testDisjunction() {
-        StructuredGraph graph = parse("testDisjunctionSnippet");
+        StructuredGraph graph = parseEager("testDisjunctionSnippet");
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
         IfNode ifNode = (IfNode) graph.start().next();
         InstanceOfNode instanceOf = (InstanceOfNode) ifNode.condition();
-        IsNullNode x = graph.unique(new IsNullNode(graph.getParameter(0)));
+        IsNullNode x = graph.unique(IsNullNode.create(graph.getParameter(0)));
         InstanceOfNode y = instanceOf;
-        ShortCircuitOrNode disjunction = graph.unique(new ShortCircuitOrNode(x, false, y, false, NOT_FREQUENT_PROBABILITY));
-        LogicNegationNode negation = graph.unique(new LogicNegationNode(disjunction));
+        ShortCircuitOrNode disjunction = graph.unique(ShortCircuitOrNode.create(x, false, y, false, NOT_FREQUENT_PROBABILITY));
+        LogicNegationNode negation = graph.unique(LogicNegationNode.create(disjunction));
         ifNode.setCondition(negation);
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
         new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, new PhaseContext(getProviders(), null));
@@ -200,7 +199,7 @@
     @Test
     public void testInvoke() {
         test("testInvokeSnippet", new Integer(16));
-        StructuredGraph graph = parse("testInvokeSnippet");
+        StructuredGraph graph = parseEager("testInvokeSnippet");
         PhaseContext context = new PhaseContext(getProviders(), null);
         new CanonicalizerPhase(true).apply(graph, context);
         new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context);
@@ -231,7 +230,7 @@
 
     @Test
     public void testTypeMerging() {
-        StructuredGraph graph = parse("testTypeMergingSnippet");
+        StructuredGraph graph = parseEager("testTypeMergingSnippet");
         PhaseContext context = new PhaseContext(getProviders(), null);
         new CanonicalizerPhase(true).apply(graph, context);
         new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context);
@@ -249,7 +248,7 @@
 
     @Test
     public void testInstanceOfCheckCast() {
-        StructuredGraph graph = parse("testInstanceOfCheckCastSnippet");
+        StructuredGraph graph = parseEager("testInstanceOfCheckCastSnippet");
         PhaseContext context = new PhaseContext(getProviders(), null);
         new CanonicalizerPhase(true).apply(graph, context);
         new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context);
@@ -274,7 +273,7 @@
     public void testDuplicateNullChecks() {
         // This tests whether explicit null checks properly eliminate later null guards. Currently
         // it's failing.
-        StructuredGraph graph = parse("testDuplicateNullChecksSnippet");
+        StructuredGraph graph = parseEager("testDuplicateNullChecksSnippet");
         CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
         PhaseContext context = new PhaseContext(getProviders(), null);
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -45,9 +45,9 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.java.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.spi.*;
@@ -67,7 +67,7 @@
  * <p>
  * White box tests for Graal compiler transformations use this pattern:
  * <ol>
- * <li>Create a graph by {@linkplain #parse(String) parsing} a method.</li>
+ * <li>Create a graph by {@linkplain #parseEager(String) parsing} a method.</li>
  * <li>Manually modify the graph (e.g. replace a parameter node with a constant).</li>
  * <li>Apply a transformation to the graph.</li>
  * <li>Assert that the transformed graph is equal to an expected graph.</li>
@@ -323,15 +323,6 @@
         return getProviders().getLowerer();
     }
 
-    /**
-     * Parses a Java method to produce a graph.
-     *
-     * @param methodName the name of the method in {@code this.getClass()} to be parsed
-     */
-    protected StructuredGraph parse(String methodName) {
-        return parse(getMethod(methodName));
-    }
-
     private static AtomicInteger compilationId = new AtomicInteger();
 
     protected void testN(int n, final String name, final Object... args) {
@@ -422,7 +413,7 @@
         if (UseBaselineCompiler.getValue()) {
             compiledMethod = getCodeBaseline(javaMethod, method);
         } else {
-            compiledMethod = getCode(javaMethod, parse(method));
+            compiledMethod = getCode(javaMethod, parseEager(method));
         }
         try {
             return new Result(compiledMethod.executeVarargs(executeArgs), null);
@@ -667,7 +658,8 @@
     }
 
     /**
-     * Parses a Java method to produce a graph.
+     * Parses a Java method in {@linkplain GraphBuilderConfiguration#getDefault() default} mode to
+     * produce a graph.
      *
      * @param methodName the name of the method in {@code this.getClass()} to be parsed
      */
@@ -676,21 +668,34 @@
     }
 
     /**
-     * Parses a Java method to produce a graph.
-     */
-    protected StructuredGraph parse(Method m) {
-        return parse0(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getEagerDefault()));
-    }
-
-    /**
-     * Parses a Java method to produce a graph.
+     * Parses a Java method in {@linkplain GraphBuilderConfiguration#getDefault() default} mode to
+     * produce a graph.
      */
     protected StructuredGraph parseProfiled(Method m) {
         return parse0(m, getDefaultGraphBuilderSuite());
     }
 
     /**
-     * Parses a Java method in debug mode to produce a graph with extra infopoints.
+     * Parses a Java method in {@linkplain GraphBuilderConfiguration#getEagerDefault() eager} mode
+     * to produce a graph.
+     *
+     * @param methodName the name of the method in {@code this.getClass()} to be parsed
+     */
+    protected StructuredGraph parseEager(String methodName) {
+        return parseEager(getMethod(methodName));
+    }
+
+    /**
+     * Parses a Java method in {@linkplain GraphBuilderConfiguration#getEagerDefault() eager} mode
+     * to produce a graph.
+     */
+    protected StructuredGraph parseEager(Method m) {
+        return parse0(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getEagerDefault()));
+    }
+
+    /**
+     * Parses a Java method in {@linkplain GraphBuilderConfiguration#getFullDebugDefault() full
+     * debug} mode to produce a graph.
      */
     protected StructuredGraph parseDebug(Method m) {
         return parse0(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault()));
@@ -699,9 +704,11 @@
     private StructuredGraph parse0(Method m, PhaseSuite<HighTierContext> graphBuilderSuite) {
         assert m.getAnnotation(Test.class) == null : "shouldn't parse method with @Test annotation: " + m;
         ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(m);
-        StructuredGraph graph = new StructuredGraph(javaMethod);
-        graphBuilderSuite.apply(graph, new HighTierContext(providers, null, null, graphBuilderSuite, OptimisticOptimizations.ALL));
-        return graph;
+        try (Scope ds = Debug.scope("Parsing", javaMethod)) {
+            StructuredGraph graph = new StructuredGraph(javaMethod);
+            graphBuilderSuite.apply(graph, new HighTierContext(providers, null, null, graphBuilderSuite, OptimisticOptimizations.ALL));
+            return graph;
+        }
     }
 
     protected PhaseSuite<HighTierContext> getDefaultGraphBuilderSuite() {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -180,7 +180,7 @@
     }
 
     private void testCombinedIf(String snippet, int count) {
-        StructuredGraph graph = parse(snippet);
+        StructuredGraph graph = parseEager(snippet);
         PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false));
         new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
         new FloatingReadPhase().apply(graph);
@@ -193,7 +193,7 @@
     }
 
     private void test(String snippet) {
-        StructuredGraph graph = parse(snippet);
+        StructuredGraph graph = parseEager(snippet);
         ParameterNode param = graph.getNodes(ParameterNode.class).iterator().next();
         ConstantNode constant = ConstantNode.forInt(0, graph);
         for (Node n : param.usages().filter(isNotA(FrameState.class)).snapshot()) {
@@ -205,7 +205,7 @@
             fs.replaceFirstInput(param, null);
             param.safeDelete();
         }
-        StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
+        StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET);
         assertEquals(referenceGraph, graph);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -59,7 +59,7 @@
     @Test
     public void callInfopoints() {
         final Method method = getMethod("testMethod");
-        final StructuredGraph graph = parse(method);
+        final StructuredGraph graph = parseEager(method);
         CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false);
         final CompilationResult cr = compileGraph(graph, null, cc, graph.method(), getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultGraphBuilderSuite(),
                         OptimisticOptimizations.ALL, getProfilingInfo(graph), null, getSuites(), new CompilationResult(), CompilationResultBuilderFactory.Default);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IntegerEqualsCanonicalizerTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IntegerEqualsCanonicalizerTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -112,7 +112,7 @@
     }
 
     private StructuredGraph getCanonicalizedGraph(String snippet) {
-        StructuredGraph graph = parse(snippet);
+        StructuredGraph graph = parseEager(snippet);
         new CanonicalizerPhase(false).apply(graph, new PhaseContext(getProviders(), null));
         for (FrameState state : graph.getNodes(FrameState.class).snapshot()) {
             state.replaceAtUsages(null);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -71,7 +71,7 @@
     }
 
     private void test(String snippet) {
-        StructuredGraph graph = parse(snippet);
+        StructuredGraph graph = parseEager(snippet);
         Map<Invoke, Double> hints = new HashMap<>();
         for (Invoke invoke : graph.getInvokes()) {
             hints.put(invoke, 1000d);
@@ -82,7 +82,7 @@
         new InliningPhase(hints, new CanonicalizerPhase(true)).apply(graph, context);
         new CanonicalizerPhase(true).apply(graph, context);
         new DeadCodeEliminationPhase().apply(graph);
-        StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
+        StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET);
         assertEquals(referenceGraph, graph);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -89,7 +89,7 @@
 
     private StructuredGraph getGraph(String snippet) {
         Method method = getMethod(snippet);
-        StructuredGraph graph = parse(method);
+        StructuredGraph graph = parseEager(method);
         Assumptions assumptions = new Assumptions(true);
         HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
         new CanonicalizerPhase(true).apply(graph, context);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -121,8 +121,8 @@
     }
 
     private void test(String snippet, String referenceSnippet) {
-        final StructuredGraph graph = parse(snippet);
-        final StructuredGraph referenceGraph = parse(referenceSnippet);
+        final StructuredGraph graph = parseEager(snippet);
+        final StructuredGraph referenceGraph = parseEager(referenceSnippet);
 
         new LoopTransformLowPhase().apply(graph);
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,6 +24,7 @@
 
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static org.junit.Assert.*;
+
 import java.util.*;
 
 import org.junit.*;
@@ -600,7 +601,7 @@
     }
 
     private SchedulePhase getFinalSchedule(final String snippet, final TestMode mode, final MemoryScheduling memsched, final SchedulingStrategy schedulingStrategy) {
-        final StructuredGraph graph = parse(snippet);
+        final StructuredGraph graph = parseEager(snippet);
         try (Scope d = Debug.scope("FloatingReadTest", graph)) {
             try (OverrideScope s = OptionValue.override(OptScheduleOutOfLoops, schedulingStrategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS, OptImplicitNullChecks, false)) {
                 Assumptions assumptions = new Assumptions(false);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MergeCanonicalizerTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MergeCanonicalizerTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -57,7 +57,7 @@
     }
 
     private void testReturnCount(String snippet, int returnCount) {
-        StructuredGraph graph = parse(snippet);
+        StructuredGraph graph = parseEager(snippet);
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false)));
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false)));
         Debug.dump(graph, "Graph");
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,6 +23,7 @@
 package com.oracle.graal.compiler.test;
 
 import static com.oracle.graal.graph.iterators.NodePredicates.*;
+
 import java.util.*;
 
 import org.junit.*;
@@ -83,7 +84,7 @@
     }
 
     private StructuredGraph parseAndProcess(String snippet) {
-        StructuredGraph graph = parse(snippet);
+        StructuredGraph graph = parseEager(snippet);
         ParameterNode param = graph.getNodes(ParameterNode.class).first();
         if (param != null) {
             ConstantNode constant = ConstantNode.forInt(0, graph);
@@ -105,7 +106,7 @@
 
     private void test(String snippet) {
         StructuredGraph graph = parseAndProcess(snippet);
-        StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
+        StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET);
         assertEquals(referenceGraph, graph);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -145,7 +145,7 @@
     }
 
     private void test(String snippet, int rootExits, int nestedExits, int innerExits) {
-        StructuredGraph graph = parse(snippet);
+        StructuredGraph graph = parseEager(snippet);
         Debug.dump(graph, "Graph");
         ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true);
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PhiCreationTests.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PhiCreationTests.java	Mon Aug 25 21:15:59 2014 -0700
@@ -40,7 +40,7 @@
 
     @Test
     public void test1() {
-        StructuredGraph graph = parse("test1Snippet");
+        StructuredGraph graph = parseEager("test1Snippet");
         Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext());
     }
 
@@ -53,7 +53,7 @@
 
     @Test
     public void test2() {
-        StructuredGraph graph = parse("test2Snippet");
+        StructuredGraph graph = parseEager("test2Snippet");
         Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext());
     }
 
@@ -66,7 +66,7 @@
 
     @Test
     public void test3() {
-        StructuredGraph graph = parse("test3Snippet");
+        StructuredGraph graph = parseEager("test3Snippet");
         Debug.dump(graph, "Graph");
         Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext());
     }
@@ -82,7 +82,7 @@
 
     @Test
     public void test4() {
-        StructuredGraph graph = parse("test4Snippet");
+        StructuredGraph graph = parseEager("test4Snippet");
         Debug.dump(graph, "Graph");
         Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext());
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -91,7 +91,7 @@
     }
 
     private StructuredGraph compileTestSnippet(final String snippet) {
-        StructuredGraph graph = parse(snippet);
+        StructuredGraph graph = parseEager(snippet);
         PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false));
         CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
         new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushThroughIfTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushThroughIfTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -57,7 +57,7 @@
     }
 
     private void test(String snippet, String reference) {
-        StructuredGraph graph = parse(snippet);
+        StructuredGraph graph = parseEager(snippet);
         Debug.dump(graph, "Graph");
         for (FrameState fs : graph.getNodes(FrameState.class).snapshot()) {
             fs.replaceAtUsages(null);
@@ -66,7 +66,7 @@
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false)));
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false)));
 
-        StructuredGraph referenceGraph = parse(reference);
+        StructuredGraph referenceGraph = parseEager(reference);
         for (FrameState fs : referenceGraph.getNodes(FrameState.class).snapshot()) {
             fs.replaceAtUsages(null);
             GraphUtil.killWithUnusedFloatingInputs(fs);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -82,7 +82,7 @@
         try (Scope s = Debug.scope("ReadAfterCheckCastTest", new DebugDumpScope(snippet))) {
             // check shape of graph, with lots of assumptions. will probably fail if graph
             // structure changes significantly
-            StructuredGraph graph = parse(snippet);
+            StructuredGraph graph = parseEager(snippet);
             PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false));
             CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
             new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -243,10 +243,10 @@
     }
 
     private <T extends Node & IterableNodeType> void test(String test, String ref) {
-        StructuredGraph testGraph = parse(test);
+        StructuredGraph testGraph = parseEager(test);
         Assumptions assumptions = new Assumptions(false);
         new CanonicalizerPhase(true).apply(testGraph, new PhaseContext(getProviders(), assumptions));
-        StructuredGraph refGraph = parse(ref);
+        StructuredGraph refGraph = parseEager(ref);
         new CanonicalizerPhase(true).apply(refGraph, new PhaseContext(getProviders(), assumptions));
         assertEquals(testGraph, refGraph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,13 +22,13 @@
  */
 package com.oracle.graal.compiler.test;
 
-import com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase;
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.common.cfs.*;
 import com.oracle.graal.phases.tiers.*;
 
 /**
@@ -165,13 +165,13 @@
 
     private void test(final String snippet, final String referenceSnippet) {
         // No debug scope to reduce console noise for @Test(expected = ...) tests
-        StructuredGraph graph = parse(snippet);
+        StructuredGraph graph = parseEager(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
         PhaseContext context = new PhaseContext(getProviders(), assumptions);
         new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context);
         new CanonicalizerPhase(true).apply(graph, context);
-        StructuredGraph referenceGraph = parse(referenceSnippet);
+        StructuredGraph referenceGraph = parseEager(referenceSnippet);
         assertEquals(referenceGraph, graph);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.compiler.test;
 
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
 
 import java.util.*;
 
@@ -42,21 +42,21 @@
     public void testImplies() {
         StructuredGraph graph = new StructuredGraph();
 
-        AbstractEndNode trueEnd = graph.add(new EndNode());
-        AbstractEndNode falseEnd = graph.add(new EndNode());
+        AbstractEndNode trueEnd = graph.add(EndNode.create());
+        AbstractEndNode falseEnd = graph.add(EndNode.create());
 
-        BeginNode trueBegin = graph.add(new BeginNode());
+        BeginNode trueBegin = graph.add(BeginNode.create());
         trueBegin.setNext(trueEnd);
-        BeginNode falseBegin = graph.add(new BeginNode());
+        BeginNode falseBegin = graph.add(BeginNode.create());
         falseBegin.setNext(falseEnd);
 
-        IfNode ifNode = graph.add(new IfNode(null, trueBegin, falseBegin, 0.5));
+        IfNode ifNode = graph.add(IfNode.create(null, trueBegin, falseBegin, 0.5));
         graph.start().setNext(ifNode);
 
-        MergeNode merge = graph.add(new MergeNode());
+        MergeNode merge = graph.add(MergeNode.create());
         merge.addForwardEnd(trueEnd);
         merge.addForwardEnd(falseEnd);
-        ReturnNode returnNode = graph.add(new ReturnNode(null));
+        ReturnNode returnNode = graph.add(ReturnNode.create(null));
         merge.setNext(returnNode);
 
         dumpGraph(graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -109,7 +109,7 @@
     }
 
     private void testZeroReturn(String methodName) {
-        StructuredGraph graph = parse(methodName);
+        StructuredGraph graph = parseEager(methodName);
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false)));
         new DeadCodeEliminationPhase().apply(graph);
         assertConstantReturn(graph, 0);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -87,10 +87,10 @@
 
     private void test(final String snippet) {
         // No debug scope to reduce console noise for @Test(expected = ...) tests
-        StructuredGraph graph = parse(snippet);
+        StructuredGraph graph = parseEager(snippet);
         Debug.dump(graph, "Graph");
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false)));
-        StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
+        StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET);
         assertEquals(referenceGraph, graph);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,18 +24,17 @@
 
 import java.io.*;
 
-import com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase;
-
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.Verbosity;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.common.cfs.*;
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.phases.tiers.*;
 
@@ -196,7 +195,7 @@
     }
 
     private void test(String snippet, String referenceSnippet) {
-        StructuredGraph graph = parse(snippet);
+        StructuredGraph graph = parseEager(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
         /*
@@ -208,7 +207,7 @@
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
         // a second canonicalizer is needed to process nested MaterializeNodes
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
-        StructuredGraph referenceGraph = parse(referenceSnippet);
+        StructuredGraph referenceGraph = parseEager(referenceSnippet);
         new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(getProviders(), assumptions));
         assertEquals(referenceGraph, graph);
     }
@@ -256,7 +255,7 @@
     }
 
     private <T extends Node> void testHelper(String snippet, Class<T> clazz) {
-        StructuredGraph graph = parse(snippet);
+        StructuredGraph graph = parseEager(snippet);
         Assumptions assumptions = new Assumptions(false);
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
         new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, new PhaseContext(getProviders(), assumptions));
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -38,7 +38,6 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
@@ -48,7 +47,7 @@
 public class AllocatorTest extends GraalCompilerTest {
 
     protected void test(String snippet, final int expectedRegisters, final int expectedRegRegMoves, final int expectedSpillMoves) {
-        final StructuredGraph graph = parse(snippet);
+        final StructuredGraph graph = parseEager(snippet);
         try (Scope s = Debug.scope("AllocatorTest", graph, graph.method(), getCodeCache())) {
             final RegisterStats stats = getRegisterStats(graph);
             try (Scope s2 = Debug.scope("Assertions", stats.lir)) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -53,7 +53,7 @@
     @Test
     public void test1() {
         Method method = getMethod("testMethod");
-        final StructuredGraph graph = parse(method);
+        final StructuredGraph graph = parseEager(method);
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false)));
         new DeadCodeEliminationPhase().apply(graph);
 
@@ -76,7 +76,7 @@
     @Test
     public void test3() {
         Method method = getMethod("testMethod");
-        final StructuredGraph graph = parse(method);
+        final StructuredGraph graph = parseEager(method);
         final ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(method);
         InstalledCode compiledMethod = getCode(javaMethod, graph);
         try {
@@ -90,7 +90,7 @@
     @Test
     public void test4() {
         Method method = getMethod("testMethodVirtual");
-        final StructuredGraph graph = parse(method);
+        final StructuredGraph graph = parseEager(method);
         final ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(method);
         InstalledCode compiledMethod = getCode(javaMethod, graph);
         try {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/MonitorDeoptTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/MonitorDeoptTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -136,7 +136,7 @@
     public void run0() throws Throwable {
         Method method = getMethod("test");
 
-        StructuredGraph graph = parse(method);
+        StructuredGraph graph = parseEager(method);
         removeLoopSafepoint(graph);
 
         ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(method);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -40,7 +40,7 @@
 
     @Override
     protected void processMethod(final String snippet) {
-        graph = parse(snippet);
+        graph = parseEager(snippet);
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
         new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -276,9 +276,8 @@
         return obj2.x instanceof TestClassObject;
     }
 
-    @SuppressWarnings("unused")
     public static void testNewNodeSnippet() {
-        new ValueAnchorNode(null);
+        ValueAnchorNode.create(null);
     }
 
     /**
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -84,7 +84,7 @@
     }
 
     private void processMethod(final String snippet) {
-        graph = parse(snippet);
+        graph = parseEager(snippet);
         HighTierContext context = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
         new IterativeInliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,6 +23,7 @@
 package com.oracle.graal.compiler.test.ea;
 
 import static org.junit.Assert.*;
+
 import java.util.*;
 
 import org.junit.*;
@@ -243,7 +244,7 @@
     }
 
     protected void processMethod(final String snippet) {
-        graph = parse(snippet);
+        graph = parseEager(snippet);
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
         new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PoorMansEATest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PoorMansEATest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -59,7 +59,7 @@
 
     private void test(final String snippet) {
         try (Scope s = Debug.scope("PoorMansEATest", new DebugDumpScope(snippet))) {
-            StructuredGraph graph = parse(snippet);
+            StructuredGraph graph = parseEager(snippet);
             Assumptions assumptions = new Assumptions(false);
             HighTierContext highTierContext = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
             new InliningPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,6 +23,7 @@
 package com.oracle.graal.compiler.test.inlining;
 
 import static org.junit.Assert.*;
+
 import java.lang.reflect.*;
 
 import org.junit.*;
@@ -231,7 +232,7 @@
     private StructuredGraph getGraph(final String snippet, final boolean eagerInfopointMode) {
         try (Scope s = Debug.scope("InliningTest", new DebugDumpScope(snippet))) {
             Method method = getMethod(snippet);
-            StructuredGraph graph = eagerInfopointMode ? parseDebug(method) : parse(method);
+            StructuredGraph graph = eagerInfopointMode ? parseDebug(method) : parseEager(method);
             PhaseSuite<HighTierContext> graphBuilderSuite = eagerInfopointMode ? getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault()) : getDefaultGraphBuilderSuite();
             Assumptions assumptions = new Assumptions(true);
             HighTierContext context = new HighTierContext(getProviders(), assumptions, null, graphBuilderSuite, OptimisticOptimizations.ALL);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/nfi/NativeFunctionInterfaceTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,401 +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.test.nfi;
-
-import static com.oracle.graal.compiler.common.UnsafeAccess.*;
-import static java.io.File.*;
-import static java.lang.System.*;
-import static org.junit.Assert.*;
-import static org.junit.Assume.*;
-
-import java.io.*;
-import java.util.*;
-
-import org.junit.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.runtime.*;
-
-@Ignore
-public class NativeFunctionInterfaceTest {
-
-    public final NativeFunctionInterface nfi;
-
-    public NativeFunctionInterfaceTest() {
-        RuntimeProvider runtimeProvider = Graal.getRequiredCapability(RuntimeProvider.class);
-        Assume.assumeTrue(runtimeProvider.getHostBackend() instanceof HostBackend);
-        nfi = ((HostBackend) runtimeProvider.getHostBackend()).getNativeFunctionInterface();
-    }
-
-    private List<Long> allocations = new ArrayList<>();
-
-    protected long malloc(int length) {
-        long buf = unsafe.allocateMemory(length);
-        allocations.add(buf);
-        return buf;
-    }
-
-    @After
-    public void cleanup() {
-        for (long buf : allocations) {
-            unsafe.freeMemory(buf);
-        }
-    }
-
-    private static void assertCStringEquals(long cString, String s) {
-        for (int i = 0; i < s.length(); i++) {
-            assertEquals(unsafe.getByte(cString + i) & 0xFF, (byte) s.charAt(i));
-        }
-        assertEquals(unsafe.getByte(cString + s.length()) & 0xFF, (byte) '\0');
-    }
-
-    @Test
-    public void test1() {
-        assumeTrue(nfi.isDefaultLibrarySearchSupported());
-        NativeFunctionHandle malloc = nfi.getFunctionHandle("malloc", long.class, int.class);
-        NativeFunctionHandle snprintf = nfi.getFunctionHandle("snprintf", int.class, long.class, int.class, long.class);
-        NativeFunctionHandle free = nfi.getFunctionHandle("free", void.class, long.class);
-
-        String string = "GRAAL";
-        int bufferLength = string.length() + 1;
-        long cString = (long) malloc.call(bufferLength);
-        writeCString(string, cString);
-
-        long cStringCopy = malloc(bufferLength);
-        int result = (int) snprintf.call(cStringCopy, bufferLength, cString);
-        Assert.assertEquals(string.length(), result);
-        assertCStringEquals(cString, string);
-        assertCStringEquals(cStringCopy, string);
-
-        free.call(cString);
-    }
-
-    @Test
-    public void test2() {
-        assumeTrue(nfi.isDefaultLibrarySearchSupported());
-        String formatString = "AB %f%f";
-        long formatCString = writeCString("AB %f%f", malloc(formatString.length() + 1));
-
-        String referenceString = "AB 1.0000001.000000";
-        int bufferLength = referenceString.length() + 1;
-        long buffer = malloc(bufferLength);
-
-        NativeFunctionHandle snprintf = nfi.getFunctionHandle("snprintf", int.class, long.class, int.class, long.class, double.class, double.class);
-        int result = (int) snprintf.call(buffer, bufferLength, formatCString, 1.0D, 1.0D);
-
-        assertCStringEquals(buffer, referenceString);
-        Assert.assertEquals(referenceString.length(), result);
-    }
-
-    @Test
-    public void test3() {
-        assumeTrue(nfi.isDefaultLibrarySearchSupported());
-        String format = "%i%i%i%i%i%i%i%i%i%i%i%i";
-        long formatCString = writeCString(format, malloc(format.length() + 1));
-        String referenceString = "01234567891011";
-
-        int bufferLength = referenceString.length() + 1;
-        long buffer = malloc(bufferLength);
-
-        NativeFunctionHandle snprintf = nfi.getFunctionHandle("snprintf", int.class, long.class, int.class, long.class, int.class, int.class, int.class, int.class, int.class, int.class, int.class,
-                        int.class, int.class, int.class, int.class, int.class);
-
-        int result = (int) snprintf.call(buffer, bufferLength, formatCString, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
-        assertCStringEquals(buffer, referenceString);
-        Assert.assertEquals(referenceString.length(), result);
-    }
-
-    @Test
-    public void test4() {
-        assumeTrue(nfi.isDefaultLibrarySearchSupported());
-        long str = malloc(49);
-        int[] val = new int[12];
-        for (int i = 0; i < 12; i++) {
-            unsafe.putByte(str + 2 * i, (byte) '%');
-            unsafe.putByte(str + 2 * i + 1, (byte) 'i');
-            val[i] = i;
-        }
-        double[] dval = new double[12];
-        for (int i = 12; i < 24; i++) {
-            unsafe.putByte(str + 2 * i, (byte) '%');
-            unsafe.putByte(str + 2 * i + 1, (byte) 'f');
-            dval[i - 12] = i + 0.5;
-        }
-        unsafe.putByte(str + 48, (byte) '\0');
-
-        String referenceString = "0123456789101112.50000013.50000014.50000015.50000016.50000017.50000018.50000019.50000020.500000" + "21.50000022.50000023.500000";
-        int bufferLength = referenceString.length() + 1;
-
-        long buffer = malloc(bufferLength);
-
-        NativeFunctionHandle snprintf = nfi.getFunctionHandle("snprintf", int.class, long.class, int.class, long.class, int.class, int.class, int.class, int.class, int.class, int.class, int.class,
-                        int.class, int.class, int.class, int.class, int.class, double.class, double.class, double.class, double.class, double.class, double.class, double.class, double.class,
-                        double.class, double.class, double.class, double.class);
-
-        int result = (int) snprintf.call(buffer, bufferLength, str, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9], val[10], val[11], dval[0], dval[1], dval[2],
-                        dval[3], dval[4], dval[5], dval[6], dval[7], dval[8], dval[9], dval[10], dval[11]);
-        assertCStringEquals(buffer, referenceString);
-        Assert.assertEquals(referenceString.length(), result);
-    }
-
-    @Test
-    public void test5() {
-        assumeTrue(nfi.isDefaultLibrarySearchSupported());
-        long str = malloc(73);
-        int[] val = new int[12];
-        for (int i = 0; i < 12; i++) {
-            unsafe.putByte(str + 2 * i, (byte) '%');
-            unsafe.putByte(str + 2 * i + 1, (byte) 'i');
-            val[i] = i;
-        }
-        double[] dval = new double[12];
-        for (int i = 12; i < 24; i++) {
-            unsafe.putByte(str + 2 * i, (byte) '%');
-            unsafe.putByte(str + 2 * i + 1, (byte) 'f');
-            dval[i - 12] = i + 0.5;
-        }
-        char[] cval = new char[12];
-        for (int i = 24; i < 36; i++) {
-            unsafe.putByte(str + 2 * i, (byte) '%');
-            unsafe.putByte(str + 2 * i + 1, (byte) 'c');
-            cval[i - 24] = (char) ('a' + (i - 24));
-        }
-        unsafe.putByte(str + 72, (byte) '\0');
-
-        String referenceString = "0123456789101112.50000013.50000014.50000015.50000016.50000017.50000018.50000019.50000020.50000021.50000022.50000023.500000abcdefghijkl";
-        int bufferLength = referenceString.length() + 1;
-
-        long buffer = malloc(bufferLength);
-
-        NativeFunctionHandle snprintf = nfi.getFunctionHandle("snprintf", int.class, long.class, int.class, long.class, int.class, int.class, int.class, int.class, int.class, int.class, int.class,
-                        int.class, int.class, int.class, int.class, int.class, double.class, double.class, double.class, double.class, double.class, double.class, double.class, double.class,
-                        double.class, double.class, double.class, double.class, char.class, char.class, char.class, char.class, char.class, char.class, char.class, char.class, char.class, char.class,
-                        char.class, char.class);
-
-        int result = (int) snprintf.call(buffer, bufferLength, str, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9], val[10], val[11], dval[0], dval[1], dval[2],
-                        dval[3], dval[4], dval[5], dval[6], dval[7], dval[8], dval[9], dval[10], dval[11], cval[0], cval[1], cval[2], cval[3], cval[4], cval[5], cval[6], cval[7], cval[8], cval[9],
-                        cval[10], cval[11]);
-        assertCStringEquals(buffer, referenceString);
-        Assert.assertEquals(referenceString.length(), result);
-    }
-
-    @Test
-    public void test6() {
-        assumeTrue(nfi.isDefaultLibrarySearchSupported());
-        NativeFunctionHandle handle = nfi.getFunctionHandle("pow", double.class, double.class, double.class);
-        double result = (double) handle.call(3D, 5.5D);
-        assertEquals(Math.pow(3D, 5.5D), result, 0);
-    }
-
-    @Test
-    public void test7() {
-        assumeTrue(nfi.isDefaultLibrarySearchSupported());
-        double result = 0;
-        NativeFunctionHandle handle = nfi.getFunctionHandle("pow", double.class, double.class, double.class);
-        for (int i = 0; i < 10; i++) {
-            result = (double) handle.call(3D, 5.5D);
-        }
-        assertEquals(Math.pow(3D, 5.5D), result, 0);
-    }
-
-    @Test
-    public void test8() {
-        assumeTrue(nfi.isDefaultLibrarySearchSupported());
-        String formatString = "AB %f%f";
-        long formatCString = writeCString("AB %f%f", malloc(formatString.length() + 1));
-
-        String expected = "AB 1.0000001.000000";
-        int bufferLength = expected.length() + 1;
-        byte[] buffer = new byte[bufferLength];
-
-        NativeFunctionHandle snprintf = nfi.getFunctionHandle("snprintf", int.class, byte[].class, int.class, long.class, double.class, double.class);
-        int result = (int) snprintf.call(buffer, bufferLength, formatCString, 1.0D, 1.0D);
-
-        // trim trailing '\0'
-        String actual = new String(buffer, 0, expected.length());
-
-        assertEquals(expected, actual);
-        Assert.assertEquals(expected.length(), result);
-    }
-
-    private static double[] someDoubles = {2454.346D, 98789.22D, Double.MAX_VALUE, Double.MIN_NORMAL, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY};
-
-    @Test
-    public void test9() {
-        assumeTrue(nfi.isDefaultLibrarySearchSupported());
-        double[] src = someDoubles.clone();
-        double[] dst = new double[src.length];
-
-        NativeFunctionHandle memcpy = nfi.getFunctionHandle("memcpy", void.class, double[].class, double[].class, int.class);
-        memcpy.call(dst, src, src.length * (Double.SIZE / Byte.SIZE));
-
-        assertArrayEquals(src, dst, 0.0D);
-    }
-
-    private static String getVMName() {
-        String vmName = System.getProperty("java.vm.name").toLowerCase();
-        String vm = null;
-        if (vmName.contains("server")) {
-            vm = "server";
-        } else if (vmName.contains("graal")) {
-            vm = "graal";
-        } else if (vmName.contains("client")) {
-            vm = "client";
-        }
-
-        Assume.assumeTrue(vm != null);
-        return vm;
-    }
-
-    private static String getVMLibPath() {
-        String vm = getVMName();
-
-        String path = String.format("%s%c%s%c%s", getProperty("sun.boot.library.path"), separatorChar, vm, separatorChar, mapLibraryName("jvm"));
-        // Only continue if the library file exists
-        Assume.assumeTrue(new File(path).exists());
-        return path;
-    }
-
-    @Test
-    public void test10() {
-        NativeLibraryHandle vmLib = nfi.getLibraryHandle(getVMLibPath());
-        NativeFunctionHandle currentTimeMillis = nfi.getFunctionHandle(vmLib, "JVM_CurrentTimeMillis", long.class);
-        long time1 = (long) currentTimeMillis.call();
-        long time2 = System.currentTimeMillis();
-        long delta = time2 - time1;
-
-        // The 2 calls to get the current time should not differ by more than
-        // 100 milliseconds at the very most
-        assertTrue(String.valueOf(delta), delta >= 0);
-        assertTrue(String.valueOf(delta), delta < 100);
-    }
-
-    private static String getJavaLibPath() {
-        String path = String.format("%s%c%s", getProperty("sun.boot.library.path"), separatorChar, mapLibraryName("java"));
-        Assume.assumeTrue(new File(path).exists());
-        return path;
-    }
-
-    private static void testD2L(NativeFunctionHandle d2l) {
-        for (double d : someDoubles) {
-            long expected = Double.doubleToRawLongBits(d);
-            long actual = (long) d2l.call(0L, 0L, d);
-            assertEquals(Double.toString(d), expected, actual);
-        }
-    }
-
-    @Test
-    public void test11() {
-        NativeLibraryHandle javaLib = nfi.getLibraryHandle(getJavaLibPath());
-        NativeFunctionHandle d2l = nfi.getFunctionHandle(javaLib, "Java_java_lang_Double_doubleToRawLongBits", long.class, long.class, long.class, double.class);
-        testD2L(d2l);
-    }
-
-    @Test
-    public void test12() {
-        NativeLibraryHandle[] libs = {nfi.getLibraryHandle(getVMLibPath()), nfi.getLibraryHandle(getJavaLibPath())};
-        NativeFunctionHandle d2l = nfi.getFunctionHandle(libs, "Java_java_lang_Double_doubleToRawLongBits", long.class, long.class, long.class, double.class);
-        testD2L(d2l);
-
-        NativeLibraryHandle[] libsReveresed = {libs[1], libs[0]};
-        d2l = nfi.getFunctionHandle(libsReveresed, "Java_java_lang_Double_doubleToRawLongBits", long.class, long.class, long.class, double.class);
-        testD2L(d2l);
-    }
-
-    @Test
-    public void test13() {
-        NativeLibraryHandle[] libs = {nfi.getLibraryHandle(getVMLibPath()), nfi.getLibraryHandle(getJavaLibPath())};
-        NativeFunctionPointer functionPointer = nfi.getFunctionPointer(libs, "Java_java_lang_Double_doubleToRawLongBits");
-        NativeFunctionHandle d2l = nfi.getFunctionHandle(functionPointer, long.class, long.class, long.class, double.class);
-        testD2L(d2l);
-
-        NativeLibraryHandle[] libsReveresed = {libs[1], libs[0]};
-        functionPointer = nfi.getFunctionPointer(libsReveresed, "Java_java_lang_Double_doubleToRawLongBits");
-        d2l = nfi.getFunctionHandle(functionPointer, long.class, long.class, long.class, double.class);
-        testD2L(d2l);
-    }
-
-    @Test
-    public void test14() {
-        if (!nfi.isDefaultLibrarySearchSupported()) {
-            try {
-                nfi.getFunctionHandle("snprintf", int.class);
-                fail();
-            } catch (UnsatisfiedLinkError e) {
-            }
-        }
-    }
-
-    @Test
-    public void test15() {
-        assumeTrue(nfi.isDefaultLibrarySearchSupported());
-        try {
-            nfi.getFunctionHandle("an invalid function name", int.class);
-            fail();
-        } catch (UnsatisfiedLinkError e) {
-        }
-    }
-
-    @Test
-    public void test16() {
-        NativeLibraryHandle javaLib = nfi.getLibraryHandle(getJavaLibPath());
-        try {
-
-            nfi.getFunctionHandle(javaLib, "an invalid function name", int.class);
-            fail();
-        } catch (UnsatisfiedLinkError e) {
-        }
-    }
-
-    @Test
-    public void test17() {
-        NativeLibraryHandle[] libs = {nfi.getLibraryHandle(getVMLibPath()), nfi.getLibraryHandle(getJavaLibPath())};
-        try {
-            nfi.getFunctionPointer(libs, "an invalid function name");
-            fail();
-        } catch (UnsatisfiedLinkError e) {
-        }
-    }
-
-    @Test
-    public void test18() {
-        NativeLibraryHandle[] libs = {nfi.getLibraryHandle(getVMLibPath()), nfi.getLibraryHandle(getJavaLibPath())};
-        try {
-            nfi.getFunctionHandle(libs, "an invalid function name", int.class);
-            fail();
-        } catch (UnsatisfiedLinkError e) {
-        }
-    }
-
-    @Test
-    public void test19() {
-        try {
-            nfi.getLibraryHandle("an invalid library name");
-            fail();
-        } catch (UnsatisfiedLinkError e) {
-        }
-    }
-
-}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/CompilerThread.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/CompilerThread.java	Mon Aug 25 21:15:59 2014 -0700
@@ -44,6 +44,7 @@
     @Override
     public void run() {
         GraalDebugConfig debugConfig = debugConfigAccess.getDebugConfig();
+        setContextClassLoader(getClass().getClassLoader());
         try {
             super.run();
         } finally {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Mon Aug 25 21:15:59 2014 -0700
@@ -29,8 +29,8 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.options.*;
@@ -38,17 +38,17 @@
 public class GraalDebugConfig implements DebugConfig {
 
     // @formatter:off
-    @Option(help = "Pattern for scope(s) to in which dumping is enabled (see DebugFilter and Debug.dump)")
+    @Option(help = "Pattern for scope(s) 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)")
+    @Option(help = "Pattern for scope(s) in which metering is enabled (see DebugFilter and Debug.metric)")
     public static final OptionValue<String> Meter = new OptionValue<>(null);
-    @Option(help = "Pattern for scope(s) to in which verification is enabled (see DebugFilter and Debug.verify)")
+    @Option(help = "Pattern for scope(s) in which verification is enabled (see DebugFilter and Debug.verify)")
     public static final OptionValue<String> Verify = new OptionValue<>(null);
-    @Option(help = "Pattern for scope(s) to in which memory use tracking is enabled (see DebugFilter and Debug.metric)")
+    @Option(help = "Pattern for scope(s) in which memory use tracking is enabled (see DebugFilter and Debug.metric)")
     public static final OptionValue<String> TrackMemUse = new OptionValue<>(null);
-    @Option(help = "Pattern for scope(s) to in which timing is enabled (see DebugFilter and Debug.timer)")
+    @Option(help = "Pattern for scope(s) in which timing is enabled (see DebugFilter and Debug.timer)")
     public static final OptionValue<String> Time = new OptionValue<>(null);
-    @Option(help = "Pattern for scope(s) to in which logging is enabled (see DebugFilter and Debug.log)")
+    @Option(help = "Pattern for scope(s) in which logging is enabled (see DebugFilter and Debug.log)")
     public static final OptionValue<String> Log = new OptionValue<>(null);
     @Option(help = "Pattern for filtering debug scope output based on method context (see MethodFilter)")
     public static final OptionValue<String> MethodFilter = new OptionValue<>(null);
@@ -259,14 +259,14 @@
             if (o instanceof Graph) {
                 Debug.log("Context obj %s", o);
                 if (DumpOnError.getValue()) {
-                    Debug.dump(o, "Exception graph");
+                    Debug.dump(o, "Exception graph: " + e);
                 } else {
                     Debug.log("Use -G:+DumpOnError to enable dumping of graphs on this error");
                 }
             } else if (o instanceof LIR) {
                 Debug.log("Context obj %s", o);
                 if (DumpOnError.getValue()) {
-                    Debug.dump(o, "LIR");
+                    Debug.dump(o, "Exception LIR: " + e);
                 } else {
                     Debug.log("Use -G:+DumpOnError to enable dumping of graphs on this error");
                 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Mon Aug 25 21:15:59 2014 -0700
@@ -42,11 +42,8 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.InstructionStateProcedure;
-import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
-import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.options.*;
@@ -615,14 +612,13 @@
         intervalsSize = operandSize();
         intervals = new Interval[intervalsSize + (intervalsSize >> SPLIT_INTERVALS_CAPACITY_RIGHT_SHIFT)];
 
-        ValueProcedure setVariableProc = new ValueProcedure() {
+        ValueConsumer setVariableConsumer = new ValueConsumer() {
 
             @Override
-            public Value doValue(Value value) {
+            public void visitValue(Value value) {
                 if (isVariable(value)) {
                     getOrCreateInterval(asVariable(value));
                 }
-                return value;
             }
         };
 
@@ -652,8 +648,8 @@
                 opIdToBlockMap[index] = block;
                 assert instructionForId(opId) == op : "must match";
 
-                op.forEachTemp(setVariableProc);
-                op.forEachOutput(setVariableProc);
+                op.visitEachTemp(setVariableConsumer);
+                op.visitEachOutput(setVariableConsumer);
 
                 index++;
                 opId += 2; // numbering of lirOps by two
@@ -682,10 +678,10 @@
                 List<LIRInstruction> instructions = ir.getLIRforBlock(block);
                 int numInst = instructions.size();
 
-                ValueProcedure useProc = new ValueProcedure() {
+                ValueConsumer useConsumer = new ValueConsumer() {
 
                     @Override
-                    protected Value doValue(Value operand) {
+                    protected void visitValue(Value operand) {
                         if (isVariable(operand)) {
                             int operandNum = operandNumber(operand);
                             if (!liveKill.get(operandNum)) {
@@ -700,25 +696,23 @@
                         if (DetailedAsserts.getValue()) {
                             verifyInput(block, liveKill, operand);
                         }
-                        return operand;
                     }
                 };
-                ValueProcedure stateProc = new ValueProcedure() {
+                ValueConsumer stateConsumer = new ValueConsumer() {
 
                     @Override
-                    public Value doValue(Value operand) {
+                    public void visitValue(Value operand) {
                         int operandNum = operandNumber(operand);
                         if (!liveKill.get(operandNum)) {
                             liveGen.set(operandNum);
                             Debug.log("liveGen in state for operand %d", operandNum);
                         }
-                        return operand;
                     }
                 };
-                ValueProcedure defProc = new ValueProcedure() {
+                ValueConsumer defConsumer = new ValueConsumer() {
 
                     @Override
-                    public Value doValue(Value operand) {
+                    public void visitValue(Value operand) {
                         if (isVariable(operand)) {
                             int varNum = operandNumber(operand);
                             liveKill.set(varNum);
@@ -734,7 +728,6 @@
                             // process them only in debug mode so that this can be checked
                             verifyTemp(liveKill, operand);
                         }
-                        return operand;
                     }
                 };
 
@@ -743,13 +736,13 @@
                     final LIRInstruction op = instructions.get(j);
 
                     try (Indent indent2 = Debug.logAndIndent("handle op %d", op.id())) {
-                        op.forEachInput(useProc);
-                        op.forEachAlive(useProc);
+                        op.visitEachInput(useConsumer);
+                        op.visitEachAlive(useConsumer);
                         // Add uses of live locals from interpreter's point of view for proper debug
                         // information generation
-                        op.forEachState(stateProc);
-                        op.forEachTemp(defProc);
-                        op.forEachOutput(defProc);
+                        op.visitEachState(stateConsumer);
+                        op.visitEachTemp(defConsumer);
+                        op.visitEachOutput(defConsumer);
                     }
                 } // end of instruction iteration
 
@@ -1145,34 +1138,32 @@
     void buildIntervals() {
 
         try (Indent indent = Debug.logAndIndent("build intervals")) {
-            InstructionValueProcedure outputProc = new InstructionValueProcedure() {
+            InstructionValueConsumer outputConsumer = new InstructionValueConsumer() {
 
                 @Override
-                public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
+                public void visitValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
                     if (isVariableOrRegister(operand)) {
                         addDef((AllocatableValue) operand, op, registerPriorityOfOutputOperand(op), operand.getLIRKind());
                         addRegisterHint(op, operand, mode, flags, true);
                     }
-                    return operand;
                 }
             };
 
-            InstructionValueProcedure tempProc = new InstructionValueProcedure() {
+            InstructionValueConsumer tempConsumer = new InstructionValueConsumer() {
 
                 @Override
-                public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
+                public void visitValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
                     if (isVariableOrRegister(operand)) {
                         addTemp((AllocatableValue) operand, op.id(), RegisterPriority.MustHaveRegister, operand.getLIRKind());
                         addRegisterHint(op, operand, mode, flags, false);
                     }
-                    return operand;
                 }
             };
 
-            InstructionValueProcedure aliveProc = new InstructionValueProcedure() {
+            InstructionValueConsumer aliveConsumer = new InstructionValueConsumer() {
 
                 @Override
-                public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
+                public void visitValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
                     if (isVariableOrRegister(operand)) {
                         RegisterPriority p = registerPriorityOfInputOperand(flags);
                         final int opId = op.id();
@@ -1180,14 +1171,13 @@
                         addUse((AllocatableValue) operand, blockFrom, opId + 1, p, operand.getLIRKind());
                         addRegisterHint(op, operand, mode, flags, false);
                     }
-                    return operand;
                 }
             };
 
-            InstructionValueProcedure inputProc = new InstructionValueProcedure() {
+            InstructionValueConsumer inputConsumer = new InstructionValueConsumer() {
 
                 @Override
-                public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
+                public void visitValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
                     if (isVariableOrRegister(operand)) {
                         final int opId = op.id();
                         final int blockFrom = getFirstLirInstructionId((blockForId(opId)));
@@ -1195,18 +1185,16 @@
                         addUse((AllocatableValue) operand, blockFrom, opId, p, operand.getLIRKind());
                         addRegisterHint(op, operand, mode, flags, false);
                     }
-                    return operand;
                 }
             };
 
-            InstructionValueProcedure stateProc = new InstructionValueProcedure() {
+            InstructionValueConsumer stateProc = new InstructionValueConsumer() {
 
                 @Override
-                public Value doValue(LIRInstruction op, Value operand) {
+                public void visitValue(LIRInstruction op, Value operand) {
                     final int opId = op.id();
                     final int blockFrom = getFirstLirInstructionId((blockForId(opId)));
                     addUse((AllocatableValue) operand, blockFrom, opId + 1, RegisterPriority.None, operand.getLIRKind());
-                    return operand;
                 }
             };
 
@@ -1263,17 +1251,17 @@
                                 Debug.log("operation destroys all caller-save registers");
                             }
 
-                            op.forEachOutput(outputProc);
-                            op.forEachTemp(tempProc);
-                            op.forEachAlive(aliveProc);
-                            op.forEachInput(inputProc);
+                            op.visitEachOutput(outputConsumer);
+                            op.visitEachTemp(tempConsumer);
+                            op.visitEachAlive(aliveConsumer);
+                            op.visitEachInput(inputConsumer);
 
                             // Add uses of live locals from interpreter's point of view for proper
                             // debug information generation
                             // Treat these operands as temp values (if the live range is extended
                             // to a call site, the value would be in a register at
                             // the call otherwise)
-                            op.forEachState(stateProc);
+                            op.visitEachState(stateProc);
 
                             // special steps for some instructions (especially moves)
                             handleMethodArguments(op);
@@ -2202,25 +2190,24 @@
         }
     }
 
-    class CheckProcedure extends ValueProcedure {
+    class CheckConsumer extends ValueConsumer {
 
         boolean ok;
         Interval curInterval;
 
         @Override
-        protected Value doValue(Value operand) {
+        protected void visitValue(Value operand) {
             if (isRegister(operand)) {
                 if (intervalFor(operand) == curInterval) {
                     ok = true;
                 }
             }
-            return operand;
         }
     }
 
     void verifyNoOopsInFixedIntervals() {
         try (Indent indent = Debug.logAndIndent("verifying that no oops are in fixed intervals *")) {
-            CheckProcedure checkProc = new CheckProcedure();
+            CheckConsumer checkConsumer = new CheckConsumer();
 
             Interval fixedIntervals;
             Interval otherIntervals;
@@ -2249,15 +2236,15 @@
                                     // This interval is live out of this op so make sure
                                     // that this interval represents some value that's
                                     // referenced by this op either as an input or output.
-                                    checkProc.curInterval = interval;
-                                    checkProc.ok = false;
+                                    checkConsumer.curInterval = interval;
+                                    checkConsumer.ok = false;
 
-                                    op.forEachInput(checkProc);
-                                    op.forEachAlive(checkProc);
-                                    op.forEachTemp(checkProc);
-                                    op.forEachOutput(checkProc);
+                                    op.visitEachInput(checkConsumer);
+                                    op.visitEachAlive(checkConsumer);
+                                    op.visitEachTemp(checkConsumer);
+                                    op.visitEachOutput(checkConsumer);
 
-                                    assert checkProc.ok : "fixed intervals should never be live across an oopmap point";
+                                    assert checkConsumer.ok : "fixed intervals should never be live across an oopmap point";
                                 }
                             }
                         }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java	Mon Aug 25 21:15:59 2014 -0700
@@ -32,7 +32,6 @@
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.phases.util.*;
@@ -187,10 +186,10 @@
     }
 
     void processOperations(List<LIRInstruction> ops, final Interval[] inputState) {
-        InstructionValueProcedure useProc = new InstructionValueProcedure() {
+        InstructionValueConsumer useConsumer = new InstructionValueConsumer() {
 
             @Override
-            public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
+            public void visitValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
                 // we skip spill moves inserted by the spill position optimization
                 if (LinearScan.isVariableOrRegister(operand) && allocator.isProcessed(operand) && op.id() != LinearScan.DOMINATOR_SPILL_MOVE_ID) {
                     Interval interval = intervalAt(operand);
@@ -200,14 +199,13 @@
 
                     assert checkState(inputState, interval.location(), interval.splitParent());
                 }
-                return operand;
             }
         };
 
-        InstructionValueProcedure defProc = new InstructionValueProcedure() {
+        InstructionValueConsumer defConsumer = new InstructionValueConsumer() {
 
             @Override
-            public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
+            public void visitValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
                 if (LinearScan.isVariableOrRegister(operand) && allocator.isProcessed(operand)) {
                     Interval interval = intervalAt(operand);
                     if (op.id() != -1) {
@@ -216,7 +214,6 @@
 
                     statePut(inputState, interval.location(), interval.splitParent());
                 }
-                return operand;
             }
         };
 
@@ -229,19 +226,19 @@
             }
 
             // check if input operands are correct
-            op.forEachInput(useProc);
+            op.visitEachInput(useConsumer);
             // invalidate all caller save registers at calls
             if (op.destroysCallerSavedRegisters()) {
                 for (Register r : allocator.frameMap.registerConfig.getCallerSaveRegisters()) {
                     statePut(inputState, r.asValue(), null);
                 }
             }
-            op.forEachAlive(useProc);
+            op.visitEachAlive(useConsumer);
             // set temp operands (some operations use temp operands also as output operands, so
             // can't set them null)
-            op.forEachTemp(defProc);
+            op.visitEachTemp(defConsumer);
             // set output operands
-            op.forEachOutput(defProc);
+            op.visitEachOutput(defConsumer);
         }
     }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchPattern.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchPattern.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,8 +23,8 @@
 package com.oracle.graal.compiler.match;
 
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
 /**
@@ -137,7 +137,7 @@
     /**
      * The inputs to match the patterns against.
      */
-    private final NodeClass.Position[] inputs;
+    private final Position[] inputs;
 
     /**
      * Can there only be one user of the node. Constant nodes can be matched even if there are other
@@ -159,7 +159,7 @@
         this.inputs = null;
     }
 
-    private MatchPattern(Class<? extends ValueNode> nodeClass, String name, boolean singleUser, MatchPattern[] patterns, NodeClass.Position[] inputs) {
+    private MatchPattern(Class<? extends ValueNode> nodeClass, String name, boolean singleUser, MatchPattern[] patterns, Position[] inputs) {
         assert inputs == null || inputs.length == patterns.length;
         this.nodeClass = nodeClass;
         this.name = name;
@@ -168,15 +168,15 @@
         this.inputs = inputs;
     }
 
-    public MatchPattern(Class<? extends ValueNode> nodeClass, String name, MatchPattern first, NodeClass.Position[] inputs, boolean singleUser) {
+    public MatchPattern(Class<? extends ValueNode> nodeClass, String name, MatchPattern first, Position[] inputs, boolean singleUser) {
         this(nodeClass, name, singleUser, new MatchPattern[]{first}, inputs);
     }
 
-    public MatchPattern(Class<? extends ValueNode> nodeClass, String name, MatchPattern first, MatchPattern second, NodeClass.Position[] inputs, boolean singleUser) {
+    public MatchPattern(Class<? extends ValueNode> nodeClass, String name, MatchPattern first, MatchPattern second, Position[] inputs, boolean singleUser) {
         this(nodeClass, name, singleUser, new MatchPattern[]{first, second}, inputs);
     }
 
-    public MatchPattern(Class<? extends ValueNode> nodeClass, String name, MatchPattern first, MatchPattern second, MatchPattern third, NodeClass.Position[] inputs, boolean singleUser) {
+    public MatchPattern(Class<? extends ValueNode> nodeClass, String name, MatchPattern first, MatchPattern second, MatchPattern third, Position[] inputs, boolean singleUser) {
         this(nodeClass, name, singleUser, new MatchPattern[]{first, second, third}, inputs);
     }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java	Mon Aug 25 21:15:59 2014 -0700
@@ -193,7 +193,7 @@
         }
 
         /**
-         * Recursively accumulate any required NodeClass.Position declarations.
+         * Recursively accumulate any required Position declarations.
          */
         void generatePositionDeclarations(Set<String> declarations) {
             matchDescriptor.generatePositionDeclarations(declarations);
@@ -460,7 +460,7 @@
         }
 
         String generatePositionDeclaration() {
-            return String.format("NodeClass.Position[] %s_positions = MatchRuleRegistry.findPositions(lookup, %s.class, new String[]{\"%s\"});", nodeType.nodeClass, nodeType.nodeClass,
+            return String.format("Position[] %s_positions = MatchRuleRegistry.findPositions(lookup, %s.class, new String[]{\"%s\"});", nodeType.nodeClass, nodeType.nodeClass,
                             String.join("\", \"", nodeType.inputs));
         }
     }
@@ -493,7 +493,7 @@
             out.println("import java.util.*;");
             out.println("import " + MatchStatementSet.class.getPackage().getName() + ".*;");
             out.println("import " + NodeLIRBuilder.class.getName() + ";");
-            out.println("import " + NodeClass.class.getName() + ";");
+            out.println("import " + Position.class.getName() + ";");
             for (String p : requiredPackages) {
                 out.println("import " + p + ".*;");
             }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java	Mon Aug 25 21:15:59 2014 -0700
@@ -44,7 +44,6 @@
      */
     public static interface NodeClassLookup {
         NodeClass get(Class<?> theClass);
-
     }
 
     static class DefaultNodeClassLookup implements NodeClassLookup {
@@ -54,19 +53,19 @@
     }
 
     /**
-     * Convert a list of field names into {@link com.oracle.graal.graph.NodeClass.Position} objects
-     * that can be used to read them during a match. The names should already have been confirmed to
-     * exist in the type.
+     * Convert a list of field names into {@link com.oracle.graal.graph.Position} objects that can
+     * be used to read them during a match. The names should already have been confirmed to exist in
+     * the type.
      *
      * @param theClass
      * @param names
      * @return an array of Position objects corresponding to the named fields.
      */
-    public static NodeClass.Position[] findPositions(NodeClassLookup lookup, Class<? extends ValueNode> theClass, String[] names) {
-        NodeClass.Position[] result = new NodeClass.Position[names.length];
+    public static Position[] findPositions(NodeClassLookup lookup, Class<? extends ValueNode> theClass, String[] names) {
+        Position[] result = new Position[names.length];
         NodeClass nodeClass = lookup.get(theClass);
         for (int i = 0; i < names.length; i++) {
-            for (NodeClass.Position position : nodeClass.getFirstLevelInputPositions()) {
+            for (Position position : nodeClass.getFirstLevelInputPositions()) {
                 String name = nodeClass.getName(position);
                 if (name.equals(names[i])) {
                     result[i] = position;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatement.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatement.java	Mon Aug 25 21:15:59 2014 -0700
@@ -32,7 +32,7 @@
 import com.oracle.graal.compiler.match.MatchPattern.Result;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.Verbosity;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
 /**
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/HostBackend.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2014, 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.target;
-
-import com.oracle.graal.api.code.*;
-
-/**
- * Common functionality of host backends.
- */
-public interface HostBackend {
-    NativeFunctionInterface getNativeFunctionInterface();
-}
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Mon Aug 25 21:15:59 2014 -0700
@@ -929,6 +929,9 @@
     private static DebugMetric createMetric(String format, Object arg1, Object arg2) {
         String name = formatDebugName(format, arg1, arg2);
         boolean conditional = enabledMetrics == null || !enabledMetrics.contains(name);
+        if (!ENABLED && conditional) {
+            return VOID_METRIC;
+        }
         return new MetricImpl(name, conditional);
     }
 
@@ -1082,19 +1085,39 @@
     static {
         Set<String> metrics = new HashSet<>();
         Set<String> timers = new HashSet<>();
-        for (Map.Entry<Object, Object> e : System.getProperties().entrySet()) {
-            String name = e.getKey().toString();
-            if (name.startsWith(ENABLE_METRIC_PROPERTY_NAME_PREFIX) && Boolean.parseBoolean(e.getValue().toString())) {
-                metrics.add(name.substring(ENABLE_METRIC_PROPERTY_NAME_PREFIX.length()));
-            }
-            if (name.startsWith(ENABLE_TIMER_PROPERTY_NAME_PREFIX) && Boolean.parseBoolean(e.getValue().toString())) {
-                timers.add(name.substring(ENABLE_TIMER_PROPERTY_NAME_PREFIX.length()));
-            }
-        }
+        parseMetricAndTimerSystemProperties(metrics, timers);
         enabledMetrics = metrics.isEmpty() ? null : metrics;
         enabledTimers = timers.isEmpty() ? null : timers;
     }
 
+    public static boolean areUnconditionalTimersEnabled() {
+        return enabledTimers != null && !enabledTimers.isEmpty();
+    }
+
+    public static boolean areUnconditionalMetricsEnabled() {
+        return enabledMetrics != null && !enabledMetrics.isEmpty();
+    }
+
+    protected static void parseMetricAndTimerSystemProperties(Set<String> metrics, Set<String> timers) {
+        do {
+            try {
+                for (Map.Entry<Object, Object> e : System.getProperties().entrySet()) {
+                    String name = e.getKey().toString();
+                    if (name.startsWith(ENABLE_METRIC_PROPERTY_NAME_PREFIX) && Boolean.parseBoolean(e.getValue().toString())) {
+                        metrics.add(name.substring(ENABLE_METRIC_PROPERTY_NAME_PREFIX.length()));
+                    }
+                    if (name.startsWith(ENABLE_TIMER_PROPERTY_NAME_PREFIX) && Boolean.parseBoolean(e.getValue().toString())) {
+                        timers.add(name.substring(ENABLE_TIMER_PROPERTY_NAME_PREFIX.length()));
+                    }
+                }
+                return;
+            } catch (ConcurrentModificationException e) {
+                // Iterating over the system properties may race with another thread that is
+                // updating the system properties. Simply try again in this case.
+            }
+        } while (true);
+    }
+
     /**
      * Creates a {@linkplain DebugTimer timer} that is enabled iff debugging is
      * {@linkplain #isEnabled() enabled} or the system property whose name is formed by adding to
@@ -1183,6 +1206,9 @@
     private static DebugTimer createTimer(String format, Object arg1, Object arg2) {
         String name = formatDebugName(format, arg1, arg2);
         boolean conditional = enabledTimers == null || !enabledTimers.contains(name);
+        if (!ENABLED && conditional) {
+            return VOID_TIMER;
+        }
         return new TimerImpl(name, conditional);
     }
 
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MemUseTrackerImpl.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MemUseTrackerImpl.java	Mon Aug 25 21:15:59 2014 -0700
@@ -38,7 +38,7 @@
      */
     private static final long threadMXBeanOverhead = -getCurrentThreadAllocatedBytes() + getCurrentThreadAllocatedBytes();
 
-    private static long getCurrentThreadAllocatedBytes() {
+    public static long getCurrentThreadAllocatedBytes() {
         return threadMXBean.getThreadAllocatedBytes(currentThread().getId()) - threadMXBeanOverhead;
     }
 
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeMapTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeMapTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,10 +27,18 @@
 import org.junit.*;
 
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 
 public class NodeMapTest {
 
-    private static class TestNode extends Node {
+    @NodeInfo
+    static class TestNode extends Node {
+        TestNode() {
+        }
+
+        public static TestNode create() {
+            return USE_GENERATED_NODES ? new NodeMapTest_TestNodeGen() : new TestNode();
+        }
     }
 
     private Graph graph;
@@ -41,7 +49,7 @@
     public void before() {
         graph = new Graph();
         for (int i = 0; i < nodes.length; i++) {
-            nodes[i] = graph.add(new TestNode());
+            nodes[i] = graph.add(TestNode.create());
         }
         map = new NodeMap<>(graph);
         for (int i = 0; i < nodes.length; i += 2) {
@@ -95,7 +103,7 @@
          * Failing here is not required, but if this behavior changes, usages of get need to be
          * checked for compatibility.
          */
-        TestNode newNode = graph.add(new TestNode());
+        TestNode newNode = graph.add(TestNode.create());
         map.get(newNode);
     }
 
@@ -105,19 +113,19 @@
          * Failing here is not required, but if this behavior changes, usages of set need to be
          * checked for compatibility.
          */
-        TestNode newNode = graph.add(new TestNode());
+        TestNode newNode = graph.add(TestNode.create());
         map.set(newNode, 1);
     }
 
     @Test
     public void testNewGetAndGrow() {
-        TestNode newNode = graph.add(new TestNode());
+        TestNode newNode = graph.add(TestNode.create());
         assertEquals(null, map.getAndGrow(newNode));
     }
 
     @Test
     public void testNewSetAndGrow() {
-        TestNode newNode = graph.add(new TestNode());
+        TestNode newNode = graph.add(TestNode.create());
         map.setAndGrow(newNode, 1);
         assertEquals((Integer) 1, map.get(newNode));
     }
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeUsagesTests.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeUsagesTests.java	Mon Aug 25 21:15:59 2014 -0700
@@ -29,19 +29,28 @@
 import org.junit.*;
 
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 
 public class NodeUsagesTests {
 
-    private static class Def extends Node {
-
+    @NodeInfo
+    static class Def extends Node {
+        public static Def create() {
+            return USE_GENERATED_NODES ? new NodeUsagesTests_DefGen() : new Def();
+        }
     }
 
-    private static class Use extends Node {
-        private @Input Def in0;
-        private @Input Def in1;
-        private @Input Def in2;
+    @NodeInfo
+    static class Use extends Node {
+        @Input Def in0;
+        @Input Def in1;
+        @Input Def in2;
 
-        public Use(Def in0, Def in1, Def in2) {
+        public static Use create(Def in0, Def in1, Def in2) {
+            return USE_GENERATED_NODES ? new NodeUsagesTests_UseGen(in0, in1, in2) : new Use(in0, in1, in2);
+        }
+
+        Use(Def in0, Def in1, Def in2) {
             this.in0 = in0;
             this.in1 = in1;
             this.in2 = in2;
@@ -51,11 +60,11 @@
     @Test
     public void testReplaceAtUsages() {
         Graph graph = new Graph();
-        Def def0 = graph.add(new Def());
-        Def def1 = graph.add(new Def());
-        Use use0 = graph.add(new Use(def0, null, null));
-        Use use1 = graph.add(new Use(null, def0, null));
-        Use use2 = graph.add(new Use(null, null, def0));
+        Def def0 = graph.add(Def.create());
+        Def def1 = graph.add(Def.create());
+        Use use0 = graph.add(Use.create(def0, null, null));
+        Use use1 = graph.add(Use.create(null, def0, null));
+        Use use2 = graph.add(Use.create(null, null, def0));
 
         assertEquals(3, def0.usages().count());
         assertThat(def0.usages(), contains(use0));
@@ -80,11 +89,11 @@
     @Test
     public void testReplaceAtUsagesWithPredicateAll() {
         Graph graph = new Graph();
-        Def def0 = graph.add(new Def());
-        Def def1 = graph.add(new Def());
-        Use use0 = graph.add(new Use(def0, null, null));
-        Use use1 = graph.add(new Use(null, def0, null));
-        Use use2 = graph.add(new Use(null, null, def0));
+        Def def0 = graph.add(Def.create());
+        Def def1 = graph.add(Def.create());
+        Use use0 = graph.add(Use.create(def0, null, null));
+        Use use1 = graph.add(Use.create(null, def0, null));
+        Use use2 = graph.add(Use.create(null, null, def0));
 
         assertEquals(3, def0.usages().count());
         assertThat(def0.usages(), contains(use0));
@@ -109,11 +118,11 @@
     @Test
     public void testReplaceAtUsagesWithPredicateNone() {
         Graph graph = new Graph();
-        Def def0 = graph.add(new Def());
-        Def def1 = graph.add(new Def());
-        Use use0 = graph.add(new Use(def0, null, null));
-        Use use1 = graph.add(new Use(null, def0, null));
-        Use use2 = graph.add(new Use(null, null, def0));
+        Def def0 = graph.add(Def.create());
+        Def def1 = graph.add(Def.create());
+        Use use0 = graph.add(Use.create(def0, null, null));
+        Use use1 = graph.add(Use.create(null, def0, null));
+        Use use2 = graph.add(Use.create(null, null, def0));
 
         assertEquals(3, def0.usages().count());
         assertThat(def0.usages(), contains(use0));
@@ -138,11 +147,11 @@
     @Test
     public void testReplaceAtUsagesWithPredicate1() {
         Graph graph = new Graph();
-        Def def0 = graph.add(new Def());
-        Def def1 = graph.add(new Def());
-        Use use0 = graph.add(new Use(def0, null, null));
-        Use use1 = graph.add(new Use(null, def0, null));
-        Use use2 = graph.add(new Use(null, null, def0));
+        Def def0 = graph.add(Def.create());
+        Def def1 = graph.add(Def.create());
+        Use use0 = graph.add(Use.create(def0, null, null));
+        Use use1 = graph.add(Use.create(null, def0, null));
+        Use use2 = graph.add(Use.create(null, null, def0));
 
         assertEquals(3, def0.usages().count());
         assertThat(def0.usages(), contains(use0));
@@ -169,11 +178,11 @@
     @Test
     public void testReplaceAtUsagesWithPredicate2() {
         Graph graph = new Graph();
-        Def def0 = graph.add(new Def());
-        Def def1 = graph.add(new Def());
-        Use use0 = graph.add(new Use(def0, null, null));
-        Use use1 = graph.add(new Use(null, def0, null));
-        Use use2 = graph.add(new Use(null, null, def0));
+        Def def0 = graph.add(Def.create());
+        Def def1 = graph.add(Def.create());
+        Use use0 = graph.add(Use.create(def0, null, null));
+        Use use1 = graph.add(Use.create(null, def0, null));
+        Use use2 = graph.add(Use.create(null, null, def0));
 
         assertEquals(3, def0.usages().count());
         assertThat(def0.usages(), contains(use0));
@@ -200,11 +209,11 @@
     @Test
     public void testReplaceAtUsagesWithPredicate0() {
         Graph graph = new Graph();
-        Def def0 = graph.add(new Def());
-        Def def1 = graph.add(new Def());
-        Use use0 = graph.add(new Use(def0, null, null));
-        Use use1 = graph.add(new Use(null, def0, null));
-        Use use2 = graph.add(new Use(null, null, def0));
+        Def def0 = graph.add(Def.create());
+        Def def1 = graph.add(Def.create());
+        Use use0 = graph.add(Use.create(def0, null, null));
+        Use use1 = graph.add(Use.create(null, def0, null));
+        Use use2 = graph.add(Use.create(null, null, def0));
 
         assertEquals(3, def0.usages().count());
         assertThat(def0.usages(), contains(use0));
@@ -231,11 +240,11 @@
     @Test
     public void testReplaceAtUsagesWithPredicate02() {
         Graph graph = new Graph();
-        Def def0 = graph.add(new Def());
-        Def def1 = graph.add(new Def());
-        Use use0 = graph.add(new Use(def0, null, null));
-        Use use1 = graph.add(new Use(null, def0, null));
-        Use use2 = graph.add(new Use(null, null, def0));
+        Def def0 = graph.add(Def.create());
+        Def def1 = graph.add(Def.create());
+        Use use0 = graph.add(Use.create(def0, null, null));
+        Use use1 = graph.add(Use.create(null, def0, null));
+        Use use2 = graph.add(Use.create(null, null, def0));
 
         assertEquals(3, def0.usages().count());
         assertThat(def0.usages(), contains(use0));
@@ -262,12 +271,12 @@
     @Test
     public void testReplaceAtUsagesWithPredicate023() {
         Graph graph = new Graph();
-        Def def0 = graph.add(new Def());
-        Def def1 = graph.add(new Def());
-        Use use0 = graph.add(new Use(def0, null, null));
-        Use use1 = graph.add(new Use(null, def0, null));
-        Use use2 = graph.add(new Use(null, null, def0));
-        Use use3 = graph.add(new Use(null, null, def0));
+        Def def0 = graph.add(Def.create());
+        Def def1 = graph.add(Def.create());
+        Use use0 = graph.add(Use.create(def0, null, null));
+        Use use1 = graph.add(Use.create(null, def0, null));
+        Use use2 = graph.add(Use.create(null, null, def0));
+        Use use3 = graph.add(Use.create(null, null, def0));
 
         assertEquals(4, def0.usages().count());
         assertThat(def0.usages(), contains(use0));
@@ -296,12 +305,12 @@
     @Test
     public void testReplaceAtUsagesWithPredicate013() {
         Graph graph = new Graph();
-        Def def0 = graph.add(new Def());
-        Def def1 = graph.add(new Def());
-        Use use0 = graph.add(new Use(def0, null, null));
-        Use use1 = graph.add(new Use(null, def0, null));
-        Use use2 = graph.add(new Use(null, null, def0));
-        Use use3 = graph.add(new Use(null, null, def0));
+        Def def0 = graph.add(Def.create());
+        Def def1 = graph.add(Def.create());
+        Use use0 = graph.add(Use.create(def0, null, null));
+        Use use1 = graph.add(Use.create(null, def0, null));
+        Use use2 = graph.add(Use.create(null, null, def0));
+        Use use3 = graph.add(Use.create(null, null, def0));
 
         assertEquals(4, def0.usages().count());
         assertThat(def0.usages(), contains(use0));
@@ -330,12 +339,12 @@
     @Test
     public void testReplaceAtUsagesWithPredicate2_3() {
         Graph graph = new Graph();
-        Def def0 = graph.add(new Def());
-        Def def1 = graph.add(new Def());
-        Use use0 = graph.add(new Use(def0, null, null));
-        Use use1 = graph.add(new Use(null, def0, null));
-        Use use2 = graph.add(new Use(null, null, def0));
-        Use use3 = graph.add(new Use(null, null, def0));
+        Def def0 = graph.add(Def.create());
+        Def def1 = graph.add(Def.create());
+        Use use0 = graph.add(Use.create(def0, null, null));
+        Use use1 = graph.add(Use.create(null, def0, null));
+        Use use2 = graph.add(Use.create(null, null, def0));
+        Use use3 = graph.add(Use.create(null, null, def0));
 
         assertEquals(4, def0.usages().count());
         assertThat(def0.usages(), contains(use0));
@@ -364,11 +373,11 @@
     @Test
     public void testReplaceAtUsagesWithPredicate01() {
         Graph graph = new Graph();
-        Def def0 = graph.add(new Def());
-        Def def1 = graph.add(new Def());
-        Use use0 = graph.add(new Use(def0, null, null));
-        Use use1 = graph.add(new Use(null, def0, null));
-        Use use2 = graph.add(new Use(null, null, def0));
+        Def def0 = graph.add(Def.create());
+        Def def1 = graph.add(Def.create());
+        Use use0 = graph.add(Use.create(def0, null, null));
+        Use use1 = graph.add(Use.create(null, def0, null));
+        Use use2 = graph.add(Use.create(null, null, def0));
 
         assertEquals(3, def0.usages().count());
         assertThat(def0.usages(), contains(use0));
@@ -395,11 +404,11 @@
     @Test
     public void testReplaceAtUsagesWithPredicate12() {
         Graph graph = new Graph();
-        Def def0 = graph.add(new Def());
-        Def def1 = graph.add(new Def());
-        Use use0 = graph.add(new Use(def0, null, null));
-        Use use1 = graph.add(new Use(null, def0, null));
-        Use use2 = graph.add(new Use(null, null, def0));
+        Def def0 = graph.add(Def.create());
+        Def def1 = graph.add(Def.create());
+        Use use0 = graph.add(Use.create(def0, null, null));
+        Use use1 = graph.add(Use.create(null, def0, null));
+        Use use2 = graph.add(Use.create(null, null, def0));
 
         assertEquals(3, def0.usages().count());
         assertThat(def0.usages(), contains(use0));
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -29,14 +29,20 @@
 import org.junit.*;
 
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 
 public class TypedNodeIteratorTest {
 
-    private static class TestNode extends Node implements IterableNodeType, TestNodeInterface {
+    @NodeInfo
+    static class TestNode extends Node implements IterableNodeType, TestNodeInterface {
 
         private final String name;
 
-        public TestNode(String name) {
+        public static TestNode create(String name) {
+            return USE_GENERATED_NODES ? new TypedNodeIteratorTest_TestNodeGen(name) : new TestNode(name);
+        }
+
+        TestNode(String name) {
             this.name = name;
         }
 
@@ -48,14 +54,14 @@
     @Test
     public void singleNodeTest() {
         Graph graph = new Graph();
-        graph.add(new TestNode("a"));
+        graph.add(TestNode.create("a"));
         assertTrue(graph.hasNode(TestNode.class));
         assertEquals("a", toString(graph.getNodes(TestNode.class)));
     }
 
     @Test
     public void deletingNodeTest() {
-        TestNode testNode = new TestNode("a");
+        TestNode testNode = TestNode.create("a");
         Graph graph = new Graph();
         graph.add(testNode);
         testNode.safeDelete();
@@ -64,29 +70,29 @@
 
     @Test
     public void deleteAndAddTest() {
-        TestNode testNode = new TestNode("b");
+        TestNode testNode = TestNode.create("b");
         Graph graph = new Graph();
-        graph.add(new TestNode("a"));
+        graph.add(TestNode.create("a"));
         graph.add(testNode);
         testNode.safeDelete();
         assertEquals("a", toString(graph.getNodes(TestNode.class)));
-        graph.add(new TestNode("c"));
+        graph.add(TestNode.create("c"));
         assertEquals("ac", toString(graph.getNodes(TestNode.class)));
     }
 
     @Test
     public void iteratorBehaviorTest() {
         Graph graph = new Graph();
-        graph.add(new TestNode("a"));
+        graph.add(TestNode.create("a"));
         Iterator<TestNode> iterator = graph.getNodes(TestNode.class).iterator();
         assertTrue(iterator.hasNext());
         assertEquals("a", iterator.next().getName());
         assertFalse(iterator.hasNext());
-        graph.add(new TestNode("b"));
+        graph.add(TestNode.create("b"));
         assertTrue(iterator.hasNext());
         assertEquals("b", iterator.next().getName());
         assertFalse(iterator.hasNext());
-        TestNode c = new TestNode("c");
+        TestNode c = TestNode.create("c");
         graph.add(c);
         assertTrue(iterator.hasNext());
         c.safeDelete();
@@ -96,26 +102,26 @@
     @Test
     public void complicatedIterationTest() {
         Graph graph = new Graph();
-        graph.add(new TestNode("a"));
+        graph.add(TestNode.create("a"));
         for (TestNode tn : graph.getNodes(TestNode.class)) {
             String name = tn.getName();
             for (int i = 0; i < name.length(); ++i) {
                 char c = name.charAt(i);
                 if (c == 'a') {
                     tn.safeDelete();
-                    graph.add(new TestNode("b"));
-                    graph.add(new TestNode("c"));
+                    graph.add(TestNode.create("b"));
+                    graph.add(TestNode.create("c"));
                 } else if (c == 'b') {
                     tn.safeDelete();
                 } else if (c == 'c') {
-                    graph.add(new TestNode("d"));
-                    graph.add(new TestNode("e"));
-                    graph.add(new TestNode("d"));
-                    graph.add(new TestNode("e"));
-                    graph.add(new TestNode("e"));
-                    graph.add(new TestNode("d"));
-                    graph.add(new TestNode("e"));
-                    graph.add(new TestNode("d"));
+                    graph.add(TestNode.create("d"));
+                    graph.add(TestNode.create("e"));
+                    graph.add(TestNode.create("d"));
+                    graph.add(TestNode.create("e"));
+                    graph.add(TestNode.create("e"));
+                    graph.add(TestNode.create("d"));
+                    graph.add(TestNode.create("e"));
+                    graph.add(TestNode.create("d"));
                 } else if (c == 'd') {
                     for (TestNode tn2 : graph.getNodes(TestNode.class)) {
                         if (tn2.getName().equals("e")) {
@@ -135,12 +141,12 @@
     @Test
     public void addingNodeDuringIterationTest() {
         Graph graph = new Graph();
-        graph.add(new TestNode("a"));
+        graph.add(TestNode.create("a"));
         StringBuilder sb = new StringBuilder();
         int z = 0;
         for (TestNode tn : graph.getNodes(TestNode.class)) {
             if (z == 0) {
-                graph.add(new TestNode("b"));
+                graph.add(TestNode.create("b"));
             }
             sb.append(tn.getName());
             z++;
@@ -150,7 +156,7 @@
         z = 0;
         for (TestNode tn : graph.getNodes(TestNode.class)) {
             if (z == 0) {
-                graph.add(new TestNode("c"));
+                graph.add(TestNode.create("c"));
             }
             assertNotNull(tn);
             z++;
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest2.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest2.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,14 +27,20 @@
 import org.junit.*;
 
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 
 public class TypedNodeIteratorTest2 {
 
-    private static class NodeA extends Node implements TestNodeInterface {
+    @NodeInfo
+    static class NodeA extends Node implements TestNodeInterface {
 
         private final String name;
 
-        public NodeA(String name) {
+        public static NodeA create(String name) {
+            return USE_GENERATED_NODES ? new TypedNodeIteratorTest2_NodeAGen(name) : new NodeA(name);
+        }
+
+        NodeA(String name) {
             this.name = name;
         }
 
@@ -43,23 +49,36 @@
         }
     }
 
-    private static class NodeB extends NodeA implements IterableNodeType {
+    @NodeInfo
+    static class NodeB extends NodeA implements IterableNodeType {
 
-        public NodeB(String name) {
+        public static NodeB create(String name) {
+            return USE_GENERATED_NODES ? new TypedNodeIteratorTest2_NodeBGen(name) : new NodeB(name);
+        }
+
+        NodeB(String name) {
             super(name);
         }
     }
 
-    private static class NodeC extends NodeB {
+    @NodeInfo
+    static class NodeC extends NodeB {
+        public static NodeC create(String name) {
+            return USE_GENERATED_NODES ? new TypedNodeIteratorTest2_NodeCGen(name) : new NodeC(name);
+        }
 
-        public NodeC(String name) {
+        NodeC(String name) {
             super(name);
         }
     }
 
-    private static class NodeD extends NodeC {
+    @NodeInfo
+    static class NodeD extends NodeC {
+        public static NodeD create(String name) {
+            return USE_GENERATED_NODES ? new TypedNodeIteratorTest2_NodeDGen(name) : new NodeD(name);
+        }
 
-        public NodeD(String name) {
+        NodeD(String name) {
             super(name);
         }
     }
@@ -67,8 +86,8 @@
     @Test
     public void simpleSubclassTest() {
         Graph graph = new Graph();
-        graph.add(new NodeB("b"));
-        graph.add(new NodeD("d"));
+        graph.add(NodeB.create("b"));
+        graph.add(NodeD.create("d"));
 
         Assert.assertEquals("bd", TypedNodeIteratorTest.toString(graph.getNodes(NodeB.class)));
         Assert.assertEquals("d", TypedNodeIteratorTest.toString(graph.getNodes(NodeD.class)));
@@ -77,19 +96,19 @@
     @Test
     public void addingNodeDuringIterationTest() {
         Graph graph = new Graph();
-        graph.add(new NodeB("b1"));
-        NodeD d1 = graph.add(new NodeD("d1"));
+        graph.add(NodeB.create("b1"));
+        NodeD d1 = graph.add(NodeD.create("d1"));
         StringBuilder sb = new StringBuilder();
         for (NodeB tn : graph.getNodes(NodeB.class)) {
             if (tn == d1) {
-                graph.add(new NodeB("b2"));
+                graph.add(NodeB.create("b2"));
             }
             sb.append(tn.getName());
         }
         assertEquals("b1d1b2", sb.toString());
         for (NodeB tn : graph.getNodes(NodeB.class)) {
             if (tn == d1) {
-                graph.add(new NodeB("b3"));
+                graph.add(NodeB.create("b3"));
             }
             assertNotNull(tn);
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/FirstLevelPositionCollection.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.graph;
+
+import static com.oracle.graal.graph.Node.*;
+
+import java.util.*;
+
+import com.oracle.graal.graph.Node.Input;
+import com.oracle.graal.graph.Node.Successor;
+
+/**
+ * A collection of the positions of the {@link Node} and {@link NodeList} fields in a node.
+ */
+public final class FirstLevelPositionCollection extends AbstractCollection<Position> implements Collection<Position> {
+
+    public static final FirstLevelPositionCollection Empty = new FirstLevelPositionCollection(0, 0, false);
+
+    /**
+     * The total number of {@link Node} and {@link NodeList} fields.
+     */
+    protected final int allNodeRefFields;
+
+    /**
+     * The number of {@link Node} fields.
+     */
+    protected final int nodeFields;
+
+    /**
+     * Specifies if this iterator iterates over {@linkplain Input inputs} or {@linkplain Successor
+     * successors}.
+     */
+    private final boolean isInputs;
+
+    /**
+     * Creates a collection of the positions of the {@link Node} and {@link NodeList} fields in a
+     * node.
+     */
+    public FirstLevelPositionCollection(int nodeFields, int nodeListFields, boolean isInputs) {
+        this.allNodeRefFields = nodeListFields + nodeFields;
+        this.nodeFields = nodeFields;
+        this.isInputs = isInputs;
+    }
+
+    @Override
+    public int size() {
+        return allNodeRefFields;
+    }
+
+    @Override
+    public Iterator<Position> iterator() {
+        return new FirstLevelPositionIterator(nodeFields, allNodeRefFields - nodeFields, isInputs);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/FirstLevelPositionIterator.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.graph;
+
+import static com.oracle.graal.graph.Node.*;
+
+import java.util.*;
+
+import com.oracle.graal.graph.Node.Input;
+import com.oracle.graal.graph.Node.Successor;
+
+/**
+ * An iterator over the {@link Node} and {@link NodeList} fields in a node.
+ */
+public class FirstLevelPositionIterator implements Iterator<Position> {
+
+    public static final FirstLevelPositionIterator Empty = new FirstLevelPositionIterator(0, 0, false);
+
+    /**
+     * The total number of {@link Node} and {@link NodeList} fields.
+     */
+    protected final int allNodeRefFields;
+
+    /**
+     * The number of {@link Node} fields.
+     */
+    protected final int nodeFields;
+
+    /**
+     * Specifies if this iterator iterates over {@linkplain Input inputs} or {@linkplain Successor
+     * successors}.
+     */
+    private final boolean isInputs;
+
+    /**
+     * Current field iteration index.
+     */
+    protected int index;
+
+    /**
+     * Creates an iterator over the {@link Node} and {@link NodeList} fields in a node.
+     *
+     * @param nodeFields the number of {@link Node} fields in the class hierarchy of the node being
+     *            iterated
+     * @param nodeListFields the number of {@link NodeList} fields in the class hierarchy of the
+     *            node being iterated
+     */
+    protected FirstLevelPositionIterator(int nodeFields, int nodeListFields, boolean isInputs) {
+        this.allNodeRefFields = nodeListFields + nodeFields;
+        this.nodeFields = nodeFields;
+        this.isInputs = isInputs;
+        index = Node.NOT_ITERABLE;
+    }
+
+    @Override
+    public void remove() {
+        throw new UnsupportedOperationException();
+    }
+
+    public Position next() {
+        Position pos = new Position(isInputs, index, index >= nodeFields ? NODE_LIST : NOT_ITERABLE);
+        index++;
+        return pos;
+    }
+
+    public boolean hasNext() {
+        return index < allNodeRefFields;
+    }
+
+    public int size() {
+        return allNodeRefFields;
+    }
+}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,13 +22,14 @@
  */
 package com.oracle.graal.graph;
 
+import static com.oracle.graal.graph.Node.*;
+
 import java.util.*;
 
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.Node.ValueNumberable;
 import com.oracle.graal.graph.NodeClass.NodeClassIterator;
-import com.oracle.graal.graph.NodeClass.Position;
 import com.oracle.graal.graph.iterators.*;
 
 /**
@@ -85,7 +86,7 @@
 
         public CacheEntry(Node node) {
             assert node.getNodeClass().valueNumberable();
-            assert node.getNodeClass().isLeafNode();
+            assert node.isLeafNode();
             this.node = node;
         }
 
@@ -117,7 +118,7 @@
         this(null);
     }
 
-    static final boolean MODIFICATION_COUNTS_ENABLED = assertionsEnabled();
+    public static final boolean MODIFICATION_COUNTS_ENABLED = assertionsEnabled();
 
     /**
      * Determines if assertions are enabled for the {@link Graph} class.
@@ -440,7 +441,7 @@
             return (T) other;
         } else {
             Node result = addIfMissing ? addHelper(node) : node;
-            if (node.getNodeClass().isLeafNode()) {
+            if (node.isLeafNode()) {
                 putNodeIntoCache(result);
             }
             return (T) result;
@@ -450,7 +451,7 @@
     void putNodeIntoCache(Node node) {
         assert node.graph() == this || node.graph() == null;
         assert node.getNodeClass().valueNumberable();
-        assert node.getNodeClass().isLeafNode() : node.getClass();
+        assert node.isLeafNode() : node.getClass();
         cachedNodes.put(new CacheEntry(node), node);
     }
 
@@ -467,7 +468,7 @@
     public Node findDuplicate(Node node) {
         NodeClass nodeClass = node.getNodeClass();
         assert nodeClass.valueNumberable();
-        if (nodeClass.isLeafNode()) {
+        if (node.isLeafNode()) {
             Node cachedNode = findNodeInCache(node);
             if (cachedNode != null) {
                 return cachedNode;
@@ -646,8 +647,18 @@
         };
     }
 
-    private static final Node PLACE_HOLDER = new Node() {
-    };
+    // Fully qualified annotation name is required to satisfy javac
+    @com.oracle.graal.nodeinfo.NodeInfo
+    static class PlaceHolderNode extends Node {
+        public static PlaceHolderNode create() {
+            return new PlaceHolderNode();
+        }
+
+        PlaceHolderNode() {
+        }
+    }
+
+    private static final Node PLACE_HOLDER = USE_GENERATED_NODES ? new Graph_PlaceHolderNodeGen() : new PlaceHolderNode();
 
     /**
      * When the percent of live nodes in {@link #nodes} fall below this number, a call to
@@ -698,15 +709,17 @@
         return true;
     }
 
-    private class TypedNodeIterator<T extends IterableNodeType> implements Iterator<T> {
+    private static class TypedNodeIterator<T extends IterableNodeType> implements Iterator<T> {
 
+        private final Graph graph;
         private final int[] ids;
         private final Node[] current;
 
         private int currentIdIndex;
         private boolean needsForward;
 
-        public TypedNodeIterator(NodeClass clazz) {
+        public TypedNodeIterator(NodeClass clazz, Graph graph) {
+            this.graph = graph;
             ids = clazz.iterableIds();
             currentIdIndex = 0;
             current = new Node[ids.length];
@@ -732,7 +745,7 @@
             return current();
         }
 
-        private Node skipDeleted(Node node) {
+        private static Node skipDeleted(Node node) {
             Node n = node;
             while (n != null && n.isDeleted()) {
                 n = n.typeCacheNext;
@@ -746,7 +759,7 @@
             while (true) {
                 Node next;
                 if (current() == PLACE_HOLDER) {
-                    next = getStartNode(ids[currentIdIndex]);
+                    next = graph.getStartNode(ids[currentIdIndex]);
                 } else {
                     next = current().typeCacheNext;
                 }
@@ -810,7 +823,7 @@
 
             @Override
             public Iterator<T> iterator() {
-                return new TypedNodeIterator<>(nodeClass);
+                return new TypedNodeIterator<>(nodeClass, Graph.this);
             }
         };
     }
@@ -861,7 +874,7 @@
         nodesSize++;
 
         int nodeClassId = node.getNodeClass().iterableId();
-        if (nodeClassId != NodeClass.NOT_ITERABLE) {
+        if (nodeClassId != Node.NOT_ITERABLE) {
             while (nodeCacheFirst.size() <= nodeClassId) {
                 nodeCacheFirst.add(null);
                 nodeCacheLast.add(null);
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/InputType.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2014, 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;
-
-public enum InputType {
-    /**
-     * Inputs that consume an actual value generated by the referenced node.
-     */
-    Value,
-    /**
-     * Inputs that consume the memory state of the referenced node.
-     */
-    Memory,
-    /**
-     * Inputs that reference a condition.
-     */
-    Condition,
-    /**
-     * Inputs that reference a frame state.
-     */
-    State,
-    /**
-     * Inputs that reference a guard (guards, begin nodes).
-     */
-    Guard,
-    /**
-     * Inputs that reference an anchor (begin nodes, value anchors).
-     */
-    Anchor,
-    /**
-     * Inputs that represent an association between nodes, e.g., a phi and the merge or a loop begin
-     * and loop exits and ends.
-     */
-    Association,
-    /**
-     * Inputs that connect tightly coupled nodes, e.g., an InvokeNode and its CallTargetNode.
-     */
-    Extension,
-    /**
-     * Inputs of this type are temporarily exempt from type checking. This should only be used in
-     * exceptional cases and should never survive to later stages of compilation.
-     */
-    Unchecked
-}
\ No newline at end of file
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,10 +27,11 @@
 import java.lang.annotation.*;
 import java.util.*;
 
+import com.oracle.graal.graph.Graph.NodeEventListener;
 import com.oracle.graal.graph.NodeClass.NodeClassIterator;
-import com.oracle.graal.graph.NodeClass.Position;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 
 /**
  * This class is the base class for all nodes, it represent a node which can be inserted in a
@@ -52,20 +53,26 @@
  * exception or return true. They can thus be used within an assert statement, so that the check is
  * only performed if assertions are enabled.
  */
+@NodeInfo
 public abstract class Node implements Cloneable, Formattable {
 
+    public final static boolean USE_GENERATED_NODES = Boolean.getBoolean("graal.useGeneratedNodes");
+
     static final int DELETED_ID_START = -1000000000;
     static final int INITIAL_ID = -1;
     static final int ALIVE_ID_START = 0;
 
+    // The use of fully qualified class names here and in the rest
+    // of this file works around a problem javac has resolving symbols
+
     /**
      * Denotes a non-optional (non-null) node input. This should be applied to exactly the fields of
      * a node that are of type {@link Node} or {@link NodeInputList}. Nodes that update fields of
      * type {@link Node} outside of their constructor should call
      * {@link Node#updateUsages(Node, Node)} just prior to doing the update of the input.
      */
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.FIELD)
+    @java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
+    @java.lang.annotation.Target(ElementType.FIELD)
     public static @interface Input {
         InputType value() default InputType.Value;
     }
@@ -76,14 +83,14 @@
      * {@link Node} outside of their constructor should call {@link Node#updateUsages(Node, Node)}
      * just prior to doing the update of the input.
      */
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.FIELD)
+    @java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
+    @java.lang.annotation.Target(ElementType.FIELD)
     public static @interface OptionalInput {
         InputType value() default InputType.Value;
     }
 
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.FIELD)
+    @java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
+    @java.lang.annotation.Target(ElementType.FIELD)
     public static @interface Successor {
     }
 
@@ -91,8 +98,8 @@
      * Denotes that a parameter of an {@linkplain NodeIntrinsic intrinsic} method must be a compile
      * time constant at all call sites to the intrinsic method.
      */
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.PARAMETER)
+    @java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
+    @java.lang.annotation.Target(ElementType.PARAMETER)
     public static @interface ConstantNodeParameter {
     }
 
@@ -102,8 +109,8 @@
      * an argument for the annotated parameter. Injected parameters must precede all non-injected
      * parameters in a constructor.
      */
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.PARAMETER)
+    @java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
+    @java.lang.annotation.Target(ElementType.PARAMETER)
     public static @interface InjectedNodeParameter {
     }
 
@@ -112,10 +119,10 @@
      * annotated method can be replaced with an instance of the node class denoted by
      * {@link #value()}. For this reason, the signature of the annotated method must match the
      * signature (excluding a prefix of {@linkplain InjectedNodeParameter injected} parameters) of a
-     * constructor in the node class.
+     * factory method named {@code "create"} in the node class.
      */
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.METHOD)
+    @java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
+    @java.lang.annotation.Target(ElementType.METHOD)
     public static @interface NodeIntrinsic {
 
         /**
@@ -145,20 +152,25 @@
     // therefore points to the next Node of the same type.
     Node typeCacheNext;
 
-    private static final int INLINE_USAGE_COUNT = 2;
+    static final int INLINE_USAGE_COUNT = 2;
     private static final Node[] NO_NODES = {};
 
     /**
      * Head of usage list. The elements of the usage list in order are {@link #usage0},
      * {@link #usage1} and {@link #extraUsages}. The first null entry terminates the list.
      */
-    private Node usage0;
-    private Node usage1;
-    private Node[] extraUsages;
+    Node usage0;
+    Node usage1;
+    Node[] extraUsages;
 
     private Node predecessor;
 
+    public static final int NODE_LIST = -2;
+    public static final int NOT_ITERABLE = -1;
+
     public Node() {
+        assert USE_GENERATED_NODES == (getClass().getAnnotation(GeneratedNode.class) != null) : getClass() + " is not a generated Node class - forgot @" + NodeInfo.class.getSimpleName() +
+                        " on class declaration?";
         init();
     }
 
@@ -198,95 +210,6 @@
         return getNodeClass().getSuccessorIterable(this);
     }
 
-    class NodeUsageIterator implements Iterator<Node> {
-
-        int index = -1;
-        Node current;
-
-        private void advance() {
-            current = null;
-            index++;
-            if (index == 0) {
-                current = usage0;
-            } else if (index == 1) {
-                current = usage1;
-            } else {
-                if (index - INLINE_USAGE_COUNT < extraUsages.length) {
-                    current = extraUsages[index - INLINE_USAGE_COUNT];
-                }
-            }
-        }
-
-        public NodeUsageIterator() {
-            advance();
-        }
-
-        public boolean hasNext() {
-            return current != null;
-        }
-
-        public Node next() {
-            Node result = current;
-            if (result == null) {
-                throw new NoSuchElementException();
-            }
-            advance();
-            return result;
-        }
-
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    class NodeUsageWithModCountIterator extends NodeUsageIterator {
-
-        private final int expectedModCount = usageModCount();
-
-        @Override
-        public boolean hasNext() {
-            if (expectedModCount != usageModCount()) {
-                throw new ConcurrentModificationException();
-            }
-            return super.hasNext();
-        }
-
-        @Override
-        public Node next() {
-            if (expectedModCount != usageModCount()) {
-                throw new ConcurrentModificationException();
-            }
-            return super.next();
-        }
-    }
-
-    class NodeUsageIterable implements NodeIterable<Node> {
-
-        public NodeUsageIterator iterator() {
-            if (MODIFICATION_COUNTS_ENABLED) {
-                return new NodeUsageWithModCountIterator();
-            } else {
-                return new NodeUsageIterator();
-            }
-        }
-
-        @Override
-        public boolean isEmpty() {
-            return usage0 == null;
-        }
-
-        @Override
-        public boolean isNotEmpty() {
-            return usage0 != null;
-        }
-
-        @Override
-        public int count() {
-            return usageCount();
-        }
-    }
-
     int getUsageCountUpperBound() {
         assert recordsUsages();
         if (usage0 == null) {
@@ -303,7 +226,7 @@
      */
     public final NodeIterable<Node> usages() {
         assert recordsUsages() : this;
-        return new NodeUsageIterable();
+        return new NodeUsageIterable(this);
     }
 
     /**
@@ -380,7 +303,7 @@
         }
     }
 
-    private int usageCount() {
+    int usageCount() {
         if (usage0 == null) {
             return 0;
         }
@@ -524,7 +447,7 @@
         return predecessor;
     }
 
-    final int modCount() {
+    public final int modCount() {
         if (MODIFICATION_COUNTS_ENABLED && graph != null) {
             return graph.modCount(this);
         }
@@ -840,7 +763,7 @@
 
     final Node clone(Graph into, boolean clearInputsAndSuccessors) {
         NodeClass nodeClass = getNodeClass();
-        if (into != null && nodeClass.valueNumberable() && nodeClass.isLeafNode()) {
+        if (into != null && nodeClass.valueNumberable() && isLeafNode()) {
             Node otherNode = into.findNodeInCache(this);
             if (otherNode != null) {
                 return otherNode;
@@ -868,13 +791,20 @@
         newNode.extraUsages = NO_NODES;
         newNode.predecessor = null;
 
-        if (into != null && nodeClass.valueNumberable() && nodeClass.isLeafNode()) {
+        if (into != null && nodeClass.valueNumberable() && isLeafNode()) {
             into.putNodeIntoCache(newNode);
         }
         newNode.afterClone(this);
         return newNode;
     }
 
+    /**
+     * @returns true if this node has no inputs and no successors
+     */
+    public boolean isLeafNode() {
+        return USE_GENERATED_NODES || getNodeClass().isLeafNode();
+    }
+
     protected void afterClone(@SuppressWarnings("unused") Node other) {
     }
 
@@ -996,34 +926,6 @@
         return toString(Verbosity.Short);
     }
 
-    public enum Verbosity {
-        /**
-         * Only the id of the node.
-         */
-        Id,
-        /**
-         * Only the name of the node, which may contain some more information for certain node types
-         * (constants, ...).
-         */
-        Name,
-        /**
-         * {@link #Id} + {@link #Name}.
-         */
-        Short,
-        /**
-         * Defaults to {@link #Short} and may be enhanced by subclasses.
-         */
-        Long,
-        /**
-         * For use by a custom formatting facility in an IDE.
-         */
-        Debugger,
-        /**
-         * All the other information plus all debug properties of the node.
-         */
-        All
-    }
-
     /**
      * Creates a String representation for this node with a given {@link Verbosity}.
      */
@@ -1120,4 +1022,39 @@
             }
         }
     }
+
+    // NEW API IMPLEMENTED BY GENERATED METHODS - NOT YET USED
+
+    public NodeRefIterable inputsV2() {
+        return NodeRefIterable.Empty;
+    }
+
+    public Collection<Position> getFirstLevelInputs() {
+        return Collections.emptyList();
+    }
+
+    public Collection<Position> getFirstLevelSuccessors() {
+        return Collections.emptyList();
+    }
+
+    /**
+     * @param pos
+     */
+    public InputType getInputTypeAt(Position pos) {
+        throw new NoSuchElementException();
+    }
+
+    /**
+     * @param pos
+     */
+    public String getNameOf(Position pos) {
+        throw new NoSuchElementException();
+    }
+
+    /**
+     * @param pos
+     */
+    public boolean isOptionalInputAt(Position pos) {
+        throw new NoSuchElementException();
+    }
 }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,6 +23,7 @@
 package com.oracle.graal.graph;
 
 import static com.oracle.graal.graph.Graph.*;
+import static com.oracle.graal.graph.Node.*;
 import static com.oracle.graal.graph.util.CollectionsAccess.*;
 
 import java.lang.reflect.*;
@@ -33,8 +34,8 @@
 import com.oracle.graal.graph.Graph.DuplicationReplacement;
 import com.oracle.graal.graph.Node.Input;
 import com.oracle.graal.graph.Node.Successor;
-import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 
 /**
  * Metadata for every {@link Node} type. The metadata includes:
@@ -53,7 +54,9 @@
      */
     @SuppressWarnings("unchecked")
     public static NodeClass get(Class<?> c) {
-        Class<? extends Node> key = (Class<? extends Node>) c;
+        GeneratedNode gen = c.getAnnotation(GeneratedNode.class);
+        Class<? extends Node> key = gen == null ? (Class<? extends Node>) c : (Class<? extends Node>) gen.value();
+
         NodeClass value = (NodeClass) allClasses.get(key);
         // The fact that {@link ConcurrentHashMap#put} and {@link ConcurrentHashMap#get}
         // are used makes the double-checked locking idiom work.
@@ -72,9 +75,6 @@
         return value;
     }
 
-    public static final int NOT_ITERABLE = -1;
-    public static final int NODE_LIST = -2;
-
     private static final Class<?> NODE_CLASS = Node.class;
     private static final Class<?> INPUT_LIST_CLASS = NodeInputList.class;
     private static final Class<?> SUCCESSOR_LIST_CLASS = NodeSuccessorList.class;
@@ -89,7 +89,6 @@
     private final long[] successorOffsets;
     private final Class<?>[] dataTypes;
     private final boolean canGVN;
-    private final boolean isLeafNode;
     private final int startGVNNumber;
     private final String shortName;
     private final String nameTemplate;
@@ -109,6 +108,7 @@
      * Determines if this node type implements {@link Simplifiable}.
      */
     private final boolean isSimplifiable;
+    private final boolean isLeafNode;
 
     public NodeClass(Class<?> clazz) {
         this(clazz, new DefaultCalcOffset(), null, 0);
@@ -165,6 +165,8 @@
             if (!info.nameTemplate().isEmpty()) {
                 newNameTemplate = info.nameTemplate();
             }
+        } else {
+            System.out.println("No NodeInfo for " + clazz);
         }
         EnumSet<InputType> newAllowedUsageTypes = EnumSet.noneOf(InputType.class);
         Class<?> current = clazz;
@@ -205,10 +207,9 @@
             }
             this.iterableIds = ids;
         } else {
-            this.iterableId = NOT_ITERABLE;
+            this.iterableId = Node.NOT_ITERABLE;
             this.iterableIds = null;
         }
-
         isLeafNode = (this.inputOffsets.length == 0 && this.successorOffsets.length == 0);
         nodeIterableCount = Debug.metric("NodeIterable_%s", shortName);
     }
@@ -233,6 +234,16 @@
         fieldTypes.putAll(scanner.fieldTypes);
     }
 
+    private boolean isNodeClassFor(Node n) {
+        if (Node.USE_GENERATED_NODES) {
+            GeneratedNode gen = n.getClass().getAnnotation(GeneratedNode.class);
+            assert gen != null;
+            return gen.value() == getClazz();
+        } else {
+            return n.getNodeClass().getClazz() == n.getClass();
+        }
+    }
+
     public String shortName() {
         return shortName;
     }
@@ -250,10 +261,6 @@
         return canGVN;
     }
 
-    public boolean isLeafNode() {
-        return isLeafNode;
-    }
-
     /**
      * Determines if this node type implements {@link Canonicalizable}.
      */
@@ -296,13 +303,14 @@
                 assert !field.isAnnotationPresent(Node.Successor.class) : "field cannot be both input and successor";
                 assert field.isAnnotationPresent(Node.Input.class) ^ field.isAnnotationPresent(Node.OptionalInput.class) : "inputs can either be optional or non-optional";
                 if (INPUT_LIST_CLASS.isAssignableFrom(type)) {
-                    GraalInternalError.guarantee(Modifier.isFinal(field.getModifiers()), "NodeInputList input field %s should be final", field);
+                    // NodeInputList fields should not be final since they are
+                    // written (via Unsafe) in clearInputs()
+                    GraalInternalError.guarantee(!Modifier.isFinal(field.getModifiers()), "NodeInputList input field %s should not be final", field);
                     GraalInternalError.guarantee(!Modifier.isPublic(field.getModifiers()), "NodeInputList input field %s should not be public", field);
                     inputListOffsets.add(offset);
                 } else {
                     GraalInternalError.guarantee(NODE_CLASS.isAssignableFrom(type) || type.isInterface(), "invalid input type: %s", type);
                     GraalInternalError.guarantee(!Modifier.isFinal(field.getModifiers()), "Node input field %s should not be final", field);
-                    GraalInternalError.guarantee(Modifier.isPrivate(field.getModifiers()), "Node input field %s should be private", field);
                     inputOffsets.add(offset);
                 }
                 if (field.isAnnotationPresent(Node.Input.class)) {
@@ -316,13 +324,14 @@
                 }
             } else if (field.isAnnotationPresent(Node.Successor.class)) {
                 if (SUCCESSOR_LIST_CLASS.isAssignableFrom(type)) {
-                    GraalInternalError.guarantee(Modifier.isFinal(field.getModifiers()), "NodeSuccessorList successor field % should be final", field);
+                    // NodeSuccessorList fields should not be final since they are
+                    // written (via Unsafe) in clearSuccessors()
+                    GraalInternalError.guarantee(!Modifier.isFinal(field.getModifiers()), "NodeSuccessorList successor field % should not be final", field);
                     GraalInternalError.guarantee(!Modifier.isPublic(field.getModifiers()), "NodeSuccessorList successor field %s should not be public", field);
                     successorListOffsets.add(offset);
                 } else {
                     GraalInternalError.guarantee(NODE_CLASS.isAssignableFrom(type), "invalid successor type: %s", type);
                     GraalInternalError.guarantee(!Modifier.isFinal(field.getModifiers()), "Node successor field %s should not be final", field);
-                    GraalInternalError.guarantee(Modifier.isPrivate(field.getModifiers()), "Node successor field %s should be private", field);
                     successorOffsets.add(offset);
                 }
                 names.put(offset, field.getName());
@@ -354,104 +363,6 @@
         return str.toString();
     }
 
-    /**
-     * Describes an edge slot for a {@link NodeClass}.
-     *
-     * @see NodeClass#get(Node, Position)
-     * @see NodeClass#getName(Position)
-     */
-    public static final class Position {
-
-        private final boolean input;
-        private final int index;
-        private final int subIndex;
-
-        public Position(boolean input, int index, int subIndex) {
-            this.input = input;
-            this.index = index;
-            this.subIndex = subIndex;
-        }
-
-        @Override
-        public String toString() {
-            return (input ? "input " : "successor ") + index + "/" + subIndex;
-        }
-
-        public Node get(Node node) {
-            return node.getNodeClass().get(node, this);
-        }
-
-        public InputType getInputType(Node node) {
-            return node.getNodeClass().getInputType(this);
-        }
-
-        public String getInputName(Node node) {
-            return node.getNodeClass().getName(this);
-        }
-
-        public boolean isInputOptional(Node node) {
-            return node.getNodeClass().isInputOptional(this);
-        }
-
-        public void set(Node node, Node value) {
-            node.getNodeClass().set(node, this, value);
-        }
-
-        public void initialize(Node node, Node value) {
-            node.getNodeClass().initializePosition(node, this, value);
-        }
-
-        public boolean isValidFor(Node node, Node from) {
-            return node.getNodeClass().isValid(this, from.getNodeClass());
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + index;
-            result = prime * result + (input ? 1231 : 1237);
-            result = prime * result + subIndex;
-            return result;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj == null) {
-                return false;
-            }
-            if (getClass() != obj.getClass()) {
-                return false;
-            }
-            Position other = (Position) obj;
-            if (index != other.index) {
-                return false;
-            }
-            if (input != other.input) {
-                return false;
-            }
-            if (subIndex != other.subIndex) {
-                return false;
-            }
-            return true;
-        }
-
-        public int getSubIndex() {
-            return subIndex;
-        }
-
-        public int getIndex() {
-            return index;
-        }
-
-        public boolean isInput() {
-            return input;
-        }
-    }
-
     private static Node getNode(Node node, long offset) {
         return (Node) unsafe.getObject(node, offset);
     }
@@ -966,7 +877,7 @@
 
     public NodeList<?> getNodeList(Node node, Position pos) {
         long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()];
-        assert pos.getSubIndex() == NODE_LIST;
+        assert pos.getSubIndex() == Node.NODE_LIST;
         return getNodeList(node, offset);
     }
 
@@ -1303,7 +1214,7 @@
      * @param newNode the node to which the inputs should be copied.
      */
     public void copyInputs(Node node, Node newNode) {
-        assert node.getClass() == getClazz() && newNode.getClass() == getClazz();
+        assert isNodeClassFor(node) && isNodeClassFor(newNode);
 
         int index = 0;
         while (index < directInputCount) {
@@ -1325,7 +1236,7 @@
      * @param newNode the node to which the successors should be copied.
      */
     public void copySuccessors(Node node, Node newNode) {
-        assert node.getClass() == getClazz() && newNode.getClass() == getClazz();
+        assert isNodeClassFor(node) && isNodeClassFor(newNode);
 
         int index = 0;
         while (index < directSuccessorCount) {
@@ -1344,7 +1255,7 @@
     }
 
     public boolean inputsEqual(Node node, Node other) {
-        assert node.getClass() == getClazz() && other.getClass() == getClazz();
+        assert isNodeClassFor(node) && isNodeClassFor(other);
         int index = 0;
         while (index < directInputCount) {
             if (getNode(other, inputOffsets[index]) != getNode(node, inputOffsets[index])) {
@@ -1363,7 +1274,7 @@
     }
 
     public boolean successorsEqual(Node node, Node other) {
-        assert node.getClass() == getClazz() && other.getClass() == getClazz();
+        assert isNodeClassFor(node) && isNodeClassFor(other);
         int index = 0;
         while (index < directSuccessorCount) {
             if (getNode(other, successorOffsets[index]) != getNode(node, successorOffsets[index])) {
@@ -1382,7 +1293,7 @@
     }
 
     public boolean inputContains(Node node, Node other) {
-        assert node.getClass() == getClazz();
+        assert isNodeClassFor(node);
 
         int index = 0;
         while (index < directInputCount) {
@@ -1402,7 +1313,7 @@
     }
 
     public boolean successorContains(Node node, Node other) {
-        assert node.getClass() == getClazz();
+        assert isNodeClassFor(node);
 
         int index = 0;
         while (index < directSuccessorCount) {
@@ -1425,7 +1336,7 @@
         return new AbstractCollection<Position>() {
             @Override
             public Iterator<Position> iterator() {
-                return new Iterator<NodeClass.Position>() {
+                return new Iterator<Position>() {
                     int i = 0;
 
                     @Override
@@ -1434,7 +1345,7 @@
                     }
 
                     public Position next() {
-                        Position pos = new Position(true, i, i >= directInputCount ? NODE_LIST : NOT_ITERABLE);
+                        Position pos = new Position(true, i, i >= directInputCount ? Node.NODE_LIST : Node.NOT_ITERABLE);
                         i++;
                         return pos;
                     }
@@ -1456,7 +1367,7 @@
         return new AbstractCollection<Position>() {
             @Override
             public Iterator<Position> iterator() {
-                return new Iterator<NodeClass.Position>() {
+                return new Iterator<Position>() {
                     int i = 0;
 
                     @Override
@@ -1465,7 +1376,7 @@
                     }
 
                     public Position next() {
-                        Position pos = new Position(false, i, i >= directSuccessorCount ? NODE_LIST : NOT_ITERABLE);
+                        Position pos = new Position(false, i, i >= directSuccessorCount ? Node.NODE_LIST : Node.NOT_ITERABLE);
                         i++;
                         return pos;
                     }
@@ -1663,4 +1574,8 @@
     private static boolean isAssignable(Class<?> fieldType, Node replacement) {
         return replacement == null || !NODE_CLASS.isAssignableFrom(fieldType) || fieldType.isAssignableFrom(replacement.getClass());
     }
+
+    public boolean isLeafNode() {
+        return isLeafNode;
+    }
 }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClassIterable.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClassIterable.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,7 +23,6 @@
 package com.oracle.graal.graph;
 
 import com.oracle.graal.graph.NodeClass.NodeClassIterator;
-import com.oracle.graal.graph.NodeClass.Position;
 import com.oracle.graal.graph.iterators.*;
 
 /**
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInfo.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.graph;
-
-import java.lang.annotation.*;
-
-import com.oracle.graal.graph.Node.Verbosity;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-public @interface NodeInfo {
-
-    String shortName() default "";
-
-    /**
-     * The template used to build the {@link Verbosity#Name} version. Variable part are specified
-     * using &#123;i#inputName&#125; or &#123;p#propertyName&#125;.
-     */
-    String nameTemplate() default "";
-
-    InputType[] allowedUsageTypes() default {};
-}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputList.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputList.java	Mon Aug 25 21:15:59 2014 -0700
@@ -61,7 +61,7 @@
     }
 
     @Override
-    public boolean add(T node) {
+    public boolean add(Node node) {
         assert node == null || !node.isDeleted();
         self.incModCount();
         return super.add(node);
@@ -86,7 +86,7 @@
     }
 
     @Override
-    void copy(NodeList<T> other) {
+    void copy(NodeList<? extends Node> other) {
         self.incModCount();
         super.copy(other);
     }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java	Mon Aug 25 21:15:59 2014 -0700
@@ -121,14 +121,15 @@
         modCount++;
     }
 
+    @SuppressWarnings("unchecked")
     @Override
-    public boolean add(T node) {
+    public boolean add(Node node) {
         incModCount();
         if (size == nodes.length) {
             nodes = Arrays.copyOf(nodes, nodes.length * 2 + 1);
         }
         nodes[size++] = node;
-        update(null, node);
+        update(null, (T) node);
         return true;
     }
 
@@ -145,22 +146,22 @@
 
     @Override
     @SuppressWarnings("unchecked")
-    public T set(int index, T node) {
+    public T set(int index, Node node) {
         incModCount();
         T oldValue = (T) nodes[index];
         assert index < size();
-        update((T) nodes[index], node);
+        update((T) nodes[index], (T) node);
         nodes[index] = node;
         return oldValue;
     }
 
-    void initialize(int index, T node) {
+    public void initialize(int index, Node node) {
         incModCount();
         assert index < size();
         nodes[index] = node;
     }
 
-    void copy(NodeList<T> other) {
+    void copy(NodeList<? extends Node> other) {
         incModCount();
         nodes = Arrays.copyOf(other.nodes, other.size);
         size = other.size;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeRefIterable.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.graph;
+
+import com.oracle.graal.graph.iterators.*;
+
+/**
+ * The iterator returned by this iterable can be used to access {@link Position Positions} during
+ * iteration using {@link NodeRefIterator#nextPosition()}.
+ */
+public interface NodeRefIterable extends NodeIterable<Node> {
+    /**
+     * Returns an iterator that produces all non-null values.
+     */
+    @Override
+    NodeRefIterator iterator();
+
+    /**
+     * Returns an iterator that produces all values, including null values.
+     */
+    NodeRefIterator withNullIterator();
+
+    NodeRefIterable Empty = new NodeRefIterable() {
+
+        public NodeRefIterator withNullIterator() {
+            return NodeRefIterator.Empty;
+        }
+
+        public NodeRefIterator iterator() {
+            return NodeRefIterator.Empty;
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeRefIterator.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.graph;
+
+import java.util.*;
+
+import com.oracle.graal.graph.Node.Input;
+import com.oracle.graal.graph.Node.Successor;
+
+/**
+ * An iterator over the references to a {@link Node}'s {@linkplain Input inputs} and
+ * {@linkplain Successor successors}.
+ *
+ * An iterator of this type will not return null values, unless the field values are modified
+ * concurrently. Concurrent modifications are detected by an assertion on a best-effort basis.
+ */
+public class NodeRefIterator implements Iterator<Node> {
+
+    public static final NodeRefIterator Empty = new NodeRefIterator(0, 0, false);
+
+    /**
+     * The total number of {@link Node} and {@link NodeList} fields.
+     */
+    protected final int allNodeRefFields;
+
+    /**
+     * The number of {@link Node} fields.
+     */
+    protected final int nodeFields;
+
+    /**
+     * Specifies if this iterator iterates over {@linkplain Input inputs} or {@linkplain Successor
+     * successors}.
+     */
+    private final boolean isInputs;
+
+    /**
+     * Current field iteration index.
+     */
+    protected int index;
+
+    /**
+     * Current iteration index within a {@link NodeList} if {@link #index} denotes a
+     * {@link NodeList} field.
+     */
+    protected int subIndex;
+
+    /**
+     * Creates an iterator over a node's references (i.e., {@linkplain Input inputs} or
+     * {@linkplain Successor successors}) to other nodes. The {@link Node} fields are iterated
+     * before the {@link NodeList} fields. All elements of these NodeLists will be visited by the
+     * iterator as well.
+     *
+     * @param nodeFields the number of {@link Node} fields in the class hierarchy of the node being
+     *            iterated
+     * @param nodeListFields the number of {@link NodeList} fields in the class hierarchy of the
+     *            node being iterated
+     */
+    protected NodeRefIterator(int nodeFields, int nodeListFields, boolean isInputs) {
+        this.allNodeRefFields = nodeListFields + nodeFields;
+        this.nodeFields = nodeFields;
+        this.isInputs = isInputs;
+        index = Node.NOT_ITERABLE;
+        subIndex = 0;
+    }
+
+    /**
+     * Gets the value of a {@link Node} field in the node.
+     *
+     * @param at the index of the Node field whose value is being requested. This is guaranteed to
+     *            be between 0 and the {@code nodeFields} value this iterator was constructed with
+     */
+    protected Node getNode(int at) {
+        throw new NoSuchElementException();
+    }
+
+    /**
+     * Gets the value of a {@link NodeList} field in the node.
+     *
+     * @param at the index of the {@link NodeList} field whose value is being requested. This is
+     *            guaranteed to be between 0 and the {@code nodeListFields} value this iterator was
+     *            constructed with
+     */
+    protected NodeList<? extends Node> getNodeList(int at) {
+        throw new NoSuchElementException();
+    }
+
+    protected void forward() {
+        if (index < nodeFields) {
+            index++;
+            while (index < nodeFields) {
+                Node element = getNode(index);
+                if (element != null) {
+                    return;
+                }
+                index++;
+            }
+        } else {
+            subIndex++;
+        }
+        while (index < allNodeRefFields) {
+            NodeList<? extends Node> list = getNodeList(index - nodeFields);
+            while (subIndex < list.size()) {
+                if (list.get(subIndex) != null) {
+                    return;
+                }
+                subIndex++;
+            }
+            subIndex = 0;
+            index++;
+        }
+        return;
+    }
+
+    private Node nextElement() {
+        if (index < nodeFields) {
+            return getNode(index);
+        } else if (index < allNodeRefFields) {
+            NodeList<? extends Node> list = getNodeList(index - nodeFields);
+            return list.get(subIndex);
+        }
+        throw new NoSuchElementException();
+    }
+
+    @Override
+    public boolean hasNext() {
+        return index >= 0 && index < allNodeRefFields;
+    }
+
+    @Override
+    public Node next() {
+        try {
+            return nextElement();
+        } finally {
+            forward();
+        }
+    }
+
+    public Position nextPosition() {
+        try {
+            if (index < nodeFields) {
+                return new Position(isInputs, index, Node.NOT_ITERABLE);
+            } else {
+                return new Position(isInputs, index, subIndex);
+            }
+        } finally {
+            forward();
+        }
+    }
+
+    @Override
+    public void remove() {
+        throw new UnsupportedOperationException();
+    }
+}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeSuccessorList.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeSuccessorList.java	Mon Aug 25 21:15:59 2014 -0700
@@ -47,7 +47,7 @@
     }
 
     @Override
-    public boolean add(T node) {
+    public boolean add(Node node) {
         self.incModCount();
         return super.add(node);
     }
@@ -71,7 +71,7 @@
     }
 
     @Override
-    void copy(NodeList<T> other) {
+    void copy(NodeList<? extends Node> other) {
         self.incModCount();
         super.copy(other);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsageIterable.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.graph;
+
+import static com.oracle.graal.graph.Graph.*;
+
+import com.oracle.graal.graph.iterators.*;
+
+class NodeUsageIterable implements NodeIterable<Node> {
+
+    final Node node;
+
+    NodeUsageIterable(Node node) {
+        this.node = node;
+    }
+
+    public NodeUsageIterator iterator() {
+        if (MODIFICATION_COUNTS_ENABLED) {
+            return new NodeUsageWithModCountIterator(node);
+        } else {
+            return new NodeUsageIterator(node);
+        }
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return node.usage0 == null;
+    }
+
+    @Override
+    public boolean isNotEmpty() {
+        return node.usage0 != null;
+    }
+
+    @Override
+    public int count() {
+        return node.usageCount();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsageIterator.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.graph;
+
+import java.util.*;
+
+class NodeUsageIterator implements Iterator<Node> {
+
+    final Node node;
+    int index = -1;
+    Node current;
+
+    void advance() {
+        current = null;
+        index++;
+        if (index == 0) {
+            current = node.usage0;
+        } else if (index == 1) {
+            current = node.usage1;
+        } else {
+            if (index - Node.INLINE_USAGE_COUNT < node.extraUsages.length) {
+                current = node.extraUsages[index - Node.INLINE_USAGE_COUNT];
+            }
+        }
+    }
+
+    public NodeUsageIterator(Node node) {
+        this.node = node;
+        advance();
+    }
+
+    public boolean hasNext() {
+        return current != null;
+    }
+
+    public Node next() {
+        Node result = current;
+        if (result == null) {
+            throw new NoSuchElementException();
+        }
+        advance();
+        return result;
+    }
+
+    @Override
+    public void remove() {
+        throw new UnsupportedOperationException();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsageWithModCountIterator.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.graph;
+
+import java.util.*;
+
+class NodeUsageWithModCountIterator extends NodeUsageIterator {
+
+    public NodeUsageWithModCountIterator(Node n) {
+        super(n);
+    }
+
+    private final int expectedModCount = node.usageModCount();
+
+    @Override
+    public boolean hasNext() {
+        if (expectedModCount != node.usageModCount()) {
+            throw new ConcurrentModificationException();
+        }
+        return super.hasNext();
+    }
+
+    @Override
+    public Node next() {
+        if (expectedModCount != node.usageModCount()) {
+            throw new ConcurrentModificationException();
+        }
+        return super.next();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Position.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.graph;
+
+import com.oracle.graal.graph.Node.Input;
+import com.oracle.graal.graph.Node.OptionalInput;
+import com.oracle.graal.nodeinfo.*;
+
+/**
+ * Describes an edge slot for a {@link NodeClass}.
+ *
+ * @see NodeClass#getName(Position)
+ */
+public final class Position {
+
+    /**
+     * Specifies if this position denotes an {@link Input} or {@link OptionalInput} field.
+     */
+    private final boolean input;
+
+    /**
+     * Index of the {@link Node} or {@link NodeList} field denoted by this position.
+     */
+    private final int index;
+
+    /**
+     * Index within a {@link NodeList} if {@link #index} denotes a {@link NodeList} field otherwise
+     * {@link Node#NOT_ITERABLE}.
+     */
+    private final int subIndex;
+
+    public Position(boolean input, int index, int subIndex) {
+        this.input = input;
+        this.index = index;
+        this.subIndex = subIndex;
+    }
+
+    public Node get(Node node) {
+        return node.getNodeClass().get(node, this);
+    }
+
+    public InputType getInputType(Node node) {
+        return node.getNodeClass().getInputType(this);
+    }
+
+    public String getInputName(Node node) {
+        return node.getNodeClass().getName(this);
+    }
+
+    public boolean isInputOptional(Node node) {
+        return node.getNodeClass().isInputOptional(this);
+    }
+
+    public void set(Node node, Node value) {
+        node.getNodeClass().set(node, this, value);
+    }
+
+    public void initialize(Node node, Node value) {
+        node.getNodeClass().initializePosition(node, this, value);
+    }
+
+    @Override
+    public String toString() {
+        return (input ? "input " : "successor ") + index + "/" + subIndex;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + index;
+        result = prime * result + (input ? 1231 : 1237);
+        result = prime * result + subIndex;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        Position other = (Position) obj;
+        if (index != other.index) {
+            return false;
+        }
+        if (input != other.input) {
+            return false;
+        }
+        if (subIndex != other.subIndex) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Gets the index within a {@link NodeList} if {@link #getIndex()} denotes a {@link NodeList}
+     * field otherwise {@link Node#NOT_ITERABLE}.
+     */
+    public int getSubIndex() {
+        return subIndex;
+    }
+
+    /**
+     * Gets the index of the {@link Node} or {@link NodeList} field denoted by this position.
+     */
+    public int getIndex() {
+        return index;
+    }
+
+    /**
+     * Returns true if this position denotes an {@link Input} or {@link OptionalInput} field, false
+     * otherwise.
+     */
+    public boolean isInput() {
+        return input;
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/AMD64HotSpotFrameOmissionTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/AMD64HotSpotFrameOmissionTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -104,7 +104,7 @@
     private void testHelper(String name, CodeGenerator gen) {
         Method method = getMethod(name);
         ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(method);
-        InstalledCode installedCode = getCode(javaMethod, parse(method));
+        InstalledCode installedCode = getCode(javaMethod, parseEager(method));
 
         TargetDescription target = getCodeCache().getTarget();
         RegisterConfig registerConfig = getCodeCache().getRegisterConfig();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/CompressedNullCheckTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.amd64.test;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+
+/**
+ * Ensures that frame omission works in cases where it is expected to.
+ */
+public class CompressedNullCheckTest extends GraalCompilerTest {
+
+    private static final class Container {
+        Integer i = new Integer(1);
+    }
+
+    public static void testSnippet(Container c) {
+        c.i.intValue();
+    }
+
+    @Test
+    public void test() {
+        test("testSnippet", new Container());
+    }
+
+    @Override
+    protected boolean checkMidTierGraph(StructuredGraph graph) {
+        int count = 0;
+        for (IsNullNode isNull : graph.getNodes().filter(IsNullNode.class).snapshot()) {
+            ValueNode value = isNull.getValue();
+            if (value instanceof CompressionNode) {
+                count++;
+                isNull.replaceFirstInput(value, ((CompressionNode) value).getValue());
+            }
+        }
+        Assert.assertEquals("graph should contain exactly one IsNullNode", 1, count);
+        return super.checkMidTierGraph(graph);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Mon Aug 25 21:15:59 2014 -0700
@@ -49,6 +49,7 @@
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.nfi.api.*;
 
 /**
  * HotSpot AMD64 specific backend.
@@ -321,15 +322,18 @@
         }
     }
 
-    @Override
-    public NativeFunctionInterface getNativeFunctionInterface() {
-        HotSpotVMConfig config = getRuntime().getConfig();
+    /**
+     * Called from the VM.
+     */
+    public static NativeFunctionInterface createNativeFunctionInterface() {
+        HotSpotVMConfig config = HotSpotGraalRuntime.runtime().getConfig();
         RawNativeCallNodeFactory factory = new RawNativeCallNodeFactory() {
             public FixedWithNextNode createRawCallNode(Kind returnType, Constant functionPointer, ValueNode... args) {
-                return new AMD64RawNativeCallNode(returnType, functionPointer, args);
+                return AMD64RawNativeCallNode.create(returnType, functionPointer, args);
             }
         };
-        return new HotSpotNativeFunctionInterface(getProviders(), factory, this, config.dllLoad, config.dllLookup, config.rtldDefault);
+        Backend backend = HotSpotGraalRuntime.runtime().getBackend(AMD64.class);
+        return new HotSpotNativeFunctionInterface(HotSpotGraalRuntime.runtime().getHostProviders(), factory, backend, config.dllLoad, config.dllLookup, config.rtldDefault);
     }
 
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.StandardOp.BlockEndOp;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java	Mon Aug 25 21:15:59 2014 -0700
@@ -31,7 +31,7 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java	Mon Aug 25 21:15:59 2014 -0700
@@ -31,7 +31,7 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.StandardOp.BlockEndOp;
 import com.oracle.graal.lir.asm.*;
 
 /**
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Mon Aug 25 21:15:59 2014 -0700
@@ -559,8 +559,19 @@
     }
 
     public void emitNullCheck(Value address, LIRFrameState state) {
-        assert address.getKind() == Kind.Object : address + " - " + address.getKind() + " not an object!";
-        append(new AMD64Move.NullCheckOp(load(address), state));
+        if (address.getLIRKind().getPlatformKind() == Kind.Int) {
+            CompressEncoding encoding = config.getOopEncoding();
+            if (encoding.shift <= 3) {
+                AMD64AddressValue uncompressionAddress = emitAddress(getProviders().getRegisters().getHeapBaseRegister().asValue(), 0, load(address), 1 << encoding.shift);
+                append(new AMD64HotSpotMove.CompressedNullCheckOp(uncompressionAddress, state));
+            } else {
+                Value uncompress = emitUncompress(address, encoding, false);
+                append(new AMD64Move.NullCheckOp(load(uncompress), state));
+            }
+        } else {
+            assert address.getKind() == Kind.Object : address + " - " + address.getKind() + " not an object!";
+            append(new AMD64Move.NullCheckOp(load(address), state));
+        }
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveDeoptimizedStackFrameOp.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveDeoptimizedStackFrameOp.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.hotspot.amd64;
 
+import static com.oracle.graal.amd64.AMD64.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.amd64.AMD64.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 import com.oracle.graal.api.code.*;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,7 +27,7 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
+import com.oracle.graal.amd64.*;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
@@ -254,4 +255,24 @@
         }
     }
 
+    public static class CompressedNullCheckOp extends AMD64LIRInstruction {
+
+        @Use({COMPOSITE}) protected AMD64AddressValue address;
+        @State protected LIRFrameState state;
+
+        public CompressedNullCheckOp(AMD64AddressValue address, LIRFrameState state) {
+            this.address = address;
+            this.state = state;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            crb.recordImplicitException(masm.position(), state);
+            masm.testl(AMD64.rax, address.toAddress());
+        }
+
+        public LIRFrameState getState() {
+            return state;
+        }
+    }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java	Mon Aug 25 21:15:59 2014 -0700
@@ -47,8 +47,8 @@
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java	Mon Aug 25 21:15:59 2014 -0700
@@ -29,7 +29,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.StandardOp.BlockEndOp;
 import com.oracle.graal.lir.asm.*;
 
 /**
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java	Mon Aug 25 21:15:59 2014 -0700
@@ -31,7 +31,7 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.StandardOp.BlockEndOp;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -28,15 +28,21 @@
 import com.oracle.graal.compiler.amd64.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public class AMD64RawNativeCallNode extends FixedWithNextNode implements LIRLowerable {
 
     private final Constant functionPointer;
-    @Input private final NodeInputList<ValueNode> args;
+    @Input NodeInputList<ValueNode> args;
 
-    public AMD64RawNativeCallNode(Kind returnType, Constant functionPointer, ValueNode[] args) {
+    public static AMD64RawNativeCallNode create(Kind returnType, Constant functionPointer, ValueNode[] args) {
+        return USE_GENERATED_NODES ? new AMD64RawNativeCallNodeGen(returnType, functionPointer, args) : new AMD64RawNativeCallNode(returnType, functionPointer, args);
+    }
+
+    protected AMD64RawNativeCallNode(Kind returnType, Constant functionPointer, ValueNode[] args) {
         super(StampFactory.forKind(returnType));
         this.functionPointer = functionPointer;
         this.args = new NodeInputList<>(this, args);
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/DonorThreadPool.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2014, 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.hsail;
-
-import static com.oracle.graal.hotspot.hsail.HSAILHotSpotBackend.Options.*;
-
-import java.util.concurrent.*;
-
-import com.oracle.graal.hotspot.hsail.HSAILHotSpotBackend.Options;
-
-/**
- * Thread pool for HSAIL allocation support.
- */
-public class DonorThreadPool {
-
-    private final Thread[] threads;
-
-    void waitAt(CyclicBarrier barrier) {
-        try {
-            barrier.await();
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-
-    /**
-     * Creates a pool of threads whose size is given by {@link Options#HsailDonorThreads}.
-     */
-    DonorThreadPool() {
-        int size = HsailDonorThreads.getValue();
-        this.threads = new Thread[size];
-        CyclicBarrier barrier = new CyclicBarrier(size + 1);
-
-        // fill in threads
-        for (int i = 0; i < size; i++) {
-            threads[i] = new Thread(new Runnable() {
-                @Override
-                public void run() {
-                    while (true) {
-                        waitAt(barrier);
-                    }
-                }
-            }, "HsailDonorThread-" + i);
-            threads[i].setDaemon(true);
-            threads[i].start();
-        }
-        // creating thread waits at barrier to make sure others have started
-        waitAt(barrier);
-    }
-
-    public Thread[] getThreads() {
-        return threads;
-    }
-}
\ No newline at end of file
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/ForEachToGraal.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/ForEachToGraal.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,12 +27,12 @@
 
 import java.lang.reflect.*;
 import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.*;
 import java.util.function.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.GraalInternalError;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.hsail.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Mon Aug 25 21:15:59 2014 -0700
@@ -85,8 +85,8 @@
     public static class Options {
 
         // @formatter:off
-        @Option(help = "Number of donor threads for HSAIL kernel dispatch")
-        static public final OptionValue<Integer> HsailDonorThreads = new OptionValue<>(4);
+        @Option(help = "Number of TLABs used for HSAIL kernels which allocate")
+        static public final OptionValue<Integer> HsailKernelTlabs = new OptionValue<>(4);
         // @formatter:on
     }
 
@@ -369,25 +369,18 @@
         return result;
     }
 
-    private static final ThreadLocal<DonorThreadPool> donorThreadPool = new ThreadLocal<DonorThreadPool>() {
-        @Override
-        protected DonorThreadPool initialValue() {
-            return new DonorThreadPool();
-        }
-    };
-
     public boolean executeKernel(HotSpotInstalledCode kernel, int jobSize, Object[] args) throws InvalidInstalledCodeException {
         if (!deviceInitialized) {
             throw new GraalInternalError("Cannot execute GPU kernel if device is not initialized");
         }
         int[] oopMapArray = ((HSAILHotSpotNmethod) kernel).getOopMapArray();
 
-        // Pass donorThreadPoolArray if this kernel uses allocation, otherwise null
-        Thread[] donorThreadArray = ((HSAILHotSpotNmethod) kernel).getUsesAllocationFlag() ? donorThreadPool.get().getThreads() : null;
-        return executeKernel0(kernel, jobSize, args, donorThreadArray, HsailAllocBytesPerWorkitem.getValue(), oopMapArray);
+        // Pass HsailKernelTlabs number if this kernel uses allocation, otherwise 0
+        int numTlabs = ((HSAILHotSpotNmethod) kernel).getUsesAllocationFlag() ? HsailKernelTlabs.getValue() : 0;
+        return executeKernel0(kernel, jobSize, args, numTlabs, HsailAllocBytesPerWorkitem.getValue(), oopMapArray);
     }
 
-    private static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args, Thread[] donorThreads, int allocBytesPerWorkitem, int[] oopMapArray)
+    private static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args, int numTlabs, int allocBytesPerWorkitem, int[] oopMapArray)
                     throws InvalidInstalledCodeException;
 
     /**
@@ -633,12 +626,12 @@
             RegisterValue d16_deoptInfo = HSAIL.d16.asValue(wordLIRKind);
 
             // Aliases for d17
-            RegisterValue d17_donorThreadIndex = HSAIL.d17.asValue(wordLIRKind);
-            RegisterValue d17_safepointFlagAddrIndex = d17_donorThreadIndex;
+            RegisterValue d17_tlabIndex = HSAIL.d17.asValue(wordLIRKind);
+            RegisterValue d17_safepointFlagAddrIndex = d17_tlabIndex;
 
             // Aliases for s34
             RegisterValue s34_deoptOccurred = HSAIL.s34.asValue(LIRKind.value(Kind.Int));
-            RegisterValue s34_donorThreadIndex = s34_deoptOccurred;
+            RegisterValue s34_tlabIndex = s34_deoptOccurred;
 
             asm.emitLoadKernelArg(d16_deoptInfo, asm.getDeoptInfoName(), "u64");
             asm.emitComment("// Check if a deopt or safepoint has occurred and abort if true before doing any work");
@@ -657,15 +650,15 @@
             // load thread register if this kernel performs allocation
             if (usesAllocation) {
                 RegisterValue threadReg = getProviders().getRegisters().getThreadRegister().asValue(wordLIRKind);
-                assert HsailDonorThreads.getValue() > 0;
+                assert HsailKernelTlabs.getValue() > 0;
                 asm.emitLoad(wordKind, threadReg, new HSAILAddressValue(wordLIRKind, d16_deoptInfo, config.hsailCurTlabInfoOffset).toAddress());
-                if (HsailDonorThreads.getValue() != 1) {
-                    asm.emitComment("// map workitem to a donor thread");
-                    asm.emitString(String.format("rem_u32  $%s, %s, %d;", s34_donorThreadIndex.getRegister(), workItemReg, HsailDonorThreads.getValue()));
-                    asm.emitConvert(d17_donorThreadIndex, s34_donorThreadIndex, wordKind, Kind.Int);
-                    asm.emit("mad", threadReg, d17_donorThreadIndex, Constant.forInt(8), threadReg);
+                if (HsailKernelTlabs.getValue() != 1) {
+                    asm.emitComment("// map workitem to a tlab");
+                    asm.emitString(String.format("rem_u32  $%s, %s, %d;", s34_tlabIndex.getRegister(), workItemReg, HsailKernelTlabs.getValue()));
+                    asm.emitConvert(d17_tlabIndex, s34_tlabIndex, wordKind, Kind.Int);
+                    asm.emit("mad", threadReg, d17_tlabIndex, Constant.forInt(8), threadReg);
                 } else {
-                    // workitem is already mapped to solitary donor thread
+                    // workitem is already mapped to solitary tlab
                 }
                 asm.emitComment("// $" + getProviders().getRegisters().getThreadRegister() + " will point to holder of tlab thread info for this workitem");
             }
@@ -686,7 +679,9 @@
             String iterationObjArgReg = HSAIL.mapRegister(cc.getArgument(nonConstantParamCount - 1));
             /*
              * iterationObjArgReg will be the highest $d register in use (it is the last parameter)
-             * so tempReg can be the next higher $d register
+             * so tempReg can be the next higher $d register. As of 1.0 spec, we cannot use
+             * ld_global_u32 $dxx, [addr]; so we need a temporary $s register. We can use
+             * workItemReg+1;
              */
             String tmpReg = "$d" + (asRegister(cc.getArgument(nonConstantParamCount - 1)).encoding() + 1);
             // Convert gid to long.
@@ -699,9 +694,13 @@
             asm.emitString("add_u64 " + tmpReg + ", " + tmpReg + ", " + iterationObjArgReg + "; // Add to array ref ptr");
             // Load the object into the parameter reg.
             if (useCompressedOops) {
+                int workItemRegEncoding = asRegister(cc.getArgument(nonConstantParamCount)).encoding();
+                String tmpReg32 = "$s" + Integer.toString(workItemRegEncoding + 1);
 
-                // Load u32 into the d 64 reg since it will become an object address
-                asm.emitString("ld_global_u32 " + tmpReg + ", " + "[" + tmpReg + "]" + "; // Load compressed ptr from array");
+                // Load u32 into the temporary $s reg since it will become an object address
+
+                asm.emitString("ld_global_u32 " + tmpReg32 + ", " + "[" + tmpReg + "]" + "; // Load compressed ptr from array");
+                asm.emitString("cvt_u64_u32 " + tmpReg + ", " + tmpReg32 + ";      // cvt to 64 bits");
 
                 long narrowOopBase = config.narrowOopBase;
                 long narrowOopShift = config.narrowOopShift;
@@ -1069,10 +1068,10 @@
             return null;
         }
         StructuredGraph hostGraph = new StructuredGraph(method, -2);
-        ParameterNode deoptId = hostGraph.unique(new ParameterNode(0, StampFactory.intValue()));
-        ParameterNode hsailFrame = hostGraph.unique(new ParameterNode(1, StampFactory.forKind(providers.getCodeCache().getTarget().wordKind)));
-        ParameterNode reasonAndAction = hostGraph.unique(new ParameterNode(2, StampFactory.intValue()));
-        ParameterNode speculation = hostGraph.unique(new ParameterNode(3, StampFactory.object()));
+        ParameterNode deoptId = hostGraph.unique(ParameterNode.create(0, StampFactory.intValue()));
+        ParameterNode hsailFrame = hostGraph.unique(ParameterNode.create(1, StampFactory.forKind(providers.getCodeCache().getTarget().wordKind)));
+        ParameterNode reasonAndAction = hostGraph.unique(ParameterNode.create(2, StampFactory.intValue()));
+        ParameterNode speculation = hostGraph.unique(ParameterNode.create(3, StampFactory.object()));
         BeginNode[] branches = new BeginNode[deopts.size() + 1];
         int[] keys = new int[deopts.size()];
         int[] keySuccessors = new int[deopts.size() + 1];
@@ -1095,7 +1094,7 @@
         keyProbabilities[deopts.size()] = 0; // default
         keySuccessors[deopts.size()] = deopts.size();
         branches[deopts.size()] = createHostCrashBranch(hostGraph, deoptId);
-        IntegerSwitchNode switchNode = hostGraph.add(new IntegerSwitchNode(deoptId, branches, keys, keyProbabilities, keySuccessors));
+        IntegerSwitchNode switchNode = hostGraph.add(IntegerSwitchNode.create(deoptId, branches, keys, keyProbabilities, keySuccessors));
         StartNode start = hostGraph.start();
         start.setNext(switchNode);
         /*
@@ -1106,16 +1105,16 @@
     }
 
     private static BeginNode createHostCrashBranch(StructuredGraph hostGraph, ValueNode deoptId) {
-        VMErrorNode vmError = hostGraph.add(new VMErrorNode("Error in HSAIL deopt. DeoptId=%d", deoptId));
+        VMErrorNode vmError = hostGraph.add(VMErrorNode.create("Error in HSAIL deopt. DeoptId=%d", deoptId));
         // ConvertNode.convert(hostGraph, Kind.Long, deoptId)));
-        vmError.setNext(hostGraph.add(new ReturnNode(ConstantNode.defaultForKind(hostGraph.method().getSignature().getReturnKind(), hostGraph))));
+        vmError.setNext(hostGraph.add(ReturnNode.create(ConstantNode.defaultForKind(hostGraph.method().getSignature().getReturnKind(), hostGraph))));
         return BeginNode.begin(vmError);
     }
 
     private static BeginNode createHostDeoptBranch(DeoptimizingOp deopt, ParameterNode hsailFrame, ValueNode reasonAndAction, ValueNode speculation, HotSpotProviders providers,
                     HotSpotVMConfig config, int numSRegs, int numDRegs) {
-        BeginNode branch = hsailFrame.graph().add(new BeginNode());
-        DynamicDeoptimizeNode deoptimization = hsailFrame.graph().add(new DynamicDeoptimizeNode(reasonAndAction, speculation));
+        BeginNode branch = hsailFrame.graph().add(BeginNode.create());
+        DynamicDeoptimizeNode deoptimization = hsailFrame.graph().add(DynamicDeoptimizeNode.create(reasonAndAction, speculation));
         deoptimization.setStateBefore(createFrameState(deopt.getFrameState().topFrame, hsailFrame, providers, config, numSRegs, numDRegs));
         branch.setNext(deoptimization);
         return branch;
@@ -1148,7 +1147,7 @@
             locks[i] = lirValueToHirNode.apply(lockValue);
             monitorIds[i] = getMonitorIdForHotSpotMonitorValueFromFrame(lockValue, hsailFrame, hostGraph);
         }
-        FrameState frameState = hostGraph.add(new FrameState(lowLevelFrame.getMethod(), lowLevelFrame.getBCI(), locals, stack, locks, monitorIds, lowLevelFrame.rethrowException, false));
+        FrameState frameState = hostGraph.add(FrameState.create(lowLevelFrame.getMethod(), lowLevelFrame.getBCI(), locals, stack, locks, monitorIds, lowLevelFrame.rethrowException, false));
         if (outterFrameState != null) {
             frameState.setOuterFrameState(outterFrameState);
         }
@@ -1163,7 +1162,7 @@
                 VirtualObject virtualObject = entry.getKey();
                 VirtualObjectNode virtualObjectNode = entry.getValue();
                 List<ValueNode> fieldValues = Arrays.stream(virtualObject.getValues()).map(lirValueToHirNode).collect(Collectors.toList());
-                virtualStates.add(new VirtualObjectState(virtualObjectNode, fieldValues));
+                virtualStates.add(VirtualObjectState.create(virtualObjectNode, fieldValues));
             }
             // New virtual objects may have been discovered while processing the previous set.
             // Wait until a fixed point is reached
@@ -1208,9 +1207,9 @@
     private static ValueNode getNodeForVirtualObjectFromFrame(VirtualObject virtualObject, Map<VirtualObject, VirtualObjectNode> virtualObjects, StructuredGraph hostGraph) {
         return virtualObjects.computeIfAbsent(virtualObject, vo -> {
             if (vo.getType().isArray()) {
-                return hostGraph.add(new VirtualArrayNode(vo.getType().getComponentType(), vo.getValues().length));
+                return hostGraph.add(VirtualArrayNode.create(vo.getType().getComponentType(), vo.getValues().length));
             } else {
-                return hostGraph.add(new VirtualInstanceNode(vo.getType(), true));
+                return hostGraph.add(VirtualInstanceNode.create(vo.getType(), true));
             }
         });
     }
@@ -1230,7 +1229,7 @@
         } else {
             throw GraalInternalError.shouldNotReachHere("unknown hsail register: " + regNumber);
         }
-        valueNode = hostGraph.unique(new FloatingReadNode(hsailFrame, location, null, StampFactory.forKind(valueKind)));
+        valueNode = hostGraph.unique(FloatingReadNode.create(hsailFrame, location, null, StampFactory.forKind(valueKind)));
         return valueNode;
     }
 
@@ -1242,7 +1241,7 @@
             int intSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Int);
             long offset = config.hsailFrameHeaderSize + (intSize * numSRegs) + (longSize * numDRegs) + HSAIL.getStackOffsetStart(slot, slotSizeInBits);
             LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, valueKind, offset, hostGraph);
-            ValueNode valueNode = hostGraph.unique(new FloatingReadNode(hsailFrame, location, null, StampFactory.forKind(valueKind)));
+            ValueNode valueNode = hostGraph.unique(FloatingReadNode.create(hsailFrame, location, null, StampFactory.forKind(valueKind)));
             return valueNode;
         } else {
             throw GraalInternalError.shouldNotReachHere("unsupported stack slot kind: " + valueKind);
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,12 +26,12 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.hsail.replacements.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hsail.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.phases.util.*;
-import com.oracle.graal.hotspot.hsail.replacements.*;
 
 @ServiceProvider(HotSpotBackendFactory.class)
 public class HSAILHotSpotBackendFactory implements HotSpotBackendFactory {
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,20 +22,20 @@
  */
 package com.oracle.graal.hotspot.hsail;
 
+import java.util.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.hsail.replacements.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.hotspot.hsail.replacements.*;
-
-import java.util.HashMap;
+import com.oracle.graal.nodes.spi.*;
 
 public class HSAILHotSpotLoweringProvider extends DefaultHotSpotLoweringProvider {
 
@@ -94,7 +94,7 @@
                     default:
                         reason = DeoptimizationReason.None;
                 }
-                unwind.replaceAtPredecessor(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, reason)));
+                unwind.replaceAtPredecessor(graph.add(DeoptimizeNode.create(DeoptimizationAction.InvalidateReprofile, reason)));
                 unwind.safeDelete();
             } else {
                 // unwind whose exception is not an instance of ForeignCallNode
@@ -103,22 +103,22 @@
         }
     };
 
-    private HashMap<Class<?>, LoweringStrategy> strategyMap = new HashMap<>();
+    private HashMap<NodeClass, LoweringStrategy> strategyMap = new HashMap<>();
 
     void initStrategyMap() {
-        strategyMap.put(ConvertNode.class, PassThruStrategy);
-        strategyMap.put(FloatConvertNode.class, PassThruStrategy);
-        strategyMap.put(NewInstanceNode.class, NewObjectStrategy);
-        strategyMap.put(NewArrayNode.class, NewObjectStrategy);
-        strategyMap.put(NewMultiArrayNode.class, RejectStrategy);
-        strategyMap.put(DynamicNewArrayNode.class, RejectStrategy);
-        strategyMap.put(MonitorEnterNode.class, RejectStrategy);
-        strategyMap.put(MonitorExitNode.class, RejectStrategy);
-        strategyMap.put(UnwindNode.class, UnwindNodeStrategy);
+        strategyMap.put(NodeClass.get(ConvertNode.class), PassThruStrategy);
+        strategyMap.put(NodeClass.get(FloatConvertNode.class), PassThruStrategy);
+        strategyMap.put(NodeClass.get(NewInstanceNode.class), NewObjectStrategy);
+        strategyMap.put(NodeClass.get(NewArrayNode.class), NewObjectStrategy);
+        strategyMap.put(NodeClass.get(NewMultiArrayNode.class), RejectStrategy);
+        strategyMap.put(NodeClass.get(DynamicNewArrayNode.class), RejectStrategy);
+        strategyMap.put(NodeClass.get(MonitorEnterNode.class), RejectStrategy);
+        strategyMap.put(NodeClass.get(MonitorExitNode.class), RejectStrategy);
+        strategyMap.put(NodeClass.get(UnwindNode.class), UnwindNodeStrategy);
     }
 
     private LoweringStrategy getStrategy(Node n) {
-        return strategyMap.get(n.getClass());
+        return strategyMap.get(n.getNodeClass());
     }
 
     public HSAILHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, TargetDescription target) {
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILDirectLoadAcquireNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILDirectLoadAcquireNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,15 +23,21 @@
 package com.oracle.graal.hotspot.hsail.replacements;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.hsail.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.nodes.*;
-import com.oracle.graal.hotspot.hsail.*;
 import com.oracle.graal.word.*;
 
+@NodeInfo
 public class HSAILDirectLoadAcquireNode extends DirectReadNode {
 
-    public HSAILDirectLoadAcquireNode(ValueNode address, Kind readKind) {
+    public static HSAILDirectLoadAcquireNode create(ValueNode address, Kind readKind) {
+        return USE_GENERATED_NODES ? new HSAILDirectLoadAcquireNodeGen(address, readKind) : new HSAILDirectLoadAcquireNode(address, readKind);
+    }
+
+    protected HSAILDirectLoadAcquireNode(ValueNode address, Kind readKind) {
         super(address, readKind);
     }
 
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILDirectStoreReleaseNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILDirectStoreReleaseNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,15 +23,21 @@
 package com.oracle.graal.hotspot.hsail.replacements;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.hsail.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.nodes.*;
-import com.oracle.graal.hotspot.hsail.*;
 import com.oracle.graal.word.*;
 
+@NodeInfo
 public class HSAILDirectStoreReleaseNode extends DirectStoreNode {
 
-    public HSAILDirectStoreReleaseNode(ValueNode address, ValueNode value, Kind kind) {
+    public static HSAILDirectStoreReleaseNode create(ValueNode address, ValueNode value, Kind kind) {
+        return USE_GENERATED_NODES ? new HSAILDirectStoreReleaseNodeGen(address, value, kind) : new HSAILDirectStoreReleaseNode(address, value, kind);
+    }
+
+    protected HSAILDirectStoreReleaseNode(ValueNode address, ValueNode value, Kind kind) {
         super(address, value, kind);
     }
 
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILHotSpotReplacementsUtil.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILHotSpotReplacementsUtil.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,11 +24,11 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.replacements.Snippet.Fold;
 import com.oracle.graal.word.*;
-import com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil;
-import com.oracle.graal.hotspot.meta.*;
 
 //JaCoCo Exclude
 
@@ -50,7 +50,7 @@
     public static final LocationIdentity TLABINFO_START_LOCATION = new NamedLocationIdentity("TlabInfoStart");
     public static final LocationIdentity TLABINFO_ALLOCINFO_LOCATION = new NamedLocationIdentity("TlabInfoAllocInfo");
     public static final LocationIdentity TLABINFO_ORIGINALTOP_LOCATION = new NamedLocationIdentity("TlabInfoOriginalTop");
-    public static final LocationIdentity TLABINFO_DONORTHREAD_LOCATION = new NamedLocationIdentity("TlabInfoDonorThread");
+    public static final LocationIdentity TLABINFO_TLAB_LOCATION = new NamedLocationIdentity("TlabInfoTlab");
 
     public static final LocationIdentity ALLOCINFO_TLABINFOSPOOLNEXT_LOCATION = new NamedLocationIdentity("AllocInfoTlabInfosPoolNext");
     public static final LocationIdentity ALLOCINFO_TLABINFOSPOOLEND_LOCATION = new NamedLocationIdentity("AllocInfoTlabInfosPoolEnd");
@@ -121,12 +121,12 @@
         tlabInfo.writeWord(config().hsailTlabInfoOriginalTopOffset, val, TLABINFO_ORIGINALTOP_LOCATION);
     }
 
-    public static void writeTlabInfoDonorThread(Word tlabInfo, Word val) {
-        tlabInfo.writeWord(config().hsailTlabInfoDonorThreadOffset, val, TLABINFO_DONORTHREAD_LOCATION);
+    public static void writeTlabInfoTlab(Word tlabInfo, Word val) {
+        tlabInfo.writeWord(config().hsailTlabInfoTlabOffset, val, TLABINFO_TLAB_LOCATION);
     }
 
-    public static Word readTlabInfoDonorThread(Word tlabInfo) {
-        return tlabInfo.readWord(config().hsailTlabInfoDonorThreadOffset, TLABINFO_DONORTHREAD_LOCATION);
+    public static Word readTlabInfoTlab(Word tlabInfo) {
+        return tlabInfo.readWord(config().hsailTlabInfoTlabOffset, TLABINFO_TLAB_LOCATION);
     }
 
     public static Word readAllocInfoTlabInfosPoolEnd(Word allocInfo) {
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java	Mon Aug 25 21:15:59 2014 -0700
@@ -97,7 +97,7 @@
         Word alignReserveBytes = readAllocInfoTlabAlignReserveBytes(allocInfo);
         writeTlabInfoEnd(newTlabInfo, tlabStart.add(newTlabSize.subtract(alignReserveBytes)));
         writeTlabInfoAllocInfo(newTlabInfo, allocInfo);
-        writeTlabInfoDonorThread(newTlabInfo, readTlabInfoDonorThread(oldTlabInfo));
+        writeTlabInfoTlab(newTlabInfo, readTlabInfoTlab(oldTlabInfo));
         return (newTlabInfo);
     }
 
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILWorkItemAbsIdNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILWorkItemAbsIdNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,13 +24,19 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.hotspot.hsail.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.hotspot.hsail.*;
 
+@NodeInfo
 public class HSAILWorkItemAbsIdNode extends FixedWithNextNode implements LIRLowerable {
 
-    public HSAILWorkItemAbsIdNode() {
+    public static HSAILWorkItemAbsIdNode create() {
+        return USE_GENERATED_NODES ? new HSAILWorkItemAbsIdNodeGen() : new HSAILWorkItemAbsIdNode();
+    }
+
+    protected HSAILWorkItemAbsIdNode() {
         super(StampFactory.forKind(Kind.Int));
     }
 
--- a/graal/com.oracle.graal.hotspot.jdk8.test/src/com/oracle/graal/hotspot/jdk8/test/CRC32UpdateByteBufferSubstitutionTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2007, 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.jdk8.test;
-
-import java.io.*;
-import java.nio.*;
-import java.util.zip.*;
-
-import org.junit.*;
-
-import com.oracle.graal.compiler.test.*;
-
-/**
- * Tests compiled call to {@link CRC32#updateByteBuffer(int, long, int, int)}.
- */
-@SuppressWarnings("javadoc")
-public class CRC32UpdateByteBufferSubstitutionTest extends GraalCompilerTest {
-
-    public static long updateByteBuffer(ByteBuffer buffer) {
-        CRC32 crc = new CRC32();
-        buffer.rewind();
-        crc.update(buffer);
-        return crc.getValue();
-    }
-
-    @Test
-    public void test1() throws Throwable {
-        String classfileName = CRC32UpdateByteBufferSubstitutionTest.class.getSimpleName().replace('.', '/') + ".class";
-        InputStream s = CRC32UpdateByteBufferSubstitutionTest.class.getResourceAsStream(classfileName);
-        byte[] buf = new byte[s.available()];
-        new DataInputStream(s).readFully(buf);
-
-        ByteBuffer directBuf = ByteBuffer.allocateDirect(buf.length);
-        directBuf.put(buf);
-        ByteBuffer heapBuf = ByteBuffer.wrap(buf);
-
-        test("updateByteBuffer", directBuf);
-        test("updateByteBuffer", heapBuf);
-    }
-}
--- a/graal/com.oracle.graal.hotspot.loader/src/com/oracle/graal/hotspot/loader/Factory.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.loader/src/com/oracle/graal/hotspot/loader/Factory.java	Mon Aug 25 21:15:59 2014 -0700
@@ -40,7 +40,8 @@
     @SuppressWarnings("unused")
     private static ClassLoader newClassLoader() throws MalformedURLException {
         URL[] urls = {getGraalJarUrl("graal"), getGraalJarUrl("graal-truffle")};
-        return URLClassLoader.newInstance(urls);
+        ClassLoader parent = null;
+        return URLClassLoader.newInstance(urls, parent);
     }
 
     /**
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Mon Aug 25 21:15:59 2014 -0700
@@ -46,7 +46,6 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
-import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 import com.oracle.graal.lir.StandardOp.LabelOp;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.gen.*;
@@ -225,7 +224,7 @@
         return kernel;
     }
 
-    static final class RegisterAnalysis extends ValueProcedure {
+    static final class RegisterAnalysis extends ValueConsumer {
         private final SortedSet<Integer> signed32 = new TreeSet<>();
         private final SortedSet<Integer> signed64 = new TreeSet<>();
 
@@ -261,7 +260,7 @@
         }
 
         @Override
-        public Value doValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+        public void visitValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
             if (isVariable(value)) {
                 Variable regVal = (Variable) value;
                 Kind regKind = regVal.getKind();
@@ -310,7 +309,6 @@
                     }
                 }
             }
-            return value;
         }
     }
 
@@ -426,8 +424,8 @@
                     }
                     // Record registers used in the kernel
                     registerAnalysis.op = op;
-                    op.forEachTemp(registerAnalysis);
-                    op.forEachOutput(registerAnalysis);
+                    op.visitEachTemp(registerAnalysis);
+                    op.visitEachOutput(registerAnalysis);
                 }
             }
         }
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Mon Aug 25 21:15:59 2014 -0700
@@ -192,7 +192,7 @@
 
         InvokeNode kernelStart = createInvoke(getClass(), "getKernelStart", ConstantNode.forConstant(HotSpotObjectConstant.forObject(kernel), providers.getMetaAccess(), getGraph()));
 
-        AllocaNode buf = append(new AllocaNode(bufSize / wordSize, new BitSet()));
+        AllocaNode buf = append(AllocaNode.create(bufSize / wordSize, new BitSet()));
         ValueNode objectParametersOffsets;
         ValueNode pinnedObjects;
         ConstantNode nullWord = ConstantNode.forIntegerKind(wordKind, 0L, getGraph());
@@ -202,22 +202,22 @@
         } else {
             int intsPerWord = wordSize / intSize;
             int slots = roundUp(objectSlots.size(), intsPerWord);
-            objectParametersOffsets = append(new AllocaNode(slots, new BitSet()));
+            objectParametersOffsets = append(AllocaNode.create(slots, new BitSet()));
             // No refmap for pinned objects list since kernel execution is (currently) GC unsafe
-            pinnedObjects = append(new AllocaNode(objectSlots.size(), new BitSet()));
+            pinnedObjects = append(AllocaNode.create(objectSlots.size(), new BitSet()));
 
             // Initialize the object parameter offsets array
             int index = 0;
             for (int slot : objectSlots) {
                 int offset = slot * wordSize;
                 LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, index * intSize, getGraph());
-                append(new WriteNode(objectParametersOffsets, ConstantNode.forInt(offset, getGraph()), location, BarrierType.NONE, false));
+                append(WriteNode.create(objectParametersOffsets, ConstantNode.forInt(offset, getGraph()), location, BarrierType.NONE, false));
                 index++;
             }
         }
 
         Map<LaunchArg, ValueNode> args = new EnumMap<>(LaunchArg.class);
-        args.put(Thread, append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), true, false)));
+        args.put(Thread, append(ReadRegisterNode.create(providers.getRegisters().getThreadRegister(), true, false)));
         args.put(Kernel, kernelStart);
         args.put(DimX, forInt(1, getGraph()));
         args.put(DimY, forInt(1, getGraph()));
@@ -234,12 +234,12 @@
             ParameterNode javaParameter = javaParameters[javaParametersIndex];
             int javaParameterOffset = javaParameterOffsetsInKernelParametersBuffer[javaParametersIndex];
             LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, javaParameter.getKind(), javaParameterOffset, getGraph());
-            append(new WriteNode(buf, javaParameter, location, BarrierType.NONE, false));
+            append(WriteNode.create(buf, javaParameter, location, BarrierType.NONE, false));
             updateDimArg(method, sig, sigIndex++, args, javaParameter);
         }
         if (returnKind != Kind.Void) {
             LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, bufSize - wordSize, getGraph());
-            append(new WriteNode(buf, nullWord, location, BarrierType.NONE, false));
+            append(WriteNode.create(buf, nullWord, location, BarrierType.NONE, false));
         }
 
         HIRFrameStateBuilder fsb = new HIRFrameStateBuilder(method, getGraph(), true);
@@ -247,7 +247,7 @@
         getGraph().start().setStateAfter(fs);
 
         ValueNode[] launchArgsArray = args.values().toArray(new ValueNode[args.size()]);
-        ForeignCallNode result = append(new ForeignCallNode(providers.getForeignCalls(), CALL_KERNEL, launchArgsArray));
+        ForeignCallNode result = append(ForeignCallNode.create(providers.getForeignCalls(), CALL_KERNEL, launchArgsArray));
         result.setStateAfter(fs);
 
         InvokeNode getObjectResult = null;
@@ -261,13 +261,13 @@
             case Short:
             case Char:
             case Int:
-                returnValue = unique(new NarrowNode(result, 32));
+                returnValue = unique(NarrowNode.create(result, 32));
                 break;
             case Long:
                 returnValue = result;
                 break;
             case Float: {
-                ValueNode asInt = unique(new NarrowNode(result, 32));
+                ValueNode asInt = unique(NarrowNode.create(result, 32));
                 returnValue = ReinterpretNode.reinterpret(Kind.Float, asInt);
                 break;
             }
@@ -282,7 +282,7 @@
                 throw new GraalInternalError("%s return kind not supported", returnKind);
         }
 
-        append(new ReturnNode(returnValue));
+        append(ReturnNode.create(returnValue));
 
         if (Debug.isDumpEnabled()) {
             Debug.dump(getGraph(), "Initial kernel launch graph");
@@ -314,7 +314,7 @@
         } else {
             stamp = StampFactory.forKind(kind);
         }
-        javaParameters[javaParametersIndex] = unique(new ParameterNode(javaParametersIndex, stamp));
+        javaParameters[javaParametersIndex] = unique(ParameterNode.create(javaParametersIndex, stamp));
         bufSize += kindByteSize;
     }
 
@@ -326,7 +326,7 @@
         if (sigIndex >= 0) {
             ParallelOver parallelOver = method.getParameterAnnotation(ParallelOver.class, sigIndex);
             if (parallelOver != null && sig.getParameterType(sigIndex, method.getDeclaringClass()).equals(providers.getMetaAccess().lookupJavaType(int[].class))) {
-                ArrayLengthNode dimension = append(new ArrayLengthNode(javaParameter));
+                ArrayLengthNode dimension = append(ArrayLengthNode.create(javaParameter));
                 LaunchArg argKey = LaunchArg.valueOf(LaunchArg.class, "Dim" + parallelOver.dimension());
                 ValueNode existing = launchArgs.put(argKey, dimension);
                 if (existing != null && existing instanceof ArrayLengthNode) {
--- a/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import java.io.*;
 import java.lang.reflect.*;
 import java.util.*;
+import java.util.stream.*;
 import java.util.zip.*;
 
 import com.oracle.graal.api.runtime.*;
@@ -57,10 +58,7 @@
         }
 
         public Iterator<ZipEntry> iterator() {
-            List<ZipEntry> entries = new ArrayList<>();
-            for (ZipFile jar : jars) {
-                entries.addAll(Collections.list(jar.entries()));
-            }
+            Stream<ZipEntry> entries = jars.stream().flatMap(ZipFile::stream);
             return entries.iterator();
         }
 
@@ -148,7 +146,8 @@
     }
 
     /**
-     * Generates code for {@code GraalRuntime::set_option()}.
+     * Generates code for {@code GraalRuntime::set_option()} and
+     * {@code GraalRuntime::set_option_bool()}.
      */
     private static void genSetOption(PrintStream out) throws Exception {
         SortedMap<String, OptionDescriptor> options = getOptions();
@@ -159,21 +158,20 @@
         }
         lengths.add("PrintFlags".length());
 
-        out.println("bool GraalRuntime::set_option(KlassHandle hotSpotOptionsClass, char* name, int name_len, const char* value, TRAPS) {");
+        out.println("bool GraalRuntime::set_option_bool(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, char value, TRAPS) {");
         out.println("  bool check_only = hotSpotOptionsClass.is_null();");
-        out.println("  if (value != NULL && (value[0] == '+' || value[0] == '-')) {");
-        out.println("    // boolean options");
         genMatchers(out, lengths, options, true);
-        out.println("  } else {");
-        out.println("    // non-boolean options");
+        out.println("  return false;");
+        out.println("}");
+        out.println("bool GraalRuntime::set_option(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, const char* value, TRAPS) {");
+        out.println("  bool check_only = hotSpotOptionsClass.is_null();");
         genMatchers(out, lengths, options, false);
-        out.println("  }");
         out.println("  return false;");
         out.println("}");
     }
 
     protected static void genMatchers(PrintStream out, Set<Integer> lengths, SortedMap<String, OptionDescriptor> options, boolean isBoolean) throws Exception {
-        out.println("    switch (name_len) {");
+        out.println("  switch (name_len) {");
         for (int len : lengths) {
             boolean printedCase = false;
 
@@ -181,56 +179,56 @@
             // null terminated for <name>=<value> style options.
             if (len == "PrintFlags".length() && isBoolean) {
                 printedCase = true;
-                out.println("    case " + len + ":");
-                out.printf("      if (strncmp(name, \"PrintFlags\", %d) == 0) {%n", len);
-                out.println("        if (value[0] == '+') {");
-                out.println("          if (check_only) {");
-                out.println("            TempNewSymbol name = SymbolTable::new_symbol(\"Lcom/oracle/graal/hotspot/HotSpotOptions;\", CHECK_(true));");
-                out.println("            hotSpotOptionsClass = SystemDictionary::resolve_or_fail(name, true, CHECK_(true));");
-                out.println("          }");
-                out.println("          set_option_helper(hotSpotOptionsClass, name, name_len, Handle(), '?', Handle(), 0L);");
+                out.println("  case " + len + ":");
+                out.printf("    if (strncmp(name, \"PrintFlags\", %d) == 0) {%n", len);
+                out.println("      if (value == '+') {");
+                out.println("        if (check_only) {");
+                out.println("          TempNewSymbol name = SymbolTable::new_symbol(\"Lcom/oracle/graal/hotspot/HotSpotOptions;\", CHECK_(true));");
+                out.println("          hotSpotOptionsClass = SystemDictionary::resolve_or_fail(name, true, CHECK_(true));");
                 out.println("        }");
-                out.println("        return true;");
+                out.println("        set_option_helper(hotSpotOptionsClass, name, name_len, Handle(), '?', Handle(), 0L);");
                 out.println("      }");
+                out.println("      return true;");
+                out.println("    }");
             }
             for (Map.Entry<String, OptionDescriptor> e : options.entrySet()) {
                 OptionDescriptor desc = e.getValue();
                 if (e.getKey().length() == len && ((desc.getType() == Boolean.class) == isBoolean)) {
                     if (!printedCase) {
                         printedCase = true;
-                        out.println("    case " + len + ":");
+                        out.println("  case " + len + ":");
                     }
-                    out.printf("      if (strncmp(name, \"%s\", %d) == 0) {%n", e.getKey(), len);
+                    out.printf("    if (strncmp(name, \"%s\", %d) == 0) {%n", e.getKey(), len);
                     Class<?> declaringClass = desc.getDeclaringClass();
                     if (isBoolean) {
-                        out.printf("        Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(),
+                        out.printf("      Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(),
+                                        toInternalName(getFieldType(desc)));
+                        out.println("      if (!check_only) {");
+                        out.println("        set_option_helper(hotSpotOptionsClass, name, name_len, option, value, Handle(), 0L);");
+                        out.println("      }");
+                    } else if (desc.getType() == String.class) {
+                        out.println("      check_required_value(name, name_len, value, CHECK_(true));");
+                        out.printf("      Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(),
                                         toInternalName(getFieldType(desc)));
-                        out.println("        if (!check_only) {");
-                        out.println("          set_option_helper(hotSpotOptionsClass, name, name_len, option, value[0], Handle(), 0L);");
-                        out.println("        }");
-                    } else if (desc.getType() == String.class) {
-                        out.println("        check_required_value(name, name_len, value, CHECK_(true));");
+                        out.println("      if (!check_only) {");
+                        out.println("        Handle stringValue = java_lang_String::create_from_str(value, CHECK_(true));");
+                        out.println("        set_option_helper(hotSpotOptionsClass, name, name_len, option, 's', stringValue, 0L);");
+                        out.println("      }");
+                    } else {
+                        char spec = getPrimitiveSpecChar(desc);
+                        out.println("      jlong primitiveValue = parse_primitive_option_value('" + spec + "', name, name_len, value, CHECK_(true));");
+                        out.println("      if (!check_only) {");
                         out.printf("        Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(),
                                         toInternalName(getFieldType(desc)));
-                        out.println("        if (!check_only) {");
-                        out.println("          Handle stringValue = java_lang_String::create_from_str(value, CHECK_(true));");
-                        out.println("          set_option_helper(hotSpotOptionsClass, name, name_len, option, 's', stringValue, 0L);");
-                        out.println("        }");
-                    } else {
-                        char spec = getPrimitiveSpecChar(desc);
-                        out.println("        jlong primitiveValue = parse_primitive_option_value('" + spec + "', name, name_len, value, CHECK_(true));");
-                        out.println("        if (!check_only) {");
-                        out.printf("          Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(),
-                                        toInternalName(getFieldType(desc)));
-                        out.println("          set_option_helper(hotSpotOptionsClass, name, name_len, option, '" + spec + "', Handle(), primitiveValue);");
-                        out.println("        }");
+                        out.println("        set_option_helper(hotSpotOptionsClass, name, name_len, option, '" + spec + "', Handle(), primitiveValue);");
+                        out.println("      }");
                     }
-                    out.println("        return true;");
-                    out.println("      }");
+                    out.println("      return true;");
+                    out.println("    }");
                 }
             }
         }
-        out.println("    }");
+        out.println("  }");
     }
 
     @SuppressWarnings("unchecked")
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Mon Aug 25 21:15:59 2014 -0700
@@ -43,7 +43,6 @@
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Nop;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.RestoreWindow;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
-import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
 import com.oracle.graal.hotspot.meta.*;
@@ -250,9 +249,4 @@
         }
     }
 
-    @Override
-    public NativeFunctionInterface getNativeFunctionInterface() {
-        throw GraalInternalError.unimplemented("No NativeFunctionInterface of SPARC");
-    }
-
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java	Mon Aug 25 21:15:59 2014 -0700
@@ -30,11 +30,9 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.asm.sparc.SPARCAssembler.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.sparc.*;
-import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.lir.asm.*;
 
 /**
@@ -50,17 +48,14 @@
     @Alive(REG) AllocatableValue framePc;
     @Alive(REG) AllocatableValue senderSp;
     @Temp(REG) AllocatableValue scratch;
-    private SaveRegistersOp saveRegisterOp;
 
-    SPARCHotSpotEnterUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue scratch,
-                    SaveRegistersOp saveRegisterOp) {
+    SPARCHotSpotEnterUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue scratch) {
         this.thread = thread;
         this.threadLastJavaSpOffset = threadLastJavaSpOffset;
         this.threadLastJavaPcOffset = threadLastJavaPcOffset;
         this.framePc = framePc;
         this.senderSp = senderSp;
         this.scratch = scratch;
-        this.saveRegisterOp = saveRegisterOp;
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Mon Aug 25 21:15:59 2014 -0700
@@ -268,7 +268,7 @@
     }
 
     public void emitLeaveCurrentStackFrame(SaveRegistersOp saveRegisterOp) {
-        append(new SPARCHotSpotLeaveCurrentStackFrameOp(saveRegisterOp));
+        append(new SPARCHotSpotLeaveCurrentStackFrameOp());
     }
 
     public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) {
@@ -280,13 +280,12 @@
         Variable framePcVariable = load(framePc);
         Variable senderSpVariable = load(senderSp);
         Variable scratchVariable = newVariable(LIRKind.value(getHostWordKind()));
-        append(new SPARCHotSpotEnterUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), framePcVariable, senderSpVariable, scratchVariable,
-                        saveRegisterOp));
+        append(new SPARCHotSpotEnterUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), framePcVariable, senderSpVariable, scratchVariable));
     }
 
     public void emitLeaveUnpackFramesStackFrame(SaveRegistersOp saveRegisterOp) {
         Register thread = getProviders().getRegisters().getThreadRegister();
-        append(new SPARCHotSpotLeaveUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), saveRegisterOp));
+        append(new SPARCHotSpotLeaveUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset()));
     }
 
     public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) {
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveCurrentStackFrameOp.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveCurrentStackFrameOp.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,16 +24,11 @@
 
 import static com.oracle.graal.sparc.SPARC.*;
 
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Lddf;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.sparc.*;
-import com.oracle.graal.sparc.*;
 
 /**
  * Pops the current frame off the stack.
@@ -41,10 +36,7 @@
 @Opcode("LEAVE_CURRENT_STACK_FRAME")
 final class SPARCHotSpotLeaveCurrentStackFrameOp extends SPARCLIRInstruction {
 
-    private final SaveRegistersOp saveRegisterOp;
-
-    public SPARCHotSpotLeaveCurrentStackFrameOp(SaveRegistersOp saveRegisterOp) {
-        this.saveRegisterOp = saveRegisterOp;
+    public SPARCHotSpotLeaveCurrentStackFrameOp() {
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,18 +24,13 @@
 
 import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
 import static com.oracle.graal.sparc.SPARC.*;
-import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.sparc.*;
-import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.sparc.*;
 
 /**
  * Emits code that leaves a stack frame which is tailored to call the C++ method
@@ -49,14 +44,11 @@
     private final int threadLastJavaPcOffset;
     private final int threadJavaFrameAnchorFlagsOffset;
 
-    private final SaveRegistersOp saveRegisterOp;
-
-    SPARCHotSpotLeaveUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadJavaFrameAnchorFlagsOffset, SaveRegistersOp saveRegisterOp) {
+    SPARCHotSpotLeaveUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadJavaFrameAnchorFlagsOffset) {
         this.thread = thread;
         this.threadLastJavaSpOffset = threadLastJavaSpOffset;
         this.threadLastJavaPcOffset = threadLastJavaPcOffset;
         this.threadJavaFrameAnchorFlagsOffset = threadJavaFrameAnchorFlagsOffset;
-        this.saveRegisterOp = saveRegisterOp;
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -197,7 +197,7 @@
     }
 
     private StructuredGraph compile(String test, boolean compileAOT) {
-        StructuredGraph graph = parse(test);
+        StructuredGraph graph = parseEager(test);
         ResolvedJavaMethod method = graph.method();
 
         try (OverrideScope s = OptionValue.override(ImmutableCode, compileAOT)) {
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/BytecodeVerificationTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-/*
- * Copyright (c) 2014, 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.test;
-
-import java.io.*;
-
-import jdk.internal.org.objectweb.asm.*;
-
-import org.junit.*;
-
-import com.oracle.graal.compiler.test.*;
-
-/**
- * Tests that the Graal API can only be used to access verified bytecode.
- */
-public class BytecodeVerificationTest extends GraalCompilerTest {
-
-    @Test(expected = VerifyError.class)
-    public void test() throws Exception {
-        BadClassLoader loader = new BadClassLoader();
-        String className = BytecodeVerificationTest.class.getName() + "$BadClass";
-        Class<?> c = loader.findClass(className);
-
-        // Should fail with a verification error as long as -XX:-BytecodeVerificationRemote is not
-        // specified on the command line
-        getMetaAccess().lookupJavaMethod(c.getDeclaredMethod("getValue")).getCode();
-    }
-
-    /**
-     * Class that will be rewritten during loading to be unverifiable.
-     */
-    public static class BadClass {
-
-        public static String value;
-
-        public static String getValue() {
-            // Re-written to "return 5;"
-            return value;
-        }
-    }
-
-    /**
-     * Rewrites {@link BadClass#getValue()} to:
-     *
-     * <pre>
-     * public static String getValue() {
-     *     return 5;
-     * }
-     * </pre>
-     */
-    private static class BadClassRewriter extends ClassVisitor {
-
-        public BadClassRewriter(ClassWriter cw) {
-            super(Opcodes.ASM5, cw);
-        }
-
-        @Override
-        public MethodVisitor visitMethod(int access, String name, String d, String signature, String[] exceptions) {
-            MethodVisitor mv = super.visitMethod(access, name, d, signature, exceptions);
-            if (name.equals("getValue")) {
-                return new MethodVisitor(Opcodes.ASM5, mv) {
-                    @Override
-                    public void visitFieldInsn(int opcode, String owner, String fieldName, String fieldDesc) {
-                        if (opcode == Opcodes.GETSTATIC) {
-                            visitInsn(Opcodes.ICONST_5);
-                        } else {
-                            super.visitFieldInsn(opcode, owner, name, fieldDesc);
-                        }
-                    }
-                };
-            }
-            return mv;
-        }
-    }
-
-    /**
-     * Class loader used for loading {@link BadClass}. Using a separate class loader ensure the
-     * class is treated as "remote" so that it will be subject to verification by default.
-     */
-    private static class BadClassLoader extends ClassLoader {
-
-        @Override
-        protected Class<?> findClass(final String name) throws ClassNotFoundException {
-            byte[] classData = null;
-            try {
-                InputStream is = BytecodeVerificationTest.class.getResourceAsStream("/" + name.replace('.', '/') + ".class");
-                classData = new byte[is.available()];
-                new DataInputStream(is).readFully(classData);
-            } catch (IOException e) {
-                Assert.fail("can't access class: " + name);
-            }
-
-            ClassReader cr = new ClassReader(classData);
-            ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
-
-            BadClassRewriter rewriter = new BadClassRewriter(cw);
-            cr.accept(rewriter, ClassReader.SKIP_FRAMES);
-            classData = cw.toByteArray();
-            return defineClass(null, classData, 0, classData.length);
-        }
-    }
-}
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CRC32SubstitutionsTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CRC32SubstitutionsTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot.test;
 
 import java.io.*;
+import java.nio.*;
 import java.util.zip.*;
 
 import org.junit.*;
@@ -74,4 +75,26 @@
         }
     }
 
+    public static long updateByteBuffer(ByteBuffer buffer) {
+        CRC32 crc = new CRC32();
+        buffer.rewind();
+        crc.update(buffer);
+        return crc.getValue();
+    }
+
+    @Test
+    public void test4() throws Throwable {
+        String classfileName = CRC32SubstitutionsTest.class.getSimpleName().replace('.', '/') + ".class";
+        InputStream s = CRC32SubstitutionsTest.class.getResourceAsStream(classfileName);
+        byte[] buf = new byte[s.available()];
+        new DataInputStream(s).readFully(buf);
+
+        ByteBuffer directBuf = ByteBuffer.allocateDirect(buf.length);
+        directBuf.put(buf);
+        ByteBuffer heapBuf = ByteBuffer.wrap(buf);
+
+        test("updateByteBuffer", directBuf);
+        test("updateByteBuffer", heapBuf);
+    }
+
 }
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -50,7 +50,7 @@
     private HotSpotInstalledCode getInstalledCode(String name, Class<?>... parameterTypes) throws Exception {
         final Method method = CompressedOopTest.class.getMethod(name, parameterTypes);
         final HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(method);
-        final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(javaMethod, parse(method));
+        final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(javaMethod, parseEager(method));
         return installedBenchmarkCode;
     }
 
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/GraalClassLoaderTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2014, 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.test;
-
-import org.junit.*;
-
-import sun.management.*;
-
-import com.oracle.graal.api.runtime.*;
-import com.sun.management.*;
-
-/**
- * Tests that the Graal API is inaccessible when -XX:+UseGraalClassLoader is specified. Execute as
- * follows to show class loader based isolation:
- *
- * <pre>
- * mx unittest -XX:+UseGraalClassLoader GraalClassLoaderTest
- * </pre>
- */
-public class GraalClassLoaderTest {
-
-    @Test
-    public void test() throws Exception {
-        if (System.getProperty("java.vm.version").contains("graal")) {
-            HotSpotDiagnosticMXBean diag = ManagementFactoryHelper.getDiagnosticMXBean();
-            VMOption option = diag.getVMOption("UseGraalClassLoader");
-            if (option.getValue().equals("true")) {
-                try {
-                    Graal.getRuntime();
-                    Assert.fail();
-                } catch (NoClassDefFoundError e) {
-                    // expected
-                }
-            }
-        }
-    }
-
-}
\ No newline at end of file
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNmethodTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNmethodTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -37,7 +37,7 @@
     @Test
     public void testInstallCodeInvalidation() {
         final ResolvedJavaMethod testJavaMethod = getMetaAccess().lookupJavaMethod(getMethod("foo"));
-        final StructuredGraph graph = parse("otherFoo");
+        final StructuredGraph graph = parseEager("otherFoo");
         final HotSpotNmethod nmethod = (HotSpotNmethod) getCode(testJavaMethod, graph);
         Assert.assertTrue(nmethod.isValid());
         Object result;
@@ -61,7 +61,7 @@
     @Test
     public void testInstallCodeInvalidationWhileRunning() {
         final ResolvedJavaMethod testJavaMethod = getMetaAccess().lookupJavaMethod(getMethod("foo"));
-        final StructuredGraph graph = parse("otherFoo");
+        final StructuredGraph graph = parseEager("otherFoo");
         final HotSpotNmethod nmethod = (HotSpotNmethod) getCode(testJavaMethod, graph);
         Object result;
         try {
@@ -76,7 +76,7 @@
     @Test
     public void testInstalledCodeCalledFromCompiledCode() {
         final ResolvedJavaMethod testJavaMethod = getMetaAccess().lookupJavaMethod(getMethod("foo"));
-        final StructuredGraph graph = parse("otherFoo");
+        final StructuredGraph graph = parseEager("otherFoo");
         final HotSpotNmethod nmethod = (HotSpotNmethod) getCode(testJavaMethod, graph);
         Assert.assertTrue(nmethod.isValid());
         try {
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -50,13 +50,13 @@
     public void test1() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException {
         final Method fooMethod = InstalledCodeExecuteHelperTest.class.getMethod("foo");
         final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(fooMethod);
-        final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod));
+        final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parseEager(fooMethod));
 
         argsToBind = new Object[]{fooCode};
 
         final Method benchmarkMethod = InstalledCodeExecuteHelperTest.class.getMethod("benchmark", HotSpotInstalledCode.class);
         final ResolvedJavaMethod benchmarkJavaMethod = metaAccess.lookupJavaMethod(benchmarkMethod);
-        final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(benchmarkJavaMethod, parse(benchmarkMethod));
+        final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(benchmarkJavaMethod, parseEager(benchmarkMethod));
 
         Assert.assertEquals(Integer.valueOf(42), benchmark(fooCode));
 
@@ -79,8 +79,8 @@
     }
 
     @Override
-    protected StructuredGraph parse(Method m) {
-        StructuredGraph graph = super.parse(m);
+    protected StructuredGraph parseEager(Method m) {
+        StructuredGraph graph = super.parseEager(m);
         if (argsToBind != null) {
             Object receiver = isStatic(m.getModifiers()) ? null : this;
             Object[] args = argsWithReceiver(receiver, argsToBind);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/MemoryUsageBenchmark.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.test;
+
+import static com.oracle.graal.debug.internal.MemUseTrackerImpl.*;
+import static com.oracle.graal.hotspot.CompileTheWorld.*;
+import static com.oracle.graal.hotspot.CompileTheWorld.Options.*;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.nodes.StructuredGraph.*;
+
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.internal.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.CompileTheWorld.Config;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.printer.*;
+
+/**
+ * Used to benchmark memory usage during Graal compilation.
+ *
+ * To benchmark:
+ *
+ * <pre>
+ *     mx vm -XX:-UseGraalClassLoader -cp @com.oracle.graal.hotspot.test com.oracle.graal.hotspot.test.MemoryUsageBenchmark
+ * </pre>
+ *
+ * Memory analysis for a {@link CompileTheWorld} execution can also be performed. For example:
+ *
+ * <pre>
+ *     mx --vm server vm -XX:-UseGraalClassLoader -G:CompileTheWorldClasspath=$HOME/SPECjvm2008/SPECjvm2008.jar -cp @com.oracle.graal.hotspot.test com.oracle.graal.hotspot.test.MemoryUsageBenchmark
+ * </pre>
+ */
+public class MemoryUsageBenchmark extends GraalCompilerTest {
+
+    public static int simple(int a, int b) {
+        return a + b;
+    }
+
+    public static synchronized int complex(CharSequence cs) {
+        if (cs instanceof String) {
+            return cs.hashCode();
+        }
+
+        if (cs instanceof StringBuffer) {
+            int[] hash = {0};
+            cs.chars().forEach(c -> hash[0] += c);
+            return hash[0];
+        }
+
+        int res = 0;
+
+        // Exercise lock elimination
+        synchronized (cs) {
+            res = cs.length();
+        }
+        synchronized (cs) {
+            res = cs.hashCode() ^ 31;
+        }
+
+        for (int i = 0; i < cs.length(); i++) {
+            res *= cs.charAt(i);
+        }
+
+        // A fixed length loop with some canonicalizable arithmetics will
+        // activate loop unrolling and more canonicalization
+        int sum = 0;
+        for (int i = 0; i < 5; i++) {
+            sum += i * 2;
+        }
+        res += sum;
+
+        // Activates escape-analysis
+        res += new String("asdf").length();
+
+        return res;
+    }
+
+    static class MemoryUsageCloseable implements AutoCloseable {
+
+        private final long start;
+        private final String name;
+
+        public MemoryUsageCloseable(String name) {
+            this.name = name;
+            this.start = getCurrentThreadAllocatedBytes();
+        }
+
+        @Override
+        public void close() {
+            long end = getCurrentThreadAllocatedBytes();
+            long allocated = end - start;
+            System.out.println(name + ": " + allocated);
+        }
+    }
+
+    public static void main(String[] args) {
+        // Ensure a Graal runtime is initialized prior to Debug being initialized as the former
+        // may include processing command line options used by the latter.
+        Graal.getRuntime();
+
+        // Ensure a debug configuration for this thread is initialized
+        if (Debug.isEnabled() && DebugScope.getConfig() == null) {
+            DebugEnvironment.initialize(System.out);
+        }
+        new MemoryUsageBenchmark().run();
+    }
+
+    private void doCompilation(String methodName, String label) {
+        HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) getMetaAccess().lookupJavaMethod(getMethod(methodName));
+        HotSpotBackend backend = runtime().getHostBackend();
+
+        // invalidate any existing compiled code
+        method.reprofile();
+
+        int id = method.allocateCompileId(INVOCATION_ENTRY_BCI);
+        long ctask = 0L;
+
+        try (MemoryUsageCloseable c = label == null ? null : new MemoryUsageCloseable(label)) {
+            CompilationTask task = new CompilationTask(backend, method, INVOCATION_ENTRY_BCI, ctask, id);
+            task.runCompilation();
+        }
+    }
+
+    private void allocSpyCompilation(String methodName) {
+        if (AllocSpy.isEnabled()) {
+            HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) getMetaAccess().lookupJavaMethod(getMethod(methodName));
+            HotSpotBackend backend = runtime().getHostBackend();
+
+            // invalidate any existing compiled code
+            method.reprofile();
+
+            int id = method.allocateCompileId(INVOCATION_ENTRY_BCI);
+            long ctask = 0L;
+            try (AllocSpy as = AllocSpy.open(methodName)) {
+                CompilationTask task = new CompilationTask(backend, method, INVOCATION_ENTRY_BCI, ctask, id);
+                task.runCompilation();
+            }
+        }
+    }
+
+    private static final boolean verbose = Boolean.getBoolean("verbose");
+
+    private void compileAndTime(String methodName) {
+
+        // Parse in eager mode to resolve methods/fields/classes
+        parseEager(methodName);
+
+        // Warm up and initialize compiler phases used by this compilation
+        for (int i = 0; i < 10; i++) {
+            doCompilation(methodName, verbose ? methodName + "[warmup-" + i + "]" : null);
+        }
+
+        doCompilation(methodName, methodName);
+    }
+
+    public void run() {
+        compileAndTime("simple");
+        compileAndTime("complex");
+        if (CompileTheWorldClasspath.getValue() != SUN_BOOT_CLASS_PATH) {
+            CompileTheWorld ctw = new CompileTheWorld(CompileTheWorldClasspath.getValue(), new Config(CompileTheWorldConfig.getValue()), CompileTheWorldStartAt.getValue(),
+                            CompileTheWorldStopAt.getValue(), CompileTheWorldVerbose.getValue());
+            try {
+                ctw.compile();
+            } catch (Throwable e) {
+                e.printStackTrace();
+            }
+        }
+        allocSpyCompilation("simple");
+        allocSpyCompilation("complex");
+    }
+}
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -244,13 +244,13 @@
     private HotSpotInstalledCode getInstalledCode(String name) throws Exception {
         final Method method = WriteBarrierAdditionTest.class.getMethod(name, Object.class, Object.class, Object.class);
         final HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(method);
-        final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(javaMethod, parse(method));
+        final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(javaMethod, parseEager(method));
         return installedBenchmarkCode;
     }
 
     private void test(final String snippet, final int expectedBarriers) throws Exception, SecurityException {
         try (Scope s = Debug.scope("WriteBarrierAdditionTest", new DebugDumpScope(snippet))) {
-            StructuredGraph graph = parse(snippet);
+            StructuredGraph graph = parseEager(snippet);
             HighTierContext highContext = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
             MidTierContext midContext = new MidTierContext(getProviders(), new Assumptions(false), getCodeCache().getTarget(), OptimisticOptimizations.ALL, graph.method().getProfilingInfo(), null);
             new InliningPhase(new InlineEverythingPolicy(), new CanonicalizerPhase(true)).apply(graph, highContext);
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -613,7 +613,7 @@
 
     private void test(final String snippet, final int expectedBarriers, final int... removedBarrierIndices) {
         try (Scope d = Debug.scope("WriteBarrierVerificationTest", new DebugDumpScope(snippet))) {
-            final StructuredGraph graph = parse(snippet);
+            final StructuredGraph graph = parseEager(snippet);
             HighTierContext highTierContext = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
             new InliningPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Mon Aug 25 21:15:59 2014 -0700
@@ -52,7 +52,7 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.phases.*;
 import com.oracle.graal.java.*;
-import com.oracle.graal.java.GraphBuilderConfiguration.*;
+import com.oracle.graal.java.GraphBuilderConfiguration.DebugInfoMode;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot;
 
 import static com.oracle.graal.compiler.common.GraalOptions.*;
+import static com.oracle.graal.debug.internal.MemUseTrackerImpl.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.nodes.StructuredGraph.*;
 
@@ -41,7 +42,6 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.options.OptionValue.OverrideScope;
-import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.replacements.*;
 
 /**
@@ -158,6 +158,7 @@
     private int classFileCounter = 0;
     private int compiledMethodsCounter = 0;
     private long compileTime = 0;
+    private long memoryUsed = 0;
 
     private boolean verbose;
     private final Config config;
@@ -235,83 +236,85 @@
     private void compile(String fileList) throws Throwable {
         final String[] entries = fileList.split(File.pathSeparator);
 
-        for (int i = 0; i < entries.length; i++) {
-            final String entry = entries[i];
-
-            // For now we only compile all methods in all classes in zip/jar files.
-            if (!entry.endsWith(".zip") && !entry.endsWith(".jar")) {
-                println("CompileTheWorld : Skipped classes in " + entry);
-                println();
-                continue;
-            }
+        try (AutoCloseable s = config.apply()) {
+            for (int i = 0; i < entries.length; i++) {
+                final String entry = entries[i];
 
-            println("CompileTheWorld : Compiling all classes in " + entry);
-            println();
-
-            URL url = new URL("jar", "", "file:" + entry + "!/");
-            ClassLoader loader = new URLClassLoader(new URL[]{url});
-
-            JarFile jarFile = new JarFile(entry);
-            Enumeration<JarEntry> e = jarFile.entries();
-
-            while (e.hasMoreElements()) {
-                JarEntry je = e.nextElement();
-                if (je.isDirectory() || !je.getName().endsWith(".class")) {
+                // For now we only compile all methods in all classes in zip/jar files.
+                if (!entry.endsWith(".zip") && !entry.endsWith(".jar")) {
+                    println("CompileTheWorld : Skipped classes in " + entry);
+                    println();
                     continue;
                 }
 
-                // Are we done?
-                if (classFileCounter >= stopAt) {
-                    break;
-                }
+                println("CompileTheWorld : Compiling all classes in " + entry);
+                println();
 
-                String className = je.getName().substring(0, je.getName().length() - ".class".length());
-                classFileCounter++;
+                URL url = new URL("jar", "", "file:" + entry + "!/");
+                ClassLoader loader = new URLClassLoader(new URL[]{url});
+
+                JarFile jarFile = new JarFile(entry);
+                Enumeration<JarEntry> e = jarFile.entries();
 
-                try (AutoCloseable s = config.apply()) {
-                    // Load and initialize class
-                    Class<?> javaClass = Class.forName(className.replace('/', '.'), true, loader);
+                while (e.hasMoreElements()) {
+                    JarEntry je = e.nextElement();
+                    if (je.isDirectory() || !je.getName().endsWith(".class")) {
+                        continue;
+                    }
 
-                    // Pre-load all classes in the constant pool.
-                    try {
-                        HotSpotResolvedObjectType objectType = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(javaClass);
-                        ConstantPool constantPool = objectType.constantPool();
-                        for (int cpi = 1; cpi < constantPool.length(); cpi++) {
-                            constantPool.loadReferencedType(cpi, Bytecodes.LDC);
-                        }
-                    } catch (Throwable t) {
-                        // If something went wrong during pre-loading we just ignore it.
-                        println("Preloading failed for (%d) %s", classFileCounter, className);
+                    // Are we done?
+                    if (classFileCounter >= stopAt) {
+                        break;
                     }
 
-                    // Are we compiling this class?
-                    HotSpotMetaAccessProvider metaAccess = runtime.getHostProviders().getMetaAccess();
-                    if (classFileCounter >= startAt) {
-                        println("CompileTheWorld (%d) : %s", classFileCounter, className);
+                    String className = je.getName().substring(0, je.getName().length() - ".class".length());
+                    classFileCounter++;
+
+                    try {
+                        // Load and initialize class
+                        Class<?> javaClass = Class.forName(className.replace('/', '.'), true, loader);
 
-                        // Compile each constructor/method in the class.
-                        for (Constructor<?> constructor : javaClass.getDeclaredConstructors()) {
-                            HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaConstructor(constructor);
-                            if (canBeCompiled(javaMethod, constructor.getModifiers())) {
-                                compileMethod(javaMethod);
+                        // Pre-load all classes in the constant pool.
+                        try {
+                            HotSpotResolvedObjectType objectType = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(javaClass);
+                            ConstantPool constantPool = objectType.constantPool();
+                            for (int cpi = 1; cpi < constantPool.length(); cpi++) {
+                                constantPool.loadReferencedType(cpi, Bytecodes.LDC);
+                            }
+                        } catch (Throwable t) {
+                            // If something went wrong during pre-loading we just ignore it.
+                            println("Preloading failed for (%d) %s", classFileCounter, className);
+                        }
+
+                        // Are we compiling this class?
+                        HotSpotMetaAccessProvider metaAccess = runtime.getHostProviders().getMetaAccess();
+                        if (classFileCounter >= startAt) {
+                            println("CompileTheWorld (%d) : %s", classFileCounter, className);
+
+                            // Compile each constructor/method in the class.
+                            for (Constructor<?> constructor : javaClass.getDeclaredConstructors()) {
+                                HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaConstructor(constructor);
+                                if (canBeCompiled(javaMethod, constructor.getModifiers())) {
+                                    compileMethod(javaMethod);
+                                }
+                            }
+                            for (Method method : javaClass.getDeclaredMethods()) {
+                                HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(method);
+                                if (canBeCompiled(javaMethod, method.getModifiers())) {
+                                    compileMethod(javaMethod);
+                                }
                             }
                         }
-                        for (Method method : javaClass.getDeclaredMethods()) {
-                            HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(method);
-                            if (canBeCompiled(javaMethod, method.getModifiers())) {
-                                compileMethod(javaMethod);
-                            }
-                        }
+                    } catch (Throwable t) {
+                        println("CompileTheWorld (%d) : Skipping %s", classFileCounter, className);
                     }
-                } catch (Throwable t) {
-                    println("CompileTheWorld (%d) : Skipping %s", classFileCounter, className);
                 }
+                jarFile.close();
             }
-            jarFile.close();
         }
 
         println();
-        println("CompileTheWorld : Done (%d classes, %d methods, %d ms)", classFileCounter, compiledMethodsCounter, compileTime);
+        println("CompileTheWorld : Done (%d classes, %d methods, %d ms, %d bytes of memory used)", classFileCounter, compiledMethodsCounter, compileTime, memoryUsed);
     }
 
     class CTWCompilationTask extends CompilationTask {
@@ -321,16 +324,6 @@
         }
 
         /**
-         * Returns a fresh compilation suite for its compilation so that the CTW option value
-         * overriding configuration has effect.
-         */
-        @Override
-        protected Suites getSuites(HotSpotProviders providers) {
-            assert config.scope != null : "not inside a CTW option value overriding scope";
-            return providers.getSuites().createSuites();
-        }
-
-        /**
          * Returns empty profiling info to be as close to the CTW behavior of C1 and C2 as possible.
          */
         @Override
@@ -346,11 +339,13 @@
     private void compileMethod(HotSpotResolvedJavaMethod method) {
         try {
             long start = System.currentTimeMillis();
+            long allocatedAtStart = getCurrentThreadAllocatedBytes();
 
             HotSpotBackend backend = runtime.getHostBackend();
             CompilationTask task = new CTWCompilationTask(backend, method);
             task.runCompilation();
 
+            memoryUsed += getCurrentThreadAllocatedBytes() - allocatedAtStart;
             compileTime += (System.currentTimeMillis() - start);
             compiledMethodsCounter++;
             method.reprofile();  // makes the method also not-entrant
@@ -374,6 +369,10 @@
         if (c.dontCompileHugeMethods && javaMethod.getCodeSize() > c.hugeMethodLimit) {
             return false;
         }
+        // Allow use of -XX:CompileCommand=dontinline to exclude problematic methods
+        if (!javaMethod.canBeInlined()) {
+            return false;
+        }
         // Skip @Snippets for now
         if (javaMethod.getAnnotation(Snippet.class) != null) {
             return false;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/DebugValuesPrinter.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/DebugValuesPrinter.java	Mon Aug 25 21:15:59 2014 -0700
@@ -38,7 +38,7 @@
 public class DebugValuesPrinter {
 
     public void printDebugValues(String phase, boolean reset) throws GraalInternalError {
-        if (Debug.isEnabled() && areMetricsOrTimersEnabled()) {
+        if (Debug.areUnconditionalMetricsEnabled() || Debug.areUnconditionalTimersEnabled() || (Debug.isEnabled() && areMetricsOrTimersEnabled())) {
             TTY.println();
             if (phase != null) {
                 TTY.println("<DebugValues:" + phase + ">");
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Mon Aug 25 21:15:59 2014 -0700
@@ -36,7 +36,6 @@
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 import com.oracle.graal.lir.StandardOp.LabelOp;
 import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
 import com.oracle.graal.nodes.*;
@@ -152,15 +151,14 @@
      */
     protected static Set<Register> gatherDefinedRegisters(LIR lir) {
         final Set<Register> definedRegisters = new HashSet<>();
-        ValueProcedure defProc = new ValueProcedure() {
+        ValueConsumer defConsumer = new ValueConsumer() {
 
             @Override
-            public Value doValue(Value value) {
+            public void visitValue(Value value) {
                 if (ValueUtil.isRegister(value)) {
                     final Register reg = ValueUtil.asRegister(value);
                     definedRegisters.add(reg);
                 }
-                return value;
             }
         };
         for (AbstractBlock<?> block : lir.codeEmittingOrder()) {
@@ -168,8 +166,8 @@
                 if (op instanceof LabelOp) {
                     // Don't consider this as a definition
                 } else {
-                    op.forEachTemp(defProc);
-                    op.forEachOutput(defProc);
+                    op.visitEachTemp(defConsumer);
+                    op.visitEachOutput(defConsumer);
                 }
             }
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,7 +27,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.hotspot.meta.*;
@@ -37,7 +36,7 @@
 /**
  * Common functionality of HotSpot host backends.
  */
-public abstract class HotSpotHostBackend extends HotSpotBackend implements HostBackend {
+public abstract class HotSpotHostBackend extends HotSpotBackend {
 
     /**
      * Descriptor for {@link DeoptimizationStub#deoptimizationHandler}.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,7 +26,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 
 /**
@@ -39,11 +38,11 @@
     }
 
     @Override
-    protected Value processValue(LIRInstruction inst, InstructionValueProcedure proc, Value value) {
+    protected Value processValue(LIRInstruction inst, InstructionValueProcedureBase proc, Value value) {
         if (value instanceof HotSpotMonitorValue) {
             HotSpotMonitorValue monitor = (HotSpotMonitorValue) value;
             if (processed(monitor.getOwner())) {
-                monitor.setOwner(proc.doValue(inst, monitor.getOwner(), OperandMode.ALIVE, STATE_FLAGS));
+                monitor.setOwner(proc.processValue(inst, monitor.getOwner(), OperandMode.ALIVE, STATE_FLAGS));
             }
             return value;
         } else {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptionsLoader.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptionsLoader.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.options.*;
 
 /**
@@ -36,8 +37,7 @@
      * Initializes {@link #options} from {@link Options} services.
      */
     static {
-        ServiceLoader<Options> sl = ServiceLoader.load(Options.class);
-        for (Options opts : sl) {
+        for (Options opts : Services.load(Options.class)) {
             for (OptionDescriptor desc : opts) {
                 if (isHotSpotOption(desc)) {
                     String name = desc.getName();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Mon Aug 25 21:15:59 2014 -0700
@@ -1052,8 +1052,8 @@
     @HotSpotVMField(name = "HSAILTlabInfo::_end", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailTlabInfoEndOffset;
     @HotSpotVMField(name = "HSAILTlabInfo::_last_good_top", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailTlabInfoLastGoodTopOffset;
     @HotSpotVMField(name = "HSAILTlabInfo::_original_top", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailTlabInfoOriginalTopOffset;
-    @HotSpotVMField(name = "HSAILTlabInfo::_donor_thread", type = "JavaThread*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailTlabInfoDonorThreadOffset;
     @HotSpotVMField(name = "HSAILTlabInfo::_alloc_info", type = "HSAILAllocationInfo*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailTlabInfoAllocInfoOffset;
+    @HotSpotVMField(name = "HSAILTlabInfo::_tlab", type = "ThreadLocalAllocBuffer*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailTlabInfoTlabOffset;
     @HotSpotVMType(name = "HSAILTlabInfo", get = HotSpotVMType.Type.SIZE) @Stable public int hsailTlabInfoSize;
 
     /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Mon Aug 25 21:15:59 2014 -0700
@@ -377,18 +377,18 @@
     public static void lower(DynamicCounterNode counter, HotSpotRegistersProvider registers, HotSpotVMConfig config, Kind wordKind) {
         StructuredGraph graph = counter.graph();
 
-        ReadRegisterNode thread = graph.add(new ReadRegisterNode(registers.getThreadRegister(), wordKind, true, false));
+        ReadRegisterNode thread = graph.add(ReadRegisterNode.create(registers.getThreadRegister(), wordKind, true, false));
 
         int index = BenchmarkCounters.getIndex(counter);
         if (index >= config.graalCountersSize) {
             throw new GraalInternalError("too many counters, reduce number of counters or increase -XX:GraalCounterSize=... (current value: " + config.graalCountersSize + ")");
         }
         ConstantLocationNode arrayLocation = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, wordKind, config.graalCountersThreadOffset, graph);
-        ReadNode readArray = graph.add(new ReadNode(thread, arrayLocation, StampFactory.forKind(wordKind), BarrierType.NONE));
+        ReadNode readArray = graph.add(ReadNode.create(thread, arrayLocation, StampFactory.forKind(wordKind), BarrierType.NONE));
         ConstantLocationNode location = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, Kind.Long, Unsafe.ARRAY_LONG_INDEX_SCALE * index, graph);
-        ReadNode read = graph.add(new ReadNode(readArray, location, StampFactory.forKind(Kind.Long), BarrierType.NONE));
-        IntegerAddNode add = graph.unique(new IntegerAddNode(read, counter.getIncrement()));
-        WriteNode write = graph.add(new WriteNode(readArray, add, location, BarrierType.NONE));
+        ReadNode read = graph.add(ReadNode.create(readArray, location, StampFactory.forKind(Kind.Long), BarrierType.NONE));
+        IntegerAddNode add = graph.unique(IntegerAddNode.create(read, counter.getIncrement()));
+        WriteNode write = graph.add(WriteNode.create(readArray, add, location, BarrierType.NONE));
 
         graph.addBeforeFixed(counter, thread);
         graph.addBeforeFixed(counter, readArray);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Mon Aug 25 21:15:59 2014 -0700
@@ -198,10 +198,10 @@
                     // We use LocationNode.ANY_LOCATION for the reads that access the
                     // compiled code entry as HotSpot does not guarantee they are final
                     // values.
-                    ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, ConstantLocationNode.create(ANY_LOCATION, wordKind, runtime.getConfig().methodCompiledEntryOffset, graph),
+                    ReadNode compiledEntry = graph.add(ReadNode.create(metaspaceMethod, ConstantLocationNode.create(ANY_LOCATION, wordKind, runtime.getConfig().methodCompiledEntryOffset, graph),
                                     StampFactory.forKind(wordKind), BarrierType.NONE));
 
-                    loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(),
+                    loweredCallTarget = graph.add(HotSpotIndirectCallTargetNode.create(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(),
                                     CallingConvention.Type.JavaCall, callTarget.invokeKind()));
 
                     graph.addBeforeFixed(invoke.asNode(), metaspaceMethod);
@@ -210,7 +210,7 @@
             }
 
             if (loweredCallTarget == null) {
-                loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall,
+                loweredCallTarget = graph.add(HotSpotDirectCallTargetNode.create(parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall,
                                 callTarget.invokeKind()));
             }
             callTarget.replaceAndDelete(loweredCallTarget);
@@ -255,7 +255,7 @@
          * Anchor the read of the element klass to the cfg, because it is only valid when arrayClass
          * is an object class, which might not be the case in other parts of the compiled method.
          */
-        return graph.unique(new FloatingReadNode(arrayHub, location, null, StampFactory.forKind(wordKind), BeginNode.prevBegin(anchor)));
+        return graph.unique(FloatingReadNode.create(arrayHub, location, null, StampFactory.forKind(wordKind), BeginNode.prevBegin(anchor)));
     }
 
     @Override
@@ -293,9 +293,9 @@
     private void lowerOSRStartNode(OSRStartNode osrStart) {
         StructuredGraph graph = osrStart.graph();
         if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
-            StartNode newStart = graph.add(new StartNode());
-            ParameterNode buffer = graph.unique(new ParameterNode(0, StampFactory.forKind(runtime.getTarget().wordKind)));
-            ForeignCallNode migrationEnd = graph.add(new ForeignCallNode(foreignCalls, OSR_MIGRATION_END, buffer));
+            StartNode newStart = graph.add(StartNode.create());
+            ParameterNode buffer = graph.unique(ParameterNode.create(0, StampFactory.forKind(runtime.getTarget().wordKind)));
+            ForeignCallNode migrationEnd = graph.add(ForeignCallNode.create(foreignCalls, OSR_MIGRATION_END, buffer));
             migrationEnd.setStateAfter(osrStart.stateAfter());
 
             newStart.setNext(migrationEnd);
@@ -310,7 +310,7 @@
                 int size = HIRFrameStateBuilder.stackSlots(osrLocal.getKind());
                 int offset = localsOffset - (osrLocal.index() + size - 1) * 8;
                 IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, osrLocal.getKind(), offset, ConstantNode.forLong(0, graph), graph, 1);
-                ReadNode load = graph.add(new ReadNode(buffer, location, osrLocal.stamp(), BarrierType.NONE));
+                ReadNode load = graph.add(ReadNode.create(buffer, location, osrLocal.stamp(), BarrierType.NONE));
                 osrLocal.replaceAndDelete(load);
                 graph.addBeforeFixed(migrationEnd, load);
             }
@@ -368,7 +368,7 @@
                     throw GraalInternalError.shouldNotReachHere();
                 }
 
-                ForeignCallNode foreignCallNode = graph.add(new ForeignCallNode(foreignCalls, descriptor, node.stamp(), node.getArguments()));
+                ForeignCallNode foreignCallNode = graph.add(ForeignCallNode.create(foreignCalls, descriptor, node.stamp(), node.getArguments()));
                 graph.replaceFixedWithFixed(node, foreignCallNode);
             }
         }
@@ -393,7 +393,7 @@
         assert vtableEntryOffset > 0;
         // We use LocationNode.ANY_LOCATION for the reads that access the vtable
         // entry as HotSpot does not guarantee that this is a final value.
-        ReadNode metaspaceMethod = graph.add(new ReadNode(hub, ConstantLocationNode.create(ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind), BarrierType.NONE));
+        ReadNode metaspaceMethod = graph.add(ReadNode.create(hub, ConstantLocationNode.create(ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind), BarrierType.NONE));
         return metaspaceMethod;
     }
 
@@ -411,7 +411,7 @@
             hubStamp = StampFactory.forKind(wordKind);
         }
 
-        FloatingReadNode memoryRead = graph.unique(new FloatingReadNode(object, location, null, hubStamp, guard, BarrierType.NONE));
+        FloatingReadNode memoryRead = graph.unique(FloatingReadNode.create(object, location, null, hubStamp, guard, BarrierType.NONE));
         if (config.useCompressedClassPointers) {
             return CompressionNode.uncompress(memoryRead, config.getKlassEncoding());
         } else {
@@ -429,7 +429,7 @@
             writeValue = CompressionNode.compress(value, config.getKlassEncoding());
         }
 
-        return graph.add(new WriteNode(object, writeValue, location, BarrierType.NONE));
+        return graph.add(WriteNode.create(object, writeValue, location, BarrierType.NONE));
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java	Mon Aug 25 21:15:59 2014 -0700
@@ -159,8 +159,8 @@
         linkForeignCall(providers, DYNAMIC_NEW_ARRAY, c.dynamicNewArrayAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, INIT_LOCATION);
         linkForeignCall(providers, DYNAMIC_NEW_INSTANCE, c.dynamicNewInstanceAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, INIT_LOCATION);
         linkForeignCall(providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
-        linkForeignCall(providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS);
-        linkForeignCall(providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
         linkForeignCall(providers, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
         linkForeignCall(providers, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
         linkForeignCall(providers, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF_NOFP, NOT_REEXECUTABLE, NO_LOCATIONS);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,6 +27,7 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.phases.*;
 import com.oracle.graal.java.*;
+import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.tiers.*;
 
@@ -35,18 +36,18 @@
  */
 public class HotSpotSuitesProvider implements SuitesProvider {
 
-    protected final Suites defaultSuites;
+    protected final DerivedOptionValue<Suites> defaultSuites;
     protected final PhaseSuite<HighTierContext> defaultGraphBuilderSuite;
     protected final HotSpotGraalRuntime runtime;
 
     public HotSpotSuitesProvider(HotSpotGraalRuntime runtime) {
         this.runtime = runtime;
         this.defaultGraphBuilderSuite = createGraphBuilderSuite();
-        defaultSuites = createSuites();
+        this.defaultSuites = new DerivedOptionValue<>(this::createSuites);
     }
 
     public Suites getDefaultSuites() {
-        return defaultSuites;
+        return defaultSuites.getValue();
     }
 
     public PhaseSuite<HighTierContext> getDefaultGraphBuilderSuite() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionHandle.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionHandle.java	Mon Aug 25 21:15:59 2014 -0700
@@ -29,6 +29,7 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
+import com.oracle.nfi.api.*;
 
 public class HotSpotNativeFunctionHandle implements NativeFunctionHandle {
 
@@ -87,10 +88,6 @@
         return true;
     }
 
-    public InstalledCode getCallStub() {
-        return code;
-    }
-
     @Override
     public String toString() {
         return name + Arrays.toString(argumentTypes);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java	Mon Aug 25 21:15:59 2014 -0700
@@ -40,6 +40,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.tiers.*;
+import com.oracle.nfi.api.*;
 
 public class HotSpotNativeFunctionInterface implements NativeFunctionInterface {
 
@@ -87,7 +88,7 @@
 
     @Override
     public HotSpotNativeFunctionHandle getFunctionHandle(NativeLibraryHandle library, String name, Class<?> returnType, Class<?>... argumentTypes) {
-        HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(name, library, true);
+        HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(name, library, false);
         return createHandle(functionPointer, returnType, argumentTypes);
     }
 
@@ -178,7 +179,7 @@
         if (rtldDefault == null) {
             throw new UnsatisfiedLinkError(name);
         }
-        return lookupFunctionPointer(name, rtldDefault, true);
+        return lookupFunctionPointer(name, rtldDefault, false);
     }
 
     public boolean isDefaultLibrarySearchSupported() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionPointer.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionPointer.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.nfi;
 
-import com.oracle.graal.api.code.*;
+import com.oracle.nfi.api.*;
 
 public class HotSpotNativeFunctionPointer implements NativeFunctionPointer {
 
@@ -41,7 +41,7 @@
         return name;
     }
 
-    public long getValue() {
+    public long getRawValue() {
         return value;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeLibraryHandle.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeLibraryHandle.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.nfi;
 
-import com.oracle.graal.api.code.*;
+import com.oracle.nfi.api.*;
 
 public class HotSpotNativeLibraryHandle implements NativeLibraryHandle {
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java	Mon Aug 25 21:15:59 2014 -0700
@@ -53,10 +53,10 @@
         try {
             ResolvedJavaMethod method = providers.getMetaAccess().lookupJavaMethod(NativeCallStubGraphBuilder.class.getMethod("libCall", Object.class, Object.class, Object.class));
             StructuredGraph g = new StructuredGraph(method);
-            ParameterNode arg0 = g.unique(new ParameterNode(0, StampFactory.forKind(Kind.Object)));
-            ParameterNode arg1 = g.unique(new ParameterNode(1, StampFactory.forKind(Kind.Object)));
-            ParameterNode arg2 = g.unique(new ParameterNode(2, StampFactory.forKind(Kind.Object)));
-            FrameState frameState = g.add(new FrameState(null, method, 0, Arrays.asList(new ValueNode[]{arg0, arg1, arg2}), 3, 0, false, false, new ArrayList<MonitorIdNode>(),
+            ParameterNode arg0 = g.unique(ParameterNode.create(0, StampFactory.forKind(Kind.Object)));
+            ParameterNode arg1 = g.unique(ParameterNode.create(1, StampFactory.forKind(Kind.Object)));
+            ParameterNode arg2 = g.unique(ParameterNode.create(2, StampFactory.forKind(Kind.Object)));
+            FrameState frameState = g.add(FrameState.create(null, method, 0, Arrays.asList(new ValueNode[]{arg0, arg1, arg2}), 3, 0, false, false, new ArrayList<MonitorIdNode>(),
                             new ArrayList<EscapeObjectState>()));
             g.start().setStateAfter(frameState);
             List<ValueNode> parameters = new ArrayList<>();
@@ -84,12 +84,12 @@
                     throw new IllegalArgumentException("Return type not supported: " + returnType.getName());
                 }
                 ResolvedJavaType type = providers.getMetaAccess().lookupJavaType(callNode.getKind().toBoxedJavaClass());
-                boxedResult = g.unique(new BoxNode(callNode, type, callNode.getKind()));
+                boxedResult = g.unique(BoxNode.create(callNode, type, callNode.getKind()));
             } else {
-                boxedResult = g.unique(new BoxNode(ConstantNode.forLong(0, g), providers.getMetaAccess().lookupJavaType(Long.class), Kind.Long));
+                boxedResult = g.unique(BoxNode.create(ConstantNode.forLong(0, g), providers.getMetaAccess().lookupJavaType(Long.class), Kind.Long));
             }
 
-            ReturnNode returnNode = g.add(new ReturnNode(boxedResult));
+            ReturnNode returnNode = g.add(ReturnNode.create(boxedResult));
             callNode.setNext(returnNode);
             (new WordTypeRewriterPhase(providers.getMetaAccess(), providers.getSnippetReflection(), Kind.Long)).apply(g);
             return g;
@@ -103,7 +103,7 @@
         FixedWithNextNode last = null;
         for (int i = 0; i < numArgs; i++) {
             // load boxed array element:
-            LoadIndexedNode boxedElement = g.add(new LoadIndexedNode(argumentsArray, ConstantNode.forInt(i, g), Kind.Object));
+            LoadIndexedNode boxedElement = g.add(LoadIndexedNode.create(argumentsArray, ConstantNode.forInt(i, g), Kind.Object));
             if (i == 0) {
                 g.start().setNext(boxedElement);
                 last = boxedElement;
@@ -122,13 +122,13 @@
                 int indexScaling = getArrayIndexScale(arrayElementKind);
                 IndexedLocationNode locationNode = IndexedLocationNode.create(locationIdentity, arrayElementKind, displacement, index, g, indexScaling);
                 Stamp wordStamp = StampFactory.forKind(providers.getCodeCache().getTarget().wordKind);
-                ComputeAddressNode arrayAddress = g.unique(new ComputeAddressNode(boxedElement, locationNode, wordStamp));
+                ComputeAddressNode arrayAddress = g.unique(ComputeAddressNode.create(boxedElement, locationNode, wordStamp));
                 args.add(arrayAddress);
             } else {
                 // boxed primitive value
                 try {
                     ResolvedJavaField field = providers.getMetaAccess().lookupJavaField(kind.toBoxedJavaClass().getDeclaredField("value"));
-                    LoadFieldNode loadFieldNode = g.add(new LoadFieldNode(boxedElement, field));
+                    LoadFieldNode loadFieldNode = g.add(LoadFieldNode.create(boxedElement, field));
                     last.setNext(loadFieldNode);
                     last = loadFieldNode;
                     args.add(loadFieldNode);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -28,6 +28,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -35,7 +36,8 @@
  * Reserves a block of memory in the stack frame of a method. The block is reserved in the frame for
  * the entire execution of the associated method.
  */
-public final class AllocaNode extends FixedWithNextNode implements LIRLowerable {
+@NodeInfo
+public class AllocaNode extends FixedWithNextNode implements LIRLowerable {
 
     /**
      * The number of slots in block.
@@ -49,7 +51,11 @@
      */
     private final BitSet objects;
 
-    public AllocaNode(int slots, BitSet objects) {
+    public static AllocaNode create(int slots, BitSet objects) {
+        return USE_GENERATED_NODES ? new AllocaNodeGen(slots, objects) : new AllocaNode(slots, objects);
+    }
+
+    protected AllocaNode(int slots, BitSet objects) {
         super(StampFactory.forKind(HotSpotGraalRuntime.getHostWordKind()));
         this.slots = slots;
         this.objects = objects;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayRangeWriteBarrier.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayRangeWriteBarrier.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,12 +22,14 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
+@NodeInfo
 public abstract class ArrayRangeWriteBarrier extends WriteBarrier {
 
-    @Input private ValueNode startIndex;
-    @Input private ValueNode length;
+    @Input ValueNode startIndex;
+    @Input ValueNode length;
 
     public ArrayRangeWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) {
         super(object, null, null, true);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,8 +24,8 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -38,11 +38,15 @@
  * check on the object.
  */
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
-public final class BeginLockScopeNode extends AbstractMemoryCheckpoint implements LIRLowerable, MonitorEnter, MemoryCheckpoint.Single {
+public class BeginLockScopeNode extends AbstractMemoryCheckpoint implements LIRLowerable, MonitorEnter, MemoryCheckpoint.Single {
 
     private int lockDepth;
 
-    private BeginLockScopeNode(int lockDepth) {
+    public static BeginLockScopeNode create(int lockDepth) {
+        return USE_GENERATED_NODES ? new BeginLockScopeNodeGen(lockDepth) : new BeginLockScopeNode(lockDepth);
+    }
+
+    BeginLockScopeNode(int lockDepth) {
         super(null);
         this.lockDepth = lockDepth;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
@@ -30,11 +31,16 @@
 /**
  * Converts a compile-time constant Java string into a C string installed with the generated code.
  */
-public final class CStringNode extends FloatingNode implements LIRLowerable {
+@NodeInfo
+public class CStringNode extends FloatingNode implements LIRLowerable {
 
     private final String string;
 
-    private CStringNode(String string) {
+    public static CStringNode create(String string) {
+        return USE_GENERATED_NODES ? new CStringNodeGen(string) : new CStringNode(string);
+    }
+
+    CStringNode(String string) {
         super(null);
         this.string = string;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.replacements.nodes.*;
@@ -34,9 +35,14 @@
  *
  * @see ClassSubstitutions#cast(Class, Object)
  */
+@NodeInfo
 public class ClassCastNode extends MacroStateSplitNode implements Canonicalizable.Binary<ValueNode> {
 
-    public ClassCastNode(Invoke invoke) {
+    public static ClassCastNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new ClassCastNodeGen(invoke) : new ClassCastNode(invoke);
+    }
+
+    protected ClassCastNode(Invoke invoke) {
         super(invoke);
     }
 
@@ -62,7 +68,7 @@
             Class<?> c = (Class<?>) HotSpotObjectConstant.asObject(forJavaClass.asConstant());
             if (c != null && !c.isPrimitive()) {
                 HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(c);
-                return new CheckCastNode(type, forObject, null, false);
+                return CheckCastNode.create(type, forObject, null, false);
             }
         }
         return this;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.nodes.*;
 
@@ -35,9 +36,14 @@
  * @see ClassSubstitutions#getClassLoader0(Class)
  */
 @SuppressWarnings("javadoc")
+@NodeInfo
 public class ClassGetClassLoader0Node extends MacroStateSplitNode implements Canonicalizable {
 
-    public ClassGetClassLoader0Node(Invoke invoke) {
+    public static ClassGetClassLoader0Node create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new ClassGetClassLoader0NodeGen(invoke) : new ClassGetClassLoader0Node(invoke);
+    }
+
+    protected ClassGetClassLoader0Node(Invoke invoke) {
         super(invoke);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetComponentTypeNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetComponentTypeNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.nodes.*;
 
@@ -34,9 +35,14 @@
  *
  * @see ClassSubstitutions#getComponentType(Class)
  */
+@NodeInfo
 public class ClassGetComponentTypeNode extends MacroNode implements Canonicalizable {
 
-    public ClassGetComponentTypeNode(Invoke invoke) {
+    public static ClassGetComponentTypeNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new ClassGetComponentTypeNodeGen(invoke) : new ClassGetComponentTypeNode(invoke);
+    }
+
+    protected ClassGetComponentTypeNode(Invoke invoke) {
         super(invoke);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetModifiersNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetModifiersNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.nodes.*;
 
@@ -34,9 +35,14 @@
  *
  * @see ClassSubstitutions#getModifiers(Class)
  */
+@NodeInfo
 public class ClassGetModifiersNode extends MacroNode implements Canonicalizable {
 
-    public ClassGetModifiersNode(Invoke invoke) {
+    public static ClassGetModifiersNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new ClassGetModifiersNodeGen(invoke) : new ClassGetModifiersNode(invoke);
+    }
+
+    protected ClassGetModifiersNode(Invoke invoke) {
         super(invoke);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetSuperclassNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetSuperclassNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.nodes.*;
 
@@ -34,9 +35,14 @@
  *
  * @see ClassSubstitutions#getSuperclass(Class)
  */
+@NodeInfo
 public class ClassGetSuperclassNode extends MacroNode implements Canonicalizable {
 
-    public ClassGetSuperclassNode(Invoke invoke) {
+    public static ClassGetSuperclassNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new ClassGetSuperclassNodeGen(invoke) : new ClassGetSuperclassNode(invoke);
+    }
+
+    protected ClassGetSuperclassNode(Invoke invoke) {
         super(invoke);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsArrayNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsArrayNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.nodes.*;
 
@@ -34,9 +35,14 @@
  *
  * @see ClassSubstitutions#isArray(Class)
  */
+@NodeInfo
 public class ClassIsArrayNode extends MacroNode implements Canonicalizable {
 
-    public ClassIsArrayNode(Invoke invoke) {
+    public static ClassIsArrayNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new ClassIsArrayNodeGen(invoke) : new ClassIsArrayNode(invoke);
+    }
+
+    protected ClassIsArrayNode(Invoke invoke) {
         super(invoke);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInstanceNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInstanceNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
@@ -36,9 +37,14 @@
  *
  * @see ClassSubstitutions#isInstance(Class, Object)
  */
+@NodeInfo
 public class ClassIsInstanceNode extends MacroNode implements Canonicalizable {
 
-    public ClassIsInstanceNode(Invoke invoke) {
+    public static ClassIsInstanceNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new ClassIsInstanceNodeGen(invoke) : new ClassIsInstanceNode(invoke);
+    }
+
+    protected ClassIsInstanceNode(Invoke invoke) {
         super(invoke);
     }
 
@@ -65,8 +71,8 @@
                     return ConstantNode.forBoolean(o != null && c.isInstance(o));
                 }
                 HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(c);
-                InstanceOfNode instanceOf = new InstanceOfNode(type, object, null);
-                return new ConditionalNode(instanceOf, ConstantNode.forBoolean(true), ConstantNode.forBoolean(false));
+                InstanceOfNode instanceOf = InstanceOfNode.create(type, object, null);
+                return ConditionalNode.create(instanceOf, ConstantNode.forBoolean(true), ConstantNode.forBoolean(false));
             }
         }
         return this;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInterfaceNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInterfaceNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.nodes.*;
 
@@ -34,9 +35,14 @@
  *
  * @see ClassSubstitutions#isInterface(Class)
  */
+@NodeInfo
 public class ClassIsInterfaceNode extends MacroNode implements Canonicalizable {
 
-    public ClassIsInterfaceNode(Invoke invoke) {
+    public static ClassIsInterfaceNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new ClassIsInterfaceNodeGen(invoke) : new ClassIsInterfaceNode(invoke);
+    }
+
+    protected ClassIsInterfaceNode(Invoke invoke) {
         super(invoke);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsPrimitiveNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsPrimitiveNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.nodes.*;
 
@@ -34,9 +35,14 @@
  *
  * @see ClassSubstitutions#isPrimitive(Class)
  */
+@NodeInfo
 public class ClassIsPrimitiveNode extends MacroNode implements Canonicalizable {
 
-    public ClassIsPrimitiveNode(Invoke invoke) {
+    public static ClassIsPrimitiveNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new ClassIsPrimitiveNodeGen(invoke) : new ClassIsPrimitiveNode(invoke);
+    }
+
+    protected ClassIsPrimitiveNode(Invoke invoke) {
         super(invoke);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,12 +25,12 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -40,9 +40,9 @@
  * Compress or uncompress an oop or metaspace pointer.
  */
 @NodeInfo(nameTemplate = "{p#op/s}")
-public final class CompressionNode extends ConvertNode implements LIRLowerable {
+public class CompressionNode extends ConvertNode implements LIRLowerable {
 
-    private enum CompressionOp {
+    enum CompressionOp {
         Compress,
         Uncompress
     }
@@ -50,7 +50,11 @@
     private final CompressionOp op;
     private final CompressEncoding encoding;
 
-    private CompressionNode(CompressionOp op, ValueNode input, CompressEncoding encoding) {
+    public static CompressionNode create(CompressionOp op, ValueNode input, CompressEncoding encoding) {
+        return USE_GENERATED_NODES ? new CompressionNodeGen(op, input, encoding) : new CompressionNode(op, input, encoding);
+    }
+
+    CompressionNode(CompressionOp op, ValueNode input, CompressEncoding encoding) {
         super(mkStamp(op, input.stamp(), encoding), input);
         this.op = op;
         this.encoding = encoding;
@@ -62,11 +66,11 @@
     }
 
     public static CompressionNode compress(ValueNode input, CompressEncoding encoding) {
-        return input.graph().unique(new CompressionNode(CompressionOp.Compress, input, encoding));
+        return input.graph().unique(CompressionNode.create(CompressionOp.Compress, input, encoding));
     }
 
     public static CompressionNode uncompress(ValueNode input, CompressEncoding encoding) {
-        return input.graph().unique(new CompressionNode(CompressionOp.Uncompress, input, encoding));
+        return input.graph().unique(CompressionNode.create(CompressionOp.Uncompress, input, encoding));
     }
 
     private static Constant compress(Constant c, CompressEncoding encoding) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -29,6 +29,7 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
@@ -36,11 +37,16 @@
 /**
  * Gets the address of the C++ JavaThread object for the current thread.
  */
-public final class CurrentJavaThreadNode extends FloatingNode implements LIRLowerable {
+@NodeInfo
+public class CurrentJavaThreadNode extends FloatingNode implements LIRLowerable {
 
     private LIRKind wordKind;
 
-    private CurrentJavaThreadNode(Kind kind) {
+    public static CurrentJavaThreadNode create(Kind kind) {
+        return USE_GENERATED_NODES ? new CurrentJavaThreadNodeGen(kind) : new CurrentJavaThreadNode(kind);
+    }
+
+    CurrentJavaThreadNode(Kind kind) {
         super(StampFactory.forKind(kind));
         this.wordKind = LIRKind.value(kind);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
@@ -32,11 +33,16 @@
 /**
  * Intrinsic for getting the lock in the current {@linkplain BeginLockScopeNode lock scope}.
  */
-public final class CurrentLockNode extends FixedWithNextNode implements LIRLowerable {
+@NodeInfo
+public class CurrentLockNode extends FixedWithNextNode implements LIRLowerable {
 
     private int lockDepth;
 
-    private CurrentLockNode(int lockDepth) {
+    public static CurrentLockNode create(int lockDepth) {
+        return USE_GENERATED_NODES ? new CurrentLockNodeGen(lockDepth) : new CurrentLockNode(lockDepth);
+    }
+
+    CurrentLockNode(int lockDepth) {
         super(null);
         this.lockDepth = lockDepth;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,9 +27,9 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -41,10 +41,14 @@
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
 public class DeoptimizationFetchUnrollInfoCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Multi {
 
-    @Input private SaveAllRegistersNode registerSaver;
+    @Input SaveAllRegistersNode registerSaver;
     private final ForeignCallsProvider foreignCalls;
 
-    public DeoptimizationFetchUnrollInfoCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver) {
+    public static DeoptimizationFetchUnrollInfoCallNode create(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver) {
+        return USE_GENERATED_NODES ? new DeoptimizationFetchUnrollInfoCallNodeGen(foreignCalls, registerSaver) : new DeoptimizationFetchUnrollInfoCallNode(foreignCalls, registerSaver);
+    }
+
+    protected DeoptimizationFetchUnrollInfoCallNode(ForeignCallsProvider foreignCalls, ValueNode registerSaver) {
         super(StampFactory.forKind(Kind.fromJavaClass(FETCH_UNROLL_INFO.getResultType())));
         this.registerSaver = (SaveAllRegistersNode) registerSaver;
         this.foreignCalls = foreignCalls;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,8 +24,8 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -38,7 +38,11 @@
     private final DeoptimizationAction action;
     private final DeoptimizationReason reason;
 
-    public DeoptimizeCallerNode(DeoptimizationAction action, DeoptimizationReason reason) {
+    public static DeoptimizeCallerNode create(DeoptimizationAction action, DeoptimizationReason reason) {
+        return USE_GENERATED_NODES ? new DeoptimizeCallerNodeGen(action, reason) : new DeoptimizeCallerNode(action, reason);
+    }
+
+    protected DeoptimizeCallerNode(DeoptimizationAction action, DeoptimizationReason reason) {
         super(StampFactory.forVoid());
         this.action = action;
         this.reason = reason;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,11 +23,17 @@
 package com.oracle.graal.hotspot.nodes;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
+@NodeInfo
 public class DeoptimizingStubCall extends DeoptimizingFixedWithNextNode {
 
-    public DeoptimizingStubCall(Stamp stamp) {
+    public static DeoptimizingStubCall create(Stamp stamp) {
+        return USE_GENERATED_NODES ? new DeoptimizingStubCallGen(stamp) : new DeoptimizingStubCall(stamp);
+    }
+
+    protected DeoptimizingStubCall(Stamp stamp) {
         super(stamp);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -29,6 +29,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
@@ -37,11 +38,16 @@
  * Intrinsic for allocating an on-stack array of integers to hold the dimensions of a multianewarray
  * instruction.
  */
-public final class DimensionsNode extends FixedWithNextNode implements LIRLowerable {
+@NodeInfo
+public class DimensionsNode extends FixedWithNextNode implements LIRLowerable {
 
     private final int rank;
 
-    private DimensionsNode(int rank) {
+    public static DimensionsNode create(int rank) {
+        return USE_GENERATED_NODES ? new DimensionsNodeGen(rank) : new DimensionsNode(rank);
+    }
+
+    DimensionsNode(int rank) {
         super(null);
         this.rank = rank;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,8 +23,8 @@
 package com.oracle.graal.hotspot.nodes;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
@@ -40,14 +40,19 @@
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
 public class DirectCompareAndSwapNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single {
 
-    @Input private ValueNode object;
-    @Input private ValueNode offset;
-    @Input private ValueNode expectedValue;
-    @Input private ValueNode newValue;
+    @Input ValueNode object;
+    @Input ValueNode offset;
+    @Input ValueNode expectedValue;
+    @Input ValueNode newValue;
 
     private final LocationIdentity locationIdentity;
 
-    public DirectCompareAndSwapNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, LocationIdentity locationIdentity) {
+    public static DirectCompareAndSwapNode create(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, LocationIdentity locationIdentity) {
+        return USE_GENERATED_NODES ? new DirectCompareAndSwapNodeGen(object, offset, expected, newValue, locationIdentity) : new DirectCompareAndSwapNode(object, offset, expected, newValue,
+                        locationIdentity);
+    }
+
+    protected DirectCompareAndSwapNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, LocationIdentity locationIdentity) {
         super(expected.stamp());
         this.object = object;
         this.offset = offset;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,7 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -34,9 +34,13 @@
  * object.
  */
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
-public final class EndLockScopeNode extends AbstractMemoryCheckpoint implements LIRLowerable, MonitorExit, MemoryCheckpoint.Single {
+public class EndLockScopeNode extends AbstractMemoryCheckpoint implements LIRLowerable, MonitorExit, MemoryCheckpoint.Single {
 
-    public EndLockScopeNode() {
+    public static EndLockScopeNode create() {
+        return USE_GENERATED_NODES ? new EndLockScopeNodeGen() : new EndLockScopeNode();
+    }
+
+    protected EndLockScopeNode() {
         super(StampFactory.forVoid());
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EnterUnpackFramesStackFrameNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EnterUnpackFramesStackFrameNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,7 +25,8 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
@@ -34,14 +35,20 @@
  * Emits code to enter a low-level stack frame specifically to call out to the C++ method
  * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}.
  */
+@NodeInfo
 public class EnterUnpackFramesStackFrameNode extends FixedWithNextNode implements LIRLowerable {
 
-    @Input private ValueNode framePc;
-    @Input private ValueNode senderSp;
-    @Input private ValueNode senderFp;
-    @Input private SaveAllRegistersNode registerSaver;
+    @Input ValueNode framePc;
+    @Input ValueNode senderSp;
+    @Input ValueNode senderFp;
+    @Input SaveAllRegistersNode registerSaver;
 
-    public EnterUnpackFramesStackFrameNode(ValueNode framePc, ValueNode senderSp, ValueNode senderFp, ValueNode registerSaver) {
+    public static EnterUnpackFramesStackFrameNode create(ValueNode framePc, ValueNode senderSp, ValueNode senderFp, ValueNode registerSaver) {
+        return USE_GENERATED_NODES ? new EnterUnpackFramesStackFrameNodeGen(framePc, senderSp, senderFp, registerSaver) : new EnterUnpackFramesStackFrameNode(framePc, senderSp, senderFp,
+                        registerSaver);
+    }
+
+    protected EnterUnpackFramesStackFrameNode(ValueNode framePc, ValueNode senderSp, ValueNode senderFp, ValueNode registerSaver) {
         super(StampFactory.forVoid());
         this.framePc = framePc;
         this.senderSp = senderSp;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePostWriteBarrier.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePostWriteBarrier.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,11 +22,17 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
-public final class G1ArrayRangePostWriteBarrier extends ArrayRangeWriteBarrier {
+@NodeInfo
+public class G1ArrayRangePostWriteBarrier extends ArrayRangeWriteBarrier {
 
-    public G1ArrayRangePostWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) {
+    public static G1ArrayRangePostWriteBarrier create(ValueNode object, ValueNode startIndex, ValueNode length) {
+        return USE_GENERATED_NODES ? new G1ArrayRangePostWriteBarrierGen(object, startIndex, length) : new G1ArrayRangePostWriteBarrier(object, startIndex, length);
+    }
+
+    protected G1ArrayRangePostWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) {
         super(object, startIndex, length);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePreWriteBarrier.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePreWriteBarrier.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,11 +22,17 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
-public final class G1ArrayRangePreWriteBarrier extends ArrayRangeWriteBarrier {
+@NodeInfo
+public class G1ArrayRangePreWriteBarrier extends ArrayRangeWriteBarrier {
 
-    public G1ArrayRangePreWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) {
+    public static G1ArrayRangePreWriteBarrier create(ValueNode object, ValueNode startIndex, ValueNode length) {
+        return USE_GENERATED_NODES ? new G1ArrayRangePreWriteBarrierGen(object, startIndex, length) : new G1ArrayRangePreWriteBarrier(object, startIndex, length);
+    }
+
+    protected G1ArrayRangePreWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) {
         super(object, startIndex, length);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrier.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrier.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,14 +22,20 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 
+@NodeInfo
 public class G1PostWriteBarrier extends WriteBarrier {
 
     private final boolean alwaysNull;
 
-    public G1PostWriteBarrier(ValueNode object, ValueNode value, LocationNode location, boolean precise, boolean alwaysNull) {
+    public static G1PostWriteBarrier create(ValueNode object, ValueNode value, LocationNode location, boolean precise, boolean alwaysNull) {
+        return USE_GENERATED_NODES ? new G1PostWriteBarrierGen(object, value, location, precise, alwaysNull) : new G1PostWriteBarrier(object, value, location, precise, alwaysNull);
+    }
+
+    protected G1PostWriteBarrier(ValueNode object, ValueNode value, LocationNode location, boolean precise, boolean alwaysNull) {
         super(object, value, location, precise);
         this.alwaysNull = alwaysNull;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,17 +22,22 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 
+@NodeInfo
 public class G1PreWriteBarrier extends WriteBarrier implements DeoptimizingNode.DeoptBefore {
 
-    @OptionalInput(InputType.State) private FrameState stateBefore;
+    @OptionalInput(InputType.State) FrameState stateBefore;
     private final boolean nullCheck;
     private final boolean doLoad;
 
-    public G1PreWriteBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad, boolean nullCheck) {
+    public static G1PreWriteBarrier create(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad, boolean nullCheck) {
+        return USE_GENERATED_NODES ? new G1PreWriteBarrierGen(object, expectedObject, location, doLoad, nullCheck) : new G1PreWriteBarrier(object, expectedObject, location, doLoad, nullCheck);
+    }
+
+    protected G1PreWriteBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad, boolean nullCheck) {
         super(object, expectedObject, location, true);
         this.doLoad = doLoad;
         this.nullCheck = nullCheck;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ReferentFieldReadBarrier.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ReferentFieldReadBarrier.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 
@@ -31,11 +32,16 @@
  * {@code UnsafeLoadNode}). The return value of the read is passed to the snippet implementing the
  * read barrier and consequently is added to the SATB queue if the concurrent marker is enabled.
  */
+@NodeInfo
 public class G1ReferentFieldReadBarrier extends WriteBarrier {
 
     private final boolean doLoad;
 
-    public G1ReferentFieldReadBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad) {
+    public static G1ReferentFieldReadBarrier create(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad) {
+        return USE_GENERATED_NODES ? new G1ReferentFieldReadBarrierGen(object, expectedObject, location, doLoad) : new G1ReferentFieldReadBarrier(object, expectedObject, location, doLoad);
+    }
+
+    protected G1ReferentFieldReadBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad) {
         super(object, expectedObject, location, true);
         this.doLoad = doLoad;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -32,11 +33,16 @@
  * {@link #get(Object)} and all uses of the returned value must be atomic. The only exception to
  * this is if the usage is not an attempt to dereference the value.
  */
+@NodeInfo
 public class GetObjectAddressNode extends FixedWithNextNode implements LIRLowerable {
 
-    @Input private ValueNode object;
+    @Input ValueNode object;
 
-    public GetObjectAddressNode(ValueNode obj) {
+    public static GetObjectAddressNode create(ValueNode obj) {
+        return USE_GENERATED_NODES ? new GetObjectAddressNodeGen(obj) : new GetObjectAddressNode(obj);
+    }
+
+    protected GetObjectAddressNode(ValueNode obj) {
         super(StampFactory.forKind(Kind.Long));
         this.object = obj;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,10 +27,17 @@
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
+@NodeInfo
 public class HotSpotDirectCallTargetNode extends DirectCallTargetNode {
-    public HotSpotDirectCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, Type callType, InvokeKind invokeKind) {
+    public static HotSpotDirectCallTargetNode create(List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, Type callType, InvokeKind invokeKind) {
+        return USE_GENERATED_NODES ? new HotSpotDirectCallTargetNodeGen(arguments, returnStamp, signature, target, callType, invokeKind) : new HotSpotDirectCallTargetNode(arguments, returnStamp,
+                        signature, target, callType, invokeKind);
+    }
+
+    protected HotSpotDirectCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, Type callType, InvokeKind invokeKind) {
         super(arguments, returnStamp, signature, target, callType, invokeKind);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,13 +27,21 @@
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
+@NodeInfo
 public class HotSpotIndirectCallTargetNode extends IndirectCallTargetNode {
 
-    @Input private ValueNode metaspaceMethod;
+    @Input ValueNode metaspaceMethod;
 
-    public HotSpotIndirectCallTargetNode(ValueNode metaspaceMethod, ValueNode computedAddress, List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target,
+    public static HotSpotIndirectCallTargetNode create(ValueNode metaspaceMethod, ValueNode computedAddress, List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature,
+                    ResolvedJavaMethod target, Type callType, InvokeKind invokeKind) {
+        return USE_GENERATED_NODES ? new HotSpotIndirectCallTargetNodeGen(metaspaceMethod, computedAddress, arguments, returnStamp, signature, target, callType, invokeKind)
+                        : new HotSpotIndirectCallTargetNode(metaspaceMethod, computedAddress, arguments, returnStamp, signature, target, callType, invokeKind);
+    }
+
+    protected HotSpotIndirectCallTargetNode(ValueNode metaspaceMethod, ValueNode computedAddress, List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target,
                     Type callType, InvokeKind invokeKind) {
         super(computedAddress, arguments, returnStamp, signature, target, callType, invokeKind);
         this.metaspaceMethod = metaspaceMethod;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
@@ -32,13 +33,19 @@
  * Sets up the {@linkplain HotSpotBackend#EXCEPTION_HANDLER_IN_CALLER arguments} expected by an
  * exception handler in the caller's frame, removes the current frame and jumps to said handler.
  */
+@NodeInfo
 public class JumpToExceptionHandlerInCallerNode extends ControlSinkNode implements LIRLowerable {
 
-    @Input private ValueNode handlerInCallerPc;
-    @Input private ValueNode exception;
-    @Input private ValueNode exceptionPc;
+    @Input ValueNode handlerInCallerPc;
+    @Input ValueNode exception;
+    @Input ValueNode exceptionPc;
 
-    public JumpToExceptionHandlerInCallerNode(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) {
+    public static JumpToExceptionHandlerInCallerNode create(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) {
+        return USE_GENERATED_NODES ? new JumpToExceptionHandlerInCallerNodeGen(handlerInCallerPc, exception, exceptionPc) : new JumpToExceptionHandlerInCallerNode(handlerInCallerPc, exception,
+                        exceptionPc);
+    }
+
+    protected JumpToExceptionHandlerInCallerNode(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) {
         super(StampFactory.forVoid());
         this.handlerInCallerPc = handlerInCallerPc;
         this.exception = exception;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveCurrentStackFrameNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveCurrentStackFrameNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,7 +24,8 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -32,11 +33,16 @@
  * Emits code to leave (pop) the current low-level stack frame. This operation also removes the
  * return address if its location is on the stack.
  */
+@NodeInfo
 public class LeaveCurrentStackFrameNode extends FixedWithNextNode implements LIRLowerable {
 
-    @Input private SaveAllRegistersNode registerSaver;
+    @Input SaveAllRegistersNode registerSaver;
 
-    public LeaveCurrentStackFrameNode(ValueNode registerSaver) {
+    public static LeaveCurrentStackFrameNode create(ValueNode registerSaver) {
+        return USE_GENERATED_NODES ? new LeaveCurrentStackFrameNodeGen(registerSaver) : new LeaveCurrentStackFrameNode(registerSaver);
+    }
+
+    protected LeaveCurrentStackFrameNode(ValueNode registerSaver) {
         super(StampFactory.forVoid());
         this.registerSaver = (SaveAllRegistersNode) registerSaver;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
@@ -34,12 +35,17 @@
  * Emits code to leave (pop) the current low-level stack frame which is being deoptimized. This node
  * is only used in {@link DeoptimizationStub}.
  */
+@NodeInfo
 public class LeaveDeoptimizedStackFrameNode extends FixedWithNextNode implements LIRLowerable {
 
-    @Input private ValueNode frameSize;
-    @Input private ValueNode initialInfo;
+    @Input ValueNode frameSize;
+    @Input ValueNode initialInfo;
 
-    public LeaveDeoptimizedStackFrameNode(ValueNode frameSize, ValueNode initialInfo) {
+    public static LeaveDeoptimizedStackFrameNode create(ValueNode frameSize, ValueNode initialInfo) {
+        return USE_GENERATED_NODES ? new LeaveDeoptimizedStackFrameNodeGen(frameSize, initialInfo) : new LeaveDeoptimizedStackFrameNode(frameSize, initialInfo);
+    }
+
+    protected LeaveDeoptimizedStackFrameNode(ValueNode frameSize, ValueNode initialInfo) {
         super(StampFactory.forVoid());
         this.frameSize = frameSize;
         this.initialInfo = initialInfo;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,7 +24,8 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -32,11 +33,16 @@
  * Emits code to leave a low-level stack frame specifically to call out to the C++ method
  * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}.
  */
+@NodeInfo
 public class LeaveUnpackFramesStackFrameNode extends FixedWithNextNode implements LIRLowerable {
 
-    @Input private SaveAllRegistersNode registerSaver;
+    @Input SaveAllRegistersNode registerSaver;
 
-    public LeaveUnpackFramesStackFrameNode(ValueNode registerSaver) {
+    public static LeaveUnpackFramesStackFrameNode create(ValueNode registerSaver) {
+        return USE_GENERATED_NODES ? new LeaveUnpackFramesStackFrameNodeGen(registerSaver) : new LeaveUnpackFramesStackFrameNode(registerSaver);
+    }
+
+    protected LeaveUnpackFramesStackFrameNode(ValueNode registerSaver) {
         super(StampFactory.forVoid());
         this.registerSaver = (SaveAllRegistersNode) registerSaver;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
@@ -33,9 +34,14 @@
 /**
  * Node that is used to maintain a stack based counter of how many locks are currently held.
  */
-public final class MonitorCounterNode extends FloatingNode implements LIRLowerable {
+@NodeInfo
+public class MonitorCounterNode extends FloatingNode implements LIRLowerable {
 
-    private MonitorCounterNode() {
+    public static MonitorCounterNode create() {
+        return USE_GENERATED_NODES ? new MonitorCounterNodeGen() : new MonitorCounterNode();
+    }
+
+    MonitorCounterNode() {
         super(null);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java	Mon Aug 25 21:15:59 2014 -0700
@@ -29,6 +29,7 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
@@ -36,14 +37,19 @@
 /**
  * A call to the {@link NewArrayStub}.
  */
+@NodeInfo
 public class NewArrayStubCall extends DeoptimizingStubCall implements LIRLowerable {
 
     private static final Stamp defaultStamp = StampFactory.objectNonNull();
 
-    @Input private ValueNode hub;
-    @Input private ValueNode length;
+    @Input ValueNode hub;
+    @Input ValueNode length;
 
-    public NewArrayStubCall(ValueNode hub, ValueNode length) {
+    public static NewArrayStubCall create(ValueNode hub, ValueNode length) {
+        return USE_GENERATED_NODES ? new NewArrayStubCallGen(hub, length) : new NewArrayStubCall(hub, length);
+    }
+
+    protected NewArrayStubCall(ValueNode hub, ValueNode length) {
         super(defaultStamp);
         this.hub = hub;
         this.length = length;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Mon Aug 25 21:15:59 2014 -0700
@@ -29,6 +29,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
@@ -36,13 +37,18 @@
 /**
  * A call to the {@link NewInstanceStub}.
  */
+@NodeInfo
 public class NewInstanceStubCall extends DeoptimizingStubCall implements LIRLowerable {
 
     private static final Stamp defaultStamp = StampFactory.objectNonNull();
 
-    @Input private ValueNode hub;
+    @Input ValueNode hub;
 
-    public NewInstanceStubCall(ValueNode hub) {
+    public static NewInstanceStubCall create(ValueNode hub) {
+        return USE_GENERATED_NODES ? new NewInstanceStubCallGen(hub) : new NewInstanceStubCall(hub);
+    }
+
+    protected NewInstanceStubCall(ValueNode hub) {
         super(defaultStamp);
         this.hub = hub;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java	Mon Aug 25 21:15:59 2014 -0700
@@ -28,6 +28,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -36,15 +37,20 @@
 /**
  * Node implementing a call to {@code GraalRuntime::new_multi_array}.
  */
+@NodeInfo
 public class NewMultiArrayStubCall extends ForeignCallNode {
 
     private static final Stamp defaultStamp = StampFactory.objectNonNull();
 
-    @Input private ValueNode hub;
-    @Input private ValueNode dims;
+    @Input ValueNode hub;
+    @Input ValueNode dims;
     private final int rank;
 
-    public NewMultiArrayStubCall(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode hub, int rank, ValueNode dims) {
+    public static NewMultiArrayStubCall create(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode hub, int rank, ValueNode dims) {
+        return USE_GENERATED_NODES ? new NewMultiArrayStubCallGen(foreignCalls, hub, rank, dims) : new NewMultiArrayStubCall(foreignCalls, hub, rank, dims);
+    }
+
+    protected NewMultiArrayStubCall(ForeignCallsProvider foreignCalls, ValueNode hub, int rank, ValueNode dims) {
         super(foreignCalls, NEW_MULTI_ARRAY, defaultStamp);
         this.hub = hub;
         this.rank = rank;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PatchReturnAddressNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PatchReturnAddressNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
@@ -31,11 +32,16 @@
 /**
  * Modifies the return address of the current frame.
  */
+@NodeInfo
 public class PatchReturnAddressNode extends FixedWithNextNode implements LIRLowerable {
 
-    @Input private ValueNode address;
+    @Input ValueNode address;
 
-    public PatchReturnAddressNode(ValueNode address) {
+    public static PatchReturnAddressNode create(ValueNode address) {
+        return USE_GENERATED_NODES ? new PatchReturnAddressNodeGen(address) : new PatchReturnAddressNode(address);
+    }
+
+    protected PatchReturnAddressNode(ValueNode address) {
         super(StampFactory.forVoid());
         this.address = address;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,16 +25,22 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
 
+@NodeInfo
 public class PrefetchAllocateNode extends FixedWithNextNode implements LIRLowerable {
 
-    @Input private ValueNode distance;
-    @Input private ValueNode address;
+    @Input ValueNode distance;
+    @Input ValueNode address;
 
-    public PrefetchAllocateNode(ValueNode address, ValueNode distance) {
+    public static PrefetchAllocateNode create(ValueNode address, ValueNode distance) {
+        return USE_GENERATED_NODES ? new PrefetchAllocateNodeGen(address, distance) : new PrefetchAllocateNode(address, distance);
+    }
+
+    protected PrefetchAllocateNode(ValueNode address, ValueNode distance) {
         super(StampFactory.forVoid());
         this.address = address;
         this.distance = distance;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PushInterpreterFrameNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PushInterpreterFrameNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
@@ -32,14 +33,19 @@
 /**
  * A call to the runtime code implementing the uncommon trap logic.
  */
+@NodeInfo
 public class PushInterpreterFrameNode extends FixedWithNextNode implements LIRLowerable {
 
-    @Input private ValueNode framePc;
-    @Input private ValueNode frameSize;
-    @Input private ValueNode senderSp;
-    @Input private ValueNode initialInfo;
+    @Input ValueNode framePc;
+    @Input ValueNode frameSize;
+    @Input ValueNode senderSp;
+    @Input ValueNode initialInfo;
 
-    public PushInterpreterFrameNode(ValueNode frameSize, ValueNode framePc, ValueNode senderSp, ValueNode initialInfo) {
+    public static PushInterpreterFrameNode create(ValueNode frameSize, ValueNode framePc, ValueNode senderSp, ValueNode initialInfo) {
+        return USE_GENERATED_NODES ? new PushInterpreterFrameNodeGen(frameSize, framePc, senderSp, initialInfo) : new PushInterpreterFrameNode(frameSize, framePc, senderSp, initialInfo);
+    }
+
+    protected PushInterpreterFrameNode(ValueNode frameSize, ValueNode framePc, ValueNode senderSp, ValueNode initialInfo) {
         super(StampFactory.forVoid());
         this.frameSize = frameSize;
         this.framePc = framePc;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SaveAllRegistersNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SaveAllRegistersNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,9 +24,9 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -39,7 +39,11 @@
 
     private SaveRegistersOp saveRegistersOp;
 
-    public SaveAllRegistersNode() {
+    public static SaveAllRegistersNode create() {
+        return USE_GENERATED_NODES ? new SaveAllRegistersNodeGen() : new SaveAllRegistersNode();
+    }
+
+    protected SaveAllRegistersNode() {
         super(StampFactory.forKind(Kind.Long));
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialArrayRangeWriteBarrier.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialArrayRangeWriteBarrier.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,11 +22,17 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
-public final class SerialArrayRangeWriteBarrier extends ArrayRangeWriteBarrier {
+@NodeInfo
+public class SerialArrayRangeWriteBarrier extends ArrayRangeWriteBarrier {
 
-    public SerialArrayRangeWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) {
+    public static SerialArrayRangeWriteBarrier create(ValueNode object, ValueNode startIndex, ValueNode length) {
+        return USE_GENERATED_NODES ? new SerialArrayRangeWriteBarrierGen(object, startIndex, length) : new SerialArrayRangeWriteBarrier(object, startIndex, length);
+    }
+
+    protected SerialArrayRangeWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) {
         super(object, startIndex, length);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialWriteBarrier.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialWriteBarrier.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,14 +22,20 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 
+@NodeInfo
 public class SerialWriteBarrier extends WriteBarrier {
 
     private final boolean alwaysNull;
 
-    public SerialWriteBarrier(ValueNode object, LocationNode location, boolean precise, boolean alwaysNull) {
+    public static SerialWriteBarrier create(ValueNode object, LocationNode location, boolean precise, boolean alwaysNull) {
+        return USE_GENERATED_NODES ? new SerialWriteBarrierGen(object, location, precise, alwaysNull) : new SerialWriteBarrier(object, location, precise, alwaysNull);
+    }
+
+    protected SerialWriteBarrier(ValueNode object, LocationNode location, boolean precise, boolean alwaysNull) {
         super(object, null, location, precise);
         this.alwaysNull = alwaysNull;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetAnchorNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetAnchorNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,15 +23,19 @@
 package com.oracle.graal.hotspot.nodes;
 
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Value, InputType.Anchor, InputType.Guard})
-public final class SnippetAnchorNode extends FixedWithNextNode implements Simplifiable, GuardingNode {
+public class SnippetAnchorNode extends FixedWithNextNode implements Simplifiable, GuardingNode {
 
-    public SnippetAnchorNode() {
+    public static SnippetAnchorNode create() {
+        return USE_GENERATED_NODES ? new SnippetAnchorNodeGen() : new SnippetAnchorNode();
+    }
+
+    protected SnippetAnchorNode() {
         super(StampFactory.object());
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetLocationProxyNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetLocationProxyNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,16 +25,21 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Association, InputType.Value})
-public final class SnippetLocationProxyNode extends FloatingNode implements Canonicalizable {
+public class SnippetLocationProxyNode extends FloatingNode implements Canonicalizable {
+
+    @Input(InputType.Unchecked) ValueNode location;
 
-    @Input(InputType.Unchecked) private ValueNode location;
+    public static SnippetLocationProxyNode create(ValueNode location) {
+        return USE_GENERATED_NODES ? new SnippetLocationProxyNodeGen(location) : new SnippetLocationProxyNode(location);
+    }
 
-    public SnippetLocationProxyNode(ValueNode location) {
+    protected SnippetLocationProxyNode(ValueNode location) {
         super(StampFactory.object());
         this.location = location;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -29,6 +29,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -39,12 +40,16 @@
 @NodeInfo(nameTemplate = "StubForeignCall#{p#descriptor/s}", allowedUsageTypes = {InputType.Memory})
 public class StubForeignCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Multi {
 
-    @Input private final NodeInputList<ValueNode> arguments;
+    @Input NodeInputList<ValueNode> arguments;
     private final ForeignCallsProvider foreignCalls;
 
     private final ForeignCallDescriptor descriptor;
 
-    public StubForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) {
+    public static StubForeignCallNode create(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) {
+        return USE_GENERATED_NODES ? new StubForeignCallNodeGen(foreignCalls, descriptor, arguments) : new StubForeignCallNode(foreignCalls, descriptor, arguments);
+    }
+
+    protected StubForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) {
         super(StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType())));
         this.arguments = new NodeInputList<>(this, arguments);
         this.descriptor = descriptor;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubStartNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubStartNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,16 +23,22 @@
 package com.oracle.graal.hotspot.nodes;
 
 import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
 /**
  * Start node for a {@link Stub}'s graph.
  */
+@NodeInfo
 public class StubStartNode extends StartNode {
 
     private final Stub stub;
 
-    public StubStartNode(Stub stub) {
+    public static StubStartNode create(Stub stub) {
+        return USE_GENERATED_NODES ? new StubStartNodeGen(stub) : new StubStartNode(stub);
+    }
+
+    protected StubStartNode(Stub stub) {
         this.stub = stub;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -29,10 +29,10 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -40,10 +40,11 @@
  * Performs a tail call to the specified target compiled method, with the parameter taken from the
  * supplied FrameState.
  */
+@NodeInfo
 public class TailcallNode extends FixedWithNextNode implements LIRLowerable {
 
-    @Input(InputType.State) private FrameState frameState;
-    @Input private ValueNode target;
+    @Input(InputType.State) FrameState frameState;
+    @Input ValueNode target;
 
     /**
      * Creates a TailcallNode.
@@ -51,7 +52,11 @@
      * @param target points to the start of an nmethod
      * @param frameState the parameters will be taken from this FrameState
      */
-    public TailcallNode(ValueNode target, FrameState frameState) {
+    public static TailcallNode create(ValueNode target, FrameState frameState) {
+        return USE_GENERATED_NODES ? new TailcallNodeGen(target, frameState) : new TailcallNode(target, frameState);
+    }
+
+    protected TailcallNode(ValueNode target, FrameState frameState) {
         super(StampFactory.forVoid());
         this.target = target;
         this.frameState = frameState;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,9 +27,9 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -41,11 +41,15 @@
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
 public class UncommonTrapCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Multi {
 
-    @Input private ValueNode trapRequest;
-    @Input private SaveAllRegistersNode registerSaver;
+    @Input ValueNode trapRequest;
+    @Input SaveAllRegistersNode registerSaver;
     private final ForeignCallsProvider foreignCalls;
 
-    public UncommonTrapCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver, ValueNode trapRequest) {
+    public static UncommonTrapCallNode create(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver, ValueNode trapRequest) {
+        return USE_GENERATED_NODES ? new UncommonTrapCallNodeGen(foreignCalls, registerSaver, trapRequest) : new UncommonTrapCallNode(foreignCalls, registerSaver, trapRequest);
+    }
+
+    protected UncommonTrapCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver, ValueNode trapRequest) {
         super(StampFactory.forKind(Kind.fromJavaClass(UNCOMMON_TRAP.getResultType())));
         this.trapRequest = trapRequest;
         this.registerSaver = (SaveAllRegistersNode) registerSaver;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -28,6 +28,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
@@ -36,12 +37,17 @@
  * Causes the VM to exit with a description of the current Java location and an optional
  * {@linkplain Log#printf(String, long) formatted} error message specified.
  */
-public final class VMErrorNode extends DeoptimizingStubCall implements LIRLowerable {
+@NodeInfo
+public class VMErrorNode extends DeoptimizingStubCall implements LIRLowerable {
 
     private final String format;
-    @Input private ValueNode value;
+    @Input ValueNode value;
 
-    public VMErrorNode(String format, ValueNode value) {
+    public static VMErrorNode create(String format, ValueNode value) {
+        return USE_GENERATED_NODES ? new VMErrorNodeGen(format, value) : new VMErrorNode(format, value);
+    }
+
+    protected VMErrorNode(String format, ValueNode value) {
         super(StampFactory.forVoid());
         this.format = format;
         this.value = value;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,16 +23,17 @@
 package com.oracle.graal.hotspot.nodes;
 
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public abstract class WriteBarrier extends FixedWithNextNode implements Lowerable {
 
-    @Input private ValueNode object;
-    @OptionalInput private ValueNode value;
-    @OptionalInput(InputType.Association) private LocationNode location;
+    @Input ValueNode object;
+    @OptionalInput ValueNode value;
+    @OptionalInput(InputType.Association) LocationNode location;
     private final boolean precise;
 
     public WriteBarrier(ValueNode object, ValueNode value, LocationNode location, boolean precise) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -28,7 +28,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.hotspot.HotSpotVMConfig.*;
+import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.*;
@@ -91,7 +91,7 @@
             ConstantNode klassNode = ConstantNode.forConstant(klass, metaAccess, graph);
 
             Stamp stamp = StampFactory.exactNonNull(metaAccess.lookupJavaType(Class.class));
-            FloatingReadNode freadNode = graph.unique(new FloatingReadNode(klassNode, location, null, stamp));
+            FloatingReadNode freadNode = graph.unique(FloatingReadNode.create(klassNode, location, null, stamp));
 
             if (HotSpotObjectConstant.isCompressed(constant)) {
                 return CompressionNode.compress(freadNode, oopEncoding);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,9 +26,9 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.loop.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.util.*;
@@ -84,7 +84,7 @@
 
         FrameState osrState = osr.stateAfter();
         osr.setStateAfter(null);
-        OSRStartNode osrStart = graph.add(new OSRStartNode());
+        OSRStartNode osrStart = graph.add(OSRStartNode.create());
         StartNode start = graph.start();
         FixedNode next = osr.next();
         osr.setNext(null);
@@ -100,7 +100,7 @@
                  * we need to drop the stamp since the types we see during OSR may be too precise
                  * (if a branch was not parsed for example).
                  */
-                proxy.replaceAndDelete(graph.unique(new OSRLocalNode(i, proxy.stamp().unrestricted())));
+                proxy.replaceAndDelete(graph.unique(OSRLocalNode.create(i, proxy.stamp().unrestricted())));
             } else {
                 assert value == null || value instanceof OSRLocalNode;
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -63,7 +63,7 @@
     private static void addReadNodeBarriers(ReadNode node, StructuredGraph graph) {
         if (node.getBarrierType() == BarrierType.PRECISE) {
             assert useG1GC();
-            G1ReferentFieldReadBarrier barrier = graph.add(new G1ReferentFieldReadBarrier(node.object(), node, node.location(), false));
+            G1ReferentFieldReadBarrier barrier = graph.add(G1ReferentFieldReadBarrier.create(node.object(), node, node.location(), false));
             graph.addAfterFixed(node, barrier);
         } else {
             assert node.getBarrierType() == BarrierType.NONE : "Non precise read barrier has been attached to read node.";
@@ -71,7 +71,7 @@
     }
 
     protected static void addG1PreWriteBarrier(FixedAccessNode node, ValueNode object, ValueNode value, LocationNode location, boolean doLoad, boolean nullCheck, StructuredGraph graph) {
-        G1PreWriteBarrier preBarrier = graph.add(new G1PreWriteBarrier(object, value, location, doLoad, nullCheck));
+        G1PreWriteBarrier preBarrier = graph.add(G1PreWriteBarrier.create(object, value, location, doLoad, nullCheck));
         preBarrier.setStateBefore(node.stateBefore());
         node.setNullCheck(false);
         node.setStateBefore(null);
@@ -80,13 +80,13 @@
 
     protected void addG1PostWriteBarrier(FixedAccessNode node, ValueNode object, ValueNode value, LocationNode location, boolean precise, StructuredGraph graph) {
         final boolean alwaysNull = StampTool.isObjectAlwaysNull(value);
-        graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(object, value, location, precise, alwaysNull)));
+        graph.addAfterFixed(node, graph.add(G1PostWriteBarrier.create(object, value, location, precise, alwaysNull)));
     }
 
     protected void addSerialPostWriteBarrier(FixedAccessNode node, ValueNode object, ValueNode value, LocationNode location, boolean precise, StructuredGraph graph) {
         final boolean alwaysNull = StampTool.isObjectAlwaysNull(value);
         final LocationNode loc = (precise ? location : null);
-        graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(object, loc, precise, alwaysNull)));
+        graph.addAfterFixed(node, graph.add(SerialWriteBarrier.create(object, loc, precise, alwaysNull)));
     }
 
     private void addWriteNodeBarriers(WriteNode node, StructuredGraph graph) {
@@ -157,13 +157,13 @@
     private static void addArrayRangeBarriers(ArrayRangeWriteNode node, StructuredGraph graph) {
         if (useG1GC()) {
             if (!node.isInitialization()) {
-                G1ArrayRangePreWriteBarrier g1ArrayRangePreWriteBarrier = graph.add(new G1ArrayRangePreWriteBarrier(node.getArray(), node.getIndex(), node.getLength()));
+                G1ArrayRangePreWriteBarrier g1ArrayRangePreWriteBarrier = graph.add(G1ArrayRangePreWriteBarrier.create(node.getArray(), node.getIndex(), node.getLength()));
                 graph.addBeforeFixed(node, g1ArrayRangePreWriteBarrier);
             }
-            G1ArrayRangePostWriteBarrier g1ArrayRangePostWriteBarrier = graph.add(new G1ArrayRangePostWriteBarrier(node.getArray(), node.getIndex(), node.getLength()));
+            G1ArrayRangePostWriteBarrier g1ArrayRangePostWriteBarrier = graph.add(G1ArrayRangePostWriteBarrier.create(node.getArray(), node.getIndex(), node.getLength()));
             graph.addAfterFixed(node, g1ArrayRangePostWriteBarrier);
         } else {
-            SerialArrayRangeWriteBarrier serialArrayRangeWriteBarrier = graph.add(new SerialArrayRangeWriteBarrier(node.getArray(), node.getIndex(), node.getLength()));
+            SerialArrayRangeWriteBarrier serialArrayRangeWriteBarrier = graph.add(SerialArrayRangeWriteBarrier.create(node.getArray(), node.getIndex(), node.getLength()));
             graph.addAfterFixed(node, serialArrayRangeWriteBarrier);
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -128,7 +128,7 @@
     }
 
     private static boolean validateBarrier(FixedAccessNode write, WriteBarrier barrier) {
-        assert write instanceof WriteNode || write instanceof LoweredCompareAndSwapNode : "Node must be of type requiring a write barrier";
+        assert write instanceof WriteNode || write instanceof LoweredCompareAndSwapNode || write instanceof LoweredAtomicReadAndWriteNode : "Node must be of type requiring a write barrier " + write;
         if ((barrier.getObject() == write.object()) && (!barrier.usePrecise() || (barrier.usePrecise() && barrier.getLocation() == write.location()))) {
             return true;
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -30,9 +30,9 @@
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
@@ -41,13 +41,13 @@
 import com.oracle.graal.runtime.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
-public final class ArrayCopyCallNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
+public class ArrayCopyCallNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
 
-    @Input private ValueNode src;
-    @Input private ValueNode srcPos;
-    @Input private ValueNode dest;
-    @Input private ValueNode destPos;
-    @Input private ValueNode length;
+    @Input ValueNode src;
+    @Input ValueNode srcPos;
+    @Input ValueNode dest;
+    @Input ValueNode destPos;
+    @Input ValueNode length;
 
     private Kind elementKind;
 
@@ -58,7 +58,13 @@
     private boolean disjoint;
     private boolean uninitialized;
 
-    private ArrayCopyCallNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind, boolean aligned, boolean disjoint, boolean uninitialized) {
+    public static ArrayCopyCallNode create(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind, boolean aligned, boolean disjoint,
+                    boolean uninitialized) {
+        return USE_GENERATED_NODES ? new ArrayCopyCallNodeGen(src, srcPos, dest, destPos, length, elementKind, aligned, disjoint, uninitialized) : new ArrayCopyCallNode(src, srcPos, dest, destPos,
+                        length, elementKind, aligned, disjoint, uninitialized);
+    }
+
+    ArrayCopyCallNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind, boolean aligned, boolean disjoint, boolean uninitialized) {
         super(StampFactory.forVoid());
         assert elementKind != null;
         this.src = src;
@@ -72,7 +78,12 @@
         this.uninitialized = uninitialized;
     }
 
-    private ArrayCopyCallNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind, boolean disjoint) {
+    public static ArrayCopyCallNode create(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind, boolean disjoint) {
+        return USE_GENERATED_NODES ? new ArrayCopyCallNodeGen(src, srcPos, dest, destPos, length, elementKind, disjoint) : new ArrayCopyCallNode(src, srcPos, dest, destPos, length, elementKind,
+                        disjoint);
+    }
+
+    ArrayCopyCallNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind, boolean disjoint) {
         this(src, srcPos, dest, destPos, length, elementKind, false, disjoint, false);
     }
 
@@ -113,10 +124,10 @@
     }
 
     private ValueNode computeBase(ValueNode base, ValueNode pos) {
-        FixedWithNextNode basePtr = graph().add(new GetObjectAddressNode(base));
+        FixedWithNextNode basePtr = graph().add(GetObjectAddressNode.create(base));
         graph().addBeforeFixed(this, basePtr);
         ValueNode loc = IndexedLocationNode.create(getLocationIdentity(), elementKind, arrayBaseOffset(elementKind), pos, graph(), arrayIndexScale(elementKind));
-        return graph().unique(new ComputeAddressNode(basePtr, loc, StampFactory.forKind(Kind.Long)));
+        return graph().unique(ComputeAddressNode.create(basePtr, loc, StampFactory.forKind(Kind.Long)));
     }
 
     @Override
@@ -131,7 +142,7 @@
             if (len.stamp().getStackKind() != Kind.Long) {
                 len = IntegerConvertNode.convert(len, StampFactory.forKind(Kind.Long), graph());
             }
-            ForeignCallNode call = graph.add(new ForeignCallNode(Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getForeignCalls(), desc, srcAddr, destAddr, len));
+            ForeignCallNode call = graph.add(ForeignCallNode.create(Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getForeignCalls(), desc, srcAddr, destAddr, len));
             call.setStateAfter(stateAfter());
             graph.replaceFixedWithFixed(this, call);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -30,6 +30,7 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.loop.phases.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -38,9 +39,14 @@
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.replacements.nodes.*;
 
+@NodeInfo
 public class ArrayCopyNode extends MacroStateSplitNode implements Virtualizable, Lowerable {
 
-    public ArrayCopyNode(Invoke invoke) {
+    public static ArrayCopyNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new ArrayCopyNodeGen(invoke) : new ArrayCopyNode(invoke);
+    }
+
+    protected ArrayCopyNode(Invoke invoke) {
         super(invoke);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -29,13 +29,19 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.nodes.*;
 
+@NodeInfo
 public class CallSiteTargetNode extends MacroStateSplitNode implements Canonicalizable, Lowerable {
 
-    public CallSiteTargetNode(Invoke invoke) {
+    public static CallSiteTargetNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new CallSiteTargetNodeGen(invoke) : new CallSiteTargetNode(invoke);
+    }
+
+    protected CallSiteTargetNode(Invoke invoke) {
         super(invoke);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompositeValueClassSubstitutions.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompositeValueClassSubstitutions.java	Mon Aug 25 21:15:59 2014 -0700
@@ -28,6 +28,7 @@
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.nodes.*;
@@ -43,9 +44,14 @@
      * knowledge about node classes to replace itself with a constant value for a constant
      * {@link Class} parameter.
      */
+    @NodeInfo
     public static class CompositeValueClassGetNode extends PureFunctionMacroNode {
 
-        public CompositeValueClassGetNode(Invoke invoke) {
+        public static CompositeValueClassGetNode create(Invoke invoke) {
+            return USE_GENERATED_NODES ? new CompositeValueClassSubstitutions_CompositeValueClassGetNodeGen(invoke) : new CompositeValueClassGetNode(invoke);
+        }
+
+        protected CompositeValueClassGetNode(Invoke invoke) {
             super(invoke);
         }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeClassSubstitutions.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeClassSubstitutions.java	Mon Aug 25 21:15:59 2014 -0700
@@ -28,6 +28,7 @@
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.nodes.*;
@@ -43,9 +44,14 @@
      * about node classes to replace itself with a constant value for a constant {@link Class}
      * parameter.
      */
+    @NodeInfo
     public static class NodeClassGetNode extends PureFunctionMacroNode {
 
-        public NodeClassGetNode(Invoke invoke) {
+        public static NodeClassGetNode create(Invoke invoke) {
+            return USE_GENERATED_NODES ? new HotSpotNodeClassSubstitutions_NodeClassGetNodeGen(invoke) : new NodeClassGetNode(invoke);
+        }
+
+        protected NodeClassGetNode(Invoke invoke) {
             super(invoke);
         }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java	Mon Aug 25 21:15:59 2014 -0700
@@ -78,9 +78,9 @@
         public void lower(LoadExceptionObjectNode loadExceptionObject, HotSpotRegistersProvider registers, LoweringTool tool) {
             if (USE_C_RUNTIME) {
                 StructuredGraph graph = loadExceptionObject.graph();
-                ReadRegisterNode thread = graph.add(new ReadRegisterNode(registers.getThreadRegister(), true, false));
+                ReadRegisterNode thread = graph.add(ReadRegisterNode.create(registers.getThreadRegister(), true, false));
                 graph.addBeforeFixed(loadExceptionObject, thread);
-                ForeignCallNode loadExceptionC = graph.add(new ForeignCallNode(providers.getForeignCalls(), LOAD_AND_CLEAR_EXCEPTION, thread));
+                ForeignCallNode loadExceptionC = graph.add(ForeignCallNode.create(providers.getForeignCalls(), LOAD_AND_CLEAR_EXCEPTION, thread));
                 loadExceptionC.setStateAfter(loadExceptionObject.stateAfter());
                 graph.replaceFixedWithFixed(loadExceptionObject, loadExceptionC);
             } else {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -34,6 +34,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.java.*;
@@ -44,6 +45,7 @@
 /**
  * Node for invocation methods defined on the class {@link MethodHandle}.
  */
+@NodeInfo
 public class MethodHandleNode extends MacroStateSplitNode implements Simplifiable {
 
     /** The method that this node is representing. */
@@ -52,9 +54,13 @@
     // Replacement method data
     private ResolvedJavaMethod replacementTargetMethod;
     private JavaType replacementReturnType;
-    @Input private final NodeInputList<ValueNode> replacementArguments;
+    @Input NodeInputList<ValueNode> replacementArguments;
 
-    public MethodHandleNode(Invoke invoke) {
+    public static MethodHandleNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new MethodHandleNodeGen(invoke) : new MethodHandleNode(invoke);
+    }
+
+    protected MethodHandleNode(Invoke invoke) {
         super(invoke);
 
         MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget();
@@ -98,10 +104,10 @@
                 throw GraalInternalError.shouldNotReachHere();
         }
         if (invoke != null) {
-            FixedNode next = next();
+            FixedNode currentNext = next();
             replaceAtUsages(invoke);
             GraphUtil.removeFixedWithUnusedInputs(this);
-            graph().addBeforeFixed(next, invoke);
+            graph().addBeforeFixed(currentNext, invoke);
         }
     }
 
@@ -230,7 +236,7 @@
                 ValueNode argument = arguments.get(index);
                 ResolvedJavaType argumentType = StampTool.typeOrNull(argument.stamp());
                 if (argumentType == null || (argumentType.isAssignableFrom(targetType) && !argumentType.equals(targetType))) {
-                    PiNode piNode = graph().unique(new PiNode(argument, StampFactory.declared(targetType)));
+                    PiNode piNode = graph().unique(PiNode.create(argument, StampFactory.declared(targetType)));
                     arguments.set(index, piNode);
                 }
             }
@@ -269,10 +275,10 @@
         // If there is already replacement information, use that instead.
         MethodCallTargetNode callTarget;
         if (replacementTargetMethod == null) {
-            callTarget = new SelfReplacingMethodCallTargetNode(invokeKind, targetMethod, targetArguments, returnType, getTargetMethod(), originalArguments, getReturnType());
+            callTarget = SelfReplacingMethodCallTargetNode.create(invokeKind, targetMethod, targetArguments, returnType, getTargetMethod(), originalArguments, getReturnType());
         } else {
             ValueNode[] args = replacementArguments.toArray(new ValueNode[replacementArguments.size()]);
-            callTarget = new SelfReplacingMethodCallTargetNode(invokeKind, targetMethod, targetArguments, returnType, replacementTargetMethod, args, replacementReturnType);
+            callTarget = SelfReplacingMethodCallTargetNode.create(invokeKind, targetMethod, targetArguments, returnType, replacementTargetMethod, args, replacementReturnType);
         }
         graph().add(callTarget);
 
@@ -283,9 +289,9 @@
         // (usually java.lang.Object).
         InvokeNode invoke;
         if (stamp() == StampFactory.forVoid()) {
-            invoke = new InvokeNode(callTarget, getBci(), stamp());
+            invoke = InvokeNode.create(callTarget, getBci(), stamp());
         } else {
-            invoke = new InvokeNode(callTarget, getBci());
+            invoke = InvokeNode.create(callTarget, getBci());
         }
         graph().add(invoke);
         invoke.setStateAfter(stateAfter());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Mon Aug 25 21:15:59 2014 -0700
@@ -495,8 +495,8 @@
                 if (nodes.isEmpty()) {
                     // Only insert the nodes if this is the first monitorenter being lowered.
                     JavaType returnType = initCounter.getMethod().getSignature().getReturnType(initCounter.getMethod().getDeclaringClass());
-                    MethodCallTargetNode callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, initCounter.getMethod(), new ValueNode[0], returnType));
-                    InvokeNode invoke = graph.add(new InvokeNode(callTarget, 0));
+                    MethodCallTargetNode callTarget = graph.add(MethodCallTargetNode.create(InvokeKind.Static, initCounter.getMethod(), new ValueNode[0], returnType));
+                    InvokeNode invoke = graph.add(InvokeNode.create(callTarget, 0));
                     invoke.setStateAfter(graph.start().stateAfter());
                     graph.addAfterFixed(graph.start(), invoke);
 
@@ -508,10 +508,10 @@
                         returnType = checkCounter.getMethod().getSignature().getReturnType(checkCounter.getMethod().getDeclaringClass());
                         String msg = "unbalanced monitors in " + graph.method().format("%H.%n(%p)") + ", count = %d";
                         ConstantNode errMsg = ConstantNode.forConstant(HotSpotObjectConstant.forObject(msg), providers.getMetaAccess(), graph);
-                        callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter.getMethod(), new ValueNode[]{errMsg}, returnType));
-                        invoke = graph.add(new InvokeNode(callTarget, 0));
+                        callTarget = graph.add(MethodCallTargetNode.create(InvokeKind.Static, checkCounter.getMethod(), new ValueNode[]{errMsg}, returnType));
+                        invoke = graph.add(InvokeNode.create(callTarget, 0));
                         List<ValueNode> stack = Collections.emptyList();
-                        FrameState stateAfter = new FrameState(graph.method(), BytecodeFrame.AFTER_BCI, new ValueNode[0], stack, new ValueNode[0], new MonitorIdNode[0], false, false);
+                        FrameState stateAfter = FrameState.create(graph.method(), BytecodeFrame.AFTER_BCI, new ValueNode[0], stack, new ValueNode[0], new MonitorIdNode[0], false, false);
                         invoke.setStateAfter(graph.add(stateAfter));
                         graph.addBeforeFixed(ret, invoke);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -32,6 +32,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
@@ -39,9 +40,14 @@
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.replacements.nodes.*;
 
+@NodeInfo
 public class ObjectCloneNode extends MacroStateSplitNode implements VirtualizableAllocation, ArrayLengthProvider {
 
-    public ObjectCloneNode(Invoke invoke) {
+    public static ObjectCloneNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new ObjectCloneNodeGen(invoke) : new ObjectCloneNode(invoke);
+    }
+
+    protected ObjectCloneNode(Invoke invoke) {
         super(invoke);
     }
 
@@ -82,16 +88,16 @@
                 type = getConcreteType(getObject().stamp(), tool.assumptions(), tool.getMetaAccess());
                 if (type != null) {
                     StructuredGraph newGraph = new StructuredGraph();
-                    ParameterNode param = newGraph.unique(new ParameterNode(0, getObject().stamp()));
-                    NewInstanceNode newInstance = newGraph.add(new NewInstanceNode(type, true));
+                    ParameterNode param = newGraph.unique(ParameterNode.create(0, getObject().stamp()));
+                    NewInstanceNode newInstance = newGraph.add(NewInstanceNode.create(type, true));
                     newGraph.addAfterFixed(newGraph.start(), newInstance);
-                    ReturnNode returnNode = newGraph.add(new ReturnNode(newInstance));
+                    ReturnNode returnNode = newGraph.add(ReturnNode.create(newInstance));
                     newGraph.addAfterFixed(newInstance, returnNode);
 
                     for (ResolvedJavaField field : type.getInstanceFields(true)) {
-                        LoadFieldNode load = newGraph.add(new LoadFieldNode(param, field));
+                        LoadFieldNode load = newGraph.add(LoadFieldNode.create(param, field));
                         newGraph.addBeforeFixed(returnNode, load);
-                        newGraph.addBeforeFixed(returnNode, newGraph.add(new StoreFieldNode(newInstance, field, load)));
+                        newGraph.addBeforeFixed(returnNode, newGraph.add(StoreFieldNode.create(newInstance, field, load)));
                     }
                     return lowerReplacement(newGraph, tool);
                 }
@@ -107,7 +113,7 @@
     /*
      * Looks at the given stamp and determines if it is an exact type (or can be assumed to be an
      * exact type) and if it is a cloneable type.
-     *
+     * 
      * If yes, then the exact type is returned, otherwise it returns null.
      */
     private static ResolvedJavaType getConcreteType(Stamp stamp, Assumptions assumptions, MetaAccessProvider metaAccess) {
@@ -153,13 +159,13 @@
             }
             ResolvedJavaType type = getConcreteType(obj.stamp(), tool.getAssumptions(), tool.getMetaAccessProvider());
             if (type != null && !type.isArray()) {
-                VirtualInstanceNode newVirtual = new VirtualInstanceNode(type, true);
+                VirtualInstanceNode newVirtual = VirtualInstanceNode.create(type, true);
                 ResolvedJavaField[] fields = newVirtual.getFields();
 
                 ValueNode[] state = new ValueNode[fields.length];
                 final LoadFieldNode[] loads = new LoadFieldNode[fields.length];
                 for (int i = 0; i < fields.length; i++) {
-                    state[i] = loads[i] = new LoadFieldNode(obj, fields[i]);
+                    state[i] = loads[i] = LoadFieldNode.create(obj, fields[i]);
                     tool.addNode(loads[i]);
                 }
                 tool.createVirtualObject(newVirtual, state, Collections.<MonitorIdNode> emptyList());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectGetClassNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectGetClassNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -28,6 +28,7 @@
 import com.oracle.graal.api.meta.ResolvedJavaType.Representation;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -37,9 +38,14 @@
  * This macro node will replace itself with the correct Java {@link Class} as soon as the object's
  * type is known (exact).
  */
+@NodeInfo
 public class ObjectGetClassNode extends MacroNode implements Virtualizable, Canonicalizable {
 
-    public ObjectGetClassNode(Invoke invoke) {
+    public static ObjectGetClassNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new ObjectGetClassNodeGen(invoke) : new ObjectGetClassNode(invoke);
+    }
+
+    protected ObjectGetClassNode(Invoke invoke) {
         super(invoke);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -29,13 +29,19 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.nodes.*;
 
+@NodeInfo
 public class ReflectionGetCallerClassNode extends MacroStateSplitNode implements Canonicalizable, Lowerable {
 
-    public ReflectionGetCallerClassNode(Invoke invoke) {
+    public static ReflectionGetCallerClassNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new ReflectionGetCallerClassNodeGen(invoke) : new ReflectionGetCallerClassNode(invoke);
+    }
+
+    protected ReflectionGetCallerClassNode(Invoke invoke) {
         super(invoke);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,12 +26,18 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.nodes.*;
 
+@NodeInfo
 public class SystemIdentityHashCodeNode extends PureFunctionMacroNode {
 
-    public SystemIdentityHashCodeNode(Invoke invoke) {
+    public static SystemIdentityHashCodeNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new SystemIdentityHashCodeNodeGen(invoke) : new SystemIdentityHashCodeNode(invoke);
+    }
+
+    protected SystemIdentityHashCodeNode(Invoke invoke) {
         super(invoke);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,25 +26,30 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.SnippetTemplate.Arguments;
 
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
-public final class UnsafeArrayCopyNode extends ArrayRangeWriteNode implements Lowerable, MemoryCheckpoint.Single {
+public class UnsafeArrayCopyNode extends ArrayRangeWriteNode implements Lowerable, MemoryCheckpoint.Single {
 
-    @Input private ValueNode src;
-    @Input private ValueNode srcPos;
-    @Input private ValueNode dest;
-    @Input private ValueNode destPos;
-    @Input private ValueNode length;
-    @OptionalInput private ValueNode layoutHelper;
+    @Input ValueNode src;
+    @Input ValueNode srcPos;
+    @Input ValueNode dest;
+    @Input ValueNode destPos;
+    @Input ValueNode length;
+    @OptionalInput ValueNode layoutHelper;
 
     private Kind elementKind;
 
-    private UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode layoutHelper, Kind elementKind) {
+    public static UnsafeArrayCopyNode create(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode layoutHelper, Kind elementKind) {
+        return USE_GENERATED_NODES ? new UnsafeArrayCopyNodeGen(src, srcPos, dest, destPos, length, layoutHelper, elementKind) : new UnsafeArrayCopyNode(src, srcPos, dest, destPos, length,
+                        layoutHelper, elementKind);
+    }
+
+    UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode layoutHelper, Kind elementKind) {
         super(StampFactory.forVoid());
         assert layoutHelper == null || elementKind == null;
         this.src = src;
@@ -56,11 +61,19 @@
         this.elementKind = elementKind;
     }
 
-    private UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind) {
+    public static UnsafeArrayCopyNode create(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind) {
+        return USE_GENERATED_NODES ? new UnsafeArrayCopyNodeGen(src, srcPos, dest, destPos, length, elementKind) : new UnsafeArrayCopyNode(src, srcPos, dest, destPos, length, elementKind);
+    }
+
+    UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind) {
         this(src, srcPos, dest, destPos, length, null, elementKind);
     }
 
-    private UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode layoutHelper) {
+    public static UnsafeArrayCopyNode create(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode layoutHelper) {
+        return USE_GENERATED_NODES ? new UnsafeArrayCopyNodeGen(src, srcPos, dest, destPos, length, layoutHelper) : new UnsafeArrayCopyNode(src, srcPos, dest, destPos, length, layoutHelper);
+    }
+
+    UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode layoutHelper) {
         this(src, srcPos, dest, destPos, length, layoutHelper, null);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Mon Aug 25 21:15:59 2014 -0700
@@ -189,14 +189,14 @@
         GraphKit kit = new GraphKit(graph, providers);
         ParameterNode[] params = createParameters(kit, args);
 
-        ReadRegisterNode thread = kit.append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), true, false));
+        ReadRegisterNode thread = kit.append(ReadRegisterNode.create(providers.getRegisters().getThreadRegister(), true, false));
         ValueNode result = createTargetCall(kit, params, thread);
         kit.createInvoke(StubUtil.class, "handlePendingException", thread, ConstantNode.forBoolean(isObjectResult, graph));
         if (isObjectResult) {
             InvokeNode object = kit.createInvoke(HotSpotReplacementsUtil.class, "getAndClearObjectResult", thread);
             result = kit.createInvoke(StubUtil.class, "verifyObject", object);
         }
-        kit.append(new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result));
+        kit.append(ReturnNode.create(linkage.getDescriptor().getResultType() == void.class ? null : result));
 
         if (Debug.isDumpEnabled()) {
             Debug.dump(graph, "Initial stub graph");
@@ -224,7 +224,7 @@
             } else {
                 stamp = StampFactory.forKind(type.getKind());
             }
-            ParameterNode param = kit.unique(new ParameterNode(i, stamp));
+            ParameterNode param = kit.unique(ParameterNode.create(i, stamp));
             params[i] = param;
         }
         return params;
@@ -235,9 +235,9 @@
             ValueNode[] targetArguments = new ValueNode[1 + params.length];
             targetArguments[0] = thread;
             System.arraycopy(params, 0, targetArguments, 1, params.length);
-            return kit.append(new StubForeignCallNode(providers.getForeignCalls(), target.getDescriptor(), targetArguments));
+            return kit.append(StubForeignCallNode.create(providers.getForeignCalls(), target.getDescriptor(), targetArguments));
         } else {
-            return kit.append(new StubForeignCallNode(providers.getForeignCalls(), target.getDescriptor(), params));
+            return kit.append(StubForeignCallNode.create(providers.getForeignCalls(), target.getDescriptor(), params));
         }
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Mon Aug 25 21:15:59 2014 -0700
@@ -148,7 +148,7 @@
             try (Scope d = Debug.sandbox("CompilingStub", DebugScope.getConfig(), providers.getCodeCache(), debugScopeContext())) {
                 final StructuredGraph graph = getGraph();
                 if (!(graph.start() instanceof StubStartNode)) {
-                    StubStartNode newStart = graph.add(new StubStartNode(Stub.this));
+                    StubStartNode newStart = graph.add(StubStartNode.create(Stub.this));
                     newStart.setStateAfter(graph.start().stateAfter());
                     graph.replaceFixed(graph.start(), newStart);
                 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java	Mon Aug 25 21:15:59 2014 -0700
@@ -64,7 +64,7 @@
         Method found = null;
         for (Method method : stubClass.getDeclaredMethods()) {
             if (Modifier.isStatic(method.getModifiers()) && method.getAnnotation(NodeIntrinsic.class) != null && method.getName().equals(name)) {
-                if (method.getAnnotation(NodeIntrinsic.class).value() == StubForeignCallNode.class) {
+                if (method.getAnnotation(NodeIntrinsic.class).value().equals(StubForeignCallNode.class)) {
                     assert found == null : "found more than one foreign call named " + name + " in " + stubClass;
                     assert method.getParameterTypes().length != 0 && method.getParameterTypes()[0] == ForeignCallDescriptor.class : "first parameter of foreign call '" + name + "' in " + stubClass +
                                     " must be of type " + ForeignCallDescriptor.class.getSimpleName();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java	Mon Aug 25 21:15:59 2014 -0700
@@ -35,7 +35,8 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.replacements.Snippet.ConstantParameter;
+import com.oracle.graal.replacements.Snippet.Fold;
 import com.oracle.graal.word.*;
 
 /**
--- a/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerBlock.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerBlock.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,9 +25,9 @@
 import java.io.*;
 import java.util.*;
 
-import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.java.decompiler.*;
 import com.oracle.graal.java.decompiler.lines.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.schedule.*;
--- a/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerAssignmentLine.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerAssignmentLine.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,8 +23,8 @@
 package com.oracle.graal.java.decompiler.lines;
 
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.java.decompiler.block.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
 public class DecompilerAssignmentLine extends DecompilerSyntaxLine {
--- a/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerControlSplitLine.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerControlSplitLine.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,8 +23,8 @@
 package com.oracle.graal.java.decompiler.lines;
 
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.java.decompiler.block.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.cfg.*;
 
 public class DecompilerControlSplitLine extends DecompilerSyntaxLine {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 
 import static com.oracle.graal.api.code.TypeCheckHints.*;
 import static com.oracle.graal.bytecode.Bytecodes.*;
+
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
@@ -895,6 +896,28 @@
         return probability == 0 && optimisticOpts.removeNeverExecutedCode() && entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI;
     }
 
+    protected double branchProbability() {
+        double probability = profilingInfo.getBranchTakenProbability(bci());
+        if (probability < 0) {
+            assert probability == -1 : "invalid probability";
+            Debug.log("missing probability in %s at bci %d", method, bci());
+            probability = 0.5;
+        }
+
+        if (!removeNeverExecutedCode()) {
+            if (probability == 0) {
+                probability = 0.0000001;
+            } else if (probability == 1) {
+                probability = 0.999999;
+            }
+        }
+        return probability;
+    }
+
+    protected boolean removeNeverExecutedCode() {
+        return optimisticOpts.removeNeverExecutedCode() && entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI;
+    }
+
     protected abstract void processBlock(BciBlock block);
 
     protected abstract void iterateBytecodesForBlock(BciBlock block);
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,21 +22,22 @@
  */
 package com.oracle.graal.java;
 
+import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.tiers.*;
 
 public class DefaultSuitesProvider implements SuitesProvider {
 
-    private final Suites defaultSuites;
+    private final DerivedOptionValue<Suites> defaultSuites;
     private final PhaseSuite<HighTierContext> defaultGraphBuilderSuite;
 
     public DefaultSuitesProvider() {
         this.defaultGraphBuilderSuite = createGraphBuilderSuite();
-        this.defaultSuites = createSuites();
+        this.defaultSuites = new DerivedOptionValue<>(this::createSuites);
     }
 
     public Suites getDefaultSuites() {
-        return defaultSuites;
+        return defaultSuites.getValue();
     }
 
     public Suites createSuites() {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -43,6 +43,7 @@
 import com.oracle.graal.java.BciBlockMapping.BciBlock;
 import com.oracle.graal.java.BciBlockMapping.ExceptionDispatchBlock;
 import com.oracle.graal.java.BciBlockMapping.LocalLiveness;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.calc.*;
@@ -99,6 +100,7 @@
          * the jump. When the block is seen the second time, a {@link MergeNode} is created to
          * correctly merge the now two different predecessor states.
          */
+        @NodeInfo
         protected static class BlockPlaceholderNode extends FixedWithNextNode {
 
             /*
@@ -108,7 +110,11 @@
              */
             private final Object nextPlaceholder;
 
-            public BlockPlaceholderNode(BytecodeParser builder) {
+            public static BlockPlaceholderNode create(BytecodeParser builder) {
+                return USE_GENERATED_NODES ? new GraphBuilderPhase_Instance_BlockPlaceholderNodeGen(builder) : new BlockPlaceholderNode(builder);
+            }
+
+            protected BlockPlaceholderNode(BytecodeParser builder) {
                 super(StampFactory.forVoid());
                 nextPlaceholder = builder.placeholders;
                 builder.placeholders = this;
@@ -320,7 +326,7 @@
             @Override
             protected void handleUnresolvedLoadConstant(JavaType type) {
                 assert !graphBuilderConfig.eagerResolving();
-                append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
+                append(DeoptimizeNode.create(InvalidateRecompile, Unresolved));
             }
 
             /**
@@ -330,7 +336,7 @@
             @Override
             protected void handleUnresolvedCheckCast(JavaType type, ValueNode object) {
                 assert !graphBuilderConfig.eagerResolving();
-                append(new FixedGuardNode(currentGraph.unique(new IsNullNode(object)), Unresolved, InvalidateRecompile));
+                append(FixedGuardNode.create(currentGraph.unique(IsNullNode.create(object)), Unresolved, InvalidateRecompile));
                 frameState.apush(appendConstant(Constant.NULL_OBJECT));
             }
 
@@ -341,9 +347,9 @@
             @Override
             protected void handleUnresolvedInstanceOf(JavaType type, ValueNode object) {
                 assert !graphBuilderConfig.eagerResolving();
-                BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode(this));
-                DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved));
-                append(new IfNode(currentGraph.unique(new IsNullNode(object)), successor, deopt, 1));
+                BlockPlaceholderNode successor = currentGraph.add(BlockPlaceholderNode.create(this));
+                DeoptimizeNode deopt = currentGraph.add(DeoptimizeNode.create(InvalidateRecompile, Unresolved));
+                append(IfNode.create(currentGraph.unique(IsNullNode.create(object)), successor, deopt, 1));
                 lastInstr = successor;
                 frameState.ipush(appendConstant(Constant.INT_0));
             }
@@ -354,7 +360,7 @@
             @Override
             protected void handleUnresolvedNewInstance(JavaType type) {
                 assert !graphBuilderConfig.eagerResolving();
-                append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
+                append(DeoptimizeNode.create(InvalidateRecompile, Unresolved));
             }
 
             /**
@@ -364,7 +370,7 @@
             @Override
             protected void handleUnresolvedNewObjectArray(JavaType type, ValueNode length) {
                 assert !graphBuilderConfig.eagerResolving();
-                append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
+                append(DeoptimizeNode.create(InvalidateRecompile, Unresolved));
             }
 
             /**
@@ -374,7 +380,7 @@
             @Override
             protected void handleUnresolvedNewMultiArray(JavaType type, List<ValueNode> dims) {
                 assert !graphBuilderConfig.eagerResolving();
-                append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
+                append(DeoptimizeNode.create(InvalidateRecompile, Unresolved));
             }
 
             /**
@@ -385,7 +391,7 @@
             @Override
             protected void handleUnresolvedLoadField(JavaField field, ValueNode receiver) {
                 assert !graphBuilderConfig.eagerResolving();
-                append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
+                append(DeoptimizeNode.create(InvalidateRecompile, Unresolved));
             }
 
             /**
@@ -397,7 +403,7 @@
             @Override
             protected void handleUnresolvedStoreField(JavaField field, ValueNode value, ValueNode receiver) {
                 assert !graphBuilderConfig.eagerResolving();
-                append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
+                append(DeoptimizeNode.create(InvalidateRecompile, Unresolved));
             }
 
             /**
@@ -407,7 +413,7 @@
             @Override
             protected void handleUnresolvedExceptionType(Representation representation, JavaType type) {
                 assert !graphBuilderConfig.eagerResolving();
-                append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
+                append(DeoptimizeNode.create(InvalidateRecompile, Unresolved));
             }
 
             /**
@@ -416,7 +422,7 @@
              */
             protected void handleUnresolvedInvoke(JavaMethod javaMethod, InvokeKind invokeKind) {
                 assert !graphBuilderConfig.eagerResolving();
-                append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
+                append(DeoptimizeNode.create(InvalidateRecompile, Unresolved));
             }
 
             private DispatchBeginNode handleException(ValueNode exceptionObject, int bci) {
@@ -438,12 +444,12 @@
 
                 DispatchBeginNode dispatchBegin;
                 if (exceptionObject == null) {
-                    dispatchBegin = currentGraph.add(new ExceptionObjectNode(metaAccess));
+                    dispatchBegin = currentGraph.add(ExceptionObjectNode.create(metaAccess));
                     dispatchState.apush(dispatchBegin);
                     dispatchState.setRethrowException(true);
                     dispatchBegin.setStateAfter(dispatchState.create(bci));
                 } else {
-                    dispatchBegin = currentGraph.add(new DispatchBeginNode());
+                    dispatchBegin = currentGraph.add(DispatchBeginNode.create());
                     dispatchState.apush(exceptionObject);
                     dispatchBegin.setStateAfter(dispatchState.create(bci));
                     dispatchState.setRethrowException(true);
@@ -456,122 +462,122 @@
 
             @Override
             protected ValueNode genLoadIndexed(ValueNode array, ValueNode index, Kind kind) {
-                return new LoadIndexedNode(array, index, kind);
+                return LoadIndexedNode.create(array, index, kind);
             }
 
             @Override
             protected ValueNode genStoreIndexed(ValueNode array, ValueNode index, Kind kind, ValueNode value) {
-                return new StoreIndexedNode(array, index, kind, value);
+                return StoreIndexedNode.create(array, index, kind, value);
             }
 
             @Override
             protected ValueNode genIntegerAdd(Kind kind, ValueNode x, ValueNode y) {
-                return new IntegerAddNode(x, y);
+                return IntegerAddNode.create(x, y);
             }
 
             @Override
             protected ValueNode genIntegerSub(Kind kind, ValueNode x, ValueNode y) {
-                return new IntegerSubNode(x, y);
+                return IntegerSubNode.create(x, y);
             }
 
             @Override
             protected ValueNode genIntegerMul(Kind kind, ValueNode x, ValueNode y) {
-                return new IntegerMulNode(x, y);
+                return IntegerMulNode.create(x, y);
             }
 
             @Override
             protected ValueNode genFloatAdd(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) {
-                return new FloatAddNode(x, y, isStrictFP);
+                return FloatAddNode.create(x, y, isStrictFP);
             }
 
             @Override
             protected ValueNode genFloatSub(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) {
-                return new FloatSubNode(x, y, isStrictFP);
+                return FloatSubNode.create(x, y, isStrictFP);
             }
 
             @Override
             protected ValueNode genFloatMul(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) {
-                return new FloatMulNode(x, y, isStrictFP);
+                return FloatMulNode.create(x, y, isStrictFP);
             }
 
             @Override
             protected ValueNode genFloatDiv(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) {
-                return new FloatDivNode(x, y, isStrictFP);
+                return FloatDivNode.create(x, y, isStrictFP);
             }
 
             @Override
             protected ValueNode genFloatRem(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) {
-                return new FloatRemNode(x, y, isStrictFP);
+                return FloatRemNode.create(x, y, isStrictFP);
             }
 
             @Override
             protected ValueNode genIntegerDiv(Kind kind, ValueNode x, ValueNode y) {
-                return new IntegerDivNode(x, y);
+                return IntegerDivNode.create(x, y);
             }
 
             @Override
             protected ValueNode genIntegerRem(Kind kind, ValueNode x, ValueNode y) {
-                return new IntegerRemNode(x, y);
+                return IntegerRemNode.create(x, y);
             }
 
             @Override
             protected ValueNode genNegateOp(ValueNode x) {
-                return (new NegateNode(x));
+                return (NegateNode.create(x));
             }
 
             @Override
             protected ValueNode genLeftShift(Kind kind, ValueNode x, ValueNode y) {
-                return new LeftShiftNode(x, y);
+                return LeftShiftNode.create(x, y);
             }
 
             @Override
             protected ValueNode genRightShift(Kind kind, ValueNode x, ValueNode y) {
-                return new RightShiftNode(x, y);
+                return RightShiftNode.create(x, y);
             }
 
             @Override
             protected ValueNode genUnsignedRightShift(Kind kind, ValueNode x, ValueNode y) {
-                return new UnsignedRightShiftNode(x, y);
+                return UnsignedRightShiftNode.create(x, y);
             }
 
             @Override
             protected ValueNode genAnd(Kind kind, ValueNode x, ValueNode y) {
-                return new AndNode(x, y);
+                return AndNode.create(x, y);
             }
 
             @Override
             protected ValueNode genOr(Kind kind, ValueNode x, ValueNode y) {
-                return new OrNode(x, y);
+                return OrNode.create(x, y);
             }
 
             @Override
             protected ValueNode genXor(Kind kind, ValueNode x, ValueNode y) {
-                return new XorNode(x, y);
+                return XorNode.create(x, y);
             }
 
             @Override
             protected ValueNode genNormalizeCompare(ValueNode x, ValueNode y, boolean isUnorderedLess) {
-                return new NormalizeCompareNode(x, y, isUnorderedLess);
+                return NormalizeCompareNode.create(x, y, isUnorderedLess);
             }
 
             @Override
             protected ValueNode genFloatConvert(FloatConvert op, ValueNode input) {
-                return new FloatConvertNode(op, input);
+                return FloatConvertNode.create(op, input);
             }
 
             @Override
             protected ValueNode genNarrow(ValueNode input, int bitCount) {
-                return new NarrowNode(input, bitCount);
+                return NarrowNode.create(input, bitCount);
             }
 
             @Override
             protected ValueNode genSignExtend(ValueNode input, int bitCount) {
-                return new SignExtendNode(input, bitCount);
+                return SignExtendNode.create(input, bitCount);
             }
 
             @Override
             protected ValueNode genZeroExtend(ValueNode input, int bitCount) {
-                return new ZeroExtendNode(input, bitCount);
+                return ZeroExtendNode.create(input, bitCount);
             }
 
             @Override
@@ -582,17 +588,17 @@
 
             @Override
             protected ValueNode genObjectEquals(ValueNode x, ValueNode y) {
-                return new ObjectEqualsNode(x, y);
+                return ObjectEqualsNode.create(x, y);
             }
 
             @Override
             protected ValueNode genIntegerEquals(ValueNode x, ValueNode y) {
-                return new IntegerEqualsNode(x, y);
+                return IntegerEqualsNode.create(x, y);
             }
 
             @Override
             protected ValueNode genIntegerLessThan(ValueNode x, ValueNode y) {
-                return new IntegerLessThanNode(x, y);
+                return IntegerLessThanNode.create(x, y);
             }
 
             @Override
@@ -601,49 +607,49 @@
             }
 
             protected ValueNode genIfNode(ValueNode condition, ValueNode falseSuccessor, ValueNode trueSuccessor, double d) {
-                return new IfNode((LogicNode) condition, (FixedNode) falseSuccessor, (FixedNode) trueSuccessor, d);
+                return IfNode.create((LogicNode) condition, (FixedNode) falseSuccessor, (FixedNode) trueSuccessor, d);
             }
 
             @Override
             protected void genThrow() {
                 ValueNode exception = frameState.apop();
-                append(new FixedGuardNode(currentGraph.unique(new IsNullNode(exception)), NullCheckException, InvalidateReprofile, true));
+                append(FixedGuardNode.create(currentGraph.unique(IsNullNode.create(exception)), NullCheckException, InvalidateReprofile, true));
                 lastInstr.setNext(handleException(exception, bci()));
             }
 
             @Override
             protected ValueNode createCheckCast(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck, boolean forStoreCheck) {
-                return new CheckCastNode(type, object, profileForTypeCheck, forStoreCheck);
+                return CheckCastNode.create(type, object, profileForTypeCheck, forStoreCheck);
             }
 
             @Override
             protected ValueNode createInstanceOf(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck) {
-                return new InstanceOfNode(type, object, profileForTypeCheck);
+                return InstanceOfNode.create(type, object, profileForTypeCheck);
             }
 
             @Override
             protected ValueNode genConditional(ValueNode x) {
-                return new ConditionalNode((LogicNode) x);
+                return ConditionalNode.create((LogicNode) x);
             }
 
             @Override
             protected NewInstanceNode createNewInstance(ResolvedJavaType type, boolean fillContents) {
-                return new NewInstanceNode(type, fillContents);
+                return NewInstanceNode.create(type, fillContents);
             }
 
             @Override
             protected NewArrayNode createNewArray(ResolvedJavaType elementType, ValueNode length, boolean fillContents) {
-                return new NewArrayNode(elementType, length, fillContents);
+                return NewArrayNode.create(elementType, length, fillContents);
             }
 
             @Override
             protected NewMultiArrayNode createNewMultiArray(ResolvedJavaType type, List<ValueNode> dimensions) {
-                return new NewMultiArrayNode(type, dimensions.toArray(new ValueNode[0]));
+                return NewMultiArrayNode.create(type, dimensions.toArray(new ValueNode[0]));
             }
 
             @Override
             protected ValueNode genLoadField(ValueNode receiver, ResolvedJavaField field) {
-                return new LoadFieldNode(receiver, field);
+                return LoadFieldNode.create(receiver, field);
             }
 
             @Override
@@ -651,12 +657,12 @@
                 if (StampTool.isObjectNonNull(receiver.stamp())) {
                     return;
                 }
-                BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode(this));
-                BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode(this));
-                append(new IfNode(currentGraph.unique(new IsNullNode(receiver)), trueSucc, falseSucc, 0.01));
+                BlockPlaceholderNode trueSucc = currentGraph.add(BlockPlaceholderNode.create(this));
+                BlockPlaceholderNode falseSucc = currentGraph.add(BlockPlaceholderNode.create(this));
+                append(IfNode.create(currentGraph.unique(IsNullNode.create(receiver)), trueSucc, falseSucc, 0.01));
                 lastInstr = falseSucc;
 
-                BytecodeExceptionNode exception = currentGraph.add(new BytecodeExceptionNode(metaAccess, NullPointerException.class));
+                BytecodeExceptionNode exception = currentGraph.add(BytecodeExceptionNode.create(metaAccess, NullPointerException.class));
                 exception.setStateAfter(frameState.create(bci()));
                 trueSucc.setNext(exception);
                 exception.setNext(handleException(exception, bci()));
@@ -664,12 +670,12 @@
 
             @Override
             protected void emitBoundsCheck(ValueNode index, ValueNode length) {
-                BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode(this));
-                BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode(this));
-                append(new IfNode(currentGraph.unique(new IntegerBelowNode(index, length)), trueSucc, falseSucc, 0.99));
+                BlockPlaceholderNode trueSucc = currentGraph.add(BlockPlaceholderNode.create(this));
+                BlockPlaceholderNode falseSucc = currentGraph.add(BlockPlaceholderNode.create(this));
+                append(IfNode.create(currentGraph.unique(IntegerBelowNode.create(index, length)), trueSucc, falseSucc, 0.99));
                 lastInstr = trueSucc;
 
-                BytecodeExceptionNode exception = currentGraph.add(new BytecodeExceptionNode(metaAccess, ArrayIndexOutOfBoundsException.class, index));
+                BytecodeExceptionNode exception = currentGraph.add(BytecodeExceptionNode.create(metaAccess, ArrayIndexOutOfBoundsException.class, index));
                 exception.setStateAfter(frameState.create(bci()));
                 falseSucc.setNext(exception);
                 exception.setNext(handleException(exception, bci()));
@@ -677,12 +683,12 @@
 
             @Override
             protected ValueNode genArrayLength(ValueNode x) {
-                return new ArrayLengthNode(x);
+                return ArrayLengthNode.create(x);
             }
 
             @Override
             protected ValueNode genStoreField(ValueNode receiver, ResolvedJavaField field, ValueNode value) {
-                return new StoreFieldNode(receiver, field, value);
+                return StoreFieldNode.create(receiver, field, value);
             }
 
             /**
@@ -783,7 +789,7 @@
             private void appendInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args) {
                 Kind resultType = targetMethod.getSignature().getReturnKind();
                 if (DeoptALot.getValue()) {
-                    append(new DeoptimizeNode(DeoptimizationAction.None, RuntimeConstraint));
+                    append(DeoptimizeNode.create(DeoptimizationAction.None, RuntimeConstraint));
                     frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, currentGraph));
                     return;
                 }
@@ -796,7 +802,7 @@
                     emitExplicitExceptions(args[0], null);
                     if (invokeKind != InvokeKind.Special && this.optimisticOpts.useTypeCheckHints()) {
                         JavaTypeProfile profile = profilingInfo.getTypeProfile(bci());
-                        args[0] = TypeProfileProxyNode.create(args[0], profile);
+                        args[0] = TypeProfileProxyNode.proxify(args[0], profile);
                     }
                 }
                 MethodCallTargetNode callTarget = currentGraph.add(createMethodCallTarget(invokeKind, targetMethod, args, returnType));
@@ -818,18 +824,18 @@
             }
 
             protected MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, JavaType returnType) {
-                return new MethodCallTargetNode(invokeKind, targetMethod, args, returnType);
+                return MethodCallTargetNode.create(invokeKind, targetMethod, args, returnType);
             }
 
             protected InvokeNode createInvoke(CallTargetNode callTarget, Kind resultType) {
-                InvokeNode invoke = append(new InvokeNode(callTarget, bci()));
+                InvokeNode invoke = append(InvokeNode.create(callTarget, bci()));
                 frameState.pushReturn(resultType, invoke);
                 return invoke;
             }
 
             protected InvokeWithExceptionNode createInvokeWithException(CallTargetNode callTarget, Kind resultType) {
                 DispatchBeginNode exceptionEdge = handleException(null, bci());
-                InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, bci()));
+                InvokeWithExceptionNode invoke = append(InvokeWithExceptionNode.create(callTarget, exceptionEdge, bci()));
                 frameState.pushReturn(resultType, invoke);
                 BciBlock nextBlock = currentBlock.getSuccessor(0);
                 invoke.setStateAfter(frameState.create(nextBlock.startBci));
@@ -849,13 +855,13 @@
                     throw new BailoutException("unbalanced monitors");
                 }
 
-                append(new ReturnNode(x));
+                append(ReturnNode.create(x));
             }
 
             @Override
             protected MonitorEnterNode genMonitorEnter(ValueNode x) {
-                MonitorIdNode monitorId = currentGraph.add(new MonitorIdNode(frameState.lockDepth()));
-                MonitorEnterNode monitorEnter = append(new MonitorEnterNode(x, monitorId));
+                MonitorIdNode monitorId = currentGraph.add(MonitorIdNode.create(frameState.lockDepth()));
+                MonitorEnterNode monitorEnter = append(MonitorEnterNode.create(x, monitorId));
                 frameState.pushLock(x, monitorId);
                 return monitorEnter;
             }
@@ -867,7 +873,7 @@
                 if (GraphUtil.originalValue(lockedObject) != GraphUtil.originalValue(x)) {
                     throw new BailoutException("unbalanced monitors: mismatch at monitorexit, %s != %s", GraphUtil.originalValue(x), GraphUtil.originalValue(lockedObject));
                 }
-                MonitorExitNode monitorExit = append(new MonitorExitNode(x, monitorId, returnValue));
+                MonitorExitNode monitorExit = append(MonitorExitNode.create(x, monitorId, returnValue));
                 return monitorExit;
             }
 
@@ -892,7 +898,7 @@
                 ValueNode local = frameState.loadLocal(localIndex);
                 JsrScope scope = currentBlock.jsrScope;
                 int retAddress = scope.nextReturnAddress();
-                append(new FixedGuardNode(currentGraph.unique(new IntegerEqualsNode(local, ConstantNode.forInt(retAddress, currentGraph))), JavaSubroutineMismatch, InvalidateReprofile));
+                append(FixedGuardNode.create(currentGraph.unique(IntegerEqualsNode.create(local, ConstantNode.forInt(retAddress, currentGraph))), JavaSubroutineMismatch, InvalidateReprofile));
                 if (!successor.jsrScope.equals(scope.pop())) {
                     throw new JsrNotSupportedBailout("unstructured control flow (ret leaves more than one scope)");
                 }
@@ -902,7 +908,7 @@
             @Override
             protected void genIntegerSwitch(ValueNode value, ArrayList<BciBlock> actualSuccessors, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
                 double[] successorProbabilities = successorProbabilites(actualSuccessors.size(), keySuccessors, keyProbabilities);
-                IntegerSwitchNode switchNode = append(new IntegerSwitchNode(value, actualSuccessors.size(), keys, keyProbabilities, keySuccessors));
+                IntegerSwitchNode switchNode = append(IntegerSwitchNode.create(value, actualSuccessors.size(), keys, keyProbabilities, keySuccessors));
                 for (int i = 0; i < actualSuccessors.size(); i++) {
                     switchNode.setBlockSuccessor(i, createBlockTarget(successorProbabilities[i], actualSuccessors.get(i), frameState));
                 }
@@ -997,7 +1003,7 @@
                         HIRFrameStateBuilder newState = state.copy();
                         for (BciBlock loop : exitLoops) {
                             LoopBeginNode loopBegin = (LoopBeginNode) loop.firstInstruction;
-                            LoopExitNode loopExit = currentGraph.add(new LoopExitNode(loopBegin));
+                            LoopExitNode loopExit = currentGraph.add(LoopExitNode.create(loopBegin));
                             if (lastLoopExit != null) {
                                 lastLoopExit.setNext(loopExit);
                             }
@@ -1020,7 +1026,7 @@
             private FixedNode createTarget(double probability, BciBlock block, HIRFrameStateBuilder stateAfter) {
                 assert probability >= 0 && probability <= 1.01 : probability;
                 if (isNeverExecutedCode(probability)) {
-                    return currentGraph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode));
+                    return currentGraph.add(DeoptimizeNode.create(InvalidateReprofile, UnreachedCode));
                 } else {
                     assert block != null;
                     return createTarget(block, stateAfter);
@@ -1037,7 +1043,7 @@
                      * return a placeholder that later can be replaced with a MergeNode when we see
                      * this block again.
                      */
-                    block.firstInstruction = currentGraph.add(new BlockPlaceholderNode(this));
+                    block.firstInstruction = currentGraph.add(BlockPlaceholderNode.create(this));
                     Target target = checkLoopExit(block.firstInstruction, block, state);
                     FixedNode result = target.fixed;
                     block.entryState = target.state == state ? state.copy() : target.state;
@@ -1059,7 +1065,7 @@
                      * the loop begin node created before.
                      */
                     LoopBeginNode loopBegin = (LoopBeginNode) block.firstInstruction;
-                    Target target = checkLoopExit(currentGraph.add(new LoopEndNode(loopBegin)), block, state);
+                    Target target = checkLoopExit(currentGraph.add(LoopEndNode.create(loopBegin)), block, state);
                     FixedNode result = target.fixed;
                     ((HIRFrameStateBuilder) block.entryState).merge(loopBegin, target.state);
 
@@ -1078,9 +1084,9 @@
                     BlockPlaceholderNode placeholder = (BlockPlaceholderNode) block.firstInstruction;
 
                     // The EndNode for the already existing edge.
-                    AbstractEndNode end = currentGraph.add(new EndNode());
+                    AbstractEndNode end = currentGraph.add(EndNode.create());
                     // The MergeNode that replaces the placeholder.
-                    MergeNode mergeNode = currentGraph.add(new MergeNode());
+                    MergeNode mergeNode = currentGraph.add(MergeNode.create());
                     FixedNode next = placeholder.next();
 
                     placeholder.setNext(end);
@@ -1093,7 +1099,7 @@
                 MergeNode mergeNode = (MergeNode) block.firstInstruction;
 
                 // The EndNode for the newly merged edge.
-                AbstractEndNode newEnd = currentGraph.add(new EndNode());
+                AbstractEndNode newEnd = currentGraph.add(EndNode.create());
                 Target target = checkLoopExit(newEnd, block, state);
                 FixedNode result = target.fixed;
                 ((HIRFrameStateBuilder) block.entryState).merge(mergeNode, target.state);
@@ -1184,7 +1190,7 @@
                 assert frameState.stackSize() == 1 : frameState;
                 ValueNode exception = frameState.apop();
                 synchronizedEpilogue(BytecodeFrame.AFTER_EXCEPTION_BCI, null);
-                append(new UnwindNode(exception));
+                append(UnwindNode.create(exception));
             }
 
             private void synchronizedEpilogue(int bci, ValueNode returnValue) {
@@ -1217,9 +1223,9 @@
                         if (skippedType.isAssignableFrom(resolvedCatchType)) {
                             BciBlock nextBlock = block.getSuccessorCount() == 1 ? unwindBlock() : block.getSuccessor(1);
                             ValueNode exception = frameState.stackAt(0);
-                            FixedNode trueSuccessor = currentGraph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode));
+                            FixedNode trueSuccessor = currentGraph.add(DeoptimizeNode.create(InvalidateReprofile, UnreachedCode));
                             FixedNode nextDispatch = createTarget(nextBlock, frameState);
-                            append(new IfNode(currentGraph.unique(new InstanceOfNode((ResolvedJavaType) catchType, exception, null)), trueSuccessor, nextDispatch, 0));
+                            append(IfNode.create(currentGraph.unique(InstanceOfNode.create((ResolvedJavaType) catchType, exception, null)), trueSuccessor, nextDispatch, 0));
                             return;
                         }
                     }
@@ -1228,7 +1234,7 @@
                 if (initialized) {
                     BciBlock nextBlock = block.getSuccessorCount() == 1 ? unwindBlock() : block.getSuccessor(1);
                     ValueNode exception = frameState.stackAt(0);
-                    CheckCastNode checkCast = currentGraph.add(new CheckCastNode((ResolvedJavaType) catchType, exception, null, false));
+                    CheckCastNode checkCast = currentGraph.add(CheckCastNode.create((ResolvedJavaType) catchType, exception, null, false));
                     frameState.apop();
                     frameState.push(Kind.Object, checkCast);
                     FixedNode catchSuccessor = createTarget(block.getSuccessor(0), frameState);
@@ -1236,7 +1242,7 @@
                     frameState.push(Kind.Object, exception);
                     FixedNode nextDispatch = createTarget(nextBlock, frameState);
                     checkCast.setNext(catchSuccessor);
-                    append(new IfNode(currentGraph.unique(new InstanceOfNode((ResolvedJavaType) catchType, exception, null)), checkCast, nextDispatch, 0.5));
+                    append(IfNode.create(currentGraph.unique(InstanceOfNode.create((ResolvedJavaType) catchType, exception, null)), checkCast, nextDispatch, 0.5));
                 } else {
                     handleUnresolvedExceptionType(Representation.ObjectHub, catchType);
                 }
@@ -1258,8 +1264,8 @@
                     // Create the loop header block, which later will merge the backward branches of
                     // the
                     // loop.
-                    AbstractEndNode preLoopEnd = currentGraph.add(new EndNode());
-                    LoopBeginNode loopBegin = currentGraph.add(new LoopBeginNode());
+                    AbstractEndNode preLoopEnd = currentGraph.add(EndNode.create());
+                    LoopBeginNode loopBegin = currentGraph.add(LoopBeginNode.create());
                     lastInstr.setNext(preLoopEnd);
                     // Add the single non-loop predecessor of the loop header.
                     loopBegin.addForwardEnd(preLoopEnd);
@@ -1311,7 +1317,7 @@
                         if (block.jsrScope != JsrScope.EMPTY_SCOPE) {
                             throw new BailoutException("OSR into a JSR scope is not supported");
                         }
-                        EntryMarkerNode x = append(new EntryMarkerNode());
+                        EntryMarkerNode x = append(EntryMarkerNode.create());
                         frameState.insertProxies(x);
                         x.setStateAfter(frameState.create(bci));
                     }
@@ -1328,7 +1334,7 @@
                         frameState.clearNonLiveLocals(currentBlock, liveness, false);
                     }
                     if (lastInstr instanceof StateSplit) {
-                        if (lastInstr.getClass() == BeginNode.class) {
+                        if (lastInstr.getClass() == BeginNode.getGenClass()) {
                             // BeginNodes do not need a frame state
                         } else {
                             StateSplit stateSplit = (StateSplit) lastInstr;
@@ -1363,9 +1369,9 @@
 
             private InfopointNode createInfoPointNode(InfopointReason reason) {
                 if (graphBuilderConfig.insertFullDebugInfo()) {
-                    return new FullInfopointNode(reason, frameState.create(bci()));
+                    return FullInfopointNode.create(reason, frameState.create(bci()));
                 } else {
-                    return new SimpleInfopointNode(reason, new BytecodePosition(null, method, bci()));
+                    return SimpleInfopointNode.create(reason, new BytecodePosition(null, method, bci()));
                 }
             }
 
@@ -1395,20 +1401,7 @@
                     return;
                 }
 
-                double probability = profilingInfo.getBranchTakenProbability(bci());
-                if (probability < 0) {
-                    assert probability == -1 : "invalid probability";
-                    Debug.log("missing probability in %s at bci %d", method, bci());
-                    probability = 0.5;
-                }
-
-                if (!optimisticOpts.removeNeverExecutedCode()) {
-                    if (probability == 0) {
-                        probability = 0.0000001;
-                    } else if (probability == 1) {
-                        probability = 0.999999;
-                    }
-                }
+                double probability = branchProbability();
 
                 // the mirroring and negation operations get the condition into canonical form
                 boolean mirror = cond.canonicalMirror();
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,13 +23,14 @@
 package com.oracle.graal.java;
 
 import static com.oracle.graal.graph.iterators.NodePredicates.*;
+
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.Node.Verbosity;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
@@ -55,7 +56,7 @@
         int index = 0;
         if (!method.isStatic()) {
             // add the receiver
-            ParameterNode receiver = graph.unique(new ParameterNode(javaIndex, StampFactory.declaredNonNull(method.getDeclaringClass())));
+            ParameterNode receiver = graph.unique(ParameterNode.create(javaIndex, StampFactory.declaredNonNull(method.getDeclaringClass())));
             storeLocal(javaIndex, receiver);
             javaIndex = 1;
             index = 1;
@@ -75,7 +76,7 @@
             } else {
                 stamp = StampFactory.forKind(kind);
             }
-            ParameterNode param = graph.unique(new ParameterNode(index, stamp));
+            ParameterNode param = graph.unique(ParameterNode.create(index, stamp));
             storeLocal(javaIndex, param);
             javaIndex += stackSlots(kind);
             index++;
@@ -122,7 +123,7 @@
     }
 
     public FrameState create(int bci) {
-        return graph.add(new FrameState(method, bci, locals, Arrays.asList(stack).subList(0, stackSize), lockedObjects, monitorIds, rethrowException, false));
+        return graph.add(FrameState.create(method, bci, locals, Arrays.asList(stack).subList(0, stackSize), lockedObjects, monitorIds, rethrowException, false));
     }
 
     @Override
@@ -189,7 +190,7 @@
                 return null;
             }
 
-            ValuePhiNode phi = graph.addWithoutUnique(new ValuePhiNode(currentValue.stamp().unrestricted(), block));
+            ValuePhiNode phi = graph.addWithoutUnique(ValuePhiNode.create(currentValue.stamp().unrestricted(), block));
             for (int i = 0; i < block.phiPredecessorCount(); i++) {
                 phi.addInput(currentValue);
             }
@@ -287,7 +288,7 @@
         }
         assert !block.isPhiAtMerge(value) : "phi function for this block already created";
 
-        ValuePhiNode phi = graph.addWithoutUnique(new ValuePhiNode(value.stamp().unrestricted(), block));
+        ValuePhiNode phi = graph.addWithoutUnique(ValuePhiNode.create(value.stamp().unrestricted(), block));
         phi.addInput(value);
         return phi;
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -57,8 +57,8 @@
     }
 
     @Override
-    protected StructuredGraph parse(Method m) {
-        StructuredGraph graph = super.parse(m);
+    protected StructuredGraph parseEager(Method m) {
+        StructuredGraph graph = super.parseEager(m);
         if (argsToBind != null) {
             Object receiver = isStatic(m.getModifiers()) ? null : this;
             Object[] args = argsWithReceiver(receiver, argsToBind);
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Mon Aug 25 21:15:59 2014 -0700
@@ -926,16 +926,16 @@
                     break;
 
                 case B2I:
-                    masm.movsbl(asIntReg(dst), (AMD64Address) crb.asIntAddr(src));
+                    masm.movsbl(asIntReg(dst), (AMD64Address) crb.asByteAddr(src));
                     break;
                 case S2I:
-                    masm.movswl(asIntReg(dst), (AMD64Address) crb.asIntAddr(src));
+                    masm.movswl(asIntReg(dst), (AMD64Address) crb.asShortAddr(src));
                     break;
                 case B2L:
-                    masm.movsbq(asLongReg(dst), (AMD64Address) crb.asIntAddr(src));
+                    masm.movsbq(asLongReg(dst), (AMD64Address) crb.asByteAddr(src));
                     break;
                 case S2L:
-                    masm.movswq(asLongReg(dst), (AMD64Address) crb.asIntAddr(src));
+                    masm.movswq(asLongReg(dst), (AMD64Address) crb.asShortAddr(src));
                     break;
                 case I2L:
                     masm.movslq(asLongReg(dst), (AMD64Address) crb.asIntAddr(src));
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java	Mon Aug 25 21:15:59 2014 -0700
@@ -167,7 +167,7 @@
 
     public static class ShiftOp extends HSAILLIRInstruction {
         @Opcode private final HSAILArithmetic opcode;
-        @Def({REG, HINT}) protected Value result;
+        @Def({REG}) protected Value result;
         @Use({REG, CONST}) protected Value x;
         @Alive({REG, CONST}) protected Value y;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest1.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.test;
+
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * This test verifies that {@link CompositeValue}s are immutable, i.e. that a write to a component
+ * of a {@link CompositeValue} results in a new {@link CompositeValue}.
+ */
+public class CompositeValueReplacementTest1 {
+
+    private static class NestedCompositeValue extends CompositeValue {
+
+        private static final long serialVersionUID = -8804214200173503527L;
+        @Component({REG, OperandFlag.ILLEGAL}) protected Value value;
+
+        public NestedCompositeValue(Value value) {
+            super(LIRKind.Illegal);
+            this.value = value;
+        }
+
+    }
+
+    private static class DummyValue extends Value {
+
+        private static final long serialVersionUID = -645435039553382737L;
+        private final int id;
+        private static int counter = 1;
+
+        protected DummyValue() {
+            super(LIRKind.Illegal);
+            this.id = counter++;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = super.hashCode();
+            result = prime * result + id;
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (!super.equals(obj)) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            DummyValue other = (DummyValue) obj;
+            if (id != other.id) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            return "DummyValue [id=" + id + "]";
+        }
+
+    }
+
+    private static class TestOp extends LIRInstruction {
+
+        @Use({COMPOSITE}) protected NestedCompositeValue compValue;
+
+        public TestOp(NestedCompositeValue compValue) {
+            this.compValue = compValue;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb) {
+            fail("should not reach!");
+        }
+
+    }
+
+    private static NestedCompositeValue createNestedCompValue(Value value, int nestingLevel) {
+        NestedCompositeValue compValue = new NestedCompositeValue(value);
+        for (int i = 0; i < nestingLevel; i++) {
+            compValue = new NestedCompositeValue(compValue);
+        }
+        return compValue;
+    }
+
+    @Test
+    public void replaceCompValueTest0() {
+        DummyValue dummyValue1 = new DummyValue();
+        DummyValue dummyValue2 = new DummyValue();
+        DummyValue dummyValue3 = new DummyValue();
+        NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 0);
+        LIRInstruction op1 = new TestOp(compValue1);
+        LIRInstruction op2 = new TestOp(compValue1);
+
+        op1.forEachInput(new InstructionValueProcedure() {
+            @Override
+            public Value doValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue1, value);
+                return dummyValue2;
+            }
+        });
+
+        op2.forEachInput(new InstructionValueProcedure() {
+            @Override
+            public Value doValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue1, value);
+                return dummyValue3;
+            }
+        });
+
+        op1.visitEachInput(new InstructionValueConsumer() {
+            @Override
+            public void visitValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue2, value);
+            }
+        });
+
+        op2.visitEachInput(new InstructionValueConsumer() {
+            @Override
+            public void visitValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue3, value);
+            }
+        });
+    }
+
+    @Test
+    public void replaceCompValueTest1() {
+        DummyValue dummyValue1 = new DummyValue();
+        DummyValue dummyValue2 = new DummyValue();
+        DummyValue dummyValue3 = new DummyValue();
+        NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 1);
+        LIRInstruction op1 = new TestOp(compValue1);
+        LIRInstruction op2 = new TestOp(compValue1);
+
+        op1.forEachInput(new InstructionValueProcedure() {
+            @Override
+            public Value doValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue1, value);
+                return dummyValue2;
+            }
+        });
+
+        op2.forEachInput(new InstructionValueProcedure() {
+            @Override
+            public Value doValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue1, value);
+                return dummyValue3;
+            }
+        });
+
+        op1.visitEachInput(new InstructionValueConsumer() {
+            @Override
+            public void visitValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue2, value);
+            }
+        });
+
+        op2.visitEachInput(new InstructionValueConsumer() {
+            @Override
+            public void visitValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue3, value);
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest2.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.test;
+
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Same as {@link CompositeValueReplacementTest1} but with value arrays.
+ *
+ * @see CompositeValueReplacementTest1
+ */
+public class CompositeValueReplacementTest2 {
+
+    private static class NestedCompositeValue extends CompositeValue {
+
+        private static final long serialVersionUID = -8804214200173503527L;
+        @Component({REG, OperandFlag.ILLEGAL}) protected Value[] values;
+
+        public NestedCompositeValue(Value value) {
+            super(LIRKind.Illegal);
+            this.values = new Value[]{value};
+        }
+
+    }
+
+    private static class DummyValue extends Value {
+
+        private static final long serialVersionUID = -645435039553382737L;
+        private final int id;
+        private static int counter = 1;
+
+        protected DummyValue() {
+            super(LIRKind.Illegal);
+            this.id = counter++;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = super.hashCode();
+            result = prime * result + id;
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (!super.equals(obj)) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            DummyValue other = (DummyValue) obj;
+            if (id != other.id) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            return "DummyValue [id=" + id + "]";
+        }
+
+    }
+
+    private static class TestOp extends LIRInstruction {
+
+        @Use({COMPOSITE}) protected NestedCompositeValue compValue;
+
+        public TestOp(NestedCompositeValue compValue) {
+            this.compValue = compValue;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb) {
+            fail("should not reach!");
+        }
+
+    }
+
+    private static NestedCompositeValue createNestedCompValue(Value value, int nestingLevel) {
+        NestedCompositeValue compValue = new NestedCompositeValue(value);
+        for (int i = 0; i < nestingLevel; i++) {
+            compValue = new NestedCompositeValue(compValue);
+        }
+        return compValue;
+    }
+
+    @Test
+    public void replaceCompValueTest0() {
+        DummyValue dummyValue1 = new DummyValue();
+        DummyValue dummyValue2 = new DummyValue();
+        DummyValue dummyValue3 = new DummyValue();
+        NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 0);
+        LIRInstruction op1 = new TestOp(compValue1);
+        LIRInstruction op2 = new TestOp(compValue1);
+
+        op1.forEachInput(new InstructionValueProcedure() {
+            @Override
+            public Value doValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue1, value);
+                return dummyValue2;
+            }
+        });
+
+        op2.forEachInput(new InstructionValueProcedure() {
+            @Override
+            public Value doValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue1, value);
+                return dummyValue3;
+            }
+        });
+
+        op1.visitEachInput(new InstructionValueConsumer() {
+            @Override
+            public void visitValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue2, value);
+            }
+        });
+
+        op2.visitEachInput(new InstructionValueConsumer() {
+            @Override
+            public void visitValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue3, value);
+            }
+        });
+    }
+
+    @Test
+    public void replaceCompValueTest1() {
+        DummyValue dummyValue1 = new DummyValue();
+        DummyValue dummyValue2 = new DummyValue();
+        DummyValue dummyValue3 = new DummyValue();
+        NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 1);
+        LIRInstruction op1 = new TestOp(compValue1);
+        LIRInstruction op2 = new TestOp(compValue1);
+
+        op1.forEachInput(new InstructionValueProcedure() {
+            @Override
+            public Value doValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue1, value);
+                return dummyValue2;
+            }
+        });
+
+        op2.forEachInput(new InstructionValueProcedure() {
+            @Override
+            public Value doValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue1, value);
+                return dummyValue3;
+            }
+        });
+
+        op1.visitEachInput(new InstructionValueConsumer() {
+            @Override
+            public void visitValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue2, value);
+            }
+        });
+
+        op2.visitEachInput(new InstructionValueConsumer() {
+            @Override
+            public void visitValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue3, value);
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest3.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.test;
+
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Same as {@link CompositeValueReplacementTest1} but with for {@link ValuePosition}s.
+ *
+ * @see CompositeValueReplacementTest1
+ */
+public class CompositeValueReplacementTest3 {
+
+    private static class NestedCompositeValue extends CompositeValue {
+
+        private static final long serialVersionUID = -8804214200173503527L;
+        @Component({REG, OperandFlag.ILLEGAL}) protected Value value;
+
+        public NestedCompositeValue(Value value) {
+            super(LIRKind.Illegal);
+            this.value = value;
+        }
+
+    }
+
+    private static class DummyValue extends Value {
+
+        private static final long serialVersionUID = -645435039553382737L;
+        private final int id;
+        private static int counter = 1;
+
+        protected DummyValue() {
+            super(LIRKind.Illegal);
+            this.id = counter++;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = super.hashCode();
+            result = prime * result + id;
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (!super.equals(obj)) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            DummyValue other = (DummyValue) obj;
+            if (id != other.id) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            return "DummyValue [id=" + id + "]";
+        }
+
+    }
+
+    private static class TestOp extends LIRInstruction {
+
+        @Use({COMPOSITE}) protected NestedCompositeValue compValue;
+
+        public TestOp(NestedCompositeValue compValue) {
+            this.compValue = compValue;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb) {
+            fail("should not reach!");
+        }
+
+    }
+
+    private static NestedCompositeValue createNestedCompValue(Value value, int nestingLevel) {
+        NestedCompositeValue compValue = new NestedCompositeValue(value);
+        for (int i = 0; i < nestingLevel; i++) {
+            compValue = new NestedCompositeValue(compValue);
+        }
+        return compValue;
+    }
+
+    @Test
+    public void replaceCompValueTest0() {
+        DummyValue dummyValue1 = new DummyValue();
+        DummyValue dummyValue2 = new DummyValue();
+        DummyValue dummyValue3 = new DummyValue();
+        NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 0);
+        LIRInstruction op1 = new TestOp(compValue1);
+        LIRInstruction op2 = new TestOp(compValue1);
+
+        op1.forEachInput(new ValuePositionProcedure() {
+
+            @Override
+            public void doValue(LIRInstruction instruction, ValuePosition position) {
+                Value value = position.get(instruction);
+                assertEquals(dummyValue1, value);
+                position.set(instruction, dummyValue2);
+            }
+        });
+
+        op2.forEachInput(new ValuePositionProcedure() {
+            @Override
+            public void doValue(LIRInstruction instruction, ValuePosition position) {
+                Value value = position.get(instruction);
+                assertEquals(dummyValue1, value);
+                position.set(instruction, dummyValue3);
+            }
+        });
+
+        op1.forEachInput(new ValuePositionProcedure() {
+            @Override
+            public void doValue(LIRInstruction instruction, ValuePosition position) {
+                Value value = position.get(instruction);
+                assertEquals(dummyValue2, value);
+            }
+        });
+
+        op2.forEachInput(new ValuePositionProcedure() {
+            @Override
+            public void doValue(LIRInstruction instruction, ValuePosition position) {
+                Value value = position.get(instruction);
+                assertEquals(dummyValue3, value);
+            }
+        });
+    }
+
+    @Test
+    public void replaceCompValueTest1() {
+        DummyValue dummyValue1 = new DummyValue();
+        DummyValue dummyValue2 = new DummyValue();
+        DummyValue dummyValue3 = new DummyValue();
+        NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 1);
+        LIRInstruction op1 = new TestOp(compValue1);
+        LIRInstruction op2 = new TestOp(compValue1);
+
+        op1.forEachInput(new ValuePositionProcedure() {
+
+            @Override
+            public void doValue(LIRInstruction instruction, ValuePosition position) {
+                Value value = position.get(instruction);
+                assertEquals(dummyValue1, value);
+                position.set(instruction, dummyValue2);
+            }
+        });
+
+        op2.forEachInput(new ValuePositionProcedure() {
+            @Override
+            public void doValue(LIRInstruction instruction, ValuePosition position) {
+                Value value = position.get(instruction);
+                assertEquals(dummyValue1, value);
+                position.set(instruction, dummyValue3);
+            }
+        });
+
+        op1.forEachInput(new ValuePositionProcedure() {
+            @Override
+            public void doValue(LIRInstruction instruction, ValuePosition position) {
+                Value value = position.get(instruction);
+                assertEquals(dummyValue2, value);
+            }
+        });
+
+        op2.forEachInput(new ValuePositionProcedure() {
+            @Override
+            public void doValue(LIRInstruction instruction, ValuePosition position) {
+                Value value = position.get(instruction);
+                assertEquals(dummyValue3, value);
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest4.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.test;
+
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Same as {@link CompositeValueReplacementTest2} but with value arrays {@link ValuePosition}s.
+ *
+ * @see CompositeValueReplacementTest2
+ */
+public class CompositeValueReplacementTest4 {
+
+    private static class NestedCompositeValue extends CompositeValue {
+
+        private static final long serialVersionUID = -8804214200173503527L;
+        @Component({REG, OperandFlag.ILLEGAL}) protected Value[] values;
+
+        public NestedCompositeValue(Value value) {
+            super(LIRKind.Illegal);
+            this.values = new Value[]{value};
+        }
+
+    }
+
+    private static class DummyValue extends Value {
+
+        private static final long serialVersionUID = -645435039553382737L;
+        private final int id;
+        private static int counter = 1;
+
+        protected DummyValue() {
+            super(LIRKind.Illegal);
+            this.id = counter++;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = super.hashCode();
+            result = prime * result + id;
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (!super.equals(obj)) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            DummyValue other = (DummyValue) obj;
+            if (id != other.id) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            return "DummyValue [id=" + id + "]";
+        }
+
+    }
+
+    private static class TestOp extends LIRInstruction {
+
+        @Use({COMPOSITE}) protected NestedCompositeValue compValue;
+
+        public TestOp(NestedCompositeValue compValue) {
+            this.compValue = compValue;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb) {
+            fail("should not reach!");
+        }
+
+    }
+
+    private static NestedCompositeValue createNestedCompValue(Value value, int nestingLevel) {
+        NestedCompositeValue compValue = new NestedCompositeValue(value);
+        for (int i = 0; i < nestingLevel; i++) {
+            compValue = new NestedCompositeValue(compValue);
+        }
+        return compValue;
+    }
+
+    @Test
+    public void replaceCompValueTest0() {
+        DummyValue dummyValue1 = new DummyValue();
+        DummyValue dummyValue2 = new DummyValue();
+        DummyValue dummyValue3 = new DummyValue();
+        NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 0);
+        LIRInstruction op1 = new TestOp(compValue1);
+        LIRInstruction op2 = new TestOp(compValue1);
+
+        op1.forEachInput(new ValuePositionProcedure() {
+
+            @Override
+            public void doValue(LIRInstruction instruction, ValuePosition position) {
+                Value value = position.get(instruction);
+                assertEquals(dummyValue1, value);
+                position.set(instruction, dummyValue2);
+            }
+        });
+
+        op2.forEachInput(new ValuePositionProcedure() {
+            @Override
+            public void doValue(LIRInstruction instruction, ValuePosition position) {
+                Value value = position.get(instruction);
+                assertEquals(dummyValue1, value);
+                position.set(instruction, dummyValue3);
+            }
+        });
+
+        op1.forEachInput(new ValuePositionProcedure() {
+            @Override
+            public void doValue(LIRInstruction instruction, ValuePosition position) {
+                Value value = position.get(instruction);
+                assertEquals(dummyValue2, value);
+            }
+        });
+
+        op2.forEachInput(new ValuePositionProcedure() {
+            @Override
+            public void doValue(LIRInstruction instruction, ValuePosition position) {
+                Value value = position.get(instruction);
+                assertEquals(dummyValue3, value);
+            }
+        });
+    }
+
+    @Test
+    public void replaceCompValueTest1() {
+        DummyValue dummyValue1 = new DummyValue();
+        DummyValue dummyValue2 = new DummyValue();
+        DummyValue dummyValue3 = new DummyValue();
+        NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 1);
+        LIRInstruction op1 = new TestOp(compValue1);
+        LIRInstruction op2 = new TestOp(compValue1);
+
+        op1.forEachInput(new ValuePositionProcedure() {
+
+            @Override
+            public void doValue(LIRInstruction instruction, ValuePosition position) {
+                Value value = position.get(instruction);
+                assertEquals(dummyValue1, value);
+                position.set(instruction, dummyValue2);
+            }
+        });
+
+        op2.forEachInput(new ValuePositionProcedure() {
+            @Override
+            public void doValue(LIRInstruction instruction, ValuePosition position) {
+                Value value = position.get(instruction);
+                assertEquals(dummyValue1, value);
+                position.set(instruction, dummyValue3);
+            }
+        });
+
+        op1.forEachInput(new ValuePositionProcedure() {
+            @Override
+            public void doValue(LIRInstruction instruction, ValuePosition position) {
+                Value value = position.get(instruction);
+                assertEquals(dummyValue2, value);
+            }
+        });
+
+        op2.forEachInput(new ValuePositionProcedure() {
+            @Override
+            public void doValue(LIRInstruction instruction, ValuePosition position) {
+                Value value = position.get(instruction);
+                assertEquals(dummyValue3, value);
+            }
+        });
+    }
+}
--- a/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest1.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest1.java	Mon Aug 25 21:15:59 2014 -0700
@@ -32,7 +32,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
-import com.oracle.graal.lir.LIRInstruction.ValuePositionProcedure;
 import com.oracle.graal.lir.asm.*;
 
 public class ValuePositionTest1 {
--- a/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest2.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest2.java	Mon Aug 25 21:15:59 2014 -0700
@@ -32,7 +32,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
-import com.oracle.graal.lir.LIRInstruction.ValuePositionProcedure;
 import com.oracle.graal.lir.asm.*;
 
 public class ValuePositionTest2 {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,16 +25,15 @@
 import java.lang.annotation.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
-import com.oracle.graal.lir.LIRInstruction.ValuePositionProcedure;
 
 /**
  * Base class to represent values that need to be stored in more than one register.
  */
-public abstract class CompositeValue extends Value {
+public abstract class CompositeValue extends Value implements Cloneable {
 
     private static final long serialVersionUID = -169180052684126180L;
 
@@ -55,11 +54,11 @@
         valueClass = CompositeValueClass.get(getClass());
     }
 
-    public final void forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueProcedure proc) {
-        valueClass.forEachComponent(inst, this, mode, proc);
+    final CompositeValue forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueProcedureBase proc) {
+        return valueClass.forEachComponent(inst, this, mode, proc);
     }
 
-    public final void forEachComponent(LIRInstruction inst, OperandMode mode, ValuePositionProcedure proc, ValuePosition outerPosition) {
+    final void forEachComponent(LIRInstruction inst, OperandMode mode, ValuePositionProcedure proc, ValuePosition outerPosition) {
         valueClass.forEachComponent(inst, this, mode, proc, outerPosition);
     }
 
@@ -86,4 +85,19 @@
         return valueClass;
     }
 
+    @Override
+    public final CompositeValue clone() {
+        CompositeValue compositeValue = null;
+        try {
+            compositeValue = (CompositeValue) super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new GraalInternalError(e);
+        }
+
+        // copy value arrays
+        getValueClass().copyValueArrays(compositeValue);
+
+        return compositeValue;
+    }
+
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java	Mon Aug 25 21:15:59 2014 -0700
@@ -28,10 +28,8 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.CompositeValue.Component;
-import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
-import com.oracle.graal.lir.LIRInstruction.ValuePositionProcedure;
 
 /**
  * Lazily associated metadata for every {@link CompositeValue} type. The metadata includes:
@@ -141,11 +139,11 @@
         return str.toString();
     }
 
-    public final void forEachComponent(LIRInstruction inst, CompositeValue obj, OperandMode mode, InstructionValueProcedure proc) {
-        forEach(inst, obj, directComponentCount, componentOffsets, mode, componentFlags, proc);
+    final CompositeValue forEachComponent(LIRInstruction inst, CompositeValue obj, OperandMode mode, InstructionValueProcedureBase proc) {
+        return forEachComponent(inst, obj, directComponentCount, componentOffsets, mode, componentFlags, proc);
     }
 
-    public final void forEachComponent(LIRInstruction inst, CompositeValue obj, OperandMode mode, ValuePositionProcedure proc, ValuePosition outerPosition) {
+    final void forEachComponent(LIRInstruction inst, CompositeValue obj, OperandMode mode, ValuePositionProcedure proc, ValuePosition outerPosition) {
         forEach(inst, obj, directComponentCount, componentOffsets, mode, componentFlags, proc, outerPosition);
     }
 
@@ -165,11 +163,21 @@
         return getValueForPosition(obj, componentOffsets, directComponentCount, pos);
     }
 
-    void setValue(CompositeValue obj, ValuePosition pos, Value value) {
-        setValueForPosition(obj, componentOffsets, directComponentCount, pos, value);
+    CompositeValue createUpdatedValue(CompositeValue compValue, ValuePosition pos, Value value) {
+        CompositeValue newCompValue = compValue.clone();
+        setValueForPosition(newCompValue, componentOffsets, directComponentCount, pos, value);
+        return newCompValue;
     }
 
     EnumSet<OperandFlag> getFlags(ValuePosition pos) {
         return componentFlags[pos.getIndex()];
     }
+
+    void copyValueArrays(CompositeValue compositeValue) {
+        for (int i = directComponentCount; i < componentOffsets.length; i++) {
+            Value[] valueArray = getValueArray(compositeValue, componentOffsets[i]);
+            Value[] newValueArray = Arrays.copyOf(valueArray, valueArray.length);
+            setValueArray(compositeValue, componentOffsets[i], newValueArray);
+        }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InstructionStateProcedure.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir;
+
+public abstract class InstructionStateProcedure {
+
+    protected abstract void doState(LIRInstruction instruction, LIRFrameState state);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InstructionValueConsumer.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.lir.LIRInstruction.*;
+
+/**
+ * Non-modifying version of {@link InstructionValueProcedure}.
+ */
+public abstract class InstructionValueConsumer extends InstructionValueProcedureBase {
+
+    /**
+     * Iterator method to be overwritten. This version of the iterator does not take additional
+     * parameters to keep the signature short.
+     *
+     * @param instruction The current instruction.
+     * @param value The value that is iterated.
+     */
+    protected void visitValue(LIRInstruction instruction, Value value) {
+        throw GraalInternalError.shouldNotReachHere("One of the visitValue() methods must be overwritten");
+    }
+
+    /**
+     * Iterator method to be overwritten. This version of the iterator gets additional parameters
+     * about the processed value.
+     *
+     * @param instruction The current instruction.
+     * @param value The value that is iterated.
+     * @param mode The operand mode for the value.
+     * @param flags A set of flags for the value.
+     */
+    protected void visitValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+        visitValue(instruction, value);
+    }
+
+    @Override
+    public final Value processValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+        assert !(value instanceof CompositeValue) : String.format("Must not visit CompositeValues! Instruction: %s Value: %s", instruction, value);
+        visitValue(instruction, value, mode, flags);
+        return value;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InstructionValueProcedure.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.lir.LIRInstruction.*;
+
+/**
+ * Iterator for iterating over a list of values. Subclasses must overwrite one of the doValue
+ * methods. Clients should not use this class directly but call
+ * {@link InstructionValueProcedureBase#processValue} instead.
+ */
+public abstract class InstructionValueProcedure extends InstructionValueProcedureBase {
+
+    /**
+     * Iterator method to be overwritten. This version of the iterator does not take additional
+     * parameters to keep the signature short.
+     *
+     * @param instruction The current instruction.
+     * @param value The value that is iterated.
+     * @return The new value to replace the value that was passed in.
+     */
+    protected Value doValue(LIRInstruction instruction, Value value) {
+        throw GraalInternalError.shouldNotReachHere("One of the doValue() methods must be overwritten");
+    }
+
+    /**
+     * Iterator method to be overwritten. This version of the iterator gets additional parameters
+     * about the processed value.
+     *
+     * @param instruction The current instruction.
+     * @param value The value that is iterated.
+     * @param mode The operand mode for the value.
+     * @param flags A set of flags for the value.
+     * @return The new value to replace the value that was passed in.
+     */
+    protected Value doValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+        return doValue(instruction, value);
+    }
+
+    @Override
+    public final Value processValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+        assert !(value instanceof CompositeValue) : String.format("Must not visit CompositeValues! Instruction: %s Value: %s", instruction, value);
+        return doValue(instruction, value, mode, flags);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InstructionValueProcedureBase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.LIRInstruction.*;
+
+/**
+ * Common base class for modifying and non-modifying {@link Value value} iterators.
+ *
+ * This type should not be sub-classed directly. Use {@link InstructionValueProcedureBase} or
+ * {@link InstructionValueConsumer} instead.
+ *
+ * @see InstructionValueProcedure
+ * @see InstructionValueConsumer
+ */
+public abstract class InstructionValueProcedureBase {
+
+    /**
+     * Iterator method to be overwritten. This version of the iterator gets additional parameters
+     * about the processed value.
+     *
+     * @param instruction The current instruction.
+     * @param value The value that is iterated.
+     * @param mode The operand mode for the value.
+     * @param flags A set of flags for the value.
+     * @return The new value to replace the value that was passed in.
+     */
+    abstract public Value processValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet<OperandFlag> flags);
+}
\ No newline at end of file
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,7 +26,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.cfg.*;
-import com.oracle.graal.lir.LIRInstruction.StateProcedure;
 import com.oracle.graal.lir.StandardOp.BlockEndOp;
 
 /**
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Mon Aug 25 21:15:59 2014 -0700
@@ -28,7 +28,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 
@@ -63,7 +62,7 @@
      *
      * @param proc The procedure called for variables.
      */
-    public void forEachState(LIRInstruction inst, InstructionValueProcedure proc) {
+    public void forEachState(LIRInstruction inst, InstructionValueProcedureBase proc) {
         for (BytecodeFrame cur = topFrame; cur != null; cur = cur.caller()) {
             processValues(inst, cur.values, proc);
         }
@@ -80,16 +79,16 @@
      */
     protected static final EnumSet<OperandFlag> STATE_FLAGS = EnumSet.of(OperandFlag.REG, OperandFlag.STACK);
 
-    protected void processValues(LIRInstruction inst, Value[] values, InstructionValueProcedure proc) {
+    protected void processValues(LIRInstruction inst, Value[] values, InstructionValueProcedureBase proc) {
         for (int i = 0; i < values.length; i++) {
             Value value = values[i];
             values[i] = processValue(inst, proc, value);
         }
     }
 
-    protected Value processValue(LIRInstruction inst, InstructionValueProcedure proc, Value value) {
+    protected Value processValue(LIRInstruction inst, InstructionValueProcedureBase proc, Value value) {
         if (processed(value)) {
-            return proc.doValue(inst, value, OperandMode.ALIVE, STATE_FLAGS);
+            return proc.processValue(inst, value, OperandMode.ALIVE, STATE_FLAGS);
         }
         return value;
     }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Mon Aug 25 21:15:59 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2014, 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
@@ -30,7 +30,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.asm.*;
 
@@ -42,111 +41,6 @@
     public static final Value[] NO_OPERANDS = {};
 
     /**
-     * Iterator for iterating over a list of {@linkplain ValuePosition value positions}.
-     */
-    public abstract static class ValuePositionProcedure {
-
-        /**
-         * Iterator method to be overwritten. This version of the iterator does not take additional
-         * parameters to keep the signature short.
-         *
-         * @param instruction The current instruction.
-         * @param position The position of the value that is iterated.
-         */
-
-        public abstract void doValue(LIRInstruction instruction, ValuePosition position);
-    }
-
-    /**
-     * Iterator for iterating over a list of values. Subclasses must overwrite one of the doValue
-     * methods. Clients of the class must only call the doValue method that takes additional
-     * parameters.
-     */
-    public abstract static class InstructionValueProcedure {
-
-        /**
-         * Iterator method to be overwritten. This version of the iterator does not take additional
-         * parameters to keep the signature short.
-         *
-         * @param instruction The current instruction.
-         * @param value The value that is iterated.
-         * @return The new value to replace the value that was passed in.
-         */
-        protected Value doValue(LIRInstruction instruction, Value value) {
-            throw GraalInternalError.shouldNotReachHere("One of the doValue() methods must be overwritten");
-        }
-
-        /**
-         * Iterator method to be overwritten. This version of the iterator gets additional
-         * parameters about the processed value.
-         *
-         * @param instruction The current instruction.
-         * @param value The value that is iterated.
-         * @param mode The operand mode for the value.
-         * @param flags A set of flags for the value.
-         * @return The new value to replace the value that was passed in.
-         */
-        public Value doValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
-            return doValue(instruction, value);
-        }
-    }
-
-    /**
-     * Similar to {@link InstructionValueProcedure} but without an {@link LIRInstruction} parameter.
-     */
-    public abstract static class ValueProcedure extends InstructionValueProcedure {
-
-        /**
-         * Iterator method to be overwritten. This version of the iterator does not take additional
-         * parameters to keep the signature short.
-         *
-         * @param value The value that is iterated.
-         * @return The new value to replace the value that was passed in.
-         */
-        protected Value doValue(Value value) {
-            throw GraalInternalError.shouldNotReachHere("One of the doValue() methods must be overwritten");
-        }
-
-        /**
-         * Iterator method to be overwritten. This version of the iterator gets additional
-         * parameters about the processed value.
-         *
-         * @param value The value that is iterated.
-         * @param mode The operand mode for the value.
-         * @param flags A set of flags for the value.
-         * @return The new value to replace the value that was passed in.
-         */
-        protected Value doValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
-            return doValue(value);
-        }
-
-        @Override
-        protected final Value doValue(LIRInstruction instruction, Value value) {
-            throw GraalInternalError.shouldNotReachHere("This doValue() methods should never be called");
-        }
-
-        @Override
-        public final Value doValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
-            return doValue(value, mode, flags);
-        }
-    }
-
-    public abstract static class InstructionStateProcedure {
-
-        protected abstract void doState(LIRInstruction instruction, LIRFrameState state);
-    }
-
-    public abstract static class StateProcedure extends InstructionStateProcedure {
-
-        protected abstract void doState(LIRFrameState state);
-
-        @Override
-        protected final void doState(LIRInstruction instruction, LIRFrameState state) {
-            doState(state);
-        }
-    }
-
-    /**
      * Constants denoting how a LIR instruction uses an operand.
      */
     public enum OperandMode {
@@ -323,6 +217,7 @@
         return false;
     }
 
+    // ValuePositionProcedures
     public final void forEachInput(ValuePositionProcedure proc) {
         instructionClass.forEachUse(this, proc);
     }
@@ -339,6 +234,7 @@
         instructionClass.forEachDef(this, proc);
     }
 
+    // InstructionValueProcedures
     public final void forEachInput(InstructionValueProcedure proc) {
         instructionClass.forEachUse(this, proc);
     }
@@ -355,6 +251,7 @@
         instructionClass.forEachDef(this, proc);
     }
 
+    // States
     public final void forEachState(InstructionValueProcedure proc) {
         instructionClass.forEachState(this, proc);
     }
@@ -363,6 +260,27 @@
         instructionClass.forEachState(this, proc);
     }
 
+    // Consumers
+    public final void visitEachInput(InstructionValueConsumer proc) {
+        instructionClass.forEachUse(this, proc);
+    }
+
+    public final void visitEachAlive(InstructionValueConsumer proc) {
+        instructionClass.forEachAlive(this, proc);
+    }
+
+    public final void visitEachTemp(InstructionValueConsumer proc) {
+        instructionClass.forEachTemp(this, proc);
+    }
+
+    public final void visitEachOutput(InstructionValueConsumer proc) {
+        instructionClass.forEachDef(this, proc);
+    }
+
+    public final void visitEachState(InstructionValueConsumer proc) {
+        instructionClass.forEachState(this, proc);
+    }
+
     /**
      * Iterates all register hints for the specified value, i.e., all preferred candidates for the
      * register to be assigned to the value.
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Mon Aug 25 21:15:59 2014 -0700
@@ -28,15 +28,12 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
-import com.oracle.graal.lir.LIRInstruction.InstructionStateProcedure;
-import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
-import com.oracle.graal.lir.LIRInstruction.ValuePositionProcedure;
 
 public class LIRInstructionClass extends LIRIntrospection {
 
-    public static final LIRInstructionClass get(Class<? extends LIRInstruction> c) {
+    static final LIRInstructionClass get(Class<? extends LIRInstruction> c) {
         LIRInstructionClass clazz = (LIRInstructionClass) allClasses.get(c);
         if (clazz != null) {
             return clazz;
@@ -74,12 +71,12 @@
     private String opcodeConstant;
     private long opcodeOffset;
 
-    public LIRInstructionClass(Class<? extends LIRInstruction> clazz) {
+    private LIRInstructionClass(Class<? extends LIRInstruction> clazz) {
         this(clazz, new DefaultCalcOffset());
     }
 
     @SuppressWarnings("unchecked")
-    public LIRInstructionClass(Class<? extends LIRInstruction> clazz, CalcOffset calcOffset) {
+    private LIRInstructionClass(Class<? extends LIRInstruction> clazz, CalcOffset calcOffset) {
         super(clazz);
         assert INSTRUCTION_CLASS.isAssignableFrom(clazz);
 
@@ -309,7 +306,7 @@
         }
     }
 
-    public final String getOpcode(LIRInstruction obj) {
+    final String getOpcode(LIRInstruction obj) {
         if (opcodeConstant != null) {
             return opcodeConstant;
         }
@@ -317,11 +314,11 @@
         return unsafe.getObject(obj, opcodeOffset).toString();
     }
 
-    public final boolean hasOperands() {
+    final boolean hasOperands() {
         return useOffsets.length > 0 || aliveOffsets.length > 0 || tempOffsets.length > 0 || defOffsets.length > 0;
     }
 
-    public final boolean hasState(LIRInstruction obj) {
+    final boolean hasState(LIRInstruction obj) {
         for (int i = 0; i < stateOffsets.length; i++) {
             if (getState(obj, stateOffsets[i]) != null) {
                 return true;
@@ -330,39 +327,39 @@
         return false;
     }
 
-    public final void forEachUse(LIRInstruction obj, ValuePositionProcedure proc) {
+    final void forEachUse(LIRInstruction obj, ValuePositionProcedure proc) {
         forEach(obj, obj, directUseCount, useOffsets, OperandMode.USE, useFlags, proc, ValuePosition.ROOT_VALUE_POSITION);
     }
 
-    public final void forEachAlive(LIRInstruction obj, ValuePositionProcedure proc) {
+    final void forEachAlive(LIRInstruction obj, ValuePositionProcedure proc) {
         forEach(obj, obj, directAliveCount, aliveOffsets, OperandMode.ALIVE, aliveFlags, proc, ValuePosition.ROOT_VALUE_POSITION);
     }
 
-    public final void forEachTemp(LIRInstruction obj, ValuePositionProcedure proc) {
+    final void forEachTemp(LIRInstruction obj, ValuePositionProcedure proc) {
         forEach(obj, obj, directTempCount, tempOffsets, OperandMode.TEMP, tempFlags, proc, ValuePosition.ROOT_VALUE_POSITION);
     }
 
-    public final void forEachDef(LIRInstruction obj, ValuePositionProcedure proc) {
+    final void forEachDef(LIRInstruction obj, ValuePositionProcedure proc) {
         forEach(obj, obj, directDefCount, defOffsets, OperandMode.DEF, defFlags, proc, ValuePosition.ROOT_VALUE_POSITION);
     }
 
-    public final void forEachUse(LIRInstruction obj, InstructionValueProcedure proc) {
-        forEach(obj, obj, directUseCount, useOffsets, OperandMode.USE, useFlags, proc);
+    final void forEachUse(LIRInstruction obj, InstructionValueProcedureBase proc) {
+        forEach(obj, directUseCount, useOffsets, OperandMode.USE, useFlags, proc);
     }
 
-    public final void forEachAlive(LIRInstruction obj, InstructionValueProcedure proc) {
-        forEach(obj, obj, directAliveCount, aliveOffsets, OperandMode.ALIVE, aliveFlags, proc);
+    final void forEachAlive(LIRInstruction obj, InstructionValueProcedureBase proc) {
+        forEach(obj, directAliveCount, aliveOffsets, OperandMode.ALIVE, aliveFlags, proc);
     }
 
-    public final void forEachTemp(LIRInstruction obj, InstructionValueProcedure proc) {
-        forEach(obj, obj, directTempCount, tempOffsets, OperandMode.TEMP, tempFlags, proc);
+    final void forEachTemp(LIRInstruction obj, InstructionValueProcedureBase proc) {
+        forEach(obj, directTempCount, tempOffsets, OperandMode.TEMP, tempFlags, proc);
     }
 
-    public final void forEachDef(LIRInstruction obj, InstructionValueProcedure proc) {
-        forEach(obj, obj, directDefCount, defOffsets, OperandMode.DEF, defFlags, proc);
+    final void forEachDef(LIRInstruction obj, InstructionValueProcedureBase proc) {
+        forEach(obj, directDefCount, defOffsets, OperandMode.DEF, defFlags, proc);
     }
 
-    public final void forEachState(LIRInstruction obj, InstructionValueProcedure proc) {
+    final void forEachState(LIRInstruction obj, InstructionValueProcedureBase proc) {
         for (int i = 0; i < stateOffsets.length; i++) {
             LIRFrameState state = getState(obj, stateOffsets[i]);
             if (state != null) {
@@ -371,7 +368,7 @@
         }
     }
 
-    public final void forEachState(LIRInstruction obj, InstructionStateProcedure proc) {
+    final void forEachState(LIRInstruction obj, InstructionStateProcedure proc) {
         for (int i = 0; i < stateOffsets.length; i++) {
             LIRFrameState state = getState(obj, stateOffsets[i]);
             if (state != null) {
@@ -380,7 +377,7 @@
         }
     }
 
-    public final Value forEachRegisterHint(LIRInstruction obj, OperandMode mode, InstructionValueProcedure proc) {
+    final Value forEachRegisterHint(LIRInstruction obj, OperandMode mode, InstructionValueProcedure proc) {
         int hintDirectCount = 0;
         long[] hintOffsets = null;
         if (mode == OperandMode.USE) {
@@ -396,7 +393,7 @@
         for (int i = 0; i < hintOffsets.length; i++) {
             if (i < hintDirectCount) {
                 Value hintValue = getValue(obj, hintOffsets[i]);
-                Value result = proc.doValue(obj, hintValue, null, null);
+                Value result = proc.processValue(obj, hintValue, null, null);
                 if (result != null) {
                     return result;
                 }
@@ -404,7 +401,7 @@
                 Value[] hintValues = getValueArray(obj, hintOffsets[i]);
                 for (int j = 0; j < hintValues.length; j++) {
                     Value hintValue = hintValues[j];
-                    Value result = proc.doValue(obj, hintValue, null, null);
+                    Value result = proc.processValue(obj, hintValue, null, null);
                     if (result != null) {
                         return result;
                     }
@@ -418,7 +415,7 @@
         return (LIRFrameState) unsafe.getObject(obj, offset);
     }
 
-    public String toString(LIRInstruction obj) {
+    String toString(LIRInstruction obj) {
         StringBuilder result = new StringBuilder();
 
         appendValues(result, obj, "", " = ", "(", ")", new String[]{""}, defOffsets);
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Mon Aug 25 21:15:59 2014 -0700
@@ -32,10 +32,8 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
-import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
-import com.oracle.graal.lir.LIRInstruction.ValuePositionProcedure;
 
 abstract class LIRIntrospection extends FieldIntrospection {
 
@@ -120,31 +118,89 @@
         }
     }
 
-    protected static void forEach(LIRInstruction inst, Object obj, int directCount, long[] offsets, OperandMode mode, EnumSet<OperandFlag>[] flags, InstructionValueProcedure proc) {
+    protected static void forEach(LIRInstruction inst, int directCount, long[] offsets, OperandMode mode, EnumSet<OperandFlag>[] flags, InstructionValueProcedureBase proc) {
+        for (int i = 0; i < offsets.length; i++) {
+            assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(flags[i]);
+
+            if (i < directCount) {
+                Value value = getValue(inst, offsets[i]);
+                Value newValue;
+                if (value instanceof CompositeValue) {
+                    CompositeValue composite = (CompositeValue) value;
+                    newValue = composite.forEachComponent(inst, mode, proc);
+                } else {
+                    newValue = proc.processValue(inst, value, mode, flags[i]);
+                }
+                if (!value.identityEquals(newValue)) {
+                    setValue(inst, offsets[i], newValue);
+                }
+            } else {
+                Value[] values = getValueArray(inst, offsets[i]);
+                for (int j = 0; j < values.length; j++) {
+                    Value value = values[j];
+                    Value newValue;
+                    if (value instanceof CompositeValue) {
+                        CompositeValue composite = (CompositeValue) value;
+                        newValue = composite.forEachComponent(inst, mode, proc);
+                    } else {
+                        newValue = proc.processValue(inst, value, mode, flags[i]);
+                    }
+                    if (!value.identityEquals(newValue)) {
+                        values[j] = newValue;
+                    }
+                }
+            }
+        }
+    }
+
+    protected static CompositeValue forEachComponent(LIRInstruction inst, CompositeValue obj, int directCount, long[] offsets, OperandMode mode, EnumSet<OperandFlag>[] flags,
+                    InstructionValueProcedureBase proc) {
+        CompositeValue newCompValue = null;
         for (int i = 0; i < offsets.length; i++) {
             assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(flags[i]);
 
             if (i < directCount) {
                 Value value = getValue(obj, offsets[i]);
+                Value newValue;
                 if (value instanceof CompositeValue) {
                     CompositeValue composite = (CompositeValue) value;
-                    composite.forEachComponent(inst, mode, proc);
+                    newValue = composite.forEachComponent(inst, mode, proc);
                 } else {
-                    setValue(obj, offsets[i], proc.doValue(inst, value, mode, flags[i]));
+                    newValue = proc.processValue(inst, value, mode, flags[i]);
+                }
+                if (!value.identityEquals(newValue)) {
+                    // lazy initialize
+                    if (newCompValue == null) {
+                        newCompValue = obj.clone();
+                    }
+                    setValue(newCompValue, offsets[i], newValue);
                 }
             } else {
                 Value[] values = getValueArray(obj, offsets[i]);
+                Value[] newValues = null;
                 for (int j = 0; j < values.length; j++) {
                     Value value = values[j];
+                    Value newValue;
                     if (value instanceof CompositeValue) {
                         CompositeValue composite = (CompositeValue) value;
-                        composite.forEachComponent(inst, mode, proc);
+                        newValue = composite.forEachComponent(inst, mode, proc);
                     } else {
-                        values[j] = proc.doValue(inst, value, mode, flags[i]);
+                        newValue = proc.processValue(inst, value, mode, flags[i]);
+                    }
+                    if (!value.identityEquals(newValue)) {
+                        // lazy initialize
+                        if (newValues == null) {
+                            if (newCompValue == null) {
+                                newCompValue = obj.clone();
+                            }
+                            newValues = getValueArray(newCompValue, offsets[i]);
+                        }
+                        newValues[j] = newValue;
                     }
                 }
             }
         }
+        return newCompValue != null ? newCompValue : obj;
     }
 
     protected static void forEach(LIRInstruction inst, Object obj, int directCount, long[] offsets, OperandMode mode, EnumSet<OperandFlag>[] flags, ValuePositionProcedure proc,
@@ -202,6 +258,10 @@
         return (Value[]) unsafe.getObject(obj, offset);
     }
 
+    protected static void setValueArray(Object obj, long offset, Value[] valueArray) {
+        unsafe.putObject(obj, offset, valueArray);
+    }
+
     protected void appendValues(StringBuilder result, Object obj, String start, String end, String startMultiple, String endMultiple, String[] prefix, long[]... moffsets) {
         int total = 0;
         for (long[] offsets : moffsets) {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Mon Aug 25 21:15:59 2014 -0700
@@ -32,10 +32,8 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
-import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 
 public final class LIRVerifier {
 
@@ -63,21 +61,21 @@
         return isRegister(value) && frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable();
     }
 
-    private static InstructionValueProcedure allowedProc = new InstructionValueProcedure() {
+    private static InstructionValueConsumer allowedConsumer = new InstructionValueConsumer() {
 
         @Override
-        public Value doValue(LIRInstruction op, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
-            return allowed(op, value, mode, flags);
+        public void visitValue(LIRInstruction op, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+            allowed(op, value, mode, flags);
         }
     };
 
     public static boolean verify(final LIRInstruction op) {
 
-        op.forEachInput(allowedProc);
-        op.forEachAlive(allowedProc);
-        op.forEachState(allowedProc);
-        op.forEachTemp(allowedProc);
-        op.forEachOutput(allowedProc);
+        op.visitEachInput(allowedConsumer);
+        op.visitEachAlive(allowedConsumer);
+        op.visitEachState(allowedConsumer);
+        op.visitEachTemp(allowedConsumer);
+        op.visitEachOutput(allowedConsumer);
 
         op.verify();
         return true;
@@ -105,18 +103,18 @@
     private BitSet curRegistersDefined;
 
     private void verify() {
-        ValueProcedure useProc = new ValueProcedure() {
+        ValueConsumer useConsumer = new ValueConsumer() {
 
             @Override
-            public Value doValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
-                return use(value, mode, flags);
+            public void visitValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+                use(value, mode, flags);
             }
         };
-        ValueProcedure defProc = new ValueProcedure() {
+        ValueConsumer defConsumer = new ValueConsumer() {
 
             @Override
-            public Value doValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
-                return def(value, mode, flags);
+            public void visitValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+                def(value, mode, flags);
             }
         };
 
@@ -141,17 +139,17 @@
             for (LIRInstruction op : lir.getLIRforBlock(block)) {
                 curInstruction = op;
 
-                op.forEachInput(useProc);
+                op.visitEachInput(useConsumer);
                 if (op.destroysCallerSavedRegisters()) {
                     for (Register register : frameMap.registerConfig.getCallerSaveRegisters()) {
                         curRegistersLive[register.number] = null;
                     }
                 }
                 curRegistersDefined.clear();
-                op.forEachAlive(useProc);
-                op.forEachState(useProc);
-                op.forEachTemp(defProc);
-                op.forEachOutput(defProc);
+                op.visitEachAlive(useConsumer);
+                op.visitEachState(useConsumer);
+                op.visitEachTemp(defConsumer);
+                op.visitEachOutput(defConsumer);
 
                 curInstruction = null;
             }
@@ -160,7 +158,7 @@
         }
     }
 
-    private Value use(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+    private void use(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
         allowed(curInstruction, value, mode, flags);
 
         if (isVariable(value)) {
@@ -190,10 +188,9 @@
                 throw GraalInternalError.shouldNotReachHere();
             }
         }
-        return value;
     }
 
-    private Value def(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+    private void def(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
         allowed(curInstruction, value, mode, flags);
 
         if (isVariable(value)) {
@@ -231,17 +228,16 @@
                 }
             }
         }
-        return value;
     }
 
     // @formatter:off
-    private static Value allowed(Object op, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+    private static void allowed(Object op, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
         if ((isVariable(value) && flags.contains(OperandFlag.REG)) ||
             (isRegister(value) && flags.contains(OperandFlag.REG)) ||
             (isStackSlot(value) && flags.contains(OperandFlag.STACK)) ||
             (isConstant(value) && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) ||
             (isIllegal(value) && flags.contains(OperandFlag.ILLEGAL))) {
-            return value;
+            return;
         }
         throw new GraalInternalError("Invalid LIR%n  Instruction: %s%n  Mode: %s%n  Flags: %s%n  Unexpected value: %s %s",
                         op, mode, flags, value.getClass().getSimpleName(), value);
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java	Mon Aug 25 21:15:59 2014 -0700
@@ -32,7 +32,6 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
-import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 import com.oracle.graal.lir.StandardOp.MoveOp;
 
 /**
@@ -363,16 +362,16 @@
             /*
              * Value procedure for the instruction's output and temp values
              */
-            class OutputValueProc extends ValueProcedure {
+            class OutputValueConsumer extends ValueConsumer {
 
                 int opValueNum;
 
-                OutputValueProc(int opValueNum) {
+                OutputValueConsumer(int opValueNum) {
                     this.opValueNum = opValueNum;
                 }
 
                 @Override
-                public Value doValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
+                public void visitValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
                     int stateIdx = getStateIdx(operand);
                     if (stateIdx >= 0) {
                         /*
@@ -381,19 +380,18 @@
                         state[stateIdx] = encodeValueNum(opValueNum++, !operand.getLIRKind().isValue());
                         Debug.log("set def %d for register %s(%d): %d", opValueNum, operand, stateIdx, state[stateIdx]);
                     }
-                    return operand;
                 }
             }
 
-            OutputValueProc outputValueProc = new OutputValueProc(valueNum);
+            OutputValueConsumer outputValueConsumer = new OutputValueConsumer(valueNum);
 
-            op.forEachTemp(outputValueProc);
+            op.visitEachTemp(outputValueConsumer);
             /*
              * Semantically the output values are written _after_ the temp values
              */
-            op.forEachOutput(outputValueProc);
+            op.visitEachOutput(outputValueConsumer);
 
-            valueNum = outputValueProc.opValueNum;
+            valueNum = outputValueConsumer.opValueNum;
 
             if (op.hasState()) {
                 /*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StateProcedure.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir;
+
+public abstract class StateProcedure extends InstructionStateProcedure {
+
+    protected abstract void doState(LIRFrameState state);
+
+    @Override
+    protected final void doState(LIRInstruction instruction, LIRFrameState state) {
+        doState(state);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValueConsumer.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.lir.LIRInstruction.*;
+
+/**
+ * Non-modifying version of {@link ValueProcedure}.
+ */
+public abstract class ValueConsumer extends InstructionValueConsumer {
+
+    /**
+     * Iterator method to be overwritten. This version of the iterator does not take additional
+     * parameters to keep the signature short.
+     *
+     * @param value The value that is iterated.
+     */
+    protected void visitValue(Value value) {
+        throw GraalInternalError.shouldNotReachHere("One of the visitValue() methods must be overwritten");
+    }
+
+    /**
+     * Iterator method to be overwritten. This version of the iterator gets additional parameters
+     * about the processed value.
+     *
+     * @param value The value that is iterated.
+     * @param mode The operand mode for the value.
+     * @param flags A set of flags for the value.
+     */
+    protected void visitValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+        visitValue(value);
+    }
+
+    @Override
+    protected final void visitValue(LIRInstruction instruction, Value value) {
+        throw GraalInternalError.shouldNotReachHere("This visitValue() method should never be called");
+    }
+
+    @Override
+    protected void visitValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+        visitValue(value, mode, flags);
+    }
+}
\ No newline at end of file
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValuePosition.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValuePosition.java	Mon Aug 25 21:15:59 2014 -0700
@@ -70,7 +70,8 @@
     public void set(LIRInstruction inst, Value value) {
         if (isCompositePosition()) {
             CompositeValue compValue = (CompositeValue) outerPosition.get(inst);
-            compValue.getValueClass().setValue(compValue, this, value);
+            CompositeValue newCompValue = compValue.getValueClass().createUpdatedValue(compValue, this, value);
+            outerPosition.set(inst, newCompValue);
         } else {
             inst.getLIRInstructionClass().setValue(inst, this, value);
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValuePositionProcedure.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir;
+
+/**
+ * Iterator for iterating over a list of {@linkplain ValuePosition value positions}.
+ */
+public abstract class ValuePositionProcedure {
+
+    /**
+     * Iterator method to be overwritten. This version of the iterator does not take additional
+     * parameters to keep the signature short.
+     *
+     * @param instruction The current instruction.
+     * @param position The position of the value that is iterated.
+     */
+
+    public abstract void doValue(LIRInstruction instruction, ValuePosition position);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValueProcedure.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.lir.LIRInstruction.*;
+
+/**
+ * Similar to {@link InstructionValueProcedure} but without an {@link LIRInstruction} parameter.
+ */
+public abstract class ValueProcedure extends InstructionValueProcedure {
+
+    /**
+     * Iterator method to be overwritten. This version of the iterator does not take additional
+     * parameters to keep the signature short.
+     *
+     * @param value The value that is iterated.
+     * @return The new value to replace the value that was passed in.
+     */
+    protected Value doValue(Value value) {
+        throw GraalInternalError.shouldNotReachHere("One of the doValue() methods must be overwritten");
+    }
+
+    /**
+     * Iterator method to be overwritten. This version of the iterator gets additional parameters
+     * about the processed value.
+     *
+     * @param value The value that is iterated.
+     * @param mode The operand mode for the value.
+     * @param flags A set of flags for the value.
+     * @return The new value to replace the value that was passed in.
+     */
+    protected Value doValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+        return doValue(value);
+    }
+
+    @Override
+    protected final Value doValue(LIRInstruction instruction, Value value) {
+        throw GraalInternalError.shouldNotReachHere("This doValue() method should never be called");
+    }
+
+    @Override
+    public final Value doValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+        return doValue(value, mode, flags);
+    }
+}
\ No newline at end of file
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java	Mon Aug 25 21:15:59 2014 -0700
@@ -86,7 +86,7 @@
             return rawStride;
         }
         if (op instanceof IntegerSubNode) {
-            return graph().unique(new NegateNode(rawStride));
+            return graph().unique(NegateNode.create(rawStride));
         }
         throw GraalInternalError.shouldNotReachHere();
     }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Mon Aug 25 21:15:59 2014 -0700
@@ -62,13 +62,13 @@
                 range = IntegerArithmeticNode.sub(graph, range, ConstantNode.forIntegerStamp(stamp, 1, graph));
             }
         }
-        IntegerDivNode div = graph.add(new IntegerDivNode(range, iv.strideNode()));
+        IntegerDivNode div = graph.add(IntegerDivNode.create(range, iv.strideNode()));
         graph.addBeforeFixed(loop.entryPoint(), div);
         ConstantNode zero = ConstantNode.forIntegerStamp(stamp, 0, graph);
         if (assumePositive) {
             return div;
         }
-        return graph.unique(new ConditionalNode(graph.unique(new IntegerLessThanNode(zero, div)), div, zero));
+        return graph.unique(ConditionalNode.create(graph.unique(IntegerLessThanNode.create(zero, div)), div, zero));
     }
 
     public boolean isConstantMaxTripCount() {
@@ -147,16 +147,16 @@
             if (oneOff) {
                 v1 = sub(graph, v1, one);
             }
-            cond = graph.unique(new IntegerLessThanNode(v1, end));
+            cond = graph.unique(IntegerLessThanNode.create(v1, end));
         } else {
             assert iv.direction() == Direction.Down;
             IntegerArithmeticNode v1 = add(graph, ConstantNode.forIntegerStamp(stamp, IntegerStamp.defaultMinValue(stamp.getBits()), graph), sub(graph, one, iv.strideNode()));
             if (oneOff) {
                 v1 = add(graph, v1, one);
             }
-            cond = graph.unique(new IntegerLessThanNode(end, v1));
+            cond = graph.unique(IntegerLessThanNode.create(end, v1));
         }
-        overflowGuard = graph.unique(new GuardNode(cond, BeginNode.prevBegin(loop.entryPoint()), DeoptimizationReason.LoopLimitCheck, DeoptimizationAction.InvalidateRecompile, true,
+        overflowGuard = graph.unique(GuardNode.create(cond, BeginNode.prevBegin(loop.entryPoint()), DeoptimizationReason.LoopLimitCheck, DeoptimizationAction.InvalidateRecompile, true,
                         Constant.NULL_OBJECT)); // TODO gd: use speculation
         loop.loopBegin().setOverflowGuard(overflowGuard);
         return overflowGuard;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java	Mon Aug 25 21:15:59 2014 -0700
@@ -86,7 +86,7 @@
     @Override
     public ValueNode strideNode() {
         if (value instanceof IntegerSubNode && base.valueNode() == value.getY()) {
-            return graph().unique(new NegateNode(base.strideNode()));
+            return graph().unique(NegateNode.create(base.strideNode()));
         }
         return base.strideNode();
     }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Mon Aug 25 21:15:59 2014 -0700
@@ -312,9 +312,9 @@
             if (newEarlyExit == null) {
                 continue;
             }
-            MergeNode merge = graph.add(new MergeNode());
-            AbstractEndNode originalEnd = graph.add(new EndNode());
-            AbstractEndNode newEnd = graph.add(new EndNode());
+            MergeNode merge = graph.add(MergeNode.create());
+            AbstractEndNode originalEnd = graph.add(EndNode.create());
+            AbstractEndNode newEnd = graph.add(EndNode.create());
             merge.addForwardEnd(originalEnd);
             merge.addForwardEnd(newEnd);
             loopEarlyExit.setNext(originalEnd);
@@ -354,9 +354,9 @@
                 if (newVpn != null) {
                     PhiNode phi;
                     if (vpn instanceof ValueProxyNode) {
-                        phi = graph.addWithoutUnique(new ValuePhiNode(vpn.stamp(), merge));
+                        phi = graph.addWithoutUnique(ValuePhiNode.create(vpn.stamp(), merge));
                     } else if (vpn instanceof GuardProxyNode) {
-                        phi = graph.addWithoutUnique(new GuardPhiNode(merge));
+                        phi = graph.addWithoutUnique(GuardPhiNode.create(merge));
                     } else {
                         throw GraalInternalError.shouldNotReachHere();
                     }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Mon Aug 25 21:15:59 2014 -0700
@@ -154,7 +154,7 @@
                     if (value != null) {
                         return value;
                     }
-                    BeginNode newValue = graph.add(new BeginNode());
+                    BeginNode newValue = graph.add(BeginNode.create());
                     seenNode.put(original, newValue);
                     return newValue;
                 }
@@ -163,7 +163,7 @@
                     if (value != null) {
                         return value;
                     }
-                    BeginNode newValue = graph.add(new BeginNode());
+                    BeginNode newValue = graph.add(BeginNode.create());
                     seenNode.put(original, newValue);
                     return newValue;
                 }
@@ -172,7 +172,7 @@
                     if (value != null) {
                         return value;
                     }
-                    EndNode newValue = graph.add(new EndNode());
+                    EndNode newValue = graph.add(EndNode.create());
                     seenNode.put(original, newValue);
                     return newValue;
                 }
@@ -189,11 +189,11 @@
     private static PhiNode patchPhi(StructuredGraph graph, PhiNode phi, MergeNode merge) {
         PhiNode ret;
         if (phi instanceof ValuePhiNode) {
-            ret = new ValuePhiNode(phi.stamp(), merge);
+            ret = ValuePhiNode.create(phi.stamp(), merge);
         } else if (phi instanceof GuardPhiNode) {
-            ret = new GuardPhiNode(merge);
+            ret = GuardPhiNode.create(merge);
         } else if (phi instanceof MemoryPhiNode) {
-            ret = new MemoryPhiNode(merge, ((MemoryPhiNode) phi).getLocationIdentity());
+            ret = MemoryPhiNode.create(merge, ((MemoryPhiNode) phi).getLocationIdentity());
         } else {
             throw GraalInternalError.shouldNotReachHere();
         }
@@ -312,12 +312,12 @@
         if (endsToMerge.size() == 1) {
             AbstractEndNode end = endsToMerge.get(0);
             assert end.usages().isEmpty();
-            newExit = graph.add(new BeginNode());
+            newExit = graph.add(BeginNode.create());
             end.replaceAtPredecessor(newExit);
             end.safeDelete();
         } else {
             assert endsToMerge.size() > 1;
-            MergeNode newExitMerge = graph.add(new MergeNode());
+            MergeNode newExitMerge = graph.add(MergeNode.create());
             newExit = newExitMerge;
             FrameState state = loopBegin.stateAfter();
             FrameState duplicateState = null;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java	Mon Aug 25 21:15:59 2014 -0700
@@ -79,7 +79,7 @@
             public Node replacement(Node o) {
                 if (o == entry) {
                     if (endNode == null) {
-                        endNode = graph.add(new EndNode());
+                        endNode = graph.add(EndNode.create());
                     }
                     return endNode;
                 }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Mon Aug 25 21:15:59 2014 -0700
@@ -30,7 +30,7 @@
 import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.NodeClass.NodeClassIterator;
-import com.oracle.graal.graph.NodeClass.Position;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.phases.common.*;
@@ -167,7 +167,7 @@
                         invariantValue = switchNode.value();
                         controls = new ArrayList<>();
                         controls.add(switchNode);
-                    } else if (switchNode.value() == invariantValue && firstSwitch.equalKeys(switchNode)) {
+                    } else if (switchNode.value() == invariantValue && firstSwitch.structureEquals(switchNode)) {
                         // Only collect switches which test the same values in the same order
                         controls.add(switchNode);
                     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodeinfo.processor/src/META-INF/services/javax.annotation.processing.Processor	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,1 @@
+com.oracle.graal.nodeinfo.processor.GraphNodeProcessor
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/ElementException.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, 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.nodeinfo.processor;
+
+import javax.lang.model.element.*;
+
+/**
+ * Denotes an error encountered while processing an element.
+ */
+@SuppressWarnings("serial")
+public class ElementException extends RuntimeException {
+    public final Element element;
+
+    public ElementException(Element element, String format, Object... args) {
+        super(String.format(format, args));
+        this.element = element;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeGenerator.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,983 @@
+/*
+ * Copyright (c) 2014, 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.nodeinfo.processor;
+
+import static com.oracle.graal.nodeinfo.processor.GraphNodeGenerator.NodeRefsType.*;
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+import static java.util.Arrays.*;
+import static javax.lang.model.element.Modifier.*;
+
+import java.util.*;
+import java.util.stream.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+import javax.tools.Diagnostic.Kind;
+
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+/**
+ * Generates the source code for a Node class.
+ */
+public class GraphNodeGenerator {
+
+    private final GraphNodeProcessor env;
+    private final Types types;
+    private final Elements elements;
+
+    private final TypeElement Input;
+    private final TypeElement OptionalInput;
+    private final TypeElement Successor;
+
+    final TypeElement Node;
+    private final TypeElement NodeList;
+    private final TypeElement NodeInputList;
+    private final TypeElement NodeSuccessorList;
+    private final TypeElement Position;
+
+    private final List<VariableElement> inputFields = new ArrayList<>();
+    private final List<VariableElement> inputListFields = new ArrayList<>();
+    private final List<VariableElement> successorFields = new ArrayList<>();
+    private final List<VariableElement> successorListFields = new ArrayList<>();
+    private final List<VariableElement> dataFields = new ArrayList<>();
+    private final Set<VariableElement> optionalInputs = new HashSet<>();
+    private final Map<VariableElement, VariableElement> inputTypes = new HashMap<>();
+
+    private CodeTypeElement genClass;
+    private String genClassName;
+
+    public GraphNodeGenerator(GraphNodeProcessor processor) {
+        this.env = processor;
+
+        this.types = processor.getProcessingEnv().getTypeUtils();
+        this.elements = processor.getProcessingEnv().getElementUtils();
+
+        this.Input = getTypeElement("com.oracle.graal.graph.Node.Input");
+        this.OptionalInput = getTypeElement("com.oracle.graal.graph.Node.OptionalInput");
+        this.Successor = getTypeElement("com.oracle.graal.graph.Node.Successor");
+        this.Node = getTypeElement("com.oracle.graal.graph.Node");
+        this.NodeList = getTypeElement("com.oracle.graal.graph.NodeList");
+        this.NodeInputList = getTypeElement("com.oracle.graal.graph.NodeInputList");
+        this.NodeSuccessorList = getTypeElement("com.oracle.graal.graph.NodeSuccessorList");
+        this.Position = getTypeElement("com.oracle.graal.graph.Position");
+    }
+
+    @SafeVarargs
+    private static Collection<VariableElement> concat(List<VariableElement> fields1, List<VariableElement> fields2, List<VariableElement>... tail) {
+        return new AbstractCollection<VariableElement>() {
+
+            @Override
+            public Iterator<VariableElement> iterator() {
+                Stream<VariableElement> joined = Stream.concat(fields1.stream(), fields2.stream());
+                for (List<VariableElement> t : tail) {
+                    joined = Stream.concat(joined, t.stream());
+                }
+                return joined.iterator();
+            }
+
+            @Override
+            public int size() {
+                return fields1.size() + fields2.size();
+            }
+        };
+    }
+
+    /**
+     * Returns a type element given a canonical name.
+     *
+     * @throw {@link NoClassDefFoundError} if a type element does not exist for {@code name}
+     */
+    public TypeElement getTypeElement(String name) {
+        TypeElement typeElement = elements.getTypeElement(name);
+        if (typeElement == null) {
+            throw new NoClassDefFoundError(name);
+        }
+        return typeElement;
+    }
+
+    public TypeMirror getType(String name) {
+        return getTypeElement(name).asType();
+    }
+
+    public TypeMirror getType(Class<?> primitiveClass) {
+        return ElementUtils.getType(getProcessingEnv(), primitiveClass);
+    }
+
+    public ProcessingEnvironment getProcessingEnv() {
+        return env.getProcessingEnv();
+    }
+
+    private static String getGeneratedClassName(TypeElement node) {
+
+        TypeElement typeElement = node;
+
+        String genClassName = typeElement.getSimpleName().toString() + "Gen";
+        Element enclosing = typeElement.getEnclosingElement();
+        while (enclosing != null) {
+            if (enclosing.getKind() == ElementKind.CLASS || enclosing.getKind() == ElementKind.INTERFACE) {
+                if (enclosing.getModifiers().contains(Modifier.PRIVATE)) {
+                    throw new ElementException(enclosing, "%s %s cannot be private", enclosing.getKind().name().toLowerCase(), enclosing);
+                }
+                genClassName = enclosing.getSimpleName() + "_" + genClassName;
+            } else {
+                assert enclosing.getKind() == ElementKind.PACKAGE;
+            }
+            enclosing = enclosing.getEnclosingElement();
+        }
+        return genClassName;
+    }
+
+    public boolean isAssignableWithErasure(Element from, Element to) {
+        TypeMirror fromType = types.erasure(from.asType());
+        TypeMirror toType = types.erasure(to.asType());
+        return types.isAssignable(fromType, toType);
+    }
+
+    private void scanFields(TypeElement node) {
+        TypeElement currentClazz = node;
+        do {
+            for (VariableElement field : ElementFilter.fieldsIn(currentClazz.getEnclosedElements())) {
+                Set<Modifier> modifiers = field.getModifiers();
+                if (modifiers.contains(STATIC) || modifiers.contains(TRANSIENT)) {
+                    continue;
+                }
+
+                List<? extends AnnotationMirror> annotations = field.getAnnotationMirrors();
+
+                boolean isNonOptionalInput = findAnnotationMirror(annotations, Input) != null;
+                boolean isOptionalInput = findAnnotationMirror(annotations, OptionalInput) != null;
+                boolean isSuccessor = findAnnotationMirror(annotations, Successor) != null;
+
+                if (isNonOptionalInput || isOptionalInput) {
+                    if (findAnnotationMirror(annotations, Successor) != null) {
+                        throw new ElementException(field, "Field cannot be both input and successor");
+                    } else if (isNonOptionalInput && isOptionalInput) {
+                        throw new ElementException(field, "Inputs must be either optional or non-optional");
+                    } else if (isAssignableWithErasure(field, NodeInputList)) {
+                        if (modifiers.contains(FINAL)) {
+                            throw new ElementException(field, "Input list field must not be final");
+                        }
+                        if (modifiers.contains(PUBLIC) || modifiers.contains(PRIVATE)) {
+                            throw new ElementException(field, "Input list field must be protected or package-private");
+                        }
+                        inputListFields.add(field);
+                    } else {
+                        if (!isAssignableWithErasure(field, Node) && field.getKind() == ElementKind.INTERFACE) {
+                            throw new ElementException(field, "Input field type must be an interface or assignable to Node");
+                        }
+                        if (modifiers.contains(FINAL)) {
+                            throw new ElementException(field, "Input field must not be final");
+                        }
+                        if (modifiers.contains(PUBLIC) || modifiers.contains(PRIVATE)) {
+                            throw new ElementException(field, "Input field must be protected or package-private");
+                        }
+                        inputFields.add(field);
+                    }
+                    if (isOptionalInput) {
+                        inputTypes.put(field, getAnnotationValue(VariableElement.class, findAnnotationMirror(annotations, OptionalInput), "value"));
+                        optionalInputs.add(field);
+                    } else {
+                        inputTypes.put(field, getAnnotationValue(VariableElement.class, findAnnotationMirror(annotations, Input), "value"));
+                    }
+                } else if (isSuccessor) {
+                    if (isAssignableWithErasure(field, NodeSuccessorList)) {
+                        if (modifiers.contains(FINAL)) {
+                            throw new ElementException(field, "Successor list field must not be final");
+                        }
+                        if (modifiers.contains(PUBLIC)) {
+                            throw new ElementException(field, "Successor list field must not be public");
+                        }
+                        successorListFields.add(field);
+                    } else {
+                        if (!isAssignableWithErasure(field, Node)) {
+                            throw new ElementException(field, "Successor field must be a Node type");
+                        }
+                        if (modifiers.contains(FINAL)) {
+                            throw new ElementException(field, "Successor field must not be final");
+                        }
+                        if (modifiers.contains(PUBLIC) || modifiers.contains(PRIVATE)) {
+                            throw new ElementException(field, "Successor field must be protected or package-private");
+                        }
+                        successorFields.add(field);
+                    }
+
+                } else {
+                    if (isAssignableWithErasure(field, Node) && !field.getSimpleName().contentEquals("Null")) {
+                        throw new ElementException(field, "Node field must be annotated with @" + Input.getSimpleName() + ", @" + OptionalInput.getSimpleName() + " or @" + Successor.getSimpleName());
+                    }
+                    if (isAssignableWithErasure(field, NodeInputList)) {
+                        throw new ElementException(field, "NodeInputList field must be annotated with @" + Input.getSimpleName() + " or @" + OptionalInput.getSimpleName());
+                    }
+                    if (isAssignableWithErasure(field, NodeSuccessorList)) {
+                        throw new ElementException(field, "NodeSuccessorList field must be annotated with @" + Successor.getSimpleName());
+                    }
+                    dataFields.add(field);
+                }
+            }
+            currentClazz = getSuperType(currentClazz);
+        } while (!isObject(getSuperType(currentClazz).asType()));
+    }
+
+    /**
+     * Determines if two parameter lists contain the
+     * {@linkplain Types#isSameType(TypeMirror, TypeMirror) same} types.
+     */
+    private boolean parametersMatch(List<? extends VariableElement> p1, List<? extends VariableElement> p2) {
+        if (p1.size() == p2.size()) {
+            for (int i = 0; i < p1.size(); i++) {
+                if (!types.isSameType(p1.get(i).asType(), p2.get(i).asType())) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Searches a type for a method based on a given name and parameter types.
+     */
+    private ExecutableElement findMethod(TypeElement type, String name, List<? extends VariableElement> parameters) {
+        List<? extends ExecutableElement> methods = ElementFilter.methodsIn(type.getEnclosedElements());
+        for (ExecutableElement method : methods) {
+            if (method.getSimpleName().toString().equals(name)) {
+                if (parametersMatch(method.getParameters(), parameters)) {
+                    return method;
+                }
+            }
+        }
+        return null;
+    }
+
+    enum NodeRefsType {
+        Inputs,
+        Successors;
+    }
+
+    CodeCompilationUnit process(TypeElement node) {
+        try {
+            return process0(node);
+        } finally {
+            reset();
+        }
+    }
+
+    private CodeCompilationUnit process0(TypeElement node) {
+
+        CodeCompilationUnit compilationUnit = new CodeCompilationUnit();
+
+        PackageElement packageElement = ElementUtils.findPackageElement(node);
+
+        genClassName = getGeneratedClassName(node);
+        genClass = new CodeTypeElement(modifiers(FINAL), ElementKind.CLASS, packageElement, genClassName);
+        genClass.setSuperClass(node.asType());
+
+        for (ExecutableElement constructor : ElementFilter.constructorsIn(node.getEnclosedElements())) {
+            if (constructor.getModifiers().contains(PUBLIC)) {
+                throw new ElementException(constructor, "Node class constructor must not be public");
+            }
+
+            checkFactoryMethodExists(node, constructor);
+
+            CodeExecutableElement subConstructor = createConstructor(genClass, constructor);
+            subConstructor.getModifiers().removeAll(Arrays.asList(PUBLIC, PRIVATE, PROTECTED));
+            genClass.add(subConstructor);
+        }
+
+        DeclaredType generatedNode = (DeclaredType) getType(GeneratedNode.class);
+        CodeAnnotationMirror generatedNodeMirror = new CodeAnnotationMirror(generatedNode);
+        generatedNodeMirror.setElementValue(generatedNodeMirror.findExecutableElement("value"), new CodeAnnotationValue(node.asType()));
+        genClass.getAnnotationMirrors().add(generatedNodeMirror);
+
+        scanFields(node);
+
+        boolean hasInputs = !inputFields.isEmpty() || !inputListFields.isEmpty();
+        boolean hasSuccessors = !successorFields.isEmpty() || !successorListFields.isEmpty();
+
+        if (hasInputs || hasSuccessors) {
+            createGetNodeAtMethod();
+            createGetInputTypeAtMethod();
+            createGetNameOfMethod();
+            createUpdateOrInitializeNodeAtMethod(false);
+            createUpdateOrInitializeNodeAtMethod(true);
+            createIsLeafNodeMethod(genClass);
+
+            if (!inputListFields.isEmpty() || !successorListFields.isEmpty()) {
+                createGetNodeListAtMethod();
+                createSetNodeListAtMethod();
+            }
+        }
+
+        if (hasInputs) {
+            createIsOptionalInputAtMethod();
+            createGetFirstLevelPositionsMethod(Inputs, inputFields, inputListFields);
+
+            createContainsMethod(Inputs, inputFields, inputListFields);
+            createIterableMethod(Inputs);
+
+            CodeTypeElement inputsIteratorClass = createIteratorClass(Inputs, packageElement, inputFields, inputListFields);
+            createAllIteratorClass(Inputs, inputsIteratorClass.asType(), packageElement, inputFields, inputListFields);
+            createWithModCountIteratorClass(Inputs, inputsIteratorClass.asType(), packageElement);
+            createIterableClass(Inputs, packageElement);
+        }
+
+        if (hasSuccessors) {
+            createGetFirstLevelPositionsMethod(Successors, successorFields, successorListFields);
+
+            createContainsMethod(Successors, successorFields, successorListFields);
+            createIterableMethod(Successors);
+
+            CodeTypeElement successorsIteratorClass = createIteratorClass(Successors, packageElement, successorFields, successorListFields);
+            createAllIteratorClass(Successors, successorsIteratorClass.asType(), packageElement, successorFields, successorListFields);
+            createWithModCountIteratorClass(Successors, successorsIteratorClass.asType(), packageElement);
+            createIterableClass(Successors, packageElement);
+        }
+
+        compilationUnit.add(genClass);
+        return compilationUnit;
+    }
+
+    /**
+     * Checks that a public static factory method named {@code "create"} exists in {@code node}
+     * whose signature matches that of a given constructor.
+     *
+     * @throws ElementException if the check fails
+     */
+    private void checkFactoryMethodExists(TypeElement node, ExecutableElement constructor) {
+        ExecutableElement create = findMethod(node, "create", constructor.getParameters());
+        if (create == null) {
+            Formatter f = new Formatter();
+            f.format("public static %s create(", node.getSimpleName());
+            String sep = "";
+            Formatter callArgs = new Formatter();
+            for (VariableElement v : constructor.getParameters()) {
+                f.format("%s%s %s", sep, ElementUtils.getSimpleName(v.asType()), v.getSimpleName());
+                callArgs.format("%s%s", sep, v.getSimpleName());
+                sep = ", ";
+            }
+            f.format(") { return new %s(%s); }", genClassName, callArgs);
+            throw new ElementException(constructor, "Missing Node class factory method '%s'", f);
+        }
+        if (!create.getModifiers().containsAll(asList(PUBLIC, STATIC))) {
+            throw new ElementException(constructor, "Node class factory method must be public and static");
+        }
+    }
+
+    private CodeExecutableElement createConstructor(TypeElement type, ExecutableElement element) {
+        CodeExecutableElement executable = CodeExecutableElement.clone(getProcessingEnv(), element);
+
+        // to create a constructor we have to set the return type to null.(TODO needs fix)
+        executable.setReturnType(null);
+        // we have to set the name manually otherwise <init> is inferred (TODO needs fix)
+        executable.setSimpleName(CodeNames.of(type.getSimpleName().toString()));
+
+        CodeTreeBuilder b = executable.createBuilder();
+        b.startStatement().startSuperCall();
+        for (VariableElement v : element.getParameters()) {
+            b.string(v.getSimpleName().toString());
+        }
+        b.end().end();
+
+        return executable;
+    }
+
+    private void reset() {
+        inputFields.clear();
+        inputListFields.clear();
+        successorFields.clear();
+        successorListFields.clear();
+        dataFields.clear();
+        optionalInputs.clear();
+        inputTypes.clear();
+        genClass = null;
+        genClassName = null;
+    }
+
+    /**
+     * Checks that a generated method overrides exactly one method in a super type and that the
+     * super type is Node.
+     */
+    private void checkOnlyInGenNode(CodeExecutableElement method) {
+        List<ExecutableElement> overriddenMethods = getDeclaredMethodsInSuperTypes(method.getEnclosingClass(), method.getSimpleName().toString(), method.getParameterTypes());
+        for (ExecutableElement overriddenMethod : overriddenMethods) {
+            if (!overriddenMethod.getEnclosingElement().equals(Node)) {
+                env.message(Kind.WARNING, overriddenMethod, "This method is overridden in a generated subclass will never be called");
+            }
+        }
+    }
+
+    private void createIsLeafNodeMethod(CodeTypeElement cls) {
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getType(boolean.class), "isLeafNode");
+        method.createBuilder().startReturn().string("false").end();
+        cls.add(method);
+        checkOnlyInGenNode(method);
+    }
+
+    private ExecutableElement createIsOptionalInputAtMethod() {
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getType(boolean.class), "isOptionalInputAt");
+        method.addParameter(new CodeVariableElement(Position.asType(), "pos"));
+        CodeTreeBuilder b = method.createBuilder();
+        b.startAssert().string("pos.isInput()").end();
+        if (!optionalInputs.isEmpty()) {
+            b.startSwitch().string("pos.getIndex()").end().startBlock();
+            int index = 0;
+            for (VariableElement f : concat(inputFields, inputListFields)) {
+                if (optionalInputs.contains(f)) {
+                    b.startCase().string(String.valueOf(index)).end();
+                }
+                index++;
+            }
+            b.startStatement().string("return true").end();
+            b.end();
+        }
+        b.startReturn().string("false").end();
+        genClass.add(method);
+        checkOnlyInGenNode(method);
+        return method;
+    }
+
+    private ExecutableElement createGetFirstLevelPositionsMethod(NodeRefsType nodeRefsType, List<VariableElement> nodeFields, List<VariableElement> nodeListFields) {
+        DeclaredType collectionOfPosition = types.getDeclaredType((TypeElement) types.asElement(getType(Collection.class)), Position.asType());
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), collectionOfPosition, "getFirstLevel" + nodeRefsType);
+        CodeTreeBuilder b = method.createBuilder();
+        b.startReturn().startNew(getTypeElement("com.oracle.graal.graph.FirstLevelPositionCollection").asType());
+        b.string(String.valueOf(nodeFields.size()));
+        b.string(String.valueOf(nodeListFields.size()));
+        b.string(String.valueOf(nodeRefsType == NodeRefsType.Inputs));
+        b.end().end();
+        genClass.add(method);
+        checkOnlyInGenNode(method);
+        return method;
+    }
+
+    private CodeTypeElement createIteratorClass(NodeRefsType nodeRefsType, PackageElement packageElement, List<VariableElement> nodeFields, List<VariableElement> nodeListFields) {
+        String name = nodeRefsType + "Iterator";
+        CodeTypeElement cls = new CodeTypeElement(modifiers(PRIVATE), ElementKind.CLASS, packageElement, name);
+        cls.setSuperClass(getType("com.oracle.graal.graph.NodeRefIterator"));
+
+        // Constructor
+        CodeExecutableElement ctor = new CodeExecutableElement(Collections.emptySet(), null, name);
+        ctor.addParameter(new CodeVariableElement(getType(boolean.class), "callForward"));
+        CodeTreeBuilder b = ctor.createBuilder();
+        b.startStatement().startSuperCall();
+        b.string(String.valueOf(nodeFields.size()));
+        b.string(String.valueOf(nodeListFields.size()));
+        b.string(String.valueOf(nodeRefsType == NodeRefsType.Inputs));
+        b.end().end();
+        b.startIf().string("callForward").end().startBlock();
+        b.startStatement().string("forward()").end();
+        b.end();
+        cls.add(ctor);
+
+        // Methods overriding those in NodeRefIterator
+        createGetFieldMethod(cls, nodeFields, Node.asType(), "getNode");
+        createGetFieldMethod(cls, nodeListFields, types.getDeclaredType(NodeList, types.getWildcardType(Node.asType(), null)), "getNodeList");
+        genClass.add(cls);
+        return cls;
+    }
+
+    private void createGetFieldMethod(CodeTypeElement cls, List<VariableElement> fields, TypeMirror returnType, String name) {
+        if (!fields.isEmpty()) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), returnType, name);
+            method.addParameter(new CodeVariableElement(getType(int.class), "at"));
+            CodeTreeBuilder b = method.createBuilder();
+            createGetFieldCases(b, fields, returnType, null);
+            cls.add(method);
+        }
+    }
+
+    private void createGetFieldCases(CodeTreeBuilder b, List<VariableElement> fields, TypeMirror returnType, String returnExpressionSuffix) {
+        for (int i = 0; i < fields.size(); i++) {
+            VariableElement field = fields.get(i);
+            b.startIf().string("at == " + i).end().startBlock();
+            b.startReturn();
+            if (returnExpressionSuffix == null && !isAssignableWithErasure(field, types.asElement(returnType))) {
+                b.cast(((DeclaredType) returnType).asElement().getSimpleName().toString());
+            }
+            b.string(genClassName + ".this." + field.getSimpleName());
+            if (returnExpressionSuffix != null) {
+                b.string(returnExpressionSuffix);
+            }
+            b.end();
+            b.end();
+        }
+        b.startThrow().startNew(getType(NoSuchElementException.class)).end().end();
+    }
+
+    private void createSetNodeListAtCases(CodeTreeBuilder b, List<VariableElement> fields, TypeMirror returnType, String returnExpressionSuffix) {
+        for (int i = 0; i < fields.size(); i++) {
+            VariableElement field = fields.get(i);
+            b.startIf().string("at == " + i).end().startBlock();
+            if (returnExpressionSuffix == null && !isAssignableWithErasure(field, types.asElement(returnType))) {
+                b.cast(((DeclaredType) returnType).asElement().getSimpleName().toString());
+            }
+            b.startStatement();
+            b.string(genClassName + ".this." + field.getSimpleName(), " = ");
+            b.cast(field.asType(), CodeTreeBuilder.singleString("list"));
+            b.end();
+            b.end();
+        }
+    }
+
+    private void createUpdateOrInitializeFieldCases(CodeTreeBuilder b, List<VariableElement> fields, boolean isInitialization, boolean isList) {
+        boolean elseIf = false;
+        for (int i = 0; i < fields.size(); i++) {
+            VariableElement field = fields.get(i);
+            String fieldRef = genClassName + ".this." + field.getSimpleName();
+            if (!isList) {
+                elseIf = b.startIf(elseIf);
+                b.string("at == " + i).end().startBlock();
+                if (!isInitialization) {
+                    b.startStatement().string("Node old = ");
+                    if (!isAssignableWithErasure(field, Node)) {
+                        b.cast(Node.asType(), CodeTreeBuilder.singleString(fieldRef));
+                    } else {
+                        b.string(fieldRef);
+                    }
+                    b.end();
+                }
+                b.startStatement().string(fieldRef, " = ");
+                if (!isAssignableWithErasure(Node, field)) {
+                    b.cast(field.asType(), CodeTreeBuilder.singleString("newValue"));
+                } else {
+                    b.string("newValue");
+                }
+                b.end();
+                if (!isInitialization) {
+                    b.startIf().string("pos.isInput()").end().startBlock();
+                    b.startStatement().string("updateUsages(old, newValue)").end();
+                    b.end();
+                    b.startElseBlock();
+                    b.startStatement().string("updatePredecessor(old, newValue)").end();
+                    b.end();
+                }
+                b.end();
+            } else {
+                elseIf = b.startIf(elseIf);
+                b.string("at == " + i).end().startBlock();
+                DeclaredType nodeListOfNode = types.getDeclaredType(NodeList, types.getWildcardType(Node.asType(), null));
+                b.declaration(nodeListOfNode, "list", fieldRef);
+                if (!isInitialization) {
+                    // if (pos.getSubIndex() < list.size()) {
+                    b.startIf().string("pos.getSubIndex() < list.size()").end().startBlock();
+                    b.startStatement().string("list.set(pos.getSubIndex(), newValue)").end();
+                    b.end();
+                    b.startElseBlock();
+                }
+
+                b.startWhile().string("list.size() <= pos.getSubIndex()").end().startBlock();
+                b.startStatement().string("list.add(null)").end();
+                b.end();
+
+                if (isInitialization) {
+                    b.startStatement().string("list.initialize(pos.getSubIndex(), newValue)").end();
+                } else {
+                    b.startStatement().string("list.add(newValue)").end();
+                    b.end();
+                }
+
+                b.end();
+            }
+        }
+        b.startElseBlock();
+        b.startThrow().startNew(getType(NoSuchElementException.class)).end().end();
+        b.end();
+    }
+
+    private void createAllIteratorClass(NodeRefsType nodeRefsType, TypeMirror inputsIteratorType, PackageElement packageElement, List<VariableElement> nodeFields, List<VariableElement> nodeListFields) {
+
+        String name = "All" + nodeRefsType + "Iterator";
+        CodeTypeElement cls = new CodeTypeElement(modifiers(PRIVATE, FINAL), ElementKind.CLASS, packageElement, name);
+        cls.setSuperClass(inputsIteratorType);
+
+        // Constructor
+        CodeExecutableElement ctor = new CodeExecutableElement(Collections.emptySet(), null, name);
+        CodeTreeBuilder b = ctor.createBuilder();
+        b.startStatement().startSuperCall();
+        b.string("true");
+        b.end().end();
+        cls.add(ctor);
+
+        // forward() method
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), getType(void.class), "forward");
+        b = method.createBuilder();
+        int nodeFieldsSize = nodeFields.size();
+        int nodeListFieldsSize = nodeListFields.size();
+        String cond = "index < " + nodeFieldsSize;
+        b.startIf().string(cond).end().startBlock();
+        b.startStatement().string("index++").end();
+        b.startIf().string(cond).end().startBlock();
+        b.startStatement().string("return").end();
+        b.end();
+        b.end();
+        b.startElseBlock();
+        b.startStatement().string("subIndex++").end();
+        b.end();
+        DeclaredType nodeListOfNode = types.getDeclaredType(NodeList, types.getWildcardType(Node.asType(), null));
+        int count = nodeFieldsSize + nodeListFieldsSize;
+        b.startWhile().string("index < " + count).end().startBlock();
+        b.declaration(nodeListOfNode, "list", "getNodeList(index - " + nodeFieldsSize + ")");
+        b.startIf().string("subIndex < list.size()").end().startBlock();
+        b.startStatement().string("return").end();
+        b.end();
+        b.startStatement().string("subIndex = 0").end();
+        b.startStatement().string("index++").end();
+        b.end();
+
+        cls.add(method);
+
+        genClass.add(cls);
+    }
+
+    private void createWithModCountIteratorClass(NodeRefsType nodeRefsType, TypeMirror superType, PackageElement packageElement) {
+
+        String name = nodeRefsType + "WithModCountIterator";
+        CodeTypeElement cls = new CodeTypeElement(modifiers(PRIVATE, FINAL), ElementKind.CLASS, packageElement, name);
+        cls.setSuperClass(superType);
+
+        // modCount field
+        cls.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getType(int.class), "modCount"));
+
+        // Constructor
+        CodeExecutableElement ctor = new CodeExecutableElement(Collections.emptySet(), null, name);
+        CodeTreeBuilder b = ctor.createBuilder();
+        b.startStatement().startSuperCall();
+        b.string("false");
+        b.end().end();
+        b.startAssert().staticReference(getType("com.oracle.graal.graph.Graph"), "MODIFICATION_COUNTS_ENABLED").end();
+        b.startStatement().string("this.modCount = modCount()").end();
+        b.startStatement().string("forward()").end();
+        cls.add(ctor);
+
+        // hasNext, next and nextPosition methods
+        overrideModWithCounterMethod(cls, "hasNext", getType(boolean.class));
+        overrideModWithCounterMethod(cls, "next", Node.asType());
+        overrideModWithCounterMethod(cls, "nextPosition", Position.asType());
+
+        genClass.add(cls);
+    }
+
+    private static void overrideModWithCounterMethod(CodeTypeElement cls, String name, TypeMirror returnType) {
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, name);
+        CodeTreeBuilder b = method.createBuilder();
+        b.startTryBlock();
+        b.startStatement().string("return super." + name + "()").end();
+        b.end().startFinallyBlock();
+        b.startAssert().string("modCount == modCount() : \"must not be modified\"").end();
+        b.end();
+        cls.add(method);
+    }
+
+    private void createIterableClass(NodeRefsType nodeRefsType, PackageElement packageElement) {
+
+        String name = nodeRefsType + "Iterable";
+        CodeTypeElement cls = new CodeTypeElement(modifiers(PRIVATE), ElementKind.CLASS, packageElement, name);
+        cls.getImplements().add(getType("com.oracle.graal.graph.NodeRefIterable"));
+
+        // iterator() method
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType("com.oracle.graal.graph.NodeRefIterator"), "iterator");
+        CodeTreeBuilder b = method.createBuilder();
+        b.startIf().staticReference(getType("com.oracle.graal.graph.Graph"), "MODIFICATION_COUNTS_ENABLED").end().startBlock();
+        b.startStatement().string("return new " + nodeRefsType + "WithModCountIterator()").end();
+        b.end();
+        b.startElseBlock();
+        b.startStatement().string("return new " + nodeRefsType + "Iterator(true)").end();
+        b.end();
+        cls.add(method);
+
+        // withNullIterator() method
+        method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType("com.oracle.graal.graph.NodeRefIterator"), "withNullIterator");
+        b = method.createBuilder();
+        b.startStatement().string("return new All" + nodeRefsType + "Iterator()").end();
+        cls.add(method);
+
+        // contains(Node) method
+        method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType(boolean.class), "contains");
+        method.addParameter(new CodeVariableElement(Node.asType(), "n"));
+        b = method.createBuilder();
+        b.startStatement().string("return " + nodeRefsType.name().toLowerCase() + "Contain(n)").end();
+        cls.add(method);
+        genClass.add(cls);
+    }
+
+    private void createContainsMethod(NodeRefsType nodeRefsType, List<VariableElement> nodeFields, List<VariableElement> nodeListFields) {
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, FINAL), getType(boolean.class), nodeRefsType.name().toLowerCase() + "Contain");
+        method.addParameter(new CodeVariableElement(Node.asType(), "n"));
+        CodeTreeBuilder b = method.createBuilder();
+        for (VariableElement f : nodeFields) {
+            b.startIf().string("n == " + f).end().startBlock();
+            b.startStatement().string("return true").end();
+            b.end();
+        }
+        for (VariableElement f : nodeListFields) {
+            b.startIf().string(f + ".contains(n)").end().startBlock();
+            b.startStatement().string("return true").end();
+            b.end();
+        }
+        b.startStatement().string("return false").end();
+        genClass.add(method);
+        checkOnlyInGenNode(method);
+    }
+
+    private static final String API_TAG = "V2";
+
+    private void createIterableMethod(NodeRefsType nodeRefsType) {
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType("com.oracle.graal.graph.NodeRefIterable"), (nodeRefsType == Inputs ? "inputs" : "successors") +
+                        API_TAG);
+        CodeTreeBuilder b = method.createBuilder();
+        b.startStatement().string("return new " + nodeRefsType + "Iterable()").end();
+        genClass.add(method);
+        checkOnlyInGenNode(method);
+    }
+
+    private void createGetNodeAtMethod() {
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), Node.asType(), "getNodeAt");
+        method.addParameter(new CodeVariableElement(Position.asType(), "pos"));
+        CodeTreeBuilder b = method.createBuilder();
+        b.startIf().string("pos.isInput()").end().startBlock();
+        createGetNodeAt(b, inputFields, inputListFields);
+        b.end();
+        b.startElseBlock();
+        createGetNodeAt(b, successorFields, successorListFields);
+        b.end();
+        genClass.add(method);
+        checkOnlyInGenNode(method);
+    }
+
+    private void createGetNodeListAtMethod() {
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), types.getDeclaredType(NodeList, types.getWildcardType(Node.asType(), null)), "getNodeListAt");
+        method.addParameter(new CodeVariableElement(Position.asType(), "pos"));
+        CodeTreeBuilder b = method.createBuilder();
+        b.startIf().string("pos.isInput()").end().startBlock();
+        createGetNodeListAt(b, inputFields, inputListFields);
+        b.end();
+        b.startElseBlock();
+        createGetNodeListAt(b, successorFields, successorListFields);
+        b.end();
+        genClass.add(method);
+        checkOnlyInGenNode(method);
+    }
+
+    private void createSetNodeListAtMethod() {
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType(void.class), "SetNodeListAt");
+
+        DeclaredType suppress = (DeclaredType) getType(SuppressWarnings.class);
+        CodeAnnotationMirror suppressMirror = new CodeAnnotationMirror(suppress);
+        suppressMirror.setElementValue(suppressMirror.findExecutableElement("value"), new CodeAnnotationValue("unchecked"));
+        method.getAnnotationMirrors().add(suppressMirror);
+
+        method.addParameter(new CodeVariableElement(Position.asType(), "pos"));
+        method.addParameter(new CodeVariableElement(types.getDeclaredType(NodeList, types.getWildcardType(Node.asType(), null)), "list"));
+        CodeTreeBuilder b = method.createBuilder();
+        b.startIf().string("pos.isInput()").end().startBlock();
+        createSetNodeListAt(b, inputFields, inputListFields);
+        b.end();
+        b.startElseBlock();
+        createSetNodeListAt(b, successorFields, successorListFields);
+        b.end();
+        genClass.add(method);
+        checkOnlyInGenNode(method);
+    }
+
+    private void createGetNameOfMethod() {
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType(String.class), "getNameOf");
+        method.addParameter(new CodeVariableElement(Position.asType(), "pos"));
+        CodeTreeBuilder b = method.createBuilder();
+
+        b.startIf().string("pos.isInput()").end().startBlock();
+        createGetNameOf(b, inputFields, inputListFields);
+        b.end();
+        b.startElseBlock();
+        createGetNameOf(b, successorFields, successorListFields);
+        b.end();
+        genClass.add(method);
+        checkOnlyInGenNode(method);
+    }
+
+    private void createGetInputTypeAtMethod() {
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType(InputType.class), "getInputTypeAt");
+        method.addParameter(new CodeVariableElement(Position.asType(), "pos"));
+        CodeTreeBuilder b = method.createBuilder();
+        b.startAssert().string("pos.isInput()").end();
+        boolean hasNodes = !inputFields.isEmpty();
+        boolean hasNodeLists = !inputListFields.isEmpty();
+        if (hasNodeLists || hasNodes) {
+            int index = 0;
+            for (VariableElement f : concat(inputFields, inputListFields)) {
+                b.startIf().string("pos.getIndex() == " + index).end().startBlock();
+                b.startStatement().string("return ").staticReference(getType(InputType.class), inputTypes.get(f).getSimpleName().toString()).end();
+                b.end();
+                index++;
+            }
+        }
+        b.startThrow().startNew(getType(NoSuchElementException.class)).end().end();
+        genClass.add(method);
+        checkOnlyInGenNode(method);
+    }
+
+    private boolean hidesField(String name) {
+        for (VariableElement field : concat(inputFields, inputListFields, successorFields, successorListFields, dataFields)) {
+            if (field.getSimpleName().contentEquals(name)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void createUpdateOrInitializeNodeAtMethod(boolean isInitialization) {
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType(void.class), (isInitialization ? "initialize" : "update") + "NodeAt");
+        method.addParameter(new CodeVariableElement(Position.asType(), "pos"));
+        CodeVariableElement newValue = new CodeVariableElement(Node.asType(), "newValue");
+        if (hidesField(newValue.getSimpleName().toString())) {
+            DeclaredType suppress = (DeclaredType) getType(SuppressWarnings.class);
+            CodeAnnotationMirror suppressMirror = new CodeAnnotationMirror(suppress);
+            suppressMirror.setElementValue(suppressMirror.findExecutableElement("value"), new CodeAnnotationValue("hiding"));
+            newValue.getAnnotationMirrors().add(suppressMirror);
+        }
+        method.addParameter(newValue);
+        CodeTreeBuilder b = method.createBuilder();
+        b.startIf().string("pos.isInput()").end().startBlock();
+        createUpdateOrInitializeNodeAt(b, inputFields, inputListFields, isInitialization);
+        b.end();
+        b.startElseBlock();
+        createUpdateOrInitializeNodeAt(b, successorFields, successorListFields, isInitialization);
+        b.end();
+        genClass.add(method);
+        checkOnlyInGenNode(method);
+    }
+
+    private void createGetNodeAt(CodeTreeBuilder b, List<VariableElement> nodes, List<VariableElement> nodeLists) {
+        boolean hasNodes = !nodes.isEmpty();
+        boolean hasNodeLists = !nodeLists.isEmpty();
+        if (!hasNodeLists && !hasNodes) {
+            b.startThrow().startNew(getType(NoSuchElementException.class)).end().end();
+        } else {
+            if (hasNodes) {
+                if (!hasNodeLists) {
+                    b.startAssert().string("pos.getSubIndex() == NOT_ITERABLE").end();
+                } else {
+                    b.startIf().string("pos.getSubIndex() == NOT_ITERABLE").end().startBlock();
+                }
+                b.declaration("int", "at", "pos.getIndex()");
+                createGetFieldCases(b, nodes, Node.asType(), null);
+                if (hasNodeLists) {
+                    b.end();
+                }
+            }
+
+            if (hasNodeLists) {
+                if (!hasNodes) {
+                    b.startAssert().string("pos.getSubIndex() != NOT_ITERABLE").end();
+                } else {
+                    b.startElseBlock();
+                }
+                b.declaration("int", "at", "pos.getIndex() - " + nodes.size());
+                createGetFieldCases(b, nodeLists, Node.asType(), ".get(pos.getSubIndex())");
+                if (hasNodes) {
+                    b.end();
+                }
+            }
+        }
+    }
+
+    private void createGetNodeListAt(CodeTreeBuilder b, List<VariableElement> nodes, List<VariableElement> nodeLists) {
+        boolean hasNodeLists = !nodeLists.isEmpty();
+        if (!hasNodeLists) {
+            b.startThrow().startNew(getType(NoSuchElementException.class)).end().end();
+        } else {
+            b.startAssert().string("pos.getSubIndex() == NODE_LIST").end();
+            b.declaration("int", "at", "pos.getIndex() - " + nodes.size());
+            createGetFieldCases(b, nodeLists, Node.asType(), "");
+        }
+    }
+
+    private void createSetNodeListAt(CodeTreeBuilder b, List<VariableElement> nodes, List<VariableElement> nodeLists) {
+        boolean hasNodeLists = !nodeLists.isEmpty();
+        if (!hasNodeLists) {
+            b.startThrow().startNew(getType(NoSuchElementException.class)).end().end();
+        } else {
+            b.startAssert().string("pos.getSubIndex() == NODE_LIST").end();
+            b.declaration("int", "at", "pos.getIndex() - " + nodes.size());
+            createSetNodeListAtCases(b, nodeLists, Node.asType(), "");
+        }
+    }
+
+    private void createGetNameOf(CodeTreeBuilder b, List<VariableElement> nodes, List<VariableElement> nodeLists) {
+        boolean hasNodes = !nodes.isEmpty();
+        boolean hasNodeLists = !nodeLists.isEmpty();
+        if (hasNodeLists || hasNodes) {
+            int index = 0;
+            for (VariableElement f : nodes) {
+                b.startIf().string("pos.getIndex() == " + index).end().startBlock();
+                b.startStatement().string("return \"" + f.getSimpleName() + "\"").end();
+                b.end();
+                index++;
+            }
+            for (VariableElement f : nodeLists) {
+                b.startIf().string("pos.getIndex() == " + index).end().startBlock();
+                b.startStatement().string("return \"" + f.getSimpleName() + "\"").end();
+                b.end();
+                index++;
+            }
+        }
+        b.startThrow().startNew(getType(NoSuchElementException.class)).end().end();
+    }
+
+    private void createUpdateOrInitializeNodeAt(CodeTreeBuilder b, List<VariableElement> nodes, List<VariableElement> nodeLists, boolean isInitialization) {
+        boolean hasNodes = !nodes.isEmpty();
+        boolean hasNodeLists = !nodeLists.isEmpty();
+        if (nodes.isEmpty() && nodeLists.isEmpty()) {
+            b.startThrow().startNew(getType(NoSuchElementException.class)).end().end();
+        } else {
+            if (hasNodes) {
+                if (!hasNodeLists) {
+                    b.startAssert().string("pos.getSubIndex() == NOT_ITERABLE").end();
+                } else {
+                    b.startIf().string("pos.getSubIndex() == NOT_ITERABLE").end().startBlock();
+                }
+                b.declaration("int", "at", "pos.getIndex()");
+                createUpdateOrInitializeFieldCases(b, nodes, isInitialization, false);
+                if (hasNodeLists) {
+                    b.end();
+                }
+            }
+
+            if (hasNodeLists) {
+                if (!hasNodes) {
+                    b.startAssert().string("pos.getSubIndex() != NOT_ITERABLE").end();
+                } else {
+                    b.startElseBlock();
+                }
+                b.declaration("int", "at", "pos.getIndex() - " + nodes.size());
+                createUpdateOrInitializeFieldCases(b, nodeLists, isInitialization, true);
+                if (hasNodes) {
+                    b.end();
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeProcessor.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2014, 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.nodeinfo.processor;
+
+import java.io.*;
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+import javax.tools.Diagnostic.Kind;
+
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.java.transform.*;
+
+@SupportedSourceVersion(SourceVersion.RELEASE_8)
+@SupportedAnnotationTypes({"com.oracle.graal.nodeinfo.NodeInfo"})
+public class GraphNodeProcessor extends AbstractProcessor {
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latest();
+    }
+
+    void errorMessage(Element element, String format, Object... args) {
+        message(Kind.ERROR, element, format, args);
+    }
+
+    void message(Kind kind, Element element, String format, Object... args) {
+        processingEnv.getMessager().printMessage(kind, String.format(format, args), element);
+    }
+
+    /**
+     * Bugs in an annotation processor can cause silent failure so try to report any exception
+     * throws as errors.
+     */
+    private void reportException(Element element, Throwable t) {
+        StringWriter buf = new StringWriter();
+        t.printStackTrace(new PrintWriter(buf));
+        buf.toString();
+        errorMessage(element, "Exception thrown during processing: %s", buf.toString());
+    }
+
+    ProcessingEnvironment getProcessingEnv() {
+        return processingEnv;
+    }
+
+    boolean isNodeType(Element element) {
+        if (element.getKind() != ElementKind.CLASS) {
+            return false;
+        }
+        TypeElement type = (TypeElement) element;
+        Types types = processingEnv.getTypeUtils();
+
+        while (type != null) {
+            if (type.toString().equals("com.oracle.graal.graph.Node")) {
+                return true;
+            }
+            type = (TypeElement) types.asElement(type.getSuperclass());
+        }
+        return false;
+    }
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        if (roundEnv.processingOver()) {
+            return false;
+        }
+
+        GraphNodeGenerator gen = new GraphNodeGenerator(this);
+
+        for (Element element : roundEnv.getElementsAnnotatedWith(NodeInfo.class)) {
+            try {
+                if (!isNodeType(element)) {
+                    errorMessage(element, "%s can only be applied to Node subclasses", NodeInfo.class.getSimpleName());
+                    continue;
+                }
+
+                NodeInfo nodeInfo = element.getAnnotation(NodeInfo.class);
+                if (nodeInfo == null) {
+                    errorMessage(element, "Cannot get %s annotation from annotated element", NodeInfo.class.getSimpleName());
+                    continue;
+                }
+
+                TypeElement typeElement = (TypeElement) element;
+
+                if (typeElement.getModifiers().contains(Modifier.FINAL)) {
+                    errorMessage(element, "%s annotated class must not be final", NodeInfo.class.getSimpleName());
+                    continue;
+                }
+
+                if (!typeElement.equals(gen.Node) && !typeElement.getModifiers().contains(Modifier.ABSTRACT)) {
+                    CodeCompilationUnit unit = gen.process(typeElement);
+                    unit.setGeneratorElement(typeElement);
+
+                    DeclaredType overrideType = (DeclaredType) ElementUtils.getType(processingEnv, Override.class);
+                    DeclaredType unusedType = (DeclaredType) ElementUtils.getType(processingEnv, SuppressWarnings.class);
+                    unit.accept(new GenerateOverrideVisitor(overrideType), null);
+                    unit.accept(new FixWarningsVisitor(processingEnv, unusedType, overrideType), null);
+                    unit.accept(new CodeWriter(processingEnv, typeElement), null);
+                }
+            } catch (ElementException ee) {
+                errorMessage(ee.element, ee.getMessage());
+            } catch (Throwable t) {
+                if (!isBug367599(t)) {
+                    reportException(element, t);
+                } else {
+                    message(Kind.NOTE, element, t.toString());
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Determines if a given exception is (most likely) caused by <a
+     * href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=367599">Bug 367599</a>.
+     */
+    public static boolean isBug367599(Throwable t) {
+        for (StackTraceElement ste : t.getStackTrace()) {
+            if (ste.toString().contains("org.eclipse.jdt.internal.apt.pluggable.core.filer.IdeFilerImpl.create")) {
+                // See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=367599
+                return true;
+            }
+        }
+        if (t.getCause() != null) {
+            return isBug367599(t.getCause());
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodeinfo/src/com/oracle/graal/nodeinfo/GeneratedNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, 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.nodeinfo;
+
+import java.lang.annotation.*;
+
+/**
+ * Denotes a Node subclass generated on the basis of a {@link NodeInfo} annotation on a Node type.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface GeneratedNode {
+
+    /**
+     * The Node class from which the annotated type was generated.
+     */
+    Class<?> value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodeinfo/src/com/oracle/graal/nodeinfo/InputType.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014, 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.nodeinfo;
+
+public enum InputType {
+    /**
+     * Inputs that consume an actual value generated by the referenced node.
+     */
+    Value,
+    /**
+     * Inputs that consume the memory state of the referenced node.
+     */
+    Memory,
+    /**
+     * Inputs that reference a condition.
+     */
+    Condition,
+    /**
+     * Inputs that reference a frame state.
+     */
+    State,
+    /**
+     * Inputs that reference a guard (guards, begin nodes).
+     */
+    Guard,
+    /**
+     * Inputs that reference an anchor (begin nodes, value anchors).
+     */
+    Anchor,
+    /**
+     * Inputs that represent an association between nodes, e.g., a phi and the merge or a loop begin
+     * and loop exits and ends.
+     */
+    Association,
+    /**
+     * Inputs that connect tightly coupled nodes, e.g., an InvokeNode and its CallTargetNode.
+     */
+    Extension,
+    /**
+     * Inputs of this type are temporarily exempt from type checking. This should only be used in
+     * exceptional cases and should never survive to later stages of compilation.
+     */
+    Unchecked
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodeinfo/src/com/oracle/graal/nodeinfo/NodeInfo.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodeinfo;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface NodeInfo {
+
+    String shortName() default "";
+
+    /**
+     * The template used to build the {@link Verbosity#Name} version. Variable part are specified
+     * using &#123;i#inputName&#125; or &#123;p#propertyName&#125;.
+     */
+    String nameTemplate() default "";
+
+    InputType[] allowedUsageTypes() default {};
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodeinfo/src/com/oracle/graal/nodeinfo/Verbosity.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014, 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.nodeinfo;
+
+public enum Verbosity {
+    /**
+     * Only the id of the node.
+     */
+    Id,
+    /**
+     * Only the name of the node, which may contain some more information for certain node types
+     * (constants, ...).
+     */
+    Name,
+    /**
+     * {@link #Id} + {@link #Name}.
+     */
+    Short,
+    /**
+     * Defaults to {@link #Short} and may be enhanced by subclasses.
+     */
+    Long,
+    /**
+     * For use by a custom formatting facility in an IDE.
+     */
+    Debugger,
+    /**
+     * All the other information plus all debug properties of the node.
+     */
+    All
+}
\ No newline at end of file
--- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/LoopPhiCanonicalizerTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/LoopPhiCanonicalizerTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -56,7 +56,7 @@
 
     @Test
     public void test() {
-        StructuredGraph graph = parse("loopSnippet");
+        StructuredGraph graph = parseEager("loopSnippet");
         NodePredicate loopPhis = node -> node instanceof PhiNode && ((PhiNode) node).merge() instanceof LoopBeginNode;
 
         PhaseContext context = new PhaseContext(getProviders(), null);
--- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/NegateNodeCanonicalizationTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/NegateNodeCanonicalizationTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -48,7 +48,7 @@
         for (byte i : a) {
             ConstantNode node = ConstantNode.forByte(i, graph);
             Constant expected = Constant.forInt(-i);
-            assertEquals(expected, new NegateNode(node).evalConst(node.asConstant()));
+            assertEquals(expected, NegateNode.create(node).evalConst(node.asConstant()));
         }
     }
 
@@ -58,7 +58,7 @@
         for (char i : a) {
             ConstantNode node = ConstantNode.forChar(i, graph);
             Constant expected = Constant.forInt(-i);
-            assertEquals(expected, new NegateNode(node).evalConst(node.asConstant()));
+            assertEquals(expected, NegateNode.create(node).evalConst(node.asConstant()));
         }
     }
 
@@ -68,7 +68,7 @@
         for (short i : a) {
             ConstantNode node = ConstantNode.forShort(i, graph);
             Constant expected = Constant.forInt(-i);
-            assertEquals(expected, new NegateNode(node).evalConst(node.asConstant()));
+            assertEquals(expected, NegateNode.create(node).evalConst(node.asConstant()));
         }
     }
 
@@ -78,7 +78,7 @@
         for (int i : a) {
             ConstantNode node = ConstantNode.forInt(i, graph);
             Constant expected = Constant.forInt(-i);
-            assertEquals(expected, new NegateNode(node).evalConst(node.asConstant()));
+            assertEquals(expected, NegateNode.create(node).evalConst(node.asConstant()));
         }
     }
 
@@ -88,7 +88,7 @@
         for (long i : a) {
             ConstantNode node = ConstantNode.forLong(i, graph);
             Constant expected = Constant.forLong(-i);
-            assertEquals(expected, new NegateNode(node).evalConst(node.asConstant()));
+            assertEquals(expected, NegateNode.create(node).evalConst(node.asConstant()));
         }
     }
 
@@ -98,7 +98,7 @@
         for (float i : a) {
             ConstantNode node = ConstantNode.forFloat(i, graph);
             Constant expected = Constant.forFloat(-i);
-            assertEquals(expected, new NegateNode(node).evalConst(node.asConstant()));
+            assertEquals(expected, NegateNode.create(node).evalConst(node.asConstant()));
         }
     }
 
@@ -108,7 +108,7 @@
         for (double i : a) {
             ConstantNode node = ConstantNode.forDouble(i, graph);
             Constant expected = Constant.forDouble(-i);
-            assertEquals(expected, new NegateNode(node).evalConst(node.asConstant()));
+            assertEquals(expected, NegateNode.create(node).evalConst(node.asConstant()));
         }
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 
 /**
  * This node represents an unconditional explicit request for immediate deoptimization.
@@ -32,9 +33,10 @@
  * After this node, execution will continue using a fallback execution engine (such as an
  * interpreter) at the position described by the {@link #stateBefore() deoptimization state}.
  */
+@NodeInfo
 public abstract class AbstractDeoptimizeNode extends ControlSinkNode implements IterableNodeType, DeoptimizingNode.DeoptBefore {
 
-    @OptionalInput(InputType.State) private FrameState stateBefore;
+    @OptionalInput(InputType.State) FrameState stateBefore;
 
     public AbstractDeoptimizeNode() {
         super(StampFactory.forVoid());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,8 +26,10 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public abstract class AbstractEndNode extends FixedNode implements IterableNodeType, LIRLowerable {
 
     protected AbstractEndNode() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,14 +24,15 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.util.*;
 
+@NodeInfo
 public abstract class AbstractFixedGuardNode extends DeoptimizingFixedWithNextNode implements Simplifiable, GuardingNode {
 
-    @Input(InputType.Condition) private LogicNode condition;
+    @Input(InputType.Condition) LogicNode condition;
     private final DeoptimizationReason reason;
     private final DeoptimizationAction action;
     private boolean negated;
@@ -84,17 +85,17 @@
     }
 
     public DeoptimizeNode lowerToIf() {
-        FixedNode next = next();
+        FixedNode currentNext = next();
         setNext(null);
-        DeoptimizeNode deopt = graph().add(new DeoptimizeNode(action, reason));
+        DeoptimizeNode deopt = graph().add(DeoptimizeNode.create(action, reason));
         deopt.setStateBefore(stateBefore());
         IfNode ifNode;
         BeginNode noDeoptSuccessor;
         if (negated) {
-            ifNode = graph().add(new IfNode(condition, deopt, next, 0));
+            ifNode = graph().add(IfNode.create(condition, deopt, currentNext, 0));
             noDeoptSuccessor = ifNode.falseSuccessor();
         } else {
-            ifNode = graph().add(new IfNode(condition, next, deopt, 1));
+            ifNode = graph().add(IfNode.create(condition, currentNext, deopt, 1));
             noDeoptSuccessor = ifNode.trueSuccessor();
         }
         ((FixedWithNextNode) predecessor()).setNext(ifNode);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractLocalNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractLocalNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.calc.*;
 
+@NodeInfo
 public abstract class AbstractLocalNode extends FloatingNode {
 
     private final int index;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMemoryCheckpoint.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMemoryCheckpoint.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,11 +23,13 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.extended.*;
 
 /**
  * Provides an implementation of {@link StateSplit}.
  */
+@NodeInfo
 public abstract class AbstractMemoryCheckpoint extends AbstractStateSplit implements MemoryCheckpoint {
 
     protected AbstractMemoryCheckpoint(Stamp stamp) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,14 +23,15 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 
 /**
  * Provides an implementation of {@link StateSplit}.
  */
+@NodeInfo
 public abstract class AbstractStateSplit extends FixedWithNextNode implements StateSplit {
 
-    @OptionalInput(InputType.State) private FrameState stateAfter;
+    @OptionalInput(InputType.State) protected FrameState stateAfter;
 
     public FrameState stateAfter() {
         return stateAfter;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -30,6 +30,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
@@ -37,11 +38,23 @@
 @NodeInfo(allowedUsageTypes = {InputType.Guard, InputType.Anchor})
 public class BeginNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, GuardingNode, AnchoringNode, IterableNodeType {
 
-    public BeginNode() {
+    public static BeginNode create() {
+        return USE_GENERATED_NODES ? new BeginNodeGen() : new BeginNode();
+    }
+
+    public static Class<? extends BeginNode> getGenClass() {
+        return USE_GENERATED_NODES ? BeginNodeGen.class : BeginNode.class;
+    }
+
+    protected BeginNode() {
         super(StampFactory.forVoid());
     }
 
-    public BeginNode(Stamp stamp) {
+    public static BeginNode create(Stamp stamp) {
+        return USE_GENERATED_NODES ? new BeginNodeGen(stamp) : new BeginNode(stamp);
+    }
+
+    protected BeginNode(Stamp stamp) {
         super(stamp);
     }
 
@@ -49,7 +62,7 @@
         if (with instanceof BeginNode) {
             return (BeginNode) with;
         }
-        BeginNode begin = with.graph().add(new BeginNode());
+        BeginNode begin = with.graph().add(BeginNode.create());
         begin.setNext(with);
         return begin;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,7 +23,7 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 
 /**
  * Base class for {@link BeginNode}s that are associated with a frame state.
@@ -32,9 +32,10 @@
  * which is not possible until loop peeling works without requiring begin nodes to have frames
  * states.
  */
+@NodeInfo
 public abstract class BeginStateSplitNode extends BeginNode implements StateSplit {
 
-    @OptionalInput(InputType.State) private FrameState stateAfter;
+    @OptionalInput(InputType.State) protected FrameState stateAfter;
 
     public BeginStateSplitNode() {
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,12 +23,14 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public abstract class BinaryOpLogicNode extends LogicNode implements LIRLowerable, Canonicalizable.Binary<ValueNode> {
 
-    @Input private ValueNode x;
-    @Input private ValueNode y;
+    @Input protected ValueNode x;
+    @Input protected ValueNode y;
 
     public ValueNode getX() {
         return x;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
@@ -33,22 +34,27 @@
  * are set up as if the breakpoint instruction was a call to a compiled Java method.
  * <p>
  * A breakpoint is usually place by defining a node intrinsic method as follows:
- * 
+ *
  * <pre>
  *     {@literal @}NodeIntrinsic(BreakpointNode.class)
  *     static void breakpoint(Object object, Word mark, Word value) {
  *          throw new GraalInternalError("");
  *     }
  * </pre>
- * 
+ *
  * Note that the signature is arbitrary. It's sole purpose is to capture values you may want to
  * inspect in the native debugger when the breakpoint is hit.
  */
-public final class BreakpointNode extends FixedWithNextNode implements LIRLowerable {
+@NodeInfo
+public class BreakpointNode extends FixedWithNextNode implements LIRLowerable {
+
+    @Input NodeInputList<ValueNode> arguments;
 
-    @Input private final NodeInputList<ValueNode> arguments;
+    public static BreakpointNode create(ValueNode[] arguments) {
+        return USE_GENERATED_NODES ? new BreakpointNodeGen(arguments) : new BreakpointNode(arguments);
+    }
 
-    public BreakpointNode(ValueNode... arguments) {
+    protected BreakpointNode(ValueNode... arguments) {
         super(StampFactory.forVoid());
         this.arguments = new NodeInputList<>(this, arguments);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,6 +27,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Extension})
@@ -42,7 +43,7 @@
         }
     }
 
-    @Input private final NodeInputList<ValueNode> arguments;
+    @Input protected NodeInputList<ValueNode> arguments;
     private ResolvedJavaMethod targetMethod;
     private InvokeKind invokeKind;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,20 +25,29 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(nameTemplate = "ConditionAnchor(!={p#negated})", allowedUsageTypes = {InputType.Guard})
-public final class ConditionAnchorNode extends FixedWithNextNode implements Canonicalizable.Unary<Node>, Lowerable, GuardingNode {
+public class ConditionAnchorNode extends FixedWithNextNode implements Canonicalizable.Unary<Node>, Lowerable, GuardingNode {
 
-    @Input(InputType.Condition) private LogicNode condition;
+    @Input(InputType.Condition) LogicNode condition;
     private boolean negated;
 
-    public ConditionAnchorNode(LogicNode condition) {
+    public static ConditionAnchorNode create(LogicNode condition) {
+        return USE_GENERATED_NODES ? new ConditionAnchorNodeGen(condition) : new ConditionAnchorNode(condition);
+    }
+
+    protected ConditionAnchorNode(LogicNode condition) {
         this(condition, false);
     }
 
-    public ConditionAnchorNode(LogicNode condition, boolean negated) {
+    public static ConditionAnchorNode create(LogicNode condition, boolean negated) {
+        return USE_GENERATED_NODES ? new ConditionAnchorNodeGen(condition, negated) : new ConditionAnchorNode(condition, negated);
+    }
+
+    protected ConditionAnchorNode(LogicNode condition, boolean negated) {
         super(StampFactory.forVoid());
         this.negated = negated;
         this.condition = condition;
@@ -64,14 +73,14 @@
     public Node canonical(CanonicalizerTool tool, Node forValue) {
         if (condition instanceof LogicNegationNode) {
             LogicNegationNode negation = (LogicNegationNode) condition;
-            return new ConditionAnchorNode(negation.getValue(), !negated);
+            return ConditionAnchorNode.create(negation.getValue(), !negated);
         }
         if (condition instanceof LogicConstantNode) {
             LogicConstantNode c = (LogicConstantNode) condition;
             if (c.getValue() != negated) {
                 return null;
             } else {
-                return new ValueAnchorNode(null);
+                return ValueAnchorNode.create(null);
             }
         }
         return this;
@@ -80,7 +89,7 @@
     @Override
     public void lower(LoweringTool tool) {
         if (graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
-            ValueAnchorNode newAnchor = graph().add(new ValueAnchorNode(null));
+            ValueAnchorNode newAnchor = graph().add(ValueAnchorNode.create(null));
             graph().replaceFixedWithFixed(this, newAnchor);
         }
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -30,6 +30,7 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -37,7 +38,7 @@
  * The {@code ConstantNode} represents a {@link Constant constant}.
  */
 @NodeInfo(shortName = "Const", nameTemplate = "Const({p#rawvalue})")
-public final class ConstantNode extends FloatingNode implements LIRLowerable {
+public class ConstantNode extends FloatingNode implements LIRLowerable {
 
     private static final DebugMetric ConstantNodes = Debug.metric("ConstantNodes");
 
@@ -45,7 +46,7 @@
 
     private static ConstantNode createPrimitive(Constant value) {
         assert value.getKind() != Kind.Object;
-        return new ConstantNode(value, StampFactory.forConstant(value));
+        return ConstantNode.create(value, StampFactory.forConstant(value));
     }
 
     /**
@@ -53,6 +54,10 @@
      *
      * @param value the constant
      */
+    public static ConstantNode create(Constant value, Stamp stamp) {
+        return USE_GENERATED_NODES ? new ConstantNodeGen(value, stamp) : new ConstantNode(value, stamp);
+    }
+
     protected ConstantNode(Constant value, Stamp stamp) {
         super(stamp);
         assert stamp != null;
@@ -108,7 +113,7 @@
             return forInt(constant.asInt(), graph);
         }
         if (constant.getKind() == Kind.Object) {
-            return unique(graph, new ConstantNode(constant, StampFactory.forConstant(constant, metaAccess)));
+            return unique(graph, ConstantNode.create(constant, StampFactory.forConstant(constant, metaAccess)));
         } else {
             return unique(graph, createPrimitive(constant));
         }
@@ -119,18 +124,18 @@
             return forInt(constant.asInt());
         }
         if (constant.getKind() == Kind.Object) {
-            return new ConstantNode(constant, StampFactory.forConstant(constant, metaAccess));
+            return ConstantNode.create(constant, StampFactory.forConstant(constant, metaAccess));
         } else {
             return createPrimitive(constant);
         }
     }
 
     public static ConstantNode forConstant(Stamp stamp, Constant constant, MetaAccessProvider metaAccess, StructuredGraph graph) {
-        return graph.unique(new ConstantNode(constant, stamp.constant(constant, metaAccess)));
+        return graph.unique(ConstantNode.create(constant, stamp.constant(constant, metaAccess)));
     }
 
     public static ConstantNode forConstant(Stamp stamp, Constant constant, MetaAccessProvider metaAccess) {
-        return new ConstantNode(constant, stamp.constant(constant, metaAccess));
+        return ConstantNode.create(constant, stamp.constant(constant, metaAccess));
     }
 
     /**
@@ -314,7 +319,7 @@
     private static ConstantNode forIntegerBits(int bits, Constant constant, StructuredGraph graph) {
         long value = constant.asLong();
         long bounds = SignExtendNode.signExtend(value, bits);
-        return unique(graph, new ConstantNode(constant, StampFactory.forInteger(bits, bounds, bounds)));
+        return unique(graph, ConstantNode.create(constant, StampFactory.forInteger(bits, bounds, bounds)));
     }
 
     /**
@@ -328,7 +333,7 @@
     private static ConstantNode forIntegerBits(int bits, Constant constant) {
         long value = constant.asLong();
         long bounds = SignExtendNode.signExtend(value, bits);
-        return new ConstantNode(constant, StampFactory.forInteger(bits, bounds, bounds));
+        return ConstantNode.create(constant, StampFactory.forInteger(bits, bounds, bounds));
     }
 
     /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,7 +23,9 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 
+@NodeInfo
 public abstract class ControlSinkNode extends FixedNode {
 
     public ControlSinkNode(Stamp stamp) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,11 +24,13 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 
 /**
  * The {@code ControlSplitNode} is a base class for all instructions that split the control flow
  * (ie. have more than one successor).
  */
+@NodeInfo
 public abstract class ControlSplitNode extends FixedNode implements IterableNodeType {
 
     public ControlSplitNode(Stamp stamp) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,7 +23,7 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}")
@@ -34,11 +34,19 @@
     private final int debugId;
     private final Constant speculation;
 
-    public DeoptimizeNode(DeoptimizationAction action, DeoptimizationReason reason) {
+    public static DeoptimizeNode create(DeoptimizationAction action, DeoptimizationReason reason) {
+        return USE_GENERATED_NODES ? new DeoptimizeNodeGen(action, reason) : new DeoptimizeNode(action, reason);
+    }
+
+    protected DeoptimizeNode(DeoptimizationAction action, DeoptimizationReason reason) {
         this(action, reason, 0, Constant.NULL_OBJECT, null);
     }
 
-    public DeoptimizeNode(DeoptimizationAction action, DeoptimizationReason reason, int debugId, Constant speculation, FrameState stateBefore) {
+    public static DeoptimizeNode create(DeoptimizationAction action, DeoptimizationReason reason, int debugId, Constant speculation, FrameState stateBefore) {
+        return USE_GENERATED_NODES ? new DeoptimizeNodeGen(action, reason, debugId, speculation, stateBefore) : new DeoptimizeNode(action, reason, debugId, speculation, stateBefore);
+    }
+
+    protected DeoptimizeNode(DeoptimizationAction action, DeoptimizationReason reason, int debugId, Constant speculation, FrameState stateBefore) {
         super(stateBefore);
         assert action != null;
         assert reason != null;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,11 +23,12 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 
+@NodeInfo
 public abstract class DeoptimizingFixedWithNextNode extends FixedWithNextNode implements DeoptimizingNode.DeoptBefore {
 
-    @OptionalInput(InputType.State) private FrameState stateBefore;
+    @OptionalInput(InputType.State) protected FrameState stateBefore;
 
     public DeoptimizingFixedWithNextNode(Stamp stamp) {
         super(stamp);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,10 +27,17 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 
+@NodeInfo
 public class DirectCallTargetNode extends LoweredCallTargetNode {
 
-    public DirectCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType, InvokeKind invokeKind) {
+    public static DirectCallTargetNode create(List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType, InvokeKind invokeKind) {
+        return USE_GENERATED_NODES ? new DirectCallTargetNodeGen(arguments, returnStamp, signature, target, callType, invokeKind) : new DirectCallTargetNode(arguments, returnStamp, signature, target,
+                        callType, invokeKind);
+    }
+
+    protected DirectCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType, InvokeKind invokeKind) {
         super(arguments, returnStamp, signature, target, callType, invokeKind);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DispatchBeginNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DispatchBeginNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,13 +23,23 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 
 /**
  * The entry node of an exception dispatcher block.
  */
+@NodeInfo
 public class DispatchBeginNode extends BeginStateSplitNode {
 
-    public DispatchBeginNode() {
+    public static DispatchBeginNode create() {
+        return USE_GENERATED_NODES ? new DispatchBeginNodeGen() : new DispatchBeginNode();
+    }
+
+    protected DispatchBeginNode() {
+    }
+
+    public static DispatchBeginNode create(Stamp stamp) {
+        return USE_GENERATED_NODES ? new DispatchBeginNodeGen(stamp) : new DispatchBeginNode(stamp);
     }
 
     protected DispatchBeginNode(Stamp stamp) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,13 +25,19 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public class DynamicDeoptimizeNode extends AbstractDeoptimizeNode implements LIRLowerable, Canonicalizable {
-    @Input private ValueNode actionAndReason;
-    @Input private ValueNode speculation;
+    @Input ValueNode actionAndReason;
+    @Input ValueNode speculation;
 
-    public DynamicDeoptimizeNode(ValueNode actionAndReason, ValueNode speculation) {
+    public static DynamicDeoptimizeNode create(ValueNode actionAndReason, ValueNode speculation) {
+        return USE_GENERATED_NODES ? new DynamicDeoptimizeNodeGen(actionAndReason, speculation) : new DynamicDeoptimizeNode(actionAndReason, speculation);
+    }
+
+    protected DynamicDeoptimizeNode(ValueNode actionAndReason, ValueNode speculation) {
         this.actionAndReason = actionAndReason;
         this.speculation = speculation;
     }
@@ -63,8 +69,8 @@
         if (actionAndReason.isConstant() && speculation.isConstant()) {
             Constant constant = actionAndReason.asConstant();
             Constant speculationConstant = speculation.asConstant();
-            DeoptimizeNode newDeopt = new DeoptimizeNode(tool.getMetaAccess().decodeDeoptAction(constant), tool.getMetaAccess().decodeDeoptReason(constant), tool.getMetaAccess().decodeDebugId(
-                            constant), speculationConstant, stateBefore());
+            DeoptimizeNode newDeopt = DeoptimizeNode.create(tool.getMetaAccess().decodeDeoptAction(constant), tool.getMetaAccess().decodeDeoptReason(constant),
+                            tool.getMetaAccess().decodeDebugId(constant), speculationConstant, stateBefore());
             return newDeopt;
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,8 +22,18 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Association})
-public final class EndNode extends AbstractEndNode {
+public class EndNode extends AbstractEndNode {
+    public static EndNode create() {
+        return USE_GENERATED_NODES ? new EndNodeGen() : new EndNode();
+    }
+
+    public static Class<? extends EndNode> getGenClass() {
+        return USE_GENERATED_NODES ? EndNodeGen.class : EndNode.class;
+    }
+
+    EndNode() {
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
@@ -34,6 +35,13 @@
 @NodeInfo(allowedUsageTypes = {InputType.Association})
 public class EntryMarkerNode extends BeginStateSplitNode implements IterableNodeType, Simplifiable, LIRLowerable {
 
+    public static EntryMarkerNode create() {
+        return USE_GENERATED_NODES ? new EntryMarkerNodeGen() : new EntryMarkerNode();
+    }
+
+    EntryMarkerNode() {
+    }
+
     @Override
     public void simplify(SimplifierTool tool) {
         // this node should not be removed, this overrides BeginNode.simplify
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,17 +25,26 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}", allowedUsageTypes = {InputType.Guard})
-public final class FixedGuardNode extends AbstractFixedGuardNode implements Lowerable, IterableNodeType {
+public class FixedGuardNode extends AbstractFixedGuardNode implements Lowerable, IterableNodeType {
 
-    public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action) {
+    public static FixedGuardNode create(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action) {
+        return USE_GENERATED_NODES ? new FixedGuardNodeGen(condition, deoptReason, action) : new FixedGuardNode(condition, deoptReason, action);
+    }
+
+    protected FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action) {
         this(condition, deoptReason, action, false);
     }
 
-    public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
+    public static FixedGuardNode create(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
+        return USE_GENERATED_NODES ? new FixedGuardNodeGen(condition, deoptReason, action, negated) : new FixedGuardNode(condition, deoptReason, action, negated);
+    }
+
+    protected FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
         super(condition, deoptReason, action, negated);
     }
 
@@ -46,12 +55,12 @@
         if (condition() instanceof LogicConstantNode) {
             LogicConstantNode c = (LogicConstantNode) condition();
             if (c.getValue() == isNegated()) {
-                FixedNode next = this.next();
-                if (next != null) {
-                    tool.deleteBranch(next);
+                FixedNode currentNext = this.next();
+                if (currentNext != null) {
+                    tool.deleteBranch(currentNext);
                 }
 
-                DeoptimizeNode deopt = graph().add(new DeoptimizeNode(getAction(), getReason()));
+                DeoptimizeNode deopt = graph().add(DeoptimizeNode.create(getAction(), getReason()));
                 deopt.setStateBefore(stateBefore());
                 setNext(deopt);
             }
@@ -65,7 +74,7 @@
         if (graph().getGuardsStage() == StructuredGraph.GuardsStage.FLOATING_GUARDS) {
             ValueNode guard = tool.createGuard(this, condition(), getReason(), getAction(), isNegated()).asNode();
             this.replaceAtUsages(guard);
-            ValueAnchorNode newAnchor = graph().add(new ValueAnchorNode(guard.asNode()));
+            ValueAnchorNode newAnchor = graph().add(ValueAnchorNode.create(guard.asNode()));
             graph().replaceFixedWithFixed(this, newAnchor);
         } else {
             lowerToIf().lower(tool);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,7 +23,9 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 
+@NodeInfo
 public abstract class FixedNode extends ValueNode {
 
     public FixedNode(Stamp stamp) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,14 +23,16 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 
 /**
  * Base class of all nodes that are fixed within the control flow graph and have an immediate
  * successor.
  */
+@NodeInfo
 public abstract class FixedWithNextNode extends FixedNode {
 
-    @Successor private FixedNode next;
+    @Successor protected FixedNode next;
 
     public FixedNode next() {
         return next;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingAnchoredNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingAnchoredNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,13 +23,14 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 
+@NodeInfo
 public abstract class FloatingAnchoredNode extends FloatingNode {
 
-    @Input(InputType.Anchor) private AnchoringNode anchor;
+    @Input(InputType.Anchor) AnchoringNode anchor;
 
     public FloatingAnchoredNode(Stamp stamp) {
         super(stamp);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,13 +23,14 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 
+@NodeInfo
 public abstract class FloatingGuardedNode extends FloatingNode implements GuardedNode {
 
-    @OptionalInput(InputType.Guard) private GuardingNode guard;
+    @OptionalInput(InputType.Guard) protected GuardingNode guard;
 
     public FloatingGuardedNode(Stamp stamp) {
         super(stamp);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Mon Aug 25 21:15:59 2014 -0700
@@ -29,6 +29,7 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.virtual.*;
 
@@ -39,7 +40,7 @@
  * This can be used as debug or deoptimization information.
  */
 @NodeInfo(nameTemplate = "FrameState@{p#method/s}:{p#bci}")
-public final class FrameState extends VirtualState implements IterableNodeType {
+public class FrameState extends VirtualState implements IterableNodeType {
 
     private static final DebugMetric METRIC_FRAMESTATE_COUNT = Debug.metric("FrameStateCount");
 
@@ -54,16 +55,16 @@
 
     private boolean duringCall;
 
-    @OptionalInput(value = InputType.State) private FrameState outerFrameState;
+    @OptionalInput(value = InputType.State) FrameState outerFrameState;
 
     /**
      * Contains the locals, the expressions and the locked objects, in this order.
      */
-    @OptionalInput private final NodeInputList<ValueNode> values;
+    @OptionalInput NodeInputList<ValueNode> values;
 
-    @OptionalInput(InputType.Association) private final NodeInputList<MonitorIdNode> monitorIds;
+    @OptionalInput(InputType.Association) NodeInputList<MonitorIdNode> monitorIds;
 
-    @Input(InputType.State) private final NodeInputList<EscapeObjectState> virtualObjectMappings;
+    @Input(InputType.State) NodeInputList<EscapeObjectState> virtualObjectMappings;
 
     /**
      * The bytecode index to which this frame state applies.
@@ -86,7 +87,13 @@
      * @param monitorIds one MonitorIdNode for each locked object
      * @param virtualObjectMappings a description of the current state for every virtual object
      */
-    public FrameState(FrameState outerFrameState, ResolvedJavaMethod method, int bci, List<ValueNode> values, int localsSize, int stackSize, boolean rethrowException, boolean duringCall,
+    public static FrameState create(FrameState outerFrameState, ResolvedJavaMethod method, int bci, List<ValueNode> values, int localsSize, int stackSize, boolean rethrowException,
+                    boolean duringCall, List<MonitorIdNode> monitorIds, List<EscapeObjectState> virtualObjectMappings) {
+        return USE_GENERATED_NODES ? new FrameStateGen(outerFrameState, method, bci, values, localsSize, stackSize, rethrowException, duringCall, monitorIds, virtualObjectMappings) : new FrameState(
+                        outerFrameState, method, bci, values, localsSize, stackSize, rethrowException, duringCall, monitorIds, virtualObjectMappings);
+    }
+
+    protected FrameState(FrameState outerFrameState, ResolvedJavaMethod method, int bci, List<ValueNode> values, int localsSize, int stackSize, boolean rethrowException, boolean duringCall,
                     List<MonitorIdNode> monitorIds, List<EscapeObjectState> virtualObjectMappings) {
         assert stackSize >= 0;
         this.outerFrameState = outerFrameState;
@@ -109,13 +116,23 @@
      *
      * @param bci marker bci, needs to be &lt; 0
      */
-    public FrameState(int bci) {
+    public static FrameState create(int bci) {
+        return USE_GENERATED_NODES ? new FrameStateGen(bci) : new FrameState(bci);
+    }
+
+    protected FrameState(int bci) {
         this(null, null, bci, Collections.<ValueNode> emptyList(), 0, 0, false, false, Collections.<MonitorIdNode> emptyList(), Collections.<EscapeObjectState> emptyList());
         assert bci == BytecodeFrame.BEFORE_BCI || bci == BytecodeFrame.AFTER_BCI || bci == BytecodeFrame.AFTER_EXCEPTION_BCI || bci == BytecodeFrame.UNKNOWN_BCI ||
                         bci == BytecodeFrame.INVALID_FRAMESTATE_BCI;
     }
 
-    public FrameState(ResolvedJavaMethod method, int bci, ValueNode[] locals, List<ValueNode> stack, ValueNode[] locks, MonitorIdNode[] monitorIds, boolean rethrowException, boolean duringCall) {
+    public static FrameState create(ResolvedJavaMethod method, int bci, ValueNode[] locals, List<ValueNode> stack, ValueNode[] locks, MonitorIdNode[] monitorIds, boolean rethrowException,
+                    boolean duringCall) {
+        return USE_GENERATED_NODES ? new FrameStateGen(method, bci, locals, stack, locks, monitorIds, rethrowException, duringCall) : new FrameState(method, bci, locals, stack, locks, monitorIds,
+                        rethrowException, duringCall);
+    }
+
+    protected FrameState(ResolvedJavaMethod method, int bci, ValueNode[] locals, List<ValueNode> stack, ValueNode[] locks, MonitorIdNode[] monitorIds, boolean rethrowException, boolean duringCall) {
         this(null, method, bci, createValues(locals, stack, locks), locals.length, stack.size(), rethrowException, duringCall, Arrays.asList(monitorIds), Collections.<EscapeObjectState> emptyList());
     }
 
@@ -192,7 +209,7 @@
      * Gets a copy of this frame state.
      */
     public FrameState duplicate(int newBci) {
-        return graph().add(new FrameState(outerFrameState(), method, newBci, values, localsSize, stackSize, rethrowException, duringCall, monitorIds, virtualObjectMappings));
+        return graph().add(FrameState.create(outerFrameState(), method, newBci, values, localsSize, stackSize, rethrowException, duringCall, monitorIds, virtualObjectMappings));
     }
 
     /**
@@ -216,7 +233,7 @@
         for (EscapeObjectState state : virtualObjectMappings) {
             newVirtualMappings.add(state.duplicateWithVirtualState());
         }
-        return graph().add(new FrameState(newOuterFrameState, method, bci, values, localsSize, stackSize, rethrowException, duringCall, monitorIds, newVirtualMappings));
+        return graph().add(FrameState.create(newOuterFrameState, method, bci, values, localsSize, stackSize, rethrowException, duringCall, monitorIds, newVirtualMappings));
     }
 
     /**
@@ -256,7 +273,7 @@
         int newStackSize = copy.size() - localsSize;
         copy.addAll(values.subList(localsSize + stackSize, values.size()));
 
-        return graph().add(new FrameState(outerFrameState(), newMethod, newBci, copy, localsSize, newStackSize, newRethrowException, false, monitorIds, virtualObjectMappings));
+        return graph().add(FrameState.create(outerFrameState(), newMethod, newBci, copy, localsSize, newStackSize, newRethrowException, false, monitorIds, virtualObjectMappings));
     }
 
     /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FullInfopointNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FullInfopointNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,16 +23,21 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
  * Nodes of this type are inserted into the graph to denote points of interest to debugging.
  */
+@NodeInfo
 public class FullInfopointNode extends InfopointNode implements LIRLowerable, NodeWithState {
-    @Input(InputType.State) private FrameState state;
+    @Input(InputType.State) FrameState state;
 
-    public FullInfopointNode(InfopointReason reason, FrameState state) {
+    public static FullInfopointNode create(InfopointReason reason, FrameState state) {
+        return USE_GENERATED_NODES ? new FullInfopointNodeGen(reason, state) : new FullInfopointNode(reason, state);
+    }
+
+    protected FullInfopointNode(InfopointReason reason, FrameState state) {
         super(reason);
         this.state = state;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.extended.*;
 
 /**
@@ -43,13 +44,17 @@
 @NodeInfo(nameTemplate = "Guard(!={p#negated}) {p#reason/s}", allowedUsageTypes = {InputType.Guard})
 public class GuardNode extends FloatingAnchoredNode implements Canonicalizable, IterableNodeType, GuardingNode {
 
-    @Input(InputType.Condition) private LogicNode condition;
+    @Input(InputType.Condition) LogicNode condition;
     private final DeoptimizationReason reason;
     private Constant speculation;
     private DeoptimizationAction action;
     private boolean negated;
 
-    public GuardNode(LogicNode condition, AnchoringNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated, Constant speculation) {
+    public static GuardNode create(LogicNode condition, AnchoringNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated, Constant speculation) {
+        return USE_GENERATED_NODES ? new GuardNodeGen(condition, anchor, reason, action, negated, speculation) : new GuardNode(condition, anchor, reason, action, negated, speculation);
+    }
+
+    protected GuardNode(LogicNode condition, AnchoringNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated, Constant speculation) {
         super(StampFactory.forVoid(), anchor);
         this.condition = condition;
         this.reason = reason;
@@ -98,7 +103,7 @@
     public Node canonical(CanonicalizerTool tool) {
         if (condition() instanceof LogicNegationNode) {
             LogicNegationNode negation = (LogicNegationNode) condition();
-            return new GuardNode(negation.getValue(), getAnchor(), reason, action, !negated, speculation);
+            return GuardNode.create(negation.getValue(), getAnchor(), reason, action, !negated, speculation);
         }
         if (condition() instanceof LogicConstantNode) {
             LogicConstantNode c = (LogicConstantNode) condition();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.extended.*;
 
 /**
@@ -32,14 +33,22 @@
 @NodeInfo(nameTemplate = "GuardPhi({i#values})", allowedUsageTypes = {InputType.Guard})
 public class GuardPhiNode extends PhiNode implements GuardingNode {
 
-    @OptionalInput(InputType.Guard) final NodeInputList<ValueNode> values;
+    @OptionalInput(InputType.Guard) NodeInputList<ValueNode> values;
 
-    public GuardPhiNode(MergeNode merge) {
+    public static GuardPhiNode create(MergeNode merge) {
+        return USE_GENERATED_NODES ? new GuardPhiNodeGen(merge) : new GuardPhiNode(merge);
+    }
+
+    protected GuardPhiNode(MergeNode merge) {
         super(StampFactory.forVoid(), merge);
         this.values = new NodeInputList<>(this);
     }
 
-    public GuardPhiNode(MergeNode merge, ValueNode[] values) {
+    public static GuardPhiNode create(MergeNode merge, ValueNode[] values) {
+        return USE_GENERATED_NODES ? new GuardPhiNodeGen(merge, values) : new GuardPhiNode(merge, values);
+    }
+
+    protected GuardPhiNode(MergeNode merge, ValueNode[] values) {
         super(StampFactory.forVoid(), merge);
         this.values = new NodeInputList<>(this, values);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,15 +24,20 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Guard})
 public class GuardProxyNode extends ProxyNode implements GuardingNode, Proxy, LIRLowerable {
 
-    @Input(InputType.Guard) private GuardingNode value;
+    @Input(InputType.Guard) GuardingNode value;
 
-    public GuardProxyNode(GuardingNode value, BeginNode proxyPoint) {
+    public static GuardProxyNode create(GuardingNode value, BeginNode proxyPoint) {
+        return USE_GENERATED_NODES ? new GuardProxyNodeGen(value, proxyPoint) : new GuardProxyNode(value, proxyPoint);
+    }
+
+    protected GuardProxyNode(GuardingNode value, BeginNode proxyPoint) {
         super(StampFactory.forVoid(), proxyPoint);
         this.value = value;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -35,18 +36,27 @@
  *
  * A GuardedValueNode will only go away if its guard is null or {@link StructuredGraph#start()}.
  */
+@NodeInfo
 public class GuardedValueNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, IterableNodeType, Canonicalizable, ValueProxy {
 
-    @Input private ValueNode object;
+    @Input ValueNode object;
     private final Stamp piStamp;
 
-    public GuardedValueNode(ValueNode object, GuardingNode guard, Stamp stamp) {
+    public static GuardedValueNode create(ValueNode object, GuardingNode guard, Stamp stamp) {
+        return USE_GENERATED_NODES ? new GuardedValueNodeGen(object, guard, stamp) : new GuardedValueNode(object, guard, stamp);
+    }
+
+    protected GuardedValueNode(ValueNode object, GuardingNode guard, Stamp stamp) {
         super(stamp, guard);
         this.object = object;
         this.piStamp = stamp;
     }
 
-    public GuardedValueNode(ValueNode object, GuardingNode guard) {
+    public static GuardedValueNode create(ValueNode object, GuardingNode guard) {
+        return USE_GENERATED_NODES ? new GuardedValueNodeGen(object, guard) : new GuardedValueNode(object, guard);
+    }
+
+    protected GuardedValueNode(ValueNode object, GuardingNode guard) {
         this(object, guard, object.stamp());
     }
 
@@ -83,7 +93,7 @@
             if (stamp().equals(object().stamp())) {
                 return object();
             } else {
-                return new PiNode(object(), stamp());
+                return PiNode.create(object(), stamp());
             }
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -37,8 +38,8 @@
 @NodeInfo(nameTemplate = "GuardingPi(!={p#negated}) {p#reason/s}")
 public class GuardingPiNode extends FixedWithNextNode implements Lowerable, Virtualizable, Canonicalizable, ValueProxy {
 
-    @Input private ValueNode object;
-    @Input(InputType.Condition) private LogicNode condition;
+    @Input ValueNode object;
+    @Input(InputType.Condition) LogicNode condition;
     private final DeoptimizationReason reason;
     private final DeoptimizationAction action;
     private final Stamp piStamp;
@@ -67,8 +68,12 @@
     /**
      * Constructor for {@link #guardingNonNull(Object)} node intrinsic.
      */
-    private GuardingPiNode(ValueNode object) {
-        this(object, object.graph().unique(new IsNullNode(object)), true, DeoptimizationReason.NullCheckException, DeoptimizationAction.None, object.stamp().join(StampFactory.objectNonNull()));
+    public static GuardingPiNode create(ValueNode object) {
+        return USE_GENERATED_NODES ? new GuardingPiNodeGen(object) : new GuardingPiNode(object);
+    }
+
+    GuardingPiNode(ValueNode object) {
+        this(object, object.graph().unique(IsNullNode.create(object)), true, DeoptimizationReason.NullCheckException, DeoptimizationAction.None, object.stamp().join(StampFactory.objectNonNull()));
     }
 
     /**
@@ -79,7 +84,11 @@
      * @param negateCondition the guard succeeds if {@code condition != negateCondition}
      * @param stamp the refined type of the object if the guard succeeds
      */
-    public GuardingPiNode(ValueNode object, ValueNode condition, boolean negateCondition, DeoptimizationReason reason, DeoptimizationAction action, Stamp stamp) {
+    public static GuardingPiNode create(ValueNode object, ValueNode condition, boolean negateCondition, DeoptimizationReason reason, DeoptimizationAction action, Stamp stamp) {
+        return USE_GENERATED_NODES ? new GuardingPiNodeGen(object, condition, negateCondition, reason, action, stamp) : new GuardingPiNode(object, condition, negateCondition, reason, action, stamp);
+    }
+
+    protected GuardingPiNode(ValueNode object, ValueNode condition, boolean negateCondition, DeoptimizationReason reason, DeoptimizationAction action, Stamp stamp) {
         super(stamp);
         assert stamp != null;
         this.piStamp = stamp;
@@ -93,9 +102,9 @@
     @Override
     public void lower(LoweringTool tool) {
         GuardingNode guard = tool.createGuard(next(), condition, reason, action, negated);
-        ValueAnchorNode anchor = graph().add(new ValueAnchorNode((ValueNode) guard));
+        ValueAnchorNode anchor = graph().add(ValueAnchorNode.create((ValueNode) guard));
         if (usages().isNotEmpty()) {
-            PiNode pi = graph().unique(new PiNode(object, stamp(), (ValueNode) guard));
+            PiNode pi = graph().unique(PiNode.create(object, stamp(), (ValueNode) guard));
             replaceAtUsages(pi);
         }
         graph().replaceFixedWithFixed(this, anchor);
@@ -118,19 +127,19 @@
     public Node canonical(CanonicalizerTool tool) {
         if (stamp() == StampFactory.illegal(object.getKind())) {
             // The guard always fails
-            return new DeoptimizeNode(action, reason);
+            return DeoptimizeNode.create(action, reason);
         }
         if (condition instanceof LogicConstantNode) {
             LogicConstantNode c = (LogicConstantNode) condition;
             if (c.getValue() == negated) {
                 // The guard always fails
-                return new DeoptimizeNode(action, reason);
+                return DeoptimizeNode.create(action, reason);
             } else if (stamp().equals(object().stamp())) {
                 // The guard always succeeds, and does not provide new type information
                 return object;
             } else {
                 // The guard always succeeds, and provides new type information
-                return new PiNode(object, stamp());
+                return PiNode.create(object, stamp());
             }
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -34,6 +34,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
@@ -43,11 +44,12 @@
  * The {@code IfNode} represents a branch that can go one of two directions depending on the outcome
  * of a comparison.
  */
-public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable {
+@NodeInfo
+public class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable {
 
-    @Successor private BeginNode trueSuccessor;
-    @Successor private BeginNode falseSuccessor;
-    @Input(InputType.Condition) private LogicNode condition;
+    @Successor BeginNode trueSuccessor;
+    @Successor BeginNode falseSuccessor;
+    @Input(InputType.Condition) LogicNode condition;
     private double trueSuccessorProbability;
 
     public LogicNode condition() {
@@ -59,11 +61,19 @@
         condition = x;
     }
 
-    public IfNode(LogicNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double trueSuccessorProbability) {
+    public static IfNode create(LogicNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double trueSuccessorProbability) {
+        return USE_GENERATED_NODES ? new IfNodeGen(condition, trueSuccessor, falseSuccessor, trueSuccessorProbability) : new IfNode(condition, trueSuccessor, falseSuccessor, trueSuccessorProbability);
+    }
+
+    protected IfNode(LogicNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double trueSuccessorProbability) {
         this(condition, BeginNode.begin(trueSuccessor), BeginNode.begin(falseSuccessor), trueSuccessorProbability);
     }
 
-    public IfNode(LogicNode condition, BeginNode trueSuccessor, BeginNode falseSuccessor, double trueSuccessorProbability) {
+    public static IfNode create(LogicNode condition, BeginNode trueSuccessor, BeginNode falseSuccessor, double trueSuccessorProbability) {
+        return USE_GENERATED_NODES ? new IfNodeGen(condition, trueSuccessor, falseSuccessor, trueSuccessorProbability) : new IfNode(condition, trueSuccessor, falseSuccessor, trueSuccessorProbability);
+    }
+
+    protected IfNode(LogicNode condition, BeginNode trueSuccessor, BeginNode falseSuccessor, double trueSuccessorProbability) {
         super(StampFactory.forVoid());
         this.condition = condition;
         this.falseSuccessor = falseSuccessor;
@@ -141,7 +151,7 @@
             setTrueSuccessor(null);
             setFalseSuccessor(null);
             LogicNegationNode negation = (LogicNegationNode) condition();
-            IfNode newIfNode = graph().add(new IfNode(negation.getValue(), falseSucc, trueSucc, 1 - trueSuccessorProbability));
+            IfNode newIfNode = graph().add(IfNode.create(negation.getValue(), falseSucc, trueSucc, 1 - trueSuccessorProbability));
             predecessor().replaceFirstSuccessor(this, newIfNode);
             GraphUtil.killWithUnusedFloatingInputs(this);
             return;
@@ -210,7 +220,8 @@
         do {
             BeginNode trueSucc = trueSuccessor();
             BeginNode falseSucc = falseSuccessor();
-            if (trueSucc.getClass() == BeginNode.class && falseSucc.getClass() == BeginNode.class && trueSucc.next() instanceof FixedWithNextNode && falseSucc.next() instanceof FixedWithNextNode) {
+            if (trueSucc.getClass() == BeginNode.getGenClass() && falseSucc.getClass() == BeginNode.getGenClass() && trueSucc.next() instanceof FixedWithNextNode &&
+                            falseSucc.next() instanceof FixedWithNextNode) {
                 FixedWithNextNode trueNext = (FixedWithNextNode) trueSucc.next();
                 FixedWithNextNode falseNext = (FixedWithNextNode) falseSucc.next();
                 NodeClass nodeClass = trueNext.getNodeClass();
@@ -222,7 +233,7 @@
                         graph().addBeforeFixed(this, trueNext);
                         for (Node usage : trueNext.usages().snapshot()) {
                             if (usage.isAlive()) {
-                                if (usage.getNodeClass().valueNumberable() && !usage.getNodeClass().isLeafNode()) {
+                                if (usage.getNodeClass().valueNumberable() && !usage.isLeafNode()) {
                                     Node newNode = graph().findDuplicate(usage);
                                     if (newNode != null) {
                                         usage.replaceAtUsages(newNode);
@@ -266,7 +277,7 @@
                      */
                     if (lessThan2.getX() == lessThan.getX() && lessThan2.getY().stamp() instanceof IntegerStamp && ((IntegerStamp) lessThan2.getY().stamp()).isPositive() &&
                                     sameDestination(trueSuccessor(), ifNode2.falseSuccessor)) {
-                        below = graph().unique(new IntegerBelowNode(lessThan2.getX(), lessThan2.getY()));
+                        below = graph().unique(IntegerBelowNode.create(lessThan2.getX(), lessThan2.getY()));
                         // swap direction
                         BeginNode tmp = falseSucc;
                         falseSucc = trueSucc;
@@ -281,14 +292,14 @@
                         Constant positive = lessThan2.getX().asConstant();
                         if (positive != null && positive.asLong() > 0 && positive.asLong() < positive.getKind().getMaxValue()) {
                             ConstantNode newLimit = ConstantNode.forIntegerKind(positive.getKind(), positive.asLong() + 1, graph());
-                            below = graph().unique(new IntegerBelowNode(lessThan.getX(), newLimit));
+                            below = graph().unique(IntegerBelowNode.create(lessThan.getX(), newLimit));
                         }
                     }
                     if (below != null) {
                         ifNode2.setTrueSuccessor(null);
                         ifNode2.setFalseSuccessor(null);
 
-                        IfNode newIfNode = graph().add(new IfNode(below, falseSucc, trueSucc, 1 - trueSuccessorProbability));
+                        IfNode newIfNode = graph().add(IfNode.create(below, falseSucc, trueSucc, 1 - trueSuccessorProbability));
                         // Remove the < 0 test.
                         tool.deleteBranch(trueSuccessor);
                         graph().removeSplit(this, falseSuccessor);
@@ -525,7 +536,7 @@
                     }
                 }
             }
-            ReturnNode newReturn = graph().add(new ReturnNode(value));
+            ReturnNode newReturn = graph().add(ReturnNode.create(value));
             replaceAtPredecessor(newReturn);
             GraphUtil.killCFG(this);
             return true;
@@ -547,7 +558,7 @@
             return null;
         }
         if (trueValue.isConstant() && falseValue.isConstant()) {
-            return graph().unique(new ConditionalNode(condition(), trueValue, falseValue));
+            return graph().unique(ConditionalNode.create(condition(), trueValue, falseValue));
         } else {
             ConditionalNode conditional = null;
             ValueNode constant = null;
@@ -577,7 +588,7 @@
             if (otherValue.isConstant()) {
                 double shortCutProbability = probability(trueSuccessor());
                 LogicNode newCondition = LogicNode.or(condition(), negateCondition, conditional.condition(), negateConditionalCondition, shortCutProbability);
-                return graph().unique(new ConditionalNode(newCondition, constant, otherValue));
+                return graph().unique(ConditionalNode.create(newCondition, constant, otherValue));
             }
         }
         return null;
@@ -832,9 +843,9 @@
             } else {
                 // Need a new phi in case the frame state is used by more than the merge being
                 // removed
-                MergeNode newMerge = graph().add(new MergeNode());
+                MergeNode newMerge = graph().add(MergeNode.create());
                 PhiNode oldPhi = (PhiNode) oldMerge.usages().first();
-                PhiNode newPhi = graph().addWithoutUnique(new ValuePhiNode(oldPhi.stamp(), newMerge));
+                PhiNode newPhi = graph().addWithoutUnique(ValuePhiNode.create(oldPhi.stamp(), newMerge));
 
                 for (AbstractEndNode end : ends) {
                     newPhi.addInput(phiValues.get(end));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,12 +27,20 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 
+@NodeInfo
 public class IndirectCallTargetNode extends LoweredCallTargetNode {
 
-    @Input private ValueNode computedAddress;
+    @Input protected ValueNode computedAddress;
 
-    public IndirectCallTargetNode(ValueNode computedAddress, List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType,
+    public static IndirectCallTargetNode create(ValueNode computedAddress, List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target,
+                    CallingConvention.Type callType, InvokeKind invokeKind) {
+        return USE_GENERATED_NODES ? new IndirectCallTargetNodeGen(computedAddress, arguments, returnStamp, signature, target, callType, invokeKind) : new IndirectCallTargetNode(computedAddress,
+                        arguments, returnStamp, signature, target, callType, invokeKind);
+    }
+
+    protected IndirectCallTargetNode(ValueNode computedAddress, List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType,
                     InvokeKind invokeKind) {
         super(arguments, returnStamp, signature, target, callType, invokeKind);
         this.computedAddress = computedAddress;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,7 +24,9 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 
+@NodeInfo
 public abstract class InfopointNode extends FixedWithNextNode {
     private final InfopointReason reason;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,7 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.CallTargetNode.*;
+import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,6 +27,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
@@ -36,11 +37,11 @@
  * The {@code InvokeNode} represents all kinds of method calls.
  */
 @NodeInfo(nameTemplate = "Invoke#{p#targetMethod/s}", allowedUsageTypes = {InputType.Memory})
-public final class InvokeNode extends AbstractMemoryCheckpoint implements Invoke, LIRLowerable, MemoryCheckpoint.Single, IterableNodeType {
+public class InvokeNode extends AbstractMemoryCheckpoint implements Invoke, LIRLowerable, MemoryCheckpoint.Single, IterableNodeType {
 
-    @Input(InputType.Extension) private CallTargetNode callTarget;
-    @OptionalInput(InputType.State) private FrameState stateDuring;
-    @OptionalInput(InputType.Guard) private GuardingNode guard;
+    @Input(InputType.Extension) CallTargetNode callTarget;
+    @OptionalInput(InputType.State) FrameState stateDuring;
+    @OptionalInput(InputType.Guard) GuardingNode guard;
     private final int bci;
     private boolean polymorphic;
     private boolean useForInlining;
@@ -51,7 +52,11 @@
      * @param callTarget the target method being called
      * @param bci the bytecode index of the original invoke (used for debug infos)
      */
-    public InvokeNode(CallTargetNode callTarget, int bci) {
+    public static InvokeNode create(CallTargetNode callTarget, int bci) {
+        return USE_GENERATED_NODES ? new InvokeNodeGen(callTarget, bci) : new InvokeNode(callTarget, bci);
+    }
+
+    protected InvokeNode(CallTargetNode callTarget, int bci) {
         this(callTarget, bci, callTarget.returnStamp());
     }
 
@@ -62,7 +67,11 @@
      * @param bci the bytecode index of the original invoke (used for debug infos)
      * @param stamp the stamp to be used for this value
      */
-    public InvokeNode(CallTargetNode callTarget, int bci, Stamp stamp) {
+    public static InvokeNode create(CallTargetNode callTarget, int bci, Stamp stamp) {
+        return USE_GENERATED_NODES ? new InvokeNodeGen(callTarget, bci, stamp) : new InvokeNode(callTarget, bci, stamp);
+    }
+
+    protected InvokeNode(CallTargetNode callTarget, int bci, Stamp stamp) {
         super(stamp);
         this.callTarget = callTarget;
         this.bci = bci;
@@ -150,10 +159,10 @@
     public void intrinsify(Node node) {
         assert !(node instanceof ValueNode) || node.isAllowedUsageType(InputType.Value) == isAllowedUsageType(InputType.Value) : "replacing " + this + " with " + node;
         CallTargetNode call = callTarget;
-        FrameState stateAfter = stateAfter();
+        FrameState currentStateAfter = stateAfter();
         if (node instanceof StateSplit) {
             StateSplit stateSplit = (StateSplit) node;
-            stateSplit.setStateAfter(stateAfter);
+            stateSplit.setStateAfter(currentStateAfter);
         }
         if (node instanceof FixedWithNextNode) {
             graph().replaceFixedWithFixed(this, (FixedWithNextNode) node);
@@ -166,8 +175,8 @@
             graph().replaceFixed(this, node);
         }
         GraphUtil.killWithUnusedFloatingInputs(call);
-        if (stateAfter.usages().isEmpty()) {
-            GraphUtil.killWithUnusedFloatingInputs(stateAfter);
+        if (currentStateAfter.usages().isEmpty()) {
+            GraphUtil.killWithUnusedFloatingInputs(currentStateAfter);
         }
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
@@ -36,18 +37,22 @@
 
     private static final double EXCEPTION_PROBA = 1e-5;
 
-    @Successor private BeginNode next;
-    @Successor private BeginNode exceptionEdge;
-    @Input(InputType.Extension) private CallTargetNode callTarget;
-    @OptionalInput(InputType.State) private FrameState stateDuring;
-    @OptionalInput(InputType.State) private FrameState stateAfter;
-    @OptionalInput(InputType.Guard) private GuardingNode guard;
+    @Successor BeginNode next;
+    @Successor BeginNode exceptionEdge;
+    @Input(InputType.Extension) CallTargetNode callTarget;
+    @OptionalInput(InputType.State) FrameState stateDuring;
+    @OptionalInput(InputType.State) FrameState stateAfter;
+    @OptionalInput(InputType.Guard) GuardingNode guard;
     private final int bci;
     private boolean polymorphic;
     private boolean useForInlining;
     private double exceptionProbability;
 
-    public InvokeWithExceptionNode(CallTargetNode callTarget, BeginNode exceptionEdge, int bci) {
+    public static InvokeWithExceptionNode create(CallTargetNode callTarget, BeginNode exceptionEdge, int bci) {
+        return USE_GENERATED_NODES ? new InvokeWithExceptionNodeGen(callTarget, exceptionEdge, bci) : new InvokeWithExceptionNode(callTarget, exceptionEdge, bci);
+    }
+
+    protected InvokeWithExceptionNode(CallTargetNode callTarget, BeginNode exceptionEdge, int bci) {
         super(callTarget.returnStamp());
         this.exceptionEdge = exceptionEdge;
         this.bci = bci;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,7 +23,7 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.extended.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
@@ -31,7 +31,11 @@
 
     private LocationIdentity locationIdentity;
 
-    public KillingBeginNode(LocationIdentity locationIdentity) {
+    public static KillingBeginNode create(LocationIdentity locationIdentity) {
+        return USE_GENERATED_NODES ? new KillingBeginNodeGen(locationIdentity) : new KillingBeginNode(locationIdentity);
+    }
+
+    protected KillingBeginNode(LocationIdentity locationIdentity) {
         this.locationIdentity = locationIdentity;
     }
 
@@ -39,7 +43,7 @@
         if (with instanceof KillingBeginNode) {
             return (KillingBeginNode) with;
         }
-        KillingBeginNode begin = with.graph().add(new KillingBeginNode(locationIdentity));
+        KillingBeginNode begin = with.graph().add(KillingBeginNode.create(locationIdentity));
         begin.setNext(with);
         return begin;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicConstantNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicConstantNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
@@ -33,6 +34,10 @@
 
     public final boolean value;
 
+    public static LogicConstantNode create(boolean value) {
+        return USE_GENERATED_NODES ? new LogicConstantNodeGen(value) : new LogicConstantNode(value);
+    }
+
     protected LogicConstantNode(boolean value) {
         super();
         this.value = value;
@@ -46,7 +51,7 @@
      * @return a node representing the boolean
      */
     public static LogicConstantNode forBoolean(boolean v, Graph graph) {
-        return graph.unique(new LogicConstantNode(v));
+        return graph.unique(LogicConstantNode.create(v));
     }
 
     /**
@@ -56,7 +61,7 @@
      * @return a node representing the boolean
      */
     public static LogicConstantNode forBoolean(boolean v) {
-        return new LogicConstantNode(v);
+        return LogicConstantNode.create(v);
     }
 
     /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNegationNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNegationNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,17 +22,22 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 
 /**
  * Logic node that negates its argument.
  */
+@NodeInfo
 public class LogicNegationNode extends LogicNode implements Canonicalizable.Unary<LogicNode> {
 
-    @Input(InputType.Condition) private LogicNode value;
+    @Input(InputType.Condition) LogicNode value;
 
-    public LogicNegationNode(LogicNode value) {
+    public static LogicNegationNode create(LogicNode value) {
+        return USE_GENERATED_NODES ? new LogicNegationNodeGen(value) : new LogicNegationNode(value);
+    }
+
+    protected LogicNegationNode(LogicNode value) {
         this.value = value;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.nodes;
 
-import static com.oracle.graal.graph.InputType.*;
+import static com.oracle.graal.nodeinfo.InputType.*;
 
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.calc.*;
 
 @NodeInfo(allowedUsageTypes = {Condition})
@@ -41,8 +41,8 @@
 
     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));
+        ShortCircuitOrNode notAorNotB = graph.unique(ShortCircuitOrNode.create(a, !negateA, b, !negateB, shortCircuitProbability));
+        return graph.unique(LogicNegationNode.create(notAorNotB));
     }
 
     public static LogicNode or(LogicNode a, LogicNode b, double shortCircuitProbability) {
@@ -50,6 +50,6 @@
     }
 
     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));
+        return a.graph().unique(ShortCircuitOrNode.create(a, negateA, b, negateB, shortCircuitProbability));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -29,19 +29,25 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
 
+@NodeInfo
 public class LoopBeginNode extends MergeNode implements IterableNodeType, LIRLowerable {
 
     private double loopFrequency;
     private int nextEndIndex;
     private int unswitches;
-    @OptionalInput(InputType.Guard) private GuardingNode overflowGuard;
+    @OptionalInput(InputType.Guard) GuardingNode overflowGuard;
 
-    public LoopBeginNode() {
+    public static LoopBeginNode create() {
+        return USE_GENERATED_NODES ? new LoopBeginNodeGen() : new LoopBeginNode();
+    }
+
+    protected LoopBeginNode() {
         loopFrequency = 1;
     }
 
@@ -187,10 +193,10 @@
     public void removeExits() {
         for (LoopExitNode loopexit : loopExits().snapshot()) {
             loopexit.removeProxies();
-            FrameState stateAfter = loopexit.stateAfter();
-            graph().replaceFixedWithFixed(loopexit, graph().add(new BeginNode()));
-            if (stateAfter != null && stateAfter.isAlive() && stateAfter.usages().isEmpty()) {
-                GraphUtil.killWithUnusedFloatingInputs(stateAfter);
+            FrameState loopStateAfter = loopexit.stateAfter();
+            graph().replaceFixedWithFixed(loopexit, graph().add(BeginNode.create()));
+            if (loopStateAfter != null && loopStateAfter.isAlive() && loopStateAfter.usages().isEmpty()) {
+                GraphUtil.killWithUnusedFloatingInputs(loopStateAfter);
             }
         }
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,15 +25,21 @@
 import java.util.*;
 
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.spi.*;
 
-public final class LoopEndNode extends AbstractEndNode {
+@NodeInfo
+public class LoopEndNode extends AbstractEndNode {
 
-    @Input(InputType.Association) private LoopBeginNode loopBegin;
+    @Input(InputType.Association) LoopBeginNode loopBegin;
     private boolean canSafepoint;
     private int endIndex;
 
-    public LoopEndNode(LoopBeginNode begin) {
+    public static LoopEndNode create(LoopBeginNode begin) {
+        return USE_GENERATED_NODES ? new LoopEndNodeGen(begin) : new LoopEndNode(begin);
+    }
+
+    protected LoopEndNode(LoopBeginNode begin) {
         int idx = begin.nextEndIndex();
         assert idx >= 0;
         this.endIndex = idx;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopExitNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopExitNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,13 +24,18 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Association})
 public class LoopExitNode extends BeginStateSplitNode implements IterableNodeType {
 
-    @Input(InputType.Association) private LoopBeginNode loopBegin;
+    @Input(InputType.Association) LoopBeginNode loopBegin;
 
-    public LoopExitNode(LoopBeginNode loop) {
+    public static LoopExitNode create(LoopBeginNode loop) {
+        return USE_GENERATED_NODES ? new LoopExitNodeGen(loop) : new LoopExitNode(loop);
+    }
+
+    protected LoopExitNode(LoopBeginNode loop) {
         assert loop != null;
         loopBegin = loop;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoweredCallTargetNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoweredCallTargetNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,7 +27,9 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 
+@NodeInfo
 public abstract class LoweredCallTargetNode extends CallTargetNode {
 
     private final Stamp returnStamp;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -29,6 +29,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -37,7 +38,7 @@
 public class MemoryMapNode extends FloatingNode implements MemoryMap, LIRLowerable {
 
     private final List<LocationIdentity> locationIdentities;
-    @Input(InputType.Memory) private final NodeInputList<ValueNode> nodes;
+    @Input(InputType.Memory) NodeInputList<ValueNode> nodes;
 
     private boolean checkOrder(Map<LocationIdentity, MemoryNode> mmap) {
         for (int i = 0; i < locationIdentities.size(); i++) {
@@ -48,7 +49,11 @@
         return true;
     }
 
-    public MemoryMapNode(Map<LocationIdentity, MemoryNode> mmap) {
+    public static MemoryMapNode create(Map<LocationIdentity, MemoryNode> mmap) {
+        return USE_GENERATED_NODES ? new MemoryMapNodeGen(mmap) : new MemoryMapNode(mmap);
+    }
+
+    protected MemoryMapNode(Map<LocationIdentity, MemoryNode> mmap) {
         super(StampFactory.forVoid());
         locationIdentities = new ArrayList<>(mmap.keySet());
         nodes = new NodeInputList<>(this, mmap.values());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.extended.*;
 
 /**
@@ -33,16 +34,24 @@
 @NodeInfo(nameTemplate = "MemoryPhi({i#values}) {p#locationIdentity/s}", allowedUsageTypes = {InputType.Memory})
 public class MemoryPhiNode extends PhiNode implements MemoryNode {
 
-    @Input(InputType.Memory) final NodeInputList<ValueNode> values;
+    @Input(InputType.Memory) NodeInputList<ValueNode> values;
     private final LocationIdentity locationIdentity;
 
-    public MemoryPhiNode(MergeNode merge, LocationIdentity locationIdentity) {
+    public static MemoryPhiNode create(MergeNode merge, LocationIdentity locationIdentity) {
+        return USE_GENERATED_NODES ? new MemoryPhiNodeGen(merge, locationIdentity) : new MemoryPhiNode(merge, locationIdentity);
+    }
+
+    protected MemoryPhiNode(MergeNode merge, LocationIdentity locationIdentity) {
         super(StampFactory.forVoid(), merge);
         this.locationIdentity = locationIdentity;
         this.values = new NodeInputList<>(this);
     }
 
-    public MemoryPhiNode(MergeNode merge, LocationIdentity locationIdentity, ValueNode[] values) {
+    public static MemoryPhiNode create(MergeNode merge, LocationIdentity locationIdentity, ValueNode[] values) {
+        return USE_GENERATED_NODES ? new MemoryPhiNodeGen(merge, locationIdentity, values) : new MemoryPhiNode(merge, locationIdentity, values);
+    }
+
+    protected MemoryPhiNode(MergeNode merge, LocationIdentity locationIdentity, ValueNode[] values) {
         super(StampFactory.forVoid(), merge);
         this.locationIdentity = locationIdentity;
         this.values = new NodeInputList<>(this, values);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -30,6 +30,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
 
@@ -38,8 +39,18 @@
  */
 @NodeInfo(allowedUsageTypes = {InputType.Association})
 public class MergeNode extends BeginStateSplitNode implements IterableNodeType, LIRLowerable {
+    public static MergeNode create() {
+        return USE_GENERATED_NODES ? new MergeNodeGen() : new MergeNode();
+    }
 
-    @Input(InputType.Association) private final NodeInputList<AbstractEndNode> ends = new NodeInputList<>(this);
+    public static Class<? extends MergeNode> getGenClass() {
+        return USE_GENERATED_NODES ? MergeNodeGen.class : MergeNode.class;
+    }
+
+    MergeNode() {
+    }
+
+    @Input(InputType.Association) NodeInputList<AbstractEndNode> ends = new NodeInputList<>(this);
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
@@ -138,9 +149,9 @@
      */
     @Override
     public void simplify(SimplifierTool tool) {
-        FixedNode next = next();
-        if (next instanceof AbstractEndNode) {
-            AbstractEndNode origLoopEnd = (AbstractEndNode) next;
+        FixedNode currentNext = next();
+        if (currentNext instanceof AbstractEndNode) {
+            AbstractEndNode origLoopEnd = (AbstractEndNode) currentNext;
             MergeNode merge = origLoopEnd.merge();
             if (merge instanceof LoopBeginNode && !(origLoopEnd instanceof LoopEndNode)) {
                 return;
@@ -168,9 +179,9 @@
                 }
                 AbstractEndNode newEnd;
                 if (merge instanceof LoopBeginNode) {
-                    newEnd = graph().add(new LoopEndNode((LoopBeginNode) merge));
+                    newEnd = graph().add(LoopEndNode.create((LoopBeginNode) merge));
                 } else {
-                    newEnd = graph().add(new EndNode());
+                    newEnd = graph().add(EndNode.create());
                     merge.addForwardEnd(newEnd);
                 }
                 for (PhiNode phi : merge.phis()) {
@@ -192,8 +203,8 @@
                 }
             }
             graph().reduceTrivialMerge(this);
-        } else if (next instanceof ReturnNode) {
-            ReturnNode returnNode = (ReturnNode) next;
+        } else if (currentNext instanceof ReturnNode) {
+            ReturnNode returnNode = (ReturnNode) currentNext;
             if (anchored().isNotEmpty() || returnNode.getMemoryMap() != null) {
                 return;
             }
@@ -209,7 +220,7 @@
             ValuePhiNode returnValuePhi = returnNode.result() == null || !isPhiAtMerge(returnNode.result()) ? null : (ValuePhiNode) returnNode.result();
             List<AbstractEndNode> endNodes = forwardEnds().snapshot();
             for (AbstractEndNode end : endNodes) {
-                ReturnNode newReturn = graph().add(new ReturnNode(returnValuePhi == null ? returnNode.result() : returnValuePhi.valueAt(end)));
+                ReturnNode newReturn = graph().add(ReturnNode.create(returnValuePhi == null ? returnNode.result() : returnValuePhi.valueAt(end)));
                 if (tool != null) {
                     tool.addToWorkList(end.predecessor());
                 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,14 +24,19 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 
 /**
  * The {@code Parameter} instruction is a placeholder for an incoming argument to a function call.
  */
 @NodeInfo(nameTemplate = "Param({p#index})")
-public final class ParameterNode extends AbstractLocalNode implements IterableNodeType {
+public class ParameterNode extends AbstractLocalNode implements IterableNodeType {
 
-    public ParameterNode(int index, Stamp stamp) {
+    public static ParameterNode create(int index, Stamp stamp) {
+        return USE_GENERATED_NODES ? new ParameterNodeGen(index, stamp) : new ParameterNode(index, stamp);
+    }
+
+    protected ParameterNode(int index, Stamp stamp) {
         super(index, stamp);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,6 +27,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.calc.*;
 
 /**
@@ -35,9 +36,10 @@
  * of the ends. For {@link LoopBeginNode}s, the first value corresponds to the loop's predecessor,
  * while the rest of the values correspond to the {@link LoopEndNode}s.
  */
+@NodeInfo
 public abstract class PhiNode extends FloatingNode implements Simplifiable {
 
-    @Input(InputType.Association) private MergeNode merge;
+    @Input(InputType.Association) MergeNode merge;
 
     protected PhiNode(Stamp stamp, MergeNode merge) {
         super(stamp);
@@ -137,9 +139,20 @@
         values().remove(index);
     }
 
-    public static final ValueNode MULTIPLE_VALUES = new ValueNode(null) {
-        // empty dummy class
-    };
+    @NodeInfo
+    static class MultipleValuesNode extends ValueNode {
+
+        public static MultipleValuesNode create() {
+            return USE_GENERATED_NODES ? new PhiNode_MultipleValuesNodeGen() : new MultipleValuesNode();
+        }
+
+        protected MultipleValuesNode() {
+            super(null);
+        }
+
+    }
+
+    public static final ValueNode MULTIPLE_VALUES = MultipleValuesNode.create();
 
     /**
      * If all inputs are the same value, this value is returned, otherwise {@link #MULTIPLE_VALUES}.
@@ -202,4 +215,4 @@
         return merge() instanceof LoopBeginNode;
     }
 
-}
\ No newline at end of file
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -33,15 +34,20 @@
  * that reads the array length, such as an {@link ArrayLengthNode}, can be canonicalized based on
  * this information.
  */
-public final class PiArrayNode extends PiNode implements ArrayLengthProvider {
+@NodeInfo
+public class PiArrayNode extends PiNode implements ArrayLengthProvider {
 
-    @Input private ValueNode length;
+    @Input ValueNode length;
 
     public ValueNode length() {
         return length;
     }
 
-    public PiArrayNode(ValueNode object, ValueNode length, Stamp stamp) {
+    public static PiArrayNode create(ValueNode object, ValueNode length, Stamp stamp) {
+        return USE_GENERATED_NODES ? new PiArrayNodeGen(object, length, stamp) : new PiArrayNode(object, length, stamp);
+    }
+
+    protected PiArrayNode(ValueNode object, ValueNode length, Stamp stamp) {
         super(object, stamp);
         this.length = length;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -28,6 +28,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -40,28 +41,41 @@
  * 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.
  */
+@NodeInfo
 public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, IterableNodeType, Canonicalizable, ValueProxy {
 
-    @Input private ValueNode object;
+    @Input ValueNode object;
     private final Stamp piStamp;
 
     public ValueNode object() {
         return object;
     }
 
-    public PiNode(ValueNode object, Stamp stamp) {
+    public static PiNode create(ValueNode object, Stamp stamp) {
+        return USE_GENERATED_NODES ? new PiNodeGen(object, stamp) : new PiNode(object, stamp);
+    }
+
+    protected PiNode(ValueNode object, Stamp stamp) {
         super(stamp);
         this.piStamp = stamp;
         this.object = object;
     }
 
-    public PiNode(ValueNode object, Stamp stamp, ValueNode anchor) {
+    public static PiNode create(ValueNode object, Stamp stamp, ValueNode anchor) {
+        return USE_GENERATED_NODES ? new PiNodeGen(object, stamp, anchor) : new PiNode(object, stamp, anchor);
+    }
+
+    protected PiNode(ValueNode object, Stamp stamp, ValueNode anchor) {
         super(stamp, (GuardingNode) anchor);
         this.object = object;
         this.piStamp = stamp;
     }
 
-    public PiNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
+    public static PiNode create(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
+        return USE_GENERATED_NODES ? new PiNodeGen(object, toType, exactType, nonNull) : new PiNode(object, toType, exactType, nonNull);
+    }
+
+    protected PiNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
         this(object, StampFactory.object(toType, exactType, nonNull || StampTool.isObjectNonNull(object.stamp())));
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.ValueNumberable;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 
@@ -32,9 +33,10 @@
  * A proxy is inserted at loop exits for any value that is created inside the loop (i.e. was not
  * live on entry to the loop) and is (potentially) used after the loop.
  */
+@NodeInfo
 public abstract class ProxyNode extends FloatingNode implements IterableNodeType, ValueNumberable {
 
-    @Input(InputType.Association) private BeginNode proxyPoint;
+    @Input(InputType.Association) BeginNode proxyPoint;
 
     public ProxyNode(Stamp stamp, BeginNode proxyPoint) {
         super(stamp);
@@ -57,10 +59,10 @@
     }
 
     public static ValueProxyNode forValue(ValueNode value, BeginNode exit, StructuredGraph graph) {
-        return graph.unique(new ValueProxyNode(value, exit));
+        return graph.unique(ValueProxyNode.create(value, exit));
     }
 
     public static GuardProxyNode forGuard(GuardingNode value, BeginNode exit, StructuredGraph graph) {
-        return graph.unique(new GuardProxyNode(value, exit));
+        return graph.unique(GuardProxyNode.create(value, exit));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,12 +24,14 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.spi.*;
 
-public final class ReturnNode extends ControlSinkNode implements LIRLowerable, IterableNodeType {
+@NodeInfo
+public class ReturnNode extends ControlSinkNode implements LIRLowerable, IterableNodeType {
 
-    @OptionalInput private ValueNode result;
-    @OptionalInput(InputType.Extension) private MemoryMapNode memoryMap;
+    @OptionalInput ValueNode result;
+    @OptionalInput(InputType.Extension) MemoryMapNode memoryMap;
 
     public ValueNode result() {
         return result;
@@ -41,22 +43,25 @@
      * @param result the instruction producing the result for this return; {@code null} if this is a
      *            void return
      */
-    public ReturnNode(ValueNode result) {
+    public static ReturnNode create(ValueNode result) {
+        return USE_GENERATED_NODES ? new ReturnNodeGen(result) : new ReturnNode(result);
+    }
+
+    protected ReturnNode(ValueNode result) {
         this(result, null);
     }
 
-    public ReturnNode(ValueNode result, MemoryMapNode memoryMap) {
+    public static ReturnNode create(ValueNode result, MemoryMapNode memoryMap) {
+        return USE_GENERATED_NODES ? new ReturnNodeGen(result, memoryMap) : new ReturnNode(result, memoryMap);
+    }
+
+    protected ReturnNode(ValueNode result, MemoryMapNode memoryMap) {
         super(StampFactory.forVoid());
         this.result = result;
         this.memoryMap = memoryMap;
     }
 
     @Override
-    public boolean verify() {
-        return super.verify();
-    }
-
-    @Override
     public void generate(NodeLIRBuilderTool gen) {
         if (this.result() == null) {
             gen.getLIRGeneratorTool().emitReturn(null);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,14 +23,20 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
  * Marks a position in the graph where a safepoint should be emitted.
  */
+@NodeInfo
 public class SafepointNode extends DeoptimizingFixedWithNextNode implements LIRLowerable {
 
-    public SafepointNode() {
+    public static SafepointNode create() {
+        return USE_GENERATED_NODES ? new SafepointNodeGen() : new SafepointNode();
+    }
+
+    protected SafepointNode() {
         super(StampFactory.forVoid());
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,7 +23,9 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 
+@NodeInfo
 public abstract class ScheduledNode extends Node {
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitOrNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitOrNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,16 +24,22 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 
+@NodeInfo
 public class ShortCircuitOrNode extends LogicNode implements IterableNodeType, Canonicalizable.Binary<LogicNode> {
 
-    @Input(InputType.Condition) private LogicNode x;
-    @Input(InputType.Condition) private LogicNode y;
+    @Input(InputType.Condition) LogicNode x;
+    @Input(InputType.Condition) LogicNode y;
     private boolean xNegated;
     private boolean yNegated;
     private double shortCircuitProbability;
 
-    public ShortCircuitOrNode(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, double shortCircuitProbability) {
+    public static ShortCircuitOrNode create(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, double shortCircuitProbability) {
+        return USE_GENERATED_NODES ? new ShortCircuitOrNodeGen(x, xNegated, y, yNegated, shortCircuitProbability) : new ShortCircuitOrNode(x, xNegated, y, yNegated, shortCircuitProbability);
+    }
+
+    protected ShortCircuitOrNode(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, double shortCircuitProbability) {
         this.x = x;
         this.xNegated = xNegated;
         this.y = y;
@@ -81,7 +87,7 @@
         }
 
         if (xCond != forX || yCond != forY) {
-            return new ShortCircuitOrNode(xCond, xNeg, yCond, yNeg, shortCircuitProbability);
+            return ShortCircuitOrNode.create(xCond, xNeg, yCond, yNeg, shortCircuitProbability);
         } else {
             return this;
         }
@@ -103,7 +109,7 @@
             if (isXNegated()) {
                 if (isYNegated()) {
                     // !a || !a = !a
-                    return new LogicNegationNode(forX);
+                    return LogicNegationNode.create(forX);
                 } else {
                     // !a || a = true
                     return LogicConstantNode.tautology();
@@ -123,7 +129,7 @@
                 return LogicConstantNode.tautology();
             } else {
                 if (isYNegated()) {
-                    return new LogicNegationNode(forY);
+                    return LogicNegationNode.create(forY);
                 } else {
                     return forY;
                 }
@@ -134,7 +140,7 @@
                 return LogicConstantNode.tautology();
             } else {
                 if (isXNegated()) {
-                    return new LogicNegationNode(forX);
+                    return LogicNegationNode.create(forX);
                 } else {
                     return forX;
                 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SimpleInfopointNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SimpleInfopointNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,12 +24,18 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public class SimpleInfopointNode extends InfopointNode implements LIRLowerable, IterableNodeType {
     private BytecodePosition position;
 
-    public SimpleInfopointNode(InfopointReason reason, BytecodePosition position) {
+    public static SimpleInfopointNode create(InfopointReason reason, BytecodePosition position) {
+        return USE_GENERATED_NODES ? new SimpleInfopointNodeGen(reason, position) : new SimpleInfopointNode(reason, position);
+    }
+
+    protected SimpleInfopointNode(InfopointReason reason, BytecodePosition position) {
         super(reason);
         this.position = position;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,7 +23,7 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.extended.*;
 
 /**
@@ -31,6 +31,12 @@
  */
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
 public class StartNode extends BeginStateSplitNode implements MemoryCheckpoint.Single {
+    public static StartNode create() {
+        return USE_GENERATED_NODES ? new StartNodeGen() : new StartNode();
+    }
+
+    protected StartNode() {
+    }
 
     @Override
     public LocationIdentity getLocationIdentity() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Mon Aug 25 21:15:59 2014 -0700
@@ -104,7 +104,7 @@
 
     private StructuredGraph(String name, ResolvedJavaMethod method, long graphId, int entryBCI) {
         super(name);
-        this.setStart(add(new StartNode()));
+        this.setStart(add(StartNode.create()));
         this.method = method;
         this.graphId = graphId;
         this.entryBCI = entryBCI;
@@ -374,7 +374,7 @@
         if (begin.forwardEndCount() == 1) { // bypass merge and remove
             reduceTrivialMerge(begin);
         } else { // convert to merge
-            MergeNode merge = this.add(new MergeNode());
+            MergeNode merge = this.add(MergeNode.create());
             this.replaceFixedWithFixed(begin, merge);
         }
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -28,6 +28,7 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -35,13 +36,14 @@
 /**
  * A node that attaches a type profile to a proxied input node.
  */
-public final class TypeProfileProxyNode extends UnaryNode implements IterableNodeType, ValueProxy {
+@NodeInfo
+public class TypeProfileProxyNode extends UnaryNode implements IterableNodeType, ValueProxy {
 
     private final JavaTypeProfile profile;
     private transient ResolvedJavaType lastCheckedType;
     private transient JavaTypeProfile lastCheckedProfile;
 
-    public static ValueNode create(ValueNode object, JavaTypeProfile profile) {
+    public static ValueNode proxify(ValueNode object, JavaTypeProfile profile) {
         if (StampTool.isExactType(object)) {
             return object;
         }
@@ -53,10 +55,14 @@
             // Only null profiling is not beneficial enough to keep the node around.
             return object;
         }
-        return object.graph().addWithoutUnique(new TypeProfileProxyNode(object, profile));
+        return object.graph().addWithoutUnique(create(object, profile));
     }
 
-    private TypeProfileProxyNode(ValueNode value, JavaTypeProfile profile) {
+    public static ValueNode create(ValueNode object, JavaTypeProfile profile) {
+        return USE_GENERATED_NODES ? new TypeProfileProxyNodeGen(object, profile) : new TypeProfileProxyNode(object, profile);
+    }
+
+    TypeProfileProxyNode(ValueNode value, JavaTypeProfile profile) {
         super(value.stamp(), value);
         this.profile = profile;
     }
@@ -91,7 +97,7 @@
             }
             if (newProfile != this.profile) {
                 Debug.log("Improved profile via other profile.");
-                return new TypeProfileProxyNode(forValue, newProfile);
+                return TypeProfileProxyNode.create(forValue, newProfile);
             }
         } else if (StampTool.typeOrNull(forValue) != null) {
             ResolvedJavaType type = StampTool.typeOrNull(forValue);
@@ -113,7 +119,7 @@
                     // Only null profiling is not beneficial enough to keep the node around.
                     return forValue;
                 }
-                return new TypeProfileProxyNode(forValue, newProfile);
+                return TypeProfileProxyNode.create(forValue, newProfile);
             }
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnaryOpLogicNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnaryOpLogicNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,11 +23,13 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public abstract class UnaryOpLogicNode extends LogicNode implements LIRLowerable, Canonicalizable.Unary<ValueNode> {
 
-    @Input private ValueNode value;
+    @Input protected ValueNode value;
 
     public ValueNode getValue() {
         return value;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,20 +24,26 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
  * Unwinds the current frame to an exception handler in the caller frame.
  */
-public final class UnwindNode extends ControlSinkNode implements Lowerable, LIRLowerable {
+@NodeInfo
+public class UnwindNode extends ControlSinkNode implements Lowerable, LIRLowerable {
 
-    @Input private ValueNode exception;
+    @Input ValueNode exception;
 
     public ValueNode exception() {
         return exception;
     }
 
-    public UnwindNode(ValueNode exception) {
+    public static UnwindNode create(ValueNode exception) {
+        return USE_GENERATED_NODES ? new UnwindNodeGen(exception) : new UnwindNode(exception);
+    }
+
+    protected UnwindNode(ValueNode exception) {
         super(StampFactory.forVoid());
         assert exception == null || exception.getKind() == Kind.Object;
         this.exception = exception;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,13 +24,14 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.nodeinfo.*;
 
 /**
  * This class represents a value within the graph, including local variables, phis, and all other
  * instructions.
  */
+@NodeInfo
 public abstract class ValueNode extends ScheduledNode implements StampProvider, KindProvider {
 
     /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.Verbosity;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.extended.*;
 
 public class ValueNodeUtil {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
@@ -32,7 +33,7 @@
 @NodeInfo(nameTemplate = "ValuePhi({i#values})")
 public class ValuePhiNode extends PhiNode {
 
-    @Input final NodeInputList<ValueNode> values;
+    @Input NodeInputList<ValueNode> values;
 
     /**
      * Create a value phi with the specified stamp.
@@ -40,7 +41,11 @@
      * @param stamp the stamp of the value
      * @param merge the merge that the new phi belongs to
      */
-    public ValuePhiNode(Stamp stamp, MergeNode merge) {
+    public static ValuePhiNode create(Stamp stamp, MergeNode merge) {
+        return USE_GENERATED_NODES ? new ValuePhiNodeGen(stamp, merge) : new ValuePhiNode(stamp, merge);
+    }
+
+    protected ValuePhiNode(Stamp stamp, MergeNode merge) {
         super(stamp, merge);
         assert stamp != StampFactory.forVoid();
         values = new NodeInputList<>(this);
@@ -53,7 +58,11 @@
      * @param merge the merge that the new phi belongs to
      * @param values the initial values of the phi
      */
-    public ValuePhiNode(Stamp stamp, MergeNode merge, ValueNode[] values) {
+    public static ValuePhiNode create(Stamp stamp, MergeNode merge, ValueNode[] values) {
+        return USE_GENERATED_NODES ? new ValuePhiNodeGen(stamp, merge, values) : new ValuePhiNode(stamp, merge, values);
+    }
+
+    protected ValuePhiNode(Stamp stamp, MergeNode merge, ValueNode[] values) {
         super(stamp, merge);
         assert stamp != StampFactory.forVoid();
         this.values = new NodeInputList<>(this, values);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,13 +24,19 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public class ValueProxyNode extends ProxyNode implements Canonicalizable, Virtualizable, ValueAndStampProxy {
 
-    @Input private ValueNode value;
+    @Input ValueNode value;
 
-    public ValueProxyNode(ValueNode value, BeginNode proxyPoint) {
+    public static ValueProxyNode create(ValueNode value, BeginNode proxyPoint) {
+        return USE_GENERATED_NODES ? new ValueProxyNodeGen(value, proxyPoint) : new ValueProxyNode(value, proxyPoint);
+    }
+
+    protected ValueProxyNode(ValueNode value, BeginNode proxyPoint) {
         super(value.stamp(), proxyPoint);
         this.value = value;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 
 /**
  * Base class for nodes that contain "virtual" state, like FrameState and VirtualObjectState.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,18 +24,26 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "&")
-public final class AndNode extends BitLogicNode implements NarrowableArithmeticNode {
+public class AndNode extends BitLogicNode implements NarrowableArithmeticNode {
+
+    public static AndNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new AndNodeGen(x, y) : new AndNode(x, y);
+    }
 
-    public AndNode(ValueNode x, ValueNode y) {
+    public static Class<? extends AndNode> getGenClass() {
+        return USE_GENERATED_NODES ? AndNodeGen.class : AndNode.class;
+    }
+
+    AndNode(ValueNode x, ValueNode y) {
         super(StampTool.and(x.stamp(), y.stamp()), x, y);
         assert x.stamp().isCompatible(y.stamp());
     }
@@ -57,7 +65,7 @@
             return forX;
         }
         if (forX.isConstant() && !forY.isConstant()) {
-            return new AndNode(forY, forX);
+            return AndNode.create(forY, forX);
         }
         if (forX.isConstant()) {
             return ConstantNode.forPrimitive(stamp(), evalConst(forX.asConstant(), forY.asConstant()));
@@ -73,7 +81,7 @@
             if (forX instanceof SignExtendNode) {
                 SignExtendNode ext = (SignExtendNode) forX;
                 if (rawY == ((1L << ext.getInputBits()) - 1)) {
-                    return new ZeroExtendNode(ext.getValue(), ext.getResultBits());
+                    return ZeroExtendNode.create(ext.getValue(), ext.getResultBits());
                 }
             }
             if (forX.stamp() instanceof IntegerStamp) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,15 +26,17 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
 /**
  * The {@code BinaryNode} class is the base of arithmetic and logic operations with two inputs.
  */
+@NodeInfo
 public abstract class BinaryNode extends FloatingNode implements Canonicalizable.Binary<ValueNode> {
 
-    @Input private ValueNode x;
-    @Input private ValueNode y;
+    @Input protected ValueNode x;
+    @Input protected ValueNode y;
 
     public ValueNode getX() {
         return x;
@@ -90,7 +92,7 @@
         if (stamp instanceof IntegerStamp) {
             return IntegerArithmeticNode.add(graph, x, y);
         } else if (stamp instanceof FloatStamp) {
-            return graph.unique(new FloatAddNode(x, y, false));
+            return graph.unique(FloatAddNode.create(x, y, false));
         } else {
             throw GraalInternalError.shouldNotReachHere();
         }
@@ -102,7 +104,7 @@
         if (stamp instanceof IntegerStamp) {
             return IntegerArithmeticNode.sub(graph, x, y);
         } else if (stamp instanceof FloatStamp) {
-            return graph.unique(new FloatSubNode(x, y, false));
+            return graph.unique(FloatSubNode.create(x, y, false));
         } else {
             throw GraalInternalError.shouldNotReachHere();
         }
@@ -114,7 +116,7 @@
         if (stamp instanceof IntegerStamp) {
             return IntegerArithmeticNode.mul(graph, x, y);
         } else if (stamp instanceof FloatStamp) {
-            return graph.unique(new FloatMulNode(x, y, false));
+            return graph.unique(FloatMulNode.create(x, y, false));
         } else {
             throw GraalInternalError.shouldNotReachHere();
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,12 +23,14 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
  * The {@code LogicNode} class definition.
  */
+@NodeInfo
 public abstract class BitLogicNode extends BinaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode {
 
     /**
@@ -43,26 +45,26 @@
     }
 
     public static BitLogicNode and(StructuredGraph graph, ValueNode v1, ValueNode v2) {
-        return graph.unique(new AndNode(v1, v2));
+        return graph.unique(AndNode.create(v1, v2));
     }
 
     public static BitLogicNode and(ValueNode v1, ValueNode v2) {
-        return new AndNode(v1, v2);
+        return AndNode.create(v1, v2);
     }
 
     public static BitLogicNode or(StructuredGraph graph, ValueNode v1, ValueNode v2) {
-        return graph.unique(new OrNode(v1, v2));
+        return graph.unique(OrNode.create(v1, v2));
     }
 
     public static BitLogicNode or(ValueNode v1, ValueNode v2) {
-        return new OrNode(v1, v2);
+        return OrNode.create(v1, v2);
     }
 
     public static BitLogicNode xor(StructuredGraph graph, ValueNode v1, ValueNode v2) {
-        return graph.unique(new XorNode(v1, v2));
+        return graph.unique(XorNode.create(v1, v2));
     }
 
     public static BitLogicNode xor(ValueNode v1, ValueNode v2) {
-        return new XorNode(v1, v2);
+        return XorNode.create(v1, v2);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
 /* TODO (thomaswue/gdub) For high-level optimization purpose the compare node should be a boolean *value* (it is currently only a helper node)
@@ -34,6 +35,7 @@
  * Compare should probably be made a value (so that it can be canonicalized for example) and in later stages some Compare usage should be transformed
  * into variants that do not materialize the value (CompareIf, CompareGuard...)
  */
+@NodeInfo
 public abstract class CompareNode extends BinaryOpLogicNode {
 
     /**
@@ -76,7 +78,7 @@
                     return conditionalNode.condition();
                 } else {
                     assert falseResult == true;
-                    return new LogicNegationNode(conditionalNode.condition());
+                    return LogicNegationNode.create(conditionalNode.condition());
 
                 }
             }
@@ -155,18 +157,18 @@
         CompareNode comparison;
         if (condition == Condition.EQ) {
             if (x.getKind() == Kind.Object) {
-                comparison = new ObjectEqualsNode(x, y);
+                comparison = ObjectEqualsNode.create(x, y);
             } else {
                 assert x.getKind().isNumericInteger();
-                comparison = new IntegerEqualsNode(x, y);
+                comparison = IntegerEqualsNode.create(x, y);
             }
         } else if (condition == Condition.LT) {
             assert x.getKind().isNumericInteger();
-            comparison = new IntegerLessThanNode(x, y);
+            comparison = IntegerLessThanNode.create(x, y);
         } else {
             assert condition == Condition.BT;
             assert x.getKind().isNumericInteger();
-            comparison = new IntegerBelowNode(x, y);
+            comparison = IntegerBelowNode.create(x, y);
         }
 
         return comparison;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,8 +27,8 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
@@ -37,21 +37,30 @@
  * The {@code ConditionalNode} class represents a comparison that yields one of two values. Note
  * that these nodes are not built directly from the bytecode but are introduced by canonicalization.
  */
-public final class ConditionalNode extends FloatingNode implements Canonicalizable, LIRLowerable {
+@NodeInfo
+public class ConditionalNode extends FloatingNode implements Canonicalizable, LIRLowerable {
 
-    @Input(InputType.Condition) private LogicNode condition;
-    @Input private ValueNode trueValue;
-    @Input private ValueNode falseValue;
+    @Input(InputType.Condition) LogicNode condition;
+    @Input ValueNode trueValue;
+    @Input ValueNode falseValue;
 
     public LogicNode condition() {
         return condition;
     }
 
-    public ConditionalNode(LogicNode condition) {
+    public static ConditionalNode create(LogicNode condition) {
+        return USE_GENERATED_NODES ? new ConditionalNodeGen(condition) : new ConditionalNode(condition);
+    }
+
+    protected ConditionalNode(LogicNode condition) {
         this(condition, ConstantNode.forInt(1, condition.graph()), ConstantNode.forInt(0, condition.graph()));
     }
 
-    public ConditionalNode(LogicNode condition, ValueNode trueValue, ValueNode falseValue) {
+    public static ConditionalNode create(LogicNode condition, ValueNode trueValue, ValueNode falseValue) {
+        return USE_GENERATED_NODES ? new ConditionalNodeGen(condition, trueValue, falseValue) : new ConditionalNode(condition, trueValue, falseValue);
+    }
+
+    protected ConditionalNode(LogicNode condition, ValueNode trueValue, ValueNode falseValue) {
         super(trueValue.stamp().meet(falseValue.stamp()));
         assert trueValue.stamp().isCompatible(falseValue.stamp());
         this.condition = condition;
@@ -76,7 +85,7 @@
     public ValueNode canonical(CanonicalizerTool tool) {
         if (condition instanceof LogicNegationNode) {
             LogicNegationNode negated = (LogicNegationNode) condition;
-            return new ConditionalNode(negated.getValue(), falseValue(), trueValue());
+            return ConditionalNode.create(negated.getValue(), falseValue(), trueValue());
         }
 
         // this optimizes the case where a value that can only be 0 or 1 is materialized to 0 or 1
@@ -118,12 +127,20 @@
         generator.emitConditional(this);
     }
 
-    private ConditionalNode(@InjectedNodeParameter StructuredGraph graph, Condition condition, ValueNode x, ValueNode y) {
+    public static ConditionalNode create(@InjectedNodeParameter StructuredGraph graph, Condition condition, ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new ConditionalNodeGen(graph, condition, x, y) : new ConditionalNode(graph, condition, x, y);
+    }
+
+    ConditionalNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y) {
         this(createCompareNode(graph, condition, x, y));
     }
 
-    private ConditionalNode(ValueNode type, ValueNode object) {
-        this(type.graph().unique(new InstanceOfDynamicNode(type, object)));
+    public static ConditionalNode create(ValueNode type, ValueNode object) {
+        return USE_GENERATED_NODES ? new ConditionalNodeGen(type, object) : new ConditionalNode(type, object);
+    }
+
+    ConditionalNode(ValueNode type, ValueNode object) {
+        this(type.graph().unique(InstanceOfDynamicNode.create(type, object)));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,11 +26,13 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
 /**
  * Represents a conversion between primitive types.
  */
+@NodeInfo
 public abstract class ConvertNode extends UnaryNode implements ArithmeticOperation {
 
     protected ConvertNode(Stamp stamp, ValueNode value) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,12 +24,14 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
+@NodeInfo
 public abstract class FixedBinaryNode extends DeoptimizingFixedWithNextNode implements Canonicalizable.Binary<ValueNode> {
 
-    @Input private ValueNode x;
-    @Input private ValueNode y;
+    @Input ValueNode x;
+    @Input ValueNode y;
 
     public FixedBinaryNode(Stamp stamp, ValueNode x, ValueNode y) {
         super(stamp);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,13 +26,22 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "+")
-public final class FloatAddNode extends FloatArithmeticNode {
+public class FloatAddNode extends FloatArithmeticNode {
+
+    public static FloatAddNode create(ValueNode x, ValueNode y, boolean isStrictFP) {
+        return USE_GENERATED_NODES ? new FloatAddNodeGen(x, y, isStrictFP) : new FloatAddNode(x, y, isStrictFP);
+    }
 
-    public FloatAddNode(ValueNode x, ValueNode y, boolean isStrictFP) {
+    public static Class<? extends FloatAddNode> getGenClass() {
+        return USE_GENERATED_NODES ? FloatAddNodeGen.class : FloatAddNode.class;
+    }
+
+    protected FloatAddNode(ValueNode x, ValueNode y, boolean isStrictFP) {
         super(x.stamp().unrestricted(), x, y, isStrictFP);
     }
 
@@ -50,7 +59,7 @@
     @Override
     public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
         if (forX.isConstant() && !forY.isConstant()) {
-            return new FloatAddNode(forY, forX, isStrictFP());
+            return FloatAddNode.create(forY, forX, isStrictFP());
         }
         if (forX.isConstant()) {
             return ConstantNode.forConstant(evalConst(forX.asConstant(), forY.asConstant()), null);
@@ -58,6 +67,7 @@
         // Constant 0.0 can't be eliminated since it can affect the sign of the result.
         // Constant -0.0 is an additive identity.
         if (forY.isConstant()) {
+            @SuppressWarnings("hiding")
             Constant y = forY.asConstant();
             switch (y.getKind()) {
                 case Float:
@@ -76,6 +86,16 @@
                     throw GraalGraphInternalError.shouldNotReachHere();
             }
         }
+        /*
+         * JVM spec, Chapter 6, dsub/fsub bytecode: For double subtraction, it is always the case
+         * that a-b produces the same result as a+(-b).
+         */
+        if (forX instanceof NegateNode) {
+            return FloatSubNode.create(forY, ((NegateNode) forX).getValue(), isStrictFP());
+        }
+        if (forY instanceof NegateNode) {
+            return FloatSubNode.create(forX, ((NegateNode) forY).getValue(), isStrictFP());
+        }
         return this;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatArithmeticNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatArithmeticNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,9 +23,11 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public abstract class FloatArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable {
 
     private final boolean isStrictFP;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -28,6 +28,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -35,11 +36,16 @@
  * A {@code FloatConvert} converts between integers and floating point numbers according to Java
  * semantics.
  */
+@NodeInfo
 public class FloatConvertNode extends ConvertNode implements Lowerable, ArithmeticLIRLowerable {
 
     private final FloatConvert op;
 
-    public FloatConvertNode(FloatConvert op, ValueNode input) {
+    public static FloatConvertNode create(FloatConvert op, ValueNode input) {
+        return USE_GENERATED_NODES ? new FloatConvertNodeGen(op, input) : new FloatConvertNode(op, input);
+    }
+
+    protected FloatConvertNode(FloatConvert op, ValueNode input) {
         super(createStamp(op, input), input);
         this.op = op;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,13 +26,18 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "/")
-public final class FloatDivNode extends FloatArithmeticNode {
+public class FloatDivNode extends FloatArithmeticNode {
 
-    public FloatDivNode(ValueNode x, ValueNode y, boolean isStrictFP) {
+    public static FloatDivNode create(ValueNode x, ValueNode y, boolean isStrictFP) {
+        return USE_GENERATED_NODES ? new FloatDivNodeGen(x, y, isStrictFP) : new FloatDivNode(x, y, isStrictFP);
+    }
+
+    protected FloatDivNode(ValueNode x, ValueNode y, boolean isStrictFP) {
         super(x.stamp().unrestricted(), x, y, isStrictFP);
     }
 
@@ -53,6 +58,7 @@
             return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant()));
         }
         if (forY.isConstant()) {
+            @SuppressWarnings("hiding")
             Constant y = forY.asConstant();
             switch (y.getKind()) {
                 case Float:
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,13 +25,13 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "==")
-public final class FloatEqualsNode extends CompareNode {
+public class FloatEqualsNode extends CompareNode {
 
     /**
      * Constructs a new floating point equality comparison node.
@@ -39,7 +39,11 @@
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
-    public FloatEqualsNode(ValueNode x, ValueNode y) {
+    public static FloatEqualsNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new FloatEqualsNodeGen(x, y) : new FloatEqualsNode(x, y);
+    }
+
+    protected FloatEqualsNode(ValueNode x, ValueNode y) {
         super(x, y);
         assert x.stamp() instanceof FloatStamp && y.stamp() instanceof FloatStamp : x.stamp() + " " + y.stamp();
         assert x.stamp().isCompatible(y.stamp());
@@ -76,9 +80,9 @@
     @Override
     protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) {
         if (newX.stamp() instanceof FloatStamp && newY.stamp() instanceof FloatStamp) {
-            return new FloatEqualsNode(newX, newY);
+            return FloatEqualsNode.create(newX, newY);
         } else if (newX.stamp() instanceof IntegerStamp && newY.stamp() instanceof IntegerStamp) {
-            return new IntegerEqualsNode(newX, newY);
+            return IntegerEqualsNode.create(newX, newY);
         }
         throw GraalInternalError.shouldNotReachHere();
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,13 +25,13 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "<")
-public final class FloatLessThanNode extends CompareNode {
+public class FloatLessThanNode extends CompareNode {
 
     private final boolean unorderedIsTrue;
 
@@ -43,7 +43,11 @@
      * @param unorderedIsTrue whether a comparison that is undecided (involving NaNs, etc.) leads to
      *            a "true" result
      */
-    public FloatLessThanNode(ValueNode x, ValueNode y, boolean unorderedIsTrue) {
+    public static FloatLessThanNode create(ValueNode x, ValueNode y, boolean unorderedIsTrue) {
+        return USE_GENERATED_NODES ? new FloatLessThanNodeGen(x, y, unorderedIsTrue) : new FloatLessThanNode(x, y, unorderedIsTrue);
+    }
+
+    protected FloatLessThanNode(ValueNode x, ValueNode y, boolean unorderedIsTrue) {
         super(x, y);
         assert x.stamp() instanceof FloatStamp && y.stamp() instanceof FloatStamp;
         assert x.stamp().isCompatible(y.stamp());
@@ -75,9 +79,9 @@
     @Override
     protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) {
         if (newX.stamp() instanceof FloatStamp && newY.stamp() instanceof FloatStamp) {
-            return new FloatLessThanNode(newX, newY, unorderedIsTrue);
+            return FloatLessThanNode.create(newX, newY, unorderedIsTrue);
         } else if (newX.stamp() instanceof IntegerStamp && newY.stamp() instanceof IntegerStamp) {
-            return new IntegerLessThanNode(newX, newY);
+            return IntegerLessThanNode.create(newX, newY);
         }
         throw GraalInternalError.shouldNotReachHere();
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,13 +26,22 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "*")
-public final class FloatMulNode extends FloatArithmeticNode {
+public class FloatMulNode extends FloatArithmeticNode {
+
+    public static FloatMulNode create(ValueNode x, ValueNode y, boolean isStrictFP) {
+        return USE_GENERATED_NODES ? new FloatMulNodeGen(x, y, isStrictFP) : new FloatMulNode(x, y, isStrictFP);
+    }
 
-    public FloatMulNode(ValueNode x, ValueNode y, boolean isStrictFP) {
+    public static Class<? extends FloatMulNode> getGenClass() {
+        return USE_GENERATED_NODES ? FloatMulNodeGen.class : FloatMulNode.class;
+    }
+
+    protected FloatMulNode(ValueNode x, ValueNode y, boolean isStrictFP) {
         super(x.stamp().unrestricted(), x, y, isStrictFP);
     }
 
@@ -50,12 +59,13 @@
     @Override
     public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
         if (forX.isConstant() && !forY.isConstant()) {
-            return new FloatMulNode(forY, forX, isStrictFP());
+            return FloatMulNode.create(forY, forX, isStrictFP());
         }
         if (forX.isConstant()) {
             return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant()));
         }
         if (forY.isConstant()) {
+            @SuppressWarnings("hiding")
             Constant y = forY.asConstant();
             switch (y.getKind()) {
                 case Float:
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,16 +23,20 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "%")
 public class FloatRemNode extends FloatArithmeticNode implements Lowerable {
 
-    public FloatRemNode(ValueNode x, ValueNode y, boolean isStrictFP) {
+    public static FloatRemNode create(ValueNode x, ValueNode y, boolean isStrictFP) {
+        return USE_GENERATED_NODES ? new FloatRemNodeGen(x, y, isStrictFP) : new FloatRemNode(x, y, isStrictFP);
+    }
+
+    protected FloatRemNode(ValueNode x, ValueNode y, boolean isStrictFP) {
         super(x.stamp().unrestricted(), x, y, isStrictFP);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,14 +26,23 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "-")
-public final class FloatSubNode extends FloatArithmeticNode {
+public class FloatSubNode extends FloatArithmeticNode {
+
+    public static FloatSubNode create(ValueNode x, ValueNode y, boolean isStrictFP) {
+        return USE_GENERATED_NODES ? new FloatSubNodeGen(x, y, isStrictFP) : new FloatSubNode(x, y, isStrictFP);
+    }
 
-    public FloatSubNode(ValueNode x, ValueNode y, boolean isStrictFP) {
+    public static Class<? extends FloatSubNode> getGenClass() {
+        return USE_GENERATED_NODES ? FloatSubNodeGen.class : FloatSubNode.class;
+    }
+
+    protected FloatSubNode(ValueNode x, ValueNode y, boolean isStrictFP) {
         super(x.stamp().unrestricted(), x, y, isStrictFP);
     }
 
@@ -56,9 +65,29 @@
         if (forX.isConstant() && forY.isConstant()) {
             return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant()));
         }
+        // Constant -0.0 is an additive identity, so (-0.0) - x == (-0.0) + (-x) == -x.
+        if (forX.isConstant()) {
+            @SuppressWarnings("hiding")
+            Constant x = forX.asConstant();
+            switch (x.getKind()) {
+                case Float:
+                    if (Float.compare(x.asFloat(), -0.0f) == 0) {
+                        return NegateNode.create(forY);
+                    }
+                    break;
+                case Double:
+                    if (Double.compare(x.asDouble(), -0.0) == 0) {
+                        return NegateNode.create(forY);
+                    }
+                    break;
+                default:
+                    throw GraalGraphInternalError.shouldNotReachHere();
+            }
+        }
         // Constant -0.0 can't be eliminated since it can affect the sign of the result.
         // Constant 0.0 is a subtractive identity.
         if (forY.isConstant()) {
+            @SuppressWarnings("hiding")
             Constant y = forY.asConstant();
             switch (y.getKind()) {
                 case Float:
@@ -77,6 +106,13 @@
                     throw GraalGraphInternalError.shouldNotReachHere();
             }
         }
+        /*
+         * JVM spec, Chapter 6, dsub/fsub bytecode: For double subtraction, it is always the case
+         * that a-b produces the same result as a+(-b).
+         */
+        if (forY instanceof NegateNode) {
+            return FloatAddNode.create(forX, ((NegateNode) forY).getValue(), isStrictFP());
+        }
         return this;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,8 +24,10 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
+@NodeInfo
 public abstract class FloatingNode extends ValueNode implements Node.ValueNumberable {
 
     public FloatingNode(Stamp stamp) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,9 +24,9 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -34,7 +34,15 @@
 @NodeInfo(shortName = "+")
 public class IntegerAddNode extends IntegerArithmeticNode implements NarrowableArithmeticNode {
 
-    public IntegerAddNode(ValueNode x, ValueNode y) {
+    public static IntegerAddNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new IntegerAddNodeGen(x, y) : new IntegerAddNode(x, y);
+    }
+
+    public static Class<? extends IntegerAddNode> getGenClass() {
+        return USE_GENERATED_NODES ? IntegerAddNodeGen.class : IntegerAddNode.class;
+    }
+
+    protected IntegerAddNode(ValueNode x, ValueNode y) {
         super(StampTool.add(x.stamp(), y.stamp()), x, y);
     }
 
@@ -52,7 +60,7 @@
     @Override
     public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
         if (forX.isConstant() && !forY.isConstant()) {
-            return new IntegerAddNode(forY, forX);
+            return IntegerAddNode.create(forY, forX);
         }
         if (forX instanceof IntegerSubNode) {
             IntegerSubNode sub = (IntegerSubNode) forX;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,9 +23,11 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public abstract class IntegerArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable {
 
     public IntegerArithmeticNode(Stamp stamp, ValueNode x, ValueNode y) {
@@ -34,26 +36,26 @@
     }
 
     public static IntegerAddNode add(StructuredGraph graph, ValueNode v1, ValueNode v2) {
-        return graph.unique(new IntegerAddNode(v1, v2));
+        return graph.unique(IntegerAddNode.create(v1, v2));
     }
 
     public static IntegerAddNode add(ValueNode v1, ValueNode v2) {
-        return new IntegerAddNode(v1, v2);
+        return IntegerAddNode.create(v1, v2);
     }
 
     public static IntegerMulNode mul(StructuredGraph graph, ValueNode v1, ValueNode v2) {
-        return graph.unique(new IntegerMulNode(v1, v2));
+        return graph.unique(IntegerMulNode.create(v1, v2));
     }
 
     public static IntegerMulNode mul(ValueNode v1, ValueNode v2) {
-        return new IntegerMulNode(v1, v2);
+        return IntegerMulNode.create(v1, v2);
     }
 
     public static IntegerSubNode sub(StructuredGraph graph, ValueNode v1, ValueNode v2) {
-        return graph.unique(new IntegerSubNode(v1, v2));
+        return graph.unique(IntegerSubNode.create(v1, v2));
     }
 
     public static IntegerSubNode sub(ValueNode v1, ValueNode v2) {
-        return new IntegerSubNode(v1, v2);
+        return IntegerSubNode.create(v1, v2);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,13 +24,13 @@
 
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "|<|")
-public final class IntegerBelowNode extends CompareNode {
+public class IntegerBelowNode extends CompareNode {
 
     /**
      * Constructs a new unsigned integer comparison node.
@@ -38,7 +38,11 @@
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
-    public IntegerBelowNode(ValueNode x, ValueNode y) {
+    public static IntegerBelowNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new IntegerBelowNodeGen(x, y) : new IntegerBelowNode(x, y);
+    }
+
+    protected IntegerBelowNode(ValueNode x, ValueNode y) {
         super(x, y);
         assert x.stamp() instanceof IntegerStamp;
         assert y.stamp() instanceof IntegerStamp;
@@ -75,13 +79,13 @@
         }
         if (forX.isConstant() && forX.asConstant().asLong() == 0) {
             // 0 |<| y is the same as 0 != y
-            return new LogicNegationNode(CompareNode.createCompareNode(Condition.EQ, forX, forY));
+            return LogicNegationNode.create(CompareNode.createCompareNode(Condition.EQ, forX, forY));
         }
         return this;
     }
 
     @Override
     protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) {
-        return new IntegerBelowNode(newX, newY);
+        return IntegerBelowNode.create(newX, newY);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,12 +23,14 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
  * An {@code IntegerConvert} converts an integer to an integer of different width.
  */
+@NodeInfo
 public abstract class IntegerConvertNode extends ConvertNode implements ArithmeticLIRLowerable {
 
     private final int resultBits;
@@ -58,7 +60,7 @@
         }
     }
 
-    protected ValueNode canonicalConvert(ValueNode value) {
+    protected ValueNode canonicalConvert(@SuppressWarnings("hiding") ValueNode value) {
         if (value.stamp() instanceof IntegerStamp) {
             int inputBits = ((IntegerStamp) value.stamp()).getBits();
             if (inputBits == resultBits) {
@@ -95,13 +97,13 @@
         if (toStamp.getBits() == fromStamp.getBits()) {
             result = input;
         } else if (toStamp.getBits() < fromStamp.getBits()) {
-            result = new NarrowNode(input, toStamp.getBits());
+            result = NarrowNode.create(input, toStamp.getBits());
         } else if (zeroExtend) {
             // toStamp.getBits() > fromStamp.getBits()
-            result = new ZeroExtendNode(input, toStamp.getBits());
+            result = ZeroExtendNode.create(input, toStamp.getBits());
         } else {
             // toStamp.getBits() > fromStamp.getBits()
-            result = new SignExtendNode(input, toStamp.getBits());
+            result = SignExtendNode.create(input, toStamp.getBits());
         }
 
         IntegerStamp resultStamp = (IntegerStamp) result.stamp();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -33,7 +34,11 @@
 @NodeInfo(shortName = "/")
 public class IntegerDivNode extends FixedBinaryNode implements Lowerable, LIRLowerable {
 
-    public IntegerDivNode(ValueNode x, ValueNode y) {
+    public static IntegerDivNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new IntegerDivNodeGen(x, y) : new IntegerDivNode(x, y);
+    }
+
+    protected IntegerDivNode(ValueNode x, ValueNode y) {
         super(StampTool.div(x.stamp(), y.stamp()), x, y);
     }
 
@@ -45,6 +50,7 @@
     @Override
     public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
         if (forX.isConstant() && forY.isConstant()) {
+            @SuppressWarnings("hiding")
             long y = forY.asConstant().asLong();
             if (y == 0) {
                 return this; // this will trap, can not canonicalize
@@ -56,7 +62,7 @@
                 return forX;
             }
             if (c == -1) {
-                return new NegateNode(forX);
+                return NegateNode.create(forX);
             }
             long abs = Math.abs(c);
             if (CodeUtil.isPowerOf2(abs) && forX.stamp() instanceof IntegerStamp) {
@@ -66,13 +72,13 @@
                 // no rounding if dividend is positive or if its low bits are always 0
                 if (stampX.canBeNegative() || (stampX.upMask() & (abs - 1)) != 0) {
                     int bits = PrimitiveStamp.getBits(stamp());
-                    RightShiftNode sign = new RightShiftNode(forX, ConstantNode.forInt(bits - 1));
-                    UnsignedRightShiftNode round = new UnsignedRightShiftNode(sign, ConstantNode.forInt(bits - log2));
+                    RightShiftNode sign = RightShiftNode.create(forX, ConstantNode.forInt(bits - 1));
+                    UnsignedRightShiftNode round = UnsignedRightShiftNode.create(sign, ConstantNode.forInt(bits - log2));
                     dividend = IntegerArithmeticNode.add(dividend, round);
                 }
-                RightShiftNode shift = new RightShiftNode(dividend, ConstantNode.forInt(log2));
+                RightShiftNode shift = RightShiftNode.create(dividend, ConstantNode.forInt(log2));
                 if (c < 0) {
-                    return new NegateNode(shift);
+                    return NegateNode.create(shift);
                 }
                 return shift;
             }
@@ -85,7 +91,7 @@
                 IntegerRemNode integerRemNode = (IntegerRemNode) integerSubNode.getY();
                 if (integerSubNode.stamp().isCompatible(this.stamp()) && integerRemNode.stamp().isCompatible(this.stamp()) && integerSubNode.getX() == integerRemNode.getX() &&
                                 forY == integerRemNode.getY()) {
-                    return new IntegerDivNode(integerSubNode.getX(), forY);
+                    return IntegerDivNode.create(integerSubNode.getX(), forY);
                 }
             }
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,13 +26,13 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "==")
-public final class IntegerEqualsNode extends CompareNode {
+public class IntegerEqualsNode extends CompareNode {
 
     /**
      * Constructs a new integer equality comparison node.
@@ -40,7 +40,11 @@
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
-    public IntegerEqualsNode(ValueNode x, ValueNode y) {
+    public static IntegerEqualsNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new IntegerEqualsNodeGen(x, y) : new IntegerEqualsNode(x, y);
+    }
+
+    protected IntegerEqualsNode(ValueNode x, ValueNode y) {
         super(x, y);
         assert !x.getKind().isNumericFloat() && x.getKind() != Kind.Object;
         assert !y.getKind().isNumericFloat() && y.getKind() != Kind.Object;
@@ -63,9 +67,9 @@
             ValueNode b = mirrored ? normalizeNode.getX() : normalizeNode.getY();
 
             if (normalizeNode.getX().getKind() == Kind.Double || normalizeNode.getX().getKind() == Kind.Float) {
-                return new FloatEqualsNode(a, b);
+                return FloatEqualsNode.create(a, b);
             } else {
-                return new IntegerEqualsNode(a, b);
+                return IntegerEqualsNode.create(a, b);
             }
         }
         return this;
@@ -74,9 +78,9 @@
     @Override
     protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) {
         if (newX.stamp() instanceof FloatStamp && newY.stamp() instanceof FloatStamp) {
-            return new FloatEqualsNode(newX, newY);
+            return FloatEqualsNode.create(newX, newY);
         } else if (newX.stamp() instanceof IntegerStamp && newY.stamp() instanceof IntegerStamp) {
-            return new IntegerEqualsNode(newX, newY);
+            return IntegerEqualsNode.create(newX, newY);
         }
         throw GraalInternalError.shouldNotReachHere();
     }
@@ -96,7 +100,7 @@
         if (constant.asLong() == 0) {
             if (nonConstant instanceof AndNode) {
                 AndNode andNode = (AndNode) nonConstant;
-                return new IntegerTestNode(andNode.getX(), andNode.getY());
+                return IntegerTestNode.create(andNode.getX(), andNode.getY());
             } else if (nonConstant instanceof ShiftNode) {
                 if (nonConstant instanceof LeftShiftNode) {
                     LeftShiftNode shift = (LeftShiftNode) nonConstant;
@@ -104,10 +108,10 @@
                         int mask = shift.getShiftAmountMask();
                         int amount = shift.getY().asConstant().asInt() & mask;
                         if (shift.getX().getKind() == Kind.Int) {
-                            return new IntegerTestNode(shift.getX(), ConstantNode.forInt(-1 >>> amount));
+                            return IntegerTestNode.create(shift.getX(), ConstantNode.forInt(-1 >>> amount));
                         } else {
                             assert shift.getX().getKind() == Kind.Long;
-                            return new IntegerTestNode(shift.getX(), ConstantNode.forLong(-1L >>> amount));
+                            return IntegerTestNode.create(shift.getX(), ConstantNode.forLong(-1L >>> amount));
                         }
                     }
                 } else if (nonConstant instanceof RightShiftNode) {
@@ -116,10 +120,10 @@
                         int mask = shift.getShiftAmountMask();
                         int amount = shift.getY().asConstant().asInt() & mask;
                         if (shift.getX().getKind() == Kind.Int) {
-                            return new IntegerTestNode(shift.getX(), ConstantNode.forInt(-1 << amount));
+                            return IntegerTestNode.create(shift.getX(), ConstantNode.forInt(-1 << amount));
                         } else {
                             assert shift.getX().getKind() == Kind.Long;
-                            return new IntegerTestNode(shift.getX(), ConstantNode.forLong(-1L << amount));
+                            return IntegerTestNode.create(shift.getX(), ConstantNode.forLong(-1L << amount));
                         }
                     }
                 } else if (nonConstant instanceof UnsignedRightShiftNode) {
@@ -128,10 +132,10 @@
                         int mask = shift.getShiftAmountMask();
                         int amount = shift.getY().asConstant().asInt() & mask;
                         if (shift.getX().getKind() == Kind.Int) {
-                            return new IntegerTestNode(shift.getX(), ConstantNode.forInt(-1 << amount));
+                            return IntegerTestNode.create(shift.getX(), ConstantNode.forInt(-1 << amount));
                         } else {
                             assert shift.getX().getKind() == Kind.Long;
-                            return new IntegerTestNode(shift.getX(), ConstantNode.forLong(-1L << amount));
+                            return IntegerTestNode.create(shift.getX(), ConstantNode.forLong(-1L << amount));
                         }
                     }
                 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,13 +26,13 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "<")
-public final class IntegerLessThanNode extends CompareNode {
+public class IntegerLessThanNode extends CompareNode {
 
     /**
      * Constructs a new integer comparison node.
@@ -40,7 +40,11 @@
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
-    public IntegerLessThanNode(ValueNode x, ValueNode y) {
+    public static IntegerLessThanNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new IntegerLessThanNodeGen(x, y) : new IntegerLessThanNode(x, y);
+    }
+
+    protected IntegerLessThanNode(ValueNode x, ValueNode y) {
         super(x, y);
         assert !x.getKind().isNumericFloat() && x.getKind() != Kind.Object;
         assert !y.getKind().isNumericFloat() && y.getKind() != Kind.Object;
@@ -64,9 +68,9 @@
             ValueNode b = mirrored ? normalizeNode.getX() : normalizeNode.getY();
 
             if (normalizeNode.getX().getKind() == Kind.Double || normalizeNode.getX().getKind() == Kind.Float) {
-                return new FloatLessThanNode(a, b, mirrored ^ normalizeNode.isUnorderedLess);
+                return FloatLessThanNode.create(a, b, mirrored ^ normalizeNode.isUnorderedLess);
             } else {
-                return new IntegerLessThanNode(a, b);
+                return IntegerLessThanNode.create(a, b);
             }
         }
         return this;
@@ -91,7 +95,7 @@
         }
         if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) {
             if (IntegerStamp.sameSign((IntegerStamp) forX.stamp(), (IntegerStamp) forY.stamp())) {
-                return new IntegerBelowNode(forX, forY);
+                return IntegerBelowNode.create(forX, forY);
             }
         }
         return this;
@@ -100,9 +104,9 @@
     @Override
     protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) {
         if (newX.stamp() instanceof FloatStamp && newY.stamp() instanceof FloatStamp) {
-            return new FloatLessThanNode(newX, newY, true);
+            return FloatLessThanNode.create(newX, newY, true);
         } else if (newX.stamp() instanceof IntegerStamp && newY.stamp() instanceof IntegerStamp) {
-            return new IntegerLessThanNode(newX, newY);
+            return IntegerLessThanNode.create(newX, newY);
         }
         throw GraalInternalError.shouldNotReachHere();
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,16 +25,24 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "*")
 public class IntegerMulNode extends IntegerArithmeticNode implements NarrowableArithmeticNode {
 
-    public IntegerMulNode(ValueNode x, ValueNode y) {
+    public static IntegerMulNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new IntegerMulNodeGen(x, y) : new IntegerMulNode(x, y);
+    }
+
+    public static Class<? extends IntegerMulNode> getGenClass() {
+        return USE_GENERATED_NODES ? IntegerMulNodeGen.class : IntegerMulNode.class;
+    }
+
+    protected IntegerMulNode(ValueNode x, ValueNode y) {
         super(x.stamp().unrestricted(), x, y);
         assert x.stamp().isCompatible(y.stamp());
     }
@@ -48,7 +56,7 @@
     @Override
     public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
         if (forX.isConstant() && !forY.isConstant()) {
-            return new IntegerMulNode(forY, forX);
+            return IntegerMulNode.create(forY, forX);
         }
         if (forX.isConstant()) {
             return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant()));
@@ -62,9 +70,9 @@
             }
             long abs = Math.abs(c);
             if (abs > 0 && CodeUtil.isPowerOf2(abs)) {
-                LeftShiftNode shift = new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(abs)));
+                LeftShiftNode shift = LeftShiftNode.create(forX, ConstantNode.forInt(CodeUtil.log2(abs)));
                 if (c < 0) {
-                    return new NegateNode(shift);
+                    return NegateNode.create(shift);
                 } else {
                     return shift;
                 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,8 +24,8 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -33,7 +33,11 @@
 @NodeInfo(shortName = "%")
 public class IntegerRemNode extends FixedBinaryNode implements Lowerable, LIRLowerable {
 
-    public IntegerRemNode(ValueNode x, ValueNode y) {
+    public static IntegerRemNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new IntegerRemNodeGen(x, y) : new IntegerRemNode(x, y);
+    }
+
+    protected IntegerRemNode(ValueNode x, ValueNode y) {
         super(StampTool.rem(x.stamp(), y.stamp()), x, y);
     }
 
@@ -45,6 +49,7 @@
     @Override
     public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
         if (forX.isConstant() && forY.isConstant()) {
+            @SuppressWarnings("hiding")
             long y = forY.asConstant().asLong();
             if (y == 0) {
                 return this; // this will trap, can not canonicalize
@@ -55,7 +60,7 @@
             if (c == 1 || c == -1) {
                 return ConstantNode.forIntegerStamp(stamp(), 0);
             } else if (c > 0 && CodeUtil.isPowerOf2(c) && forX.stamp() instanceof IntegerStamp && ((IntegerStamp) forX.stamp()).isPositive()) {
-                return new AndNode(forX, ConstantNode.forIntegerStamp(stamp(), c - 1));
+                return AndNode.create(forX, ConstantNode.forIntegerStamp(stamp(), c - 1));
             }
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,9 +24,9 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -35,7 +35,15 @@
 @NodeInfo(shortName = "-")
 public class IntegerSubNode extends IntegerArithmeticNode implements NarrowableArithmeticNode {
 
-    public IntegerSubNode(ValueNode x, ValueNode y) {
+    public static IntegerSubNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new IntegerSubNodeGen(x, y) : new IntegerSubNode(x, y);
+    }
+
+    public static Class<? extends IntegerSubNode> getGenClass() {
+        return USE_GENERATED_NODES ? IntegerSubNodeGen.class : IntegerSubNode.class;
+    }
+
+    protected IntegerSubNode(ValueNode x, ValueNode y) {
         super(StampTool.sub(x.stamp(), y.stamp()), x, y);
     }
 
@@ -50,6 +58,7 @@
         return Constant.forPrimitiveInt(PrimitiveStamp.getBits(stamp()), inputs[0].asLong() - inputs[1].asLong());
     }
 
+    @SuppressWarnings("hiding")
     @Override
     public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
         if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
@@ -69,18 +78,18 @@
             IntegerSubNode x = (IntegerSubNode) forX;
             if (x.getX() == forY) {
                 // (a - b) - a
-                return new NegateNode(x.getY());
+                return NegateNode.create(x.getY());
             }
         }
         if (forY instanceof IntegerAddNode) {
             IntegerAddNode y = (IntegerAddNode) forY;
             if (y.getX() == forX) {
                 // a - (a + b)
-                return new NegateNode(y.getY());
+                return NegateNode.create(y.getY());
             }
             if (y.getY() == forX) {
                 // b - (a + b)
-                return new NegateNode(y.getX());
+                return NegateNode.create(y.getX());
             }
         } else if (forY instanceof IntegerSubNode) {
             IntegerSubNode y = (IntegerSubNode) forY;
@@ -108,7 +117,7 @@
         } else if (forX.isConstant()) {
             long c = forX.asConstant().asLong();
             if (c == 0) {
-                return new NegateNode(forY);
+                return NegateNode.create(forY);
             }
             return BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
 /**
@@ -31,6 +32,7 @@
  * expression "(x &amp; y) == 0", meaning that it will return true if (and only if) no bit is set in
  * both x and y.
  */
+@NodeInfo
 public class IntegerTestNode extends BinaryOpLogicNode {
 
     /**
@@ -39,7 +41,11 @@
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
-    public IntegerTestNode(ValueNode x, ValueNode y) {
+    public static IntegerTestNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new IntegerTestNodeGen(x, y) : new IntegerTestNode(x, y);
+    }
+
+    protected IntegerTestNode(ValueNode x, ValueNode y) {
         super(x, y);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -32,14 +33,19 @@
 /**
  * An IsNullNode will be true if the supplied value is null, and false if it is non-null.
  */
-public final class IsNullNode extends UnaryOpLogicNode implements LIRLowerable, Virtualizable, PiPushable {
+@NodeInfo
+public class IsNullNode extends UnaryOpLogicNode implements LIRLowerable, Virtualizable, PiPushable {
 
     /**
      * Constructs a new IsNullNode instruction.
      *
      * @param object the instruction producing the object to check against null
      */
-    public IsNullNode(ValueNode object) {
+    public static IsNullNode create(ValueNode object) {
+        return USE_GENERATED_NODES ? new IsNullNodeGen(object) : new IsNullNode(object);
+    }
+
+    protected IsNullNode(ValueNode object) {
         super(object);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,17 +23,21 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "<<")
-public final class LeftShiftNode extends ShiftNode {
+public class LeftShiftNode extends ShiftNode {
 
-    public LeftShiftNode(ValueNode x, ValueNode y) {
+    public static LeftShiftNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new LeftShiftNodeGen(x, y) : new LeftShiftNode(x, y);
+    }
+
+    protected LeftShiftNode(ValueNode x, ValueNode y) {
         super(x, y);
     }
 
@@ -74,19 +78,19 @@
                         if (total != (total & mask)) {
                             return ConstantNode.forIntegerKind(getKind(), 0);
                         }
-                        return new LeftShiftNode(other.getX(), ConstantNode.forInt(total));
+                        return LeftShiftNode.create(other.getX(), ConstantNode.forInt(total));
                     } else if ((other instanceof RightShiftNode || other instanceof UnsignedRightShiftNode) && otherAmount == amount) {
                         if (getKind() == Kind.Long) {
-                            return new AndNode(other.getX(), ConstantNode.forLong(-1L << amount));
+                            return AndNode.create(other.getX(), ConstantNode.forLong(-1L << amount));
                         } else {
                             assert getKind() == Kind.Int;
-                            return new AndNode(other.getX(), ConstantNode.forInt(-1 << amount));
+                            return AndNode.create(other.getX(), ConstantNode.forInt(-1 << amount));
                         }
                     }
                 }
             }
             if (originalAmout != amount) {
-                return new LeftShiftNode(forX, ConstantNode.forInt(amount));
+                return LeftShiftNode.create(forX, ConstantNode.forInt(amount));
             }
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -33,9 +34,14 @@
 /**
  * The {@code NarrowNode} converts an integer to a narrower integer.
  */
+@NodeInfo
 public class NarrowNode extends IntegerConvertNode {
 
-    public NarrowNode(ValueNode input, int resultBits) {
+    public static NarrowNode create(ValueNode input, int resultBits) {
+        return USE_GENERATED_NODES ? new NarrowNodeGen(input, resultBits) : new NarrowNode(input, resultBits);
+    }
+
+    protected NarrowNode(ValueNode input, int resultBits) {
         super(StampTool.narrowingConversion(input.stamp(), resultBits), input, resultBits);
     }
 
@@ -71,7 +77,7 @@
             // zzzzzzzz yyyyxxxx -(narrow)-> yyyyxxxx -(narrow)-> xxxx
             // ==> zzzzzzzz yyyyxxxx -(narrow)-> xxxx
             NarrowNode other = (NarrowNode) forValue;
-            return new NarrowNode(other.getValue(), getResultBits());
+            return NarrowNode.create(other.getValue(), getResultBits());
         } else if (forValue instanceof IntegerConvertNode) {
             // SignExtendNode or ZeroExtendNode
             IntegerConvertNode other = (IntegerConvertNode) forValue;
@@ -82,16 +88,16 @@
             } else if (getResultBits() < other.getInputBits()) {
                 // yyyyxxxx -(extend)-> zzzzzzzz yyyyxxxx -(narrow)-> xxxx
                 // ==> yyyyxxxx -(narrow)-> xxxx
-                return new NarrowNode(other.getValue(), getResultBits());
+                return NarrowNode.create(other.getValue(), getResultBits());
             } else {
                 if (other instanceof SignExtendNode) {
                     // sxxx -(sign-extend)-> ssssssss sssssxxx -(narrow)-> sssssxxx
                     // ==> sxxx -(sign-extend)-> sssssxxx
-                    return new SignExtendNode(other.getValue(), getResultBits());
+                    return SignExtendNode.create(other.getValue(), getResultBits());
                 } else if (other instanceof ZeroExtendNode) {
                     // xxxx -(zero-extend)-> 00000000 00000xxx -(narrow)-> 0000xxxx
                     // ==> xxxx -(zero-extend)-> 0000xxxx
-                    return new ZeroExtendNode(other.getValue(), getResultBits());
+                    return ZeroExtendNode.create(other.getValue(), getResultBits());
                 }
             }
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -33,7 +34,8 @@
 /**
  * The {@code NegateNode} node negates its operand.
  */
-public final class NegateNode extends UnaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode {
+@NodeInfo
+public class NegateNode extends UnaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode {
 
     @Override
     public boolean inferStamp() {
@@ -45,7 +47,11 @@
      *
      * @param value the instruction producing the value that is input to this instruction
      */
-    public NegateNode(ValueNode value) {
+    public static NegateNode create(ValueNode value) {
+        return USE_GENERATED_NODES ? new NegateNodeGen(value) : new NegateNode(value);
+    }
+
+    protected NegateNode(ValueNode value) {
         super(StampTool.negate(value.stamp()), value);
     }
 
@@ -76,7 +82,7 @@
         }
         if (forValue instanceof IntegerSubNode) {
             IntegerSubNode sub = (IntegerSubNode) forValue;
-            return new IntegerSubNode(sub.getY(), sub.getX());
+            return IntegerSubNode.create(sub.getY(), sub.getX());
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -33,7 +34,8 @@
  * of the inputs is NaN), the result is 1 if isUnorderedLess is false and -1 if isUnorderedLess is
  * true.
  */
-public final class NormalizeCompareNode extends BinaryNode implements Lowerable {
+@NodeInfo
+public class NormalizeCompareNode extends BinaryNode implements Lowerable {
 
     public final boolean isUnorderedLess;
 
@@ -45,7 +47,11 @@
      * @param isUnorderedLess true when an unordered floating point comparison is interpreted as
      *            less, false when greater.
      */
-    public NormalizeCompareNode(ValueNode x, ValueNode y, boolean isUnorderedLess) {
+    public static NormalizeCompareNode create(ValueNode x, ValueNode y, boolean isUnorderedLess) {
+        return USE_GENERATED_NODES ? new NormalizeCompareNodeGen(x, y, isUnorderedLess) : new NormalizeCompareNode(x, y, isUnorderedLess);
+    }
+
+    protected NormalizeCompareNode(ValueNode x, ValueNode y, boolean isUnorderedLess) {
         super(StampFactory.forKind(Kind.Int), x, y);
         this.isUnorderedLess = isUnorderedLess;
     }
@@ -61,15 +67,15 @@
         LogicNode equalComp;
         LogicNode lessComp;
         if (getX().stamp() instanceof FloatStamp) {
-            equalComp = graph().unique(new FloatEqualsNode(getX(), getY()));
-            lessComp = graph().unique(new FloatLessThanNode(getX(), getY(), isUnorderedLess));
+            equalComp = graph().unique(FloatEqualsNode.create(getX(), getY()));
+            lessComp = graph().unique(FloatLessThanNode.create(getX(), getY(), isUnorderedLess));
         } else {
-            equalComp = graph().unique(new IntegerEqualsNode(getX(), getY()));
-            lessComp = graph().unique(new IntegerLessThanNode(getX(), getY()));
+            equalComp = graph().unique(IntegerEqualsNode.create(getX(), getY()));
+            lessComp = graph().unique(IntegerLessThanNode.create(getX(), getY()));
         }
 
-        ConditionalNode equalValue = graph().unique(new ConditionalNode(equalComp, ConstantNode.forInt(0, graph()), ConstantNode.forInt(1, graph())));
-        ConditionalNode value = graph().unique(new ConditionalNode(lessComp, ConstantNode.forInt(-1, graph()), equalValue));
+        ConditionalNode equalValue = graph().unique(ConditionalNode.create(equalComp, ConstantNode.forInt(0, graph()), ConstantNode.forInt(1, graph())));
+        ConditionalNode value = graph().unique(ConditionalNode.create(lessComp, ConstantNode.forInt(-1, graph()), equalValue));
 
         graph().replaceFloating(this, value);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -33,7 +34,8 @@
 /**
  * Binary negation of long or integer values.
  */
-public final class NotNode extends UnaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode {
+@NodeInfo
+public class NotNode extends UnaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode {
 
     @Override
     public boolean inferStamp() {
@@ -51,7 +53,11 @@
      *
      * @param x the instruction producing the value that is input to this instruction
      */
-    public NotNode(ValueNode x) {
+    public static NotNode create(ValueNode x) {
+        return USE_GENERATED_NODES ? new NotNodeGen(x) : new NotNode(x);
+    }
+
+    protected NotNode(ValueNode x) {
         super(StampTool.not(x.stamp()), x);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,15 +24,15 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.calc.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "==")
-public final class ObjectEqualsNode extends CompareNode implements Virtualizable {
+public class ObjectEqualsNode extends CompareNode implements Virtualizable {
 
     /**
      * Constructs a new object equality comparison node.
@@ -40,7 +40,11 @@
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
-    public ObjectEqualsNode(ValueNode x, ValueNode y) {
+    public static ObjectEqualsNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new ObjectEqualsNodeGen(x, y) : new ObjectEqualsNode(x, y);
+    }
+
+    protected ObjectEqualsNode(ValueNode x, ValueNode y) {
         super(x, y);
         assert x.getKind() == Kind.Object;
         assert y.getKind() == Kind.Object;
@@ -68,9 +72,9 @@
             return LogicConstantNode.contradiction();
         }
         if (StampTool.isObjectAlwaysNull(forX)) {
-            return new IsNullNode(forY);
+            return IsNullNode.create(forY);
         } else if (StampTool.isObjectAlwaysNull(forY)) {
-            return new IsNullNode(forX);
+            return IsNullNode.create(forX);
         }
         return this;
     }
@@ -81,7 +85,7 @@
                 Constant otherUnboxed = tool.getConstantReflectionProvider().unboxPrimitive(other.asConstant());
                 if (otherUnboxed != null && otherUnboxed.getKind() == Kind.Boolean) {
                     int expectedValue = otherUnboxed.asBoolean() ? 1 : 0;
-                    IntegerEqualsNode equals = new IntegerEqualsNode(state.getEntry(0), ConstantNode.forInt(expectedValue, graph()));
+                    IntegerEqualsNode equals = IntegerEqualsNode.create(state.getEntry(0), ConstantNode.forInt(expectedValue, graph()));
                     tool.addNode(equals);
                     tool.replaceWithValue(equals);
                 } else {
@@ -122,7 +126,7 @@
                 assert stateX.getVirtualObject().entryCount() == 1 && stateY.getVirtualObject().entryCount() == 1;
                 assert stateX.getVirtualObject().type().equals(stateY.getVirtualObject().type());
                 assert stateX.getVirtualObject().entryKind(0).getStackKind() == Kind.Int || stateX.getVirtualObject().entryKind(0) == Kind.Long;
-                IntegerEqualsNode equals = new IntegerEqualsNode(stateX.getEntry(0), stateY.getEntry(0));
+                IntegerEqualsNode equals = IntegerEqualsNode.create(stateX.getEntry(0), stateY.getEntry(0));
                 tool.addNode(equals);
                 tool.replaceWithValue(equals);
             } else {
@@ -134,6 +138,6 @@
 
     @Override
     protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) {
-        return new ObjectEqualsNode(newX, newY);
+        return ObjectEqualsNode.create(newX, newY);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,18 +24,26 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "|")
-public final class OrNode extends BitLogicNode {
+public class OrNode extends BitLogicNode {
+
+    public static OrNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new OrNodeGen(x, y) : new OrNode(x, y);
+    }
 
-    public OrNode(ValueNode x, ValueNode y) {
+    public static Class<? extends OrNode> getGenClass() {
+        return USE_GENERATED_NODES ? OrNodeGen.class : OrNode.class;
+    }
+
+    OrNode(ValueNode x, ValueNode y) {
         super(StampTool.or(x.stamp(), y.stamp()), x, y);
         assert x.stamp().isCompatible(y.stamp());
     }
@@ -57,7 +65,7 @@
             return forX;
         }
         if (forX.isConstant() && !forY.isConstant()) {
-            return new OrNode(forY, forX);
+            return create(forY, forX);
         }
         if (forX.isConstant()) {
             return ConstantNode.forPrimitive(stamp(), evalConst(forX.asConstant(), forY.asConstant()));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,6 +27,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -35,13 +36,22 @@
  * of a primitive value to some other incompatible stamp. The new stamp must have the same width as
  * the old stamp.
  */
+@NodeInfo
 public class ReinterpretNode extends UnaryNode implements ArithmeticLIRLowerable {
 
-    private ReinterpretNode(Kind to, ValueNode value) {
+    public static ReinterpretNode create(Kind to, ValueNode value) {
+        return USE_GENERATED_NODES ? new ReinterpretNodeGen(to, value) : new ReinterpretNode(to, value);
+    }
+
+    ReinterpretNode(Kind to, ValueNode value) {
         this(StampFactory.forKind(to), value);
     }
 
-    public ReinterpretNode(Stamp to, ValueNode value) {
+    public static ReinterpretNode create(Stamp to, ValueNode value) {
+        return USE_GENERATED_NODES ? new ReinterpretNodeGen(to, value) : new ReinterpretNode(to, value);
+    }
+
+    protected ReinterpretNode(Stamp to, ValueNode value) {
         super(to, value);
         assert to instanceof PrimitiveStamp;
     }
@@ -89,7 +99,7 @@
         }
         if (forValue instanceof ReinterpretNode) {
             ReinterpretNode reinterpret = (ReinterpretNode) forValue;
-            return new ReinterpretNode(stamp(), reinterpret.getValue());
+            return ReinterpretNode.create(stamp(), reinterpret.getValue());
         }
         return this;
     }
@@ -101,7 +111,7 @@
     }
 
     public static ValueNode reinterpret(Kind toKind, ValueNode value) {
-        return value.graph().unique(new ReinterpretNode(toKind, value));
+        return value.graph().unique(ReinterpretNode.create(toKind, value));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,17 +24,21 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = ">>")
-public final class RightShiftNode extends ShiftNode {
+public class RightShiftNode extends ShiftNode {
 
-    public RightShiftNode(ValueNode x, ValueNode y) {
+    public static RightShiftNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new RightShiftNodeGen(x, y) : new RightShiftNode(x, y);
+    }
+
+    protected RightShiftNode(ValueNode x, ValueNode y) {
         super(x, y);
     }
 
@@ -57,7 +61,7 @@
     @Override
     public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
         if (forX.stamp() instanceof IntegerStamp && ((IntegerStamp) forX.stamp()).isPositive()) {
-            return new UnsignedRightShiftNode(forX, forY);
+            return UnsignedRightShiftNode.create(forX, forY);
         }
         if (forX.isConstant() && forY.isConstant()) {
             return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant()));
@@ -91,14 +95,14 @@
                              * full shift for this kind
                              */
                             assert total >= mask;
-                            return new RightShiftNode(other.getX(), ConstantNode.forInt(mask));
+                            return RightShiftNode.create(other.getX(), ConstantNode.forInt(mask));
                         }
-                        return new RightShiftNode(other.getX(), ConstantNode.forInt(total));
+                        return RightShiftNode.create(other.getX(), ConstantNode.forInt(total));
                     }
                 }
             }
             if (originalAmout != amount) {
-                return new RightShiftNode(forX, ConstantNode.forInt(amount));
+                return RightShiftNode.create(forX, ConstantNode.forInt(amount));
             }
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,12 +23,14 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
  * The {@code ShiftOp} class represents shift operations.
  */
+@NodeInfo
 public abstract class ShiftNode extends BinaryNode implements ArithmeticLIRLowerable {
 
     /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -33,9 +34,14 @@
 /**
  * The {@code SignExtendNode} converts an integer to a wider integer using sign extension.
  */
+@NodeInfo
 public class SignExtendNode extends IntegerConvertNode {
 
-    public SignExtendNode(ValueNode input, int resultBits) {
+    public static SignExtendNode create(ValueNode input, int resultBits) {
+        return USE_GENERATED_NODES ? new SignExtendNodeGen(input, resultBits) : new SignExtendNode(input, resultBits);
+    }
+
+    protected SignExtendNode(ValueNode input, int resultBits) {
         super(StampTool.signExtend(input.stamp(), resultBits), input, resultBits);
     }
 
@@ -77,13 +83,13 @@
             // sxxx -(sign-extend)-> ssss sxxx -(sign-extend)-> ssssssss sssssxxx
             // ==> sxxx -(sign-extend)-> ssssssss sssssxxx
             SignExtendNode other = (SignExtendNode) forValue;
-            return new SignExtendNode(other.getValue(), getResultBits());
+            return SignExtendNode.create(other.getValue(), getResultBits());
         } else if (forValue instanceof ZeroExtendNode) {
             ZeroExtendNode other = (ZeroExtendNode) forValue;
             if (other.getResultBits() > other.getInputBits()) {
                 // sxxx -(zero-extend)-> 0000 sxxx -(sign-extend)-> 00000000 0000sxxx
                 // ==> sxxx -(zero-extend)-> 00000000 0000sxxx
-                return new ZeroExtendNode(other.getValue(), getResultBits());
+                return ZeroExtendNode.create(other.getValue(), getResultBits());
             }
         }
 
@@ -92,7 +98,7 @@
             if ((inputStamp.upMask() & (1L << (getInputBits() - 1))) == 0L) {
                 // 0xxx -(sign-extend)-> 0000 0xxx
                 // ==> 0xxx -(zero-extend)-> 0000 0xxx
-                return new ZeroExtendNode(forValue, getResultBits());
+                return ZeroExtendNode.create(forValue, getResultBits());
             }
         }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,15 +24,17 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
 /**
  * The {@code UnaryNode} class is the base of arithmetic and bit logic operations with exactly one
  * input.
  */
+@NodeInfo
 public abstract class UnaryNode extends FloatingNode implements Canonicalizable.Unary<ValueNode> {
 
-    @Input private ValueNode value;
+    @Input protected ValueNode value;
 
     public ValueNode getValue() {
         return value;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,15 +24,19 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "|/|")
 public class UnsignedDivNode extends FixedBinaryNode implements Lowerable, LIRLowerable {
 
-    public UnsignedDivNode(ValueNode x, ValueNode y) {
+    public static UnsignedDivNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new UnsignedDivNodeGen(x, y) : new UnsignedDivNode(x, y);
+    }
+
+    protected UnsignedDivNode(ValueNode x, ValueNode y) {
         super(x.stamp().unrestricted(), x, y);
     }
 
@@ -50,7 +54,7 @@
                 return forX;
             }
             if (CodeUtil.isPowerOf2(c)) {
-                return new UnsignedRightShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(c)));
+                return UnsignedRightShiftNode.create(forX, ConstantNode.forInt(CodeUtil.log2(c)));
             }
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,15 +24,19 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "|%|")
 public class UnsignedRemNode extends FixedBinaryNode implements Lowerable, LIRLowerable {
 
-    public UnsignedRemNode(ValueNode x, ValueNode y) {
+    public static UnsignedRemNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new UnsignedRemNodeGen(x, y) : new UnsignedRemNode(x, y);
+    }
+
+    protected UnsignedRemNode(ValueNode x, ValueNode y) {
         super(x.stamp().unrestricted(), x, y);
     }
 
@@ -49,7 +53,7 @@
             if (c == 1) {
                 return ConstantNode.forIntegerStamp(stamp(), 0);
             } else if (CodeUtil.isPowerOf2(c)) {
-                return new AndNode(forX, ConstantNode.forIntegerStamp(stamp(), c - 1));
+                return AndNode.create(forX, ConstantNode.forIntegerStamp(stamp(), c - 1));
             }
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,17 +23,21 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = ">>>")
-public final class UnsignedRightShiftNode extends ShiftNode {
+public class UnsignedRightShiftNode extends ShiftNode {
 
-    public UnsignedRightShiftNode(ValueNode x, ValueNode y) {
+    public static UnsignedRightShiftNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new UnsignedRightShiftNodeGen(x, y) : new UnsignedRightShiftNode(x, y);
+    }
+
+    protected UnsignedRightShiftNode(ValueNode x, ValueNode y) {
         super(x, y);
     }
 
@@ -74,19 +78,19 @@
                         if (total != (total & mask)) {
                             return ConstantNode.forIntegerKind(getKind(), 0);
                         }
-                        return new UnsignedRightShiftNode(other.getX(), ConstantNode.forInt(total));
+                        return UnsignedRightShiftNode.create(other.getX(), ConstantNode.forInt(total));
                     } else if (other instanceof LeftShiftNode && otherAmount == amount) {
                         if (getKind() == Kind.Long) {
-                            return new AndNode(other.getX(), ConstantNode.forLong(-1L >>> amount));
+                            return AndNode.create(other.getX(), ConstantNode.forLong(-1L >>> amount));
                         } else {
                             assert getKind() == Kind.Int;
-                            return new AndNode(other.getX(), ConstantNode.forInt(-1 >>> amount));
+                            return AndNode.create(other.getX(), ConstantNode.forInt(-1 >>> amount));
                         }
                     }
                 }
             }
             if (originalAmout != amount) {
-                return new UnsignedRightShiftNode(forX, ConstantNode.forInt(amount));
+                return UnsignedRightShiftNode.create(forX, ConstantNode.forInt(amount));
             }
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,18 +24,26 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "^")
-public final class XorNode extends BitLogicNode {
+public class XorNode extends BitLogicNode {
+
+    public static XorNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new XorNodeGen(x, y) : new XorNode(x, y);
+    }
 
-    public XorNode(ValueNode x, ValueNode y) {
+    public static Class<? extends XorNode> getGenClass() {
+        return USE_GENERATED_NODES ? XorNodeGen.class : XorNode.class;
+    }
+
+    protected XorNode(ValueNode x, ValueNode y) {
         super(StampTool.xor(x.stamp(), y.stamp()), x, y);
         assert x.stamp().isCompatible(y.stamp());
     }
@@ -57,7 +65,7 @@
             return ConstantNode.forIntegerStamp(stamp(), 0);
         }
         if (forX.isConstant() && !forY.isConstant()) {
-            return new XorNode(forY, forX);
+            return XorNode.create(forY, forX);
         }
         if (forX.isConstant()) {
             return ConstantNode.forPrimitive(stamp(), evalConst(forX.asConstant(), forY.asConstant()));
@@ -67,7 +75,7 @@
             if ((rawY & mask) == 0) {
                 return forX;
             } else if ((rawY & mask) == mask) {
-                return new NotNode(forX);
+                return NotNode.create(forX);
             }
             return BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,6 +27,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -34,9 +35,14 @@
 /**
  * The {@code ZeroExtendNode} converts an integer to a wider integer using zero extension.
  */
+@NodeInfo
 public class ZeroExtendNode extends IntegerConvertNode {
 
-    public ZeroExtendNode(ValueNode input, int resultBits) {
+    public static ZeroExtendNode create(ValueNode input, int resultBits) {
+        return USE_GENERATED_NODES ? new ZeroExtendNodeGen(input, resultBits) : new ZeroExtendNode(input, resultBits);
+    }
+
+    protected ZeroExtendNode(ValueNode input, int resultBits) {
         super(StampTool.zeroExtend(input.stamp(), resultBits), input, resultBits);
     }
 
@@ -87,7 +93,7 @@
             // xxxx -(zero-extend)-> 0000 xxxx -(zero-extend)-> 00000000 0000xxxx
             // ==> xxxx -(zero-extend)-> 00000000 0000xxxx
             ZeroExtendNode other = (ZeroExtendNode) forValue;
-            return new ZeroExtendNode(other.getValue(), getResultBits());
+            return ZeroExtendNode.create(other.getValue(), getResultBits());
         }
         if (forValue instanceof NarrowNode) {
             NarrowNode narrow = (NarrowNode) forValue;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.debug;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -34,15 +35,20 @@
  * A unique counter will be created for each unique name passed to the constructor. Depending on the
  * value of withContext, the name of the root method is added to the counter's name.
  */
+@NodeInfo
 public class DynamicCounterNode extends FixedWithNextNode implements Lowerable {
 
-    @Input private ValueNode increment;
+    @Input ValueNode increment;
 
     private final String name;
     private final String group;
     private final boolean withContext;
 
-    public DynamicCounterNode(String name, String group, ValueNode increment, boolean withContext) {
+    public static DynamicCounterNode create(String name, String group, ValueNode increment, boolean withContext) {
+        return USE_GENERATED_NODES ? new DynamicCounterNodeGen(name, group, increment, withContext) : new DynamicCounterNode(name, group, increment, withContext);
+    }
+
+    DynamicCounterNode(String name, String group, ValueNode increment, boolean withContext) {
         super(StampFactory.forVoid());
         this.name = name;
         this.group = group;
@@ -73,7 +79,7 @@
 
     public static void addCounterBefore(String group, String name, long increment, boolean withContext, FixedNode position) {
         StructuredGraph graph = position.graph();
-        graph.addBeforeFixed(position, position.graph().add(new DynamicCounterNode(name, group, ConstantNode.forLong(increment, position.graph()), withContext)));
+        graph.addBeforeFixed(position, position.graph().add(DynamicCounterNode.create(name, group, ConstantNode.forLong(increment, position.graph()), withContext)));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/WeakCounterNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/WeakCounterNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.debug;
 
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -32,11 +33,16 @@
  * only usage of the associated node. This way it only increments the counter if the node is
  * actually executed.
  */
+@NodeInfo
 public class WeakCounterNode extends DynamicCounterNode implements Simplifiable, Virtualizable {
 
-    @Input private ValueNode checkedValue;
+    @Input ValueNode checkedValue;
 
-    public WeakCounterNode(String group, String name, ValueNode increment, boolean addContext, ValueNode checkedValue) {
+    public static WeakCounterNode create(String group, String name, ValueNode increment, boolean addContext, ValueNode checkedValue) {
+        return USE_GENERATED_NODES ? new WeakCounterNodeGen(group, name, increment, addContext, checkedValue) : new WeakCounterNode(group, name, increment, addContext, checkedValue);
+    }
+
+    WeakCounterNode(String group, String name, ValueNode increment, boolean addContext, ValueNode checkedValue) {
         super(group, name, increment, addContext);
         this.checkedValue = checkedValue;
     }
@@ -59,7 +65,7 @@
 
     public static void addCounterBefore(String group, String name, long increment, boolean addContext, ValueNode checkedValue, FixedNode position) {
         StructuredGraph graph = position.graph();
-        WeakCounterNode counter = graph.add(new WeakCounterNode(name, group, ConstantNode.forLong(increment, graph), addContext, checkedValue));
+        WeakCounterNode counter = graph.add(WeakCounterNode.create(name, group, ConstantNode.forLong(increment, graph), addContext, checkedValue));
         graph.addBeforeFixed(position, counter);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,14 +25,15 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
 public abstract class AbstractWriteNode extends FixedAccessNode implements StateSplit, MemoryCheckpoint.Single, MemoryAccess, GuardingNode {
 
-    @Input private ValueNode value;
-    @OptionalInput(InputType.State) private FrameState stateAfter;
-    @OptionalInput(InputType.Memory) private Node lastLocationAccess;
+    @Input ValueNode value;
+    @OptionalInput(InputType.State) FrameState stateAfter;
+    @OptionalInput(InputType.Memory) Node lastLocationAccess;
 
     private final boolean initialization;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,6 +27,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -37,10 +38,10 @@
  * [(base + x) + y] where base is a node and x and y are location nodes.
  */
 @NodeInfo(nameTemplate = "AddLoc {p#locationIdentity/s}")
-public final class AddLocationNode extends LocationNode implements Canonicalizable.Binary<LocationNode> {
+public class AddLocationNode extends LocationNode implements Canonicalizable.Binary<LocationNode> {
 
-    @Input(InputType.Association) private ValueNode x;
-    @Input(InputType.Association) private ValueNode y;
+    @Input(InputType.Association) ValueNode x;
+    @Input(InputType.Association) ValueNode y;
 
     public LocationNode getX() {
         return (LocationNode) x;
@@ -52,10 +53,14 @@
 
     public static AddLocationNode create(LocationNode x, LocationNode y, Graph graph) {
         assert x.getValueKind().equals(y.getValueKind()) && x.getLocationIdentity() == y.getLocationIdentity();
-        return graph.unique(new AddLocationNode(x, y));
+        return graph.unique(AddLocationNode.create(x, y));
     }
 
-    private AddLocationNode(ValueNode x, ValueNode y) {
+    public static AddLocationNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new AddLocationNodeGen(x, y) : new AddLocationNode(x, y);
+    }
+
+    AddLocationNode(ValueNode x, ValueNode y) {
         super(StampFactory.forVoid());
         this.x = x;
         this.y = y;
@@ -101,7 +106,7 @@
             AddLocationNode otherAdd = (AddLocationNode) other;
             LocationNode newInner = otherAdd.canonical(constant, otherAdd.getX());
             if (newInner != otherAdd) {
-                return new AddLocationNode(newInner, otherAdd.getY());
+                return AddLocationNode.create(newInner, otherAdd.getY());
             }
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,11 +23,13 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
 /**
  * Base class for nodes that modify a range of an array.
  */
+@NodeInfo
 public abstract class ArrayRangeWriteNode extends AbstractMemoryCheckpoint {
 
     protected ArrayRangeWriteNode(Stamp stamp) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,6 +27,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
@@ -38,11 +39,16 @@
  * This node represents the boxing of a primitive value. This corresponds to a call to the valueOf
  * methods in Integer, Long, etc.
  */
+@NodeInfo
 public class BoxNode extends UnaryNode implements VirtualizableAllocation, Lowerable {
 
     private final Kind boxingKind;
 
-    public BoxNode(ValueNode value, ResolvedJavaType resultType, Kind boxingKind) {
+    public static BoxNode create(ValueNode value, ResolvedJavaType resultType, Kind boxingKind) {
+        return USE_GENERATED_NODES ? new BoxNodeGen(value, resultType, boxingKind) : new BoxNode(value, resultType, boxingKind);
+    }
+
+    BoxNode(ValueNode value, ResolvedJavaType resultType, Kind boxingKind) {
         super(StampFactory.exactNonNull(resultType), value);
         this.boxingKind = boxingKind;
     }
@@ -70,7 +76,7 @@
         ValueNode v = tool.getReplacedValue(getValue());
         ResolvedJavaType type = StampTool.typeOrNull(stamp());
 
-        VirtualBoxingNode newVirtual = new VirtualBoxingNode(type, boxingKind);
+        VirtualBoxingNode newVirtual = VirtualBoxingNode.create(type, boxingKind);
         assert newVirtual.getFields().length == 1;
 
         tool.createVirtualObject(newVirtual, new ValueNode[]{v}, Collections.<MonitorIdNode> emptyList());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -34,6 +35,7 @@
  * the if node's taken probability. Then the branch probability node will be removed. This node is
  * intended primarily for snippets, so that they can define their fast and slow paths.
  */
+@NodeInfo
 public class BranchProbabilityNode extends FloatingNode implements Simplifiable, Lowerable {
 
     public static final double LIKELY_PROBABILITY = 0.6;
@@ -48,10 +50,14 @@
     public static final double VERY_FAST_PATH_PROBABILITY = 0.999;
     public static final double VERY_SLOW_PATH_PROBABILITY = 1 - VERY_FAST_PATH_PROBABILITY;
 
-    @Input private ValueNode probability;
-    @Input private ValueNode condition;
+    @Input ValueNode probability;
+    @Input ValueNode condition;
 
-    public BranchProbabilityNode(ValueNode probability, ValueNode condition) {
+    public static BranchProbabilityNode create(ValueNode probability, ValueNode condition) {
+        return USE_GENERATED_NODES ? new BranchProbabilityNodeGen(probability, condition) : new BranchProbabilityNode(probability, condition);
+    }
+
+    BranchProbabilityNode(ValueNode probability, ValueNode condition) {
         super(condition.stamp());
         this.probability = probability;
         this.condition = condition;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BytecodeExceptionNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BytecodeExceptionNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -32,12 +33,17 @@
  * A node that represents an exception thrown implicitly by a Java bytecode. It can be lowered to
  * either a {@linkplain ForeignCallDescriptor foreign} call or a pre-allocated exception object.
  */
+@NodeInfo
 public class BytecodeExceptionNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
 
     private final Class<? extends Throwable> exceptionClass;
-    @Input private final NodeInputList<ValueNode> arguments;
+    @Input NodeInputList<ValueNode> arguments;
 
-    public BytecodeExceptionNode(MetaAccessProvider metaAccess, Class<? extends Throwable> exceptionClass, ValueNode... arguments) {
+    public static BytecodeExceptionNode create(MetaAccessProvider metaAccess, Class<? extends Throwable> exceptionClass, ValueNode... arguments) {
+        return USE_GENERATED_NODES ? new BytecodeExceptionNodeGen(metaAccess, exceptionClass, arguments) : new BytecodeExceptionNode(metaAccess, exceptionClass, arguments);
+    }
+
+    BytecodeExceptionNode(MetaAccessProvider metaAccess, Class<? extends Throwable> exceptionClass, ValueNode... arguments) {
         super(StampFactory.exactNonNull(metaAccess.lookupJavaType(exceptionClass)));
         this.exceptionClass = exceptionClass;
         this.arguments = new NodeInputList<>(this, arguments);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,15 +24,16 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public class ComputeAddressNode extends FloatingNode implements LIRLowerable {
 
-    @Input private ValueNode object;
-    @Input(InputType.Association) private ValueNode location;
+    @Input ValueNode object;
+    @Input(InputType.Association) ValueNode location;
 
     public ValueNode getObject() {
         return object;
@@ -42,7 +43,11 @@
         return (LocationNode) location;
     }
 
-    public ComputeAddressNode(ValueNode object, ValueNode location, Stamp stamp) {
+    public static ComputeAddressNode create(ValueNode object, ValueNode location, Stamp stamp) {
+        return USE_GENERATED_NODES ? new ComputeAddressNodeGen(object, location, stamp) : new ComputeAddressNode(object, location, stamp);
+    }
+
+    ComputeAddressNode(ValueNode object, ValueNode location, Stamp stamp) {
         super(stamp);
         this.object = object;
         this.location = location;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
@@ -33,21 +34,21 @@
  * where base is a node and disp is a constant.
  */
 @NodeInfo(nameTemplate = "Loc {p#locationIdentity/s}")
-public final class ConstantLocationNode extends LocationNode {
+public class ConstantLocationNode extends LocationNode {
 
     private final Kind valueKind;
     private final LocationIdentity locationIdentity;
     private final long displacement;
 
     public static ConstantLocationNode create(LocationIdentity identity, Kind kind, long displacement, Graph graph) {
-        return graph.unique(new ConstantLocationNode(identity, kind, displacement));
+        return graph.unique(ConstantLocationNode.create(identity, kind, displacement));
     }
 
     public static ConstantLocationNode create(LocationIdentity identity, Kind kind, long displacement) {
-        return new ConstantLocationNode(identity, kind, displacement);
+        return USE_GENERATED_NODES ? new ConstantLocationNodeGen(identity, kind, displacement) : new ConstantLocationNode(identity, kind, displacement);
     }
 
-    private ConstantLocationNode(LocationIdentity identity, Kind kind, long displacement) {
+    ConstantLocationNode(LocationIdentity identity, Kind kind, long displacement) {
         super(StampFactory.forVoid());
         assert kind != Kind.Illegal && kind != Kind.Void;
         this.valueKind = kind;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedAccessNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedAccessNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,18 +23,19 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
 /**
  * Accesses a value at an memory address specified by an {@linkplain #object object} and a
  * {@linkplain #accessLocation() location}. The access does not include a null check on the object.
  */
+@NodeInfo
 public abstract class FixedAccessNode extends DeoptimizingFixedWithNextNode implements Access {
 
-    @OptionalInput(InputType.Guard) private GuardingNode guard;
-    @Input private ValueNode object;
-    @Input(InputType.Association) private ValueNode location;
+    @OptionalInput(InputType.Guard) protected GuardingNode guard;
+    @Input protected ValueNode object;
+    @Input(InputType.Association) protected ValueNode location;
     private boolean nullCheck;
     private BarrierType barrierType;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,18 +23,24 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
-public final class FixedValueAnchorNode extends FixedWithNextNode implements LIRLowerable, ValueProxy {
+@NodeInfo
+public class FixedValueAnchorNode extends FixedWithNextNode implements LIRLowerable, ValueProxy {
 
-    @Input private ValueNode object;
+    @Input ValueNode object;
 
     public ValueNode object() {
         return object;
     }
 
-    public FixedValueAnchorNode(ValueNode object) {
+    public static FixedValueAnchorNode create(ValueNode object) {
+        return USE_GENERATED_NODES ? new FixedValueAnchorNodeGen(object) : new FixedValueAnchorNode(object);
+    }
+
+    FixedValueAnchorNode(ValueNode object) {
         super(StampFactory.forNodeIntrinsic());
         this.object = object;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,11 +24,13 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
 /**
  * An {@link FixedAccessNode} that can be converted to a {@link FloatingAccessNode}.
  */
+@NodeInfo
 public abstract class FloatableAccessNode extends FixedAccessNode {
 
     public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,13 +24,14 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
+@NodeInfo
 public abstract class FloatingAccessNode extends FloatingGuardedNode implements Access, MemoryAccess {
 
-    @Input private ValueNode object;
-    @Input(InputType.Association) private LocationNode location;
+    @Input ValueNode object;
+    @Input(InputType.Association) LocationNode location;
     private BarrierType barrierType;
 
     public ValueNode object() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -33,19 +34,33 @@
  * 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 IterableNodeType, LIRLowerable, Canonicalizable {
+@NodeInfo
+public class FloatingReadNode extends FloatingAccessNode implements IterableNodeType, LIRLowerable, Canonicalizable {
+
+    @OptionalInput(InputType.Memory) MemoryNode lastLocationAccess;
 
-    @OptionalInput(InputType.Memory) private MemoryNode lastLocationAccess;
+    public static FloatingReadNode create(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp) {
+        return USE_GENERATED_NODES ? new FloatingReadNodeGen(object, location, lastLocationAccess, stamp) : new FloatingReadNode(object, location, lastLocationAccess, stamp);
+    }
 
-    public FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp) {
+    FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp) {
         this(object, location, lastLocationAccess, stamp, null, BarrierType.NONE);
     }
 
-    public FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard) {
+    public static FloatingReadNode create(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard) {
+        return USE_GENERATED_NODES ? new FloatingReadNodeGen(object, location, lastLocationAccess, stamp, guard) : new FloatingReadNode(object, location, lastLocationAccess, stamp, guard);
+    }
+
+    FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard) {
         this(object, location, lastLocationAccess, stamp, guard, BarrierType.NONE);
     }
 
-    public FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard, BarrierType barrierType) {
+    public static FloatingReadNode create(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard, BarrierType barrierType) {
+        return USE_GENERATED_NODES ? new FloatingReadNodeGen(object, location, lastLocationAccess, stamp, guard, barrierType) : new FloatingReadNode(object, location, lastLocationAccess, stamp,
+                        guard, barrierType);
+    }
+
+    FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard, BarrierType barrierType) {
         super(object, location, stamp, guard, barrierType);
         this.lastLocationAccess = lastLocationAccess;
     }
@@ -69,14 +84,14 @@
     @Override
     public Node canonical(CanonicalizerTool tool) {
         if (object() instanceof PiNode && ((PiNode) object()).getGuard() == getGuard()) {
-            return new FloatingReadNode(((PiNode) object()).getOriginalNode(), location(), getLastLocationAccess(), stamp(), getGuard(), getBarrierType());
+            return FloatingReadNode.create(((PiNode) object()).getOriginalNode(), location(), getLastLocationAccess(), stamp(), getGuard(), getBarrierType());
         }
         return ReadNode.canonicalizeRead(this, location(), object(), tool);
     }
 
     @Override
     public FixedAccessNode asFixedNode() {
-        return graph().add(new ReadNode(object(), accessLocation(), stamp(), getGuard(), getBarrierType()));
+        return graph().add(ReadNode.create(object(), accessLocation(), stamp(), getGuard(), getBarrierType()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -28,6 +28,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -37,31 +38,47 @@
 @NodeInfo(nameTemplate = "ForeignCall#{p#descriptor/s}", allowedUsageTypes = {InputType.Memory})
 public class ForeignCallNode extends AbstractMemoryCheckpoint implements LIRLowerable, DeoptimizingNode.DeoptDuring, MemoryCheckpoint.Multi {
 
-    @Input private final NodeInputList<ValueNode> arguments;
-    @OptionalInput(InputType.State) private FrameState stateDuring;
+    @Input protected NodeInputList<ValueNode> arguments;
+    @OptionalInput(InputType.State) protected FrameState stateDuring;
     private final ForeignCallsProvider foreignCalls;
 
     private final ForeignCallDescriptor descriptor;
 
-    public ForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) {
+    public static ForeignCallNode create(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) {
+        return USE_GENERATED_NODES ? new ForeignCallNodeGen(foreignCalls, descriptor, arguments) : new ForeignCallNode(foreignCalls, descriptor, arguments);
+    }
+
+    ForeignCallNode(ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) {
         super(StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType())));
         this.arguments = new NodeInputList<>(this, arguments);
         this.descriptor = descriptor;
         this.foreignCalls = foreignCalls;
     }
 
-    public ForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, List<ValueNode> arguments) {
+    public static ForeignCallNode create(ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, List<ValueNode> arguments) {
+        return USE_GENERATED_NODES ? new ForeignCallNodeGen(foreignCalls, descriptor, arguments) : new ForeignCallNode(foreignCalls, descriptor, arguments);
+    }
+
+    ForeignCallNode(ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, List<ValueNode> arguments) {
         this(foreignCalls, descriptor, StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType())), arguments);
     }
 
-    public ForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp, List<ValueNode> arguments) {
+    public static ForeignCallNode create(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp, List<ValueNode> arguments) {
+        return USE_GENERATED_NODES ? new ForeignCallNodeGen(foreignCalls, descriptor, stamp, arguments) : new ForeignCallNode(foreignCalls, descriptor, stamp, arguments);
+    }
+
+    ForeignCallNode(ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp, List<ValueNode> arguments) {
         super(stamp);
         this.arguments = new NodeInputList<>(this, arguments);
         this.descriptor = descriptor;
         this.foreignCalls = foreignCalls;
     }
 
-    protected ForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp) {
+    public static ForeignCallNode create(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp) {
+        return USE_GENERATED_NODES ? new ForeignCallNodeGen(foreignCalls, descriptor, stamp) : new ForeignCallNode(foreignCalls, descriptor, stamp);
+    }
+
+    protected ForeignCallNode(ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp) {
         super(stamp);
         this.arguments = new NodeInputList<>(this);
         this.descriptor = descriptor;
@@ -112,12 +129,13 @@
     }
 
     @Override
-    public void computeStateDuring(FrameState stateAfter) {
+    public void computeStateDuring(FrameState currentStateAfter) {
         FrameState newStateDuring;
-        if ((stateAfter.stackSize() > 0 && stateAfter.stackAt(stateAfter.stackSize() - 1) == this) || (stateAfter.stackSize() > 1 && stateAfter.stackAt(stateAfter.stackSize() - 2) == this)) {
-            newStateDuring = stateAfter.duplicateModified(stateAfter.bci, stateAfter.rethrowException(), this.getKind());
+        if ((currentStateAfter.stackSize() > 0 && currentStateAfter.stackAt(currentStateAfter.stackSize() - 1) == this) ||
+                        (currentStateAfter.stackSize() > 1 && currentStateAfter.stackAt(currentStateAfter.stackSize() - 2) == this)) {
+            newStateDuring = currentStateAfter.duplicateModified(currentStateAfter.bci, currentStateAfter.rethrowException(), this.getKind());
         } else {
-            newStateDuring = stateAfter;
+            newStateDuring = currentStateAfter;
         }
         setStateDuring(newStateDuring);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -28,6 +28,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -38,12 +39,12 @@
  * constants.
  */
 @NodeInfo(nameTemplate = "IdxLoc {p#locationIdentity/s}")
-public final class IndexedLocationNode extends LocationNode implements Canonicalizable {
+public class IndexedLocationNode extends LocationNode implements Canonicalizable {
 
     private final Kind valueKind;
     private final LocationIdentity locationIdentity;
     private final long displacement;
-    @Input private ValueNode index;
+    @Input ValueNode index;
     private final int indexScaling;
 
     /**
@@ -65,14 +66,14 @@
     }
 
     public static IndexedLocationNode create(LocationIdentity identity, Kind kind, long displacement, ValueNode index, Graph graph, int indexScaling) {
-        return graph.unique(new IndexedLocationNode(identity, kind, displacement, index, indexScaling));
+        return graph.unique(IndexedLocationNode.create(identity, kind, displacement, index, indexScaling));
     }
 
     public static IndexedLocationNode create(LocationIdentity identity, Kind kind, long displacement, ValueNode index, int indexScaling) {
-        return new IndexedLocationNode(identity, kind, displacement, index, indexScaling);
+        return USE_GENERATED_NODES ? new IndexedLocationNodeGen(identity, kind, displacement, index, indexScaling) : new IndexedLocationNode(identity, kind, displacement, index, indexScaling);
     }
 
-    public IndexedLocationNode(LocationIdentity identity, Kind kind, long displacement, ValueNode index, int indexScaling) {
+    IndexedLocationNode(LocationIdentity identity, Kind kind, long displacement, ValueNode index, int indexScaling) {
         super(StampFactory.forVoid());
         assert index != null;
         assert indexScaling != 0;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,6 +27,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
@@ -35,7 +36,8 @@
  * The {@code IntegerSwitchNode} represents a switch on integer keys, with a sorted array of key
  * values. The actual implementation of the switch will be decided by the backend.
  */
-public final class IntegerSwitchNode extends SwitchNode implements LIRLowerable, Simplifiable {
+@NodeInfo
+public class IntegerSwitchNode extends SwitchNode implements LIRLowerable, Simplifiable {
 
     private final int[] keys;
 
@@ -49,7 +51,12 @@
      * @param keyProbabilities the probabilities of the keys
      * @param keySuccessors the successor index for each key
      */
-    public IntegerSwitchNode(ValueNode value, BeginNode[] successors, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
+    public static IntegerSwitchNode create(ValueNode value, BeginNode[] successors, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
+        return USE_GENERATED_NODES ? new IntegerSwitchNodeGen(value, successors, keys, keyProbabilities, keySuccessors) : new IntegerSwitchNode(value, successors, keys, keyProbabilities,
+                        keySuccessors);
+    }
+
+    IntegerSwitchNode(ValueNode value, BeginNode[] successors, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
         super(value, successors, keySuccessors, keyProbabilities);
         assert keySuccessors.length == keys.length + 1;
         assert keySuccessors.length == keyProbabilities.length;
@@ -75,7 +82,12 @@
      * @param keyProbabilities the probabilities of the keys
      * @param keySuccessors the successor index for each key
      */
-    public IntegerSwitchNode(ValueNode value, int successorCount, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
+    public static IntegerSwitchNode create(ValueNode value, int successorCount, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
+        return USE_GENERATED_NODES ? new IntegerSwitchNodeGen(value, successorCount, keys, keyProbabilities, keySuccessors) : new IntegerSwitchNode(value, successorCount, keys, keyProbabilities,
+                        keySuccessors);
+    }
+
+    IntegerSwitchNode(ValueNode value, int successorCount, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
         this(value, new BeginNode[successorCount], keys, keyProbabilities, keySuccessors);
     }
 
@@ -189,7 +201,7 @@
                     }
 
                     BeginNode[] successorsArray = newSuccessors.toArray(new BeginNode[newSuccessors.size()]);
-                    IntegerSwitchNode newSwitch = graph().add(new IntegerSwitchNode(value(), successorsArray, newKeys, newKeyProbabilities, newKeySuccessors));
+                    IntegerSwitchNode newSwitch = graph().add(IntegerSwitchNode.create(value(), successorsArray, newKeys, newKeyProbabilities, newKeySuccessors));
                     ((FixedWithNextNode) predecessor()).setNext(newSwitch);
                     GraphUtil.killWithUnusedFloatingInputs(this);
                 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -30,11 +31,16 @@
  * Read a raw memory location according to Java field or array read semantics. It will perform read
  * barriers, implicit conversions and optionally oop uncompression.
  */
-public final class JavaReadNode extends FixedAccessNode implements Lowerable, GuardingNode {
+@NodeInfo
+public class JavaReadNode extends FixedAccessNode implements Lowerable, GuardingNode {
 
     private final boolean compressible;
 
-    public JavaReadNode(ValueNode object, LocationNode location, BarrierType barrierType, boolean compressible) {
+    public static JavaReadNode create(ValueNode object, LocationNode location, BarrierType barrierType, boolean compressible) {
+        return USE_GENERATED_NODES ? new JavaReadNodeGen(object, location, barrierType, compressible) : new JavaReadNode(object, location, barrierType, compressible);
+    }
+
+    JavaReadNode(ValueNode object, LocationNode location, BarrierType barrierType, boolean compressible) {
         super(object, location, StampFactory.forKind(location.getValueKind()), barrierType);
         this.compressible = compressible;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaWriteNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaWriteNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -29,11 +30,17 @@
  * Write a raw memory location according to Java field or array write semantics. It will perform
  * write barriers, implicit conversions and optionally oop compression.
  */
-public final class JavaWriteNode extends AbstractWriteNode implements Lowerable, StateSplit, MemoryAccess, MemoryCheckpoint.Single {
+@NodeInfo
+public class JavaWriteNode extends AbstractWriteNode implements Lowerable, StateSplit, MemoryAccess, MemoryCheckpoint.Single {
 
     private final boolean compressible;
 
-    public JavaWriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible, boolean initialization) {
+    public static JavaWriteNode create(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible, boolean initialization) {
+        return USE_GENERATED_NODES ? new JavaWriteNodeGen(object, value, location, barrierType, compressible, initialization) : new JavaWriteNode(object, value, location, barrierType, compressible,
+                        initialization);
+    }
+
+    JavaWriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible, boolean initialization) {
         super(object, value, location, barrierType, initialization);
         this.compressible = compressible;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.api.meta.ResolvedJavaType.Representation;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -33,20 +34,29 @@
  * Loads an object's {@linkplain Representation#ObjectHub hub}. The object is not null-checked by
  * this operation.
  */
-public final class LoadHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, Virtualizable {
+@NodeInfo
+public class LoadHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, Virtualizable {
 
-    @Input private ValueNode value;
+    @Input ValueNode value;
 
     public ValueNode getValue() {
         return value;
     }
 
-    public LoadHubNode(ValueNode value, Kind kind) {
+    public static LoadHubNode create(ValueNode value, Kind kind) {
+        return USE_GENERATED_NODES ? new LoadHubNodeGen(value, kind) : new LoadHubNode(value, kind);
+    }
+
+    LoadHubNode(ValueNode value, Kind kind) {
         super(getKind(kind), null);
         this.value = value;
     }
 
-    public LoadHubNode(ValueNode value, Kind kind, ValueNode guard) {
+    public static LoadHubNode create(ValueNode value, Kind kind, ValueNode guard) {
+        return USE_GENERATED_NODES ? new LoadHubNodeGen(value, kind, guard) : new LoadHubNode(value, kind, guard);
+    }
+
+    LoadHubNode(ValueNode value, Kind kind, ValueNode guard) {
         super(getKind(kind), (GuardingNode) guard);
         assert value != guard;
         this.value = value;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -33,9 +34,10 @@
 /**
  * Loads a method from the virtual method table of a given hub.
  */
-public final class LoadMethodNode extends FixedWithNextNode implements Lowerable, Canonicalizable {
+@NodeInfo
+public class LoadMethodNode extends FixedWithNextNode implements Lowerable, Canonicalizable {
 
-    @Input private ValueNode hub;
+    @Input ValueNode hub;
     private final ResolvedJavaMethod method;
     private final ResolvedJavaType receiverType;
 
@@ -43,7 +45,11 @@
         return hub;
     }
 
-    public LoadMethodNode(ResolvedJavaMethod method, ResolvedJavaType receiverType, ValueNode hub, Kind kind) {
+    public static LoadMethodNode create(ResolvedJavaMethod method, ResolvedJavaType receiverType, ValueNode hub, Kind kind) {
+        return USE_GENERATED_NODES ? new LoadMethodNodeGen(method, receiverType, hub, kind) : new LoadMethodNode(method, receiverType, hub, kind);
+    }
+
+    LoadMethodNode(ResolvedJavaMethod method, ResolvedJavaType receiverType, ValueNode hub, Kind kind) {
         super(kind == Kind.Object ? StampFactory.objectNonNull() : StampFactory.forKind(kind));
         this.receiverType = receiverType;
         this.hub = hub;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,9 +24,9 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.ValueNumberable;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -32,7 +32,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -47,7 +47,11 @@
     /**
      * @param barriers a mask of the barrier constants defined in {@link MemoryBarriers}
      */
-    public MembarNode(int barriers) {
+    public static MembarNode create(int barriers) {
+        return USE_GENERATED_NODES ? new MembarNodeGen(barriers) : new MembarNode(barriers);
+    }
+
+    MembarNode(int barriers) {
         super(StampFactory.forVoid());
         this.barriers = barriers;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryAccess.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryAccess.java	Mon Aug 25 21:15:59 2014 -0700
@@ -32,7 +32,14 @@
 
     LocationIdentity getLocationIdentity();
 
-    MemoryNode getLastLocationAccess();
+    default MemoryNode getLastLocationAccess() {
+        return null;
+    }
 
-    void setLastLocationAccess(MemoryNode lla);
+    /**
+     * @param lla the {@link MemoryNode} that represents the last kill of the location
+     */
+    default void setLastLocationAccess(MemoryNode lla) {
+        // empty
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,16 +23,20 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Guard})
 public class NullCheckNode extends DeoptimizingFixedWithNextNode implements LIRLowerable, GuardingNode {
 
-    @Input private ValueNode object;
+    @Input ValueNode object;
 
-    public NullCheckNode(ValueNode object) {
+    public static NullCheckNode create(ValueNode object) {
+        return USE_GENERATED_NODES ? new NullCheckNodeGen(object) : new NullCheckNode(object);
+    }
+
+    NullCheckNode(ValueNode object) {
         super(StampFactory.forVoid());
         this.object = object;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRLocalNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRLocalNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,12 +24,17 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
 @NodeInfo(nameTemplate = "OSRLocal({p#index})")
 public class OSRLocalNode extends AbstractLocalNode implements IterableNodeType {
 
-    public OSRLocalNode(int index, Stamp stamp) {
+    public static OSRLocalNode create(int index, Stamp stamp) {
+        return USE_GENERATED_NODES ? new OSRLocalNodeGen(index, stamp) : new OSRLocalNode(index, stamp);
+    }
+
+    OSRLocalNode(int index, Stamp stamp) {
         super(index, stamp);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRStartNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRStartNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,10 +23,18 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public class OSRStartNode extends StartNode implements Lowerable {
+    public static OSRStartNode create() {
+        return USE_GENERATED_NODES ? new OSRStartNodeGen() : new OSRStartNode();
+    }
+
+    OSRStartNode() {
+    }
 
     @Override
     public void lower(LoweringTool tool) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -34,21 +35,39 @@
 /**
  * Reads an {@linkplain FixedAccessNode accessed} value.
  */
-public final class ReadNode extends FloatableAccessNode implements LIRLowerable, Canonicalizable, PiPushable, Virtualizable, GuardingNode {
+@NodeInfo
+public class ReadNode extends FloatableAccessNode implements LIRLowerable, Canonicalizable, PiPushable, Virtualizable, GuardingNode {
 
-    public ReadNode(ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType) {
+    public static ReadNode create(ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType) {
+        return USE_GENERATED_NODES ? new ReadNodeGen(object, location, stamp, barrierType) : new ReadNode(object, location, stamp, barrierType);
+    }
+
+    ReadNode(ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType) {
         super(object, location, stamp, null, barrierType);
     }
 
-    public ReadNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType) {
+    public static ReadNode create(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType) {
+        return USE_GENERATED_NODES ? new ReadNodeGen(object, location, stamp, guard, barrierType) : new ReadNode(object, location, stamp, guard, barrierType);
+    }
+
+    ReadNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType) {
         super(object, location, stamp, guard, barrierType);
     }
 
-    public ReadNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck, FrameState stateBefore) {
+    public static ReadNode create(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck, FrameState stateBefore) {
+        return USE_GENERATED_NODES ? new ReadNodeGen(object, location, stamp, guard, barrierType, nullCheck, stateBefore) : new ReadNode(object, location, stamp, guard, barrierType, nullCheck,
+                        stateBefore);
+    }
+
+    ReadNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck, FrameState stateBefore) {
         super(object, location, stamp, guard, barrierType, nullCheck, stateBefore);
     }
 
-    private ReadNode(ValueNode object, ValueNode location, ValueNode guard, BarrierType barrierType) {
+    public static ReadNode create(ValueNode object, ValueNode location, ValueNode guard, BarrierType barrierType) {
+        return USE_GENERATED_NODES ? new ReadNodeGen(object, location, guard, barrierType) : new ReadNode(object, location, guard, barrierType);
+    }
+
+    ReadNode(ValueNode object, ValueNode location, ValueNode guard, BarrierType barrierType) {
         /*
          * Used by node intrinsics. Really, you can trust me on that! Since the initial value for
          * location is a parameter, i.e., a ParameterNode, the constructor cannot use the declared
@@ -67,17 +86,16 @@
     @Override
     public Node canonical(CanonicalizerTool tool) {
         if (usages().isEmpty()) {
-            GuardingNode guard = getGuard();
-            if (guard != null && !(guard instanceof FixedNode)) {
+            if (getGuard() != null && !(getGuard() instanceof FixedNode)) {
                 // The guard is necessary even if the read goes away.
-                return new ValueAnchorNode((ValueNode) guard);
+                return ValueAnchorNode.create((ValueNode) getGuard());
             } else {
                 // Read without usages or guard can be safely removed.
                 return null;
             }
         }
         if (object() instanceof PiNode && ((PiNode) object()).getGuard() == getGuard()) {
-            return new ReadNode(((PiNode) object()).getOriginalNode(), location(), stamp(), getGuard(), getBarrierType(), getNullCheck(), stateBefore());
+            return ReadNode.create(((PiNode) object()).getOriginalNode(), location(), stamp(), getGuard(), getBarrierType(), getNullCheck(), stateBefore());
         }
         if (!getNullCheck()) {
             return canonicalizeRead(this, location(), object(), tool);
@@ -90,7 +108,7 @@
 
     @Override
     public FloatingAccessNode asFloatingNode(MemoryNode lastLocationAccess) {
-        return graph().unique(new FloatingReadNode(object(), location(), lastLocationAccess, stamp(), getGuard(), getBarrierType()));
+        return graph().unique(FloatingReadNode.create(object(), location(), lastLocationAccess, stamp(), getGuard(), getBarrierType()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,13 +23,15 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
-public final class StoreHubNode extends FixedWithNextNode implements Lowerable {
+@NodeInfo
+public class StoreHubNode extends FixedWithNextNode implements Lowerable {
 
-    @Input private ValueNode value;
-    @Input private ValueNode object;
+    @Input ValueNode value;
+    @Input ValueNode object;
 
     public ValueNode getValue() {
         return value;
@@ -39,7 +41,11 @@
         return object;
     }
 
-    private StoreHubNode(ValueNode object, ValueNode value) {
+    public static StoreHubNode create(ValueNode object, ValueNode value) {
+        return USE_GENERATED_NODES ? new StoreHubNodeGen(object, value) : new StoreHubNode(object, value);
+    }
+
+    StoreHubNode(ValueNode object, ValueNode value) {
         super(StampFactory.forVoid());
         this.value = value;
         this.object = object;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,19 +22,23 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import java.util.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
 /**
  * The {@code SwitchNode} class is the base of both lookup and table switches.
  */
+@NodeInfo
 public abstract class SwitchNode extends ControlSplitNode {
 
-    @Successor private final NodeSuccessorList<BeginNode> successors;
-    @Input private ValueNode value;
+    @Successor protected NodeSuccessorList<BeginNode> successors;
+    @Input protected ValueNode value;
 
     // do not change the contents of these arrays:
     private final double[] keyProbabilities;
@@ -103,6 +107,10 @@
      */
     public abstract Constant keyAt(int i);
 
+    public boolean structureEquals(SwitchNode switchNode) {
+        return Arrays.equals(keySuccessors, switchNode.keySuccessors) && equalKeys(switchNode);
+    }
+
     /**
      * Returns true if the switch has the same keys in the same order as this switch.
      */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,15 +25,21 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public class UnboxNode extends UnaryNode implements Virtualizable, Lowerable {
 
     private final Kind boxingKind;
 
-    public UnboxNode(ValueNode value, Kind boxingKind) {
+    public static UnboxNode create(ValueNode value, Kind boxingKind) {
+        return USE_GENERATED_NODES ? new UnboxNodeGen(value, boxingKind) : new UnboxNode(value, boxingKind);
+    }
+
+    UnboxNode(ValueNode value, Kind boxingKind) {
         super(StampFactory.forKind(boxingKind.getStackKind()), value);
         this.boxingKind = boxingKind;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,13 +26,15 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 
+@NodeInfo
 public abstract class UnsafeAccessNode extends FixedWithNextNode implements Canonicalizable {
 
-    @Input private ValueNode object;
-    @Input private ValueNode offset;
+    @Input ValueNode object;
+    @Input ValueNode offset;
     private final Kind accessKind;
     private final LocationIdentity locationIdentity;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -36,21 +37,34 @@
  * information, i.e., an unsafe cast is removed if the input object has a more precise or equal type
  * than the type this nodes casts to.
  */
+@NodeInfo
 public class UnsafeCastNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, GuardingNode, IterableNodeType, Canonicalizable, ValueProxy {
 
-    @Input private ValueNode object;
+    @Input ValueNode object;
 
-    public UnsafeCastNode(ValueNode object, Stamp stamp) {
+    public static UnsafeCastNode create(ValueNode object, Stamp stamp) {
+        return USE_GENERATED_NODES ? new UnsafeCastNodeGen(object, stamp) : new UnsafeCastNode(object, stamp);
+    }
+
+    UnsafeCastNode(ValueNode object, Stamp stamp) {
         super(stamp);
         this.object = object;
     }
 
-    public UnsafeCastNode(ValueNode object, Stamp stamp, ValueNode anchor) {
+    public static UnsafeCastNode create(ValueNode object, Stamp stamp, ValueNode anchor) {
+        return USE_GENERATED_NODES ? new UnsafeCastNodeGen(object, stamp, anchor) : new UnsafeCastNode(object, stamp, anchor);
+    }
+
+    UnsafeCastNode(ValueNode object, Stamp stamp, ValueNode anchor) {
         super(stamp, (GuardingNode) anchor);
         this.object = object;
     }
 
-    public UnsafeCastNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
+    public static UnsafeCastNode create(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
+        return USE_GENERATED_NODES ? new UnsafeCastNodeGen(object, toType, exactType, nonNull) : new UnsafeCastNode(object, toType, exactType, nonNull);
+    }
+
+    UnsafeCastNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
         this(object, toType.getKind() == Kind.Object ? StampFactory.object(toType, exactType, nonNull || StampTool.isObjectNonNull(object.stamp())) : StampFactory.forKind(toType.getKind()));
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
@@ -35,14 +35,23 @@
  * Load of a value from a location specified as an offset relative to an object. No null check is
  * performed before the load.
  */
+@NodeInfo
 public class UnsafeLoadNode extends UnsafeAccessNode implements Lowerable, Virtualizable {
-    @OptionalInput(InputType.Condition) private LogicNode guardingCondition;
+    @OptionalInput(InputType.Condition) LogicNode guardingCondition;
 
-    public UnsafeLoadNode(ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity) {
+    public static UnsafeLoadNode create(ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity) {
+        return USE_GENERATED_NODES ? new UnsafeLoadNodeGen(object, offset, accessKind, locationIdentity) : new UnsafeLoadNode(object, offset, accessKind, locationIdentity);
+    }
+
+    UnsafeLoadNode(ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity) {
         this(object, offset, accessKind, locationIdentity, null);
     }
 
-    public UnsafeLoadNode(ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity, LogicNode condition) {
+    public static UnsafeLoadNode create(ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity, LogicNode condition) {
+        return USE_GENERATED_NODES ? new UnsafeLoadNodeGen(object, offset, accessKind, locationIdentity, condition) : new UnsafeLoadNode(object, offset, accessKind, locationIdentity, condition);
+    }
+
+    UnsafeLoadNode(ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity, LogicNode condition) {
         super(StampFactory.forKind(accessKind.getStackKind()), object, offset, accessKind, locationIdentity);
         this.guardingCondition = condition;
     }
@@ -62,8 +71,8 @@
         if (state != null && state.getState() == EscapeState.Virtual) {
             ValueNode offsetValue = tool.getReplacedValue(offset());
             if (offsetValue.isConstant()) {
-                long offset = offsetValue.asConstant().asLong();
-                int entryIndex = state.getVirtualObject().entryIndexForOffset(offset);
+                long off = offsetValue.asConstant().asLong();
+                int entryIndex = state.getVirtualObject().entryIndexForOffset(off);
                 if (entryIndex != -1) {
                     ValueNode entry = state.getEntry(entryIndex);
                     if (entry.getKind() == getKind() || state.getVirtualObject().entryKind(entryIndex) == accessKind()) {
@@ -76,12 +85,12 @@
 
     @Override
     protected ValueNode cloneAsFieldAccess(ResolvedJavaField field) {
-        return new LoadFieldNode(object(), field);
+        return LoadFieldNode.create(object(), field);
     }
 
     @Override
     protected ValueNode cloneAsArrayAccess(ValueNode location, LocationIdentity identity) {
-        return new UnsafeLoadNode(object(), location, accessKind(), identity);
+        return UnsafeLoadNode.create(object(), location, accessKind(), identity, guardingCondition);
     }
 
     @SuppressWarnings({"unchecked", "unused"})
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
@@ -35,16 +35,26 @@
  * Store of a value at a location specified as an offset relative to an object. No null check is
  * performed before the store.
  */
+@NodeInfo
 public class UnsafeStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, MemoryCheckpoint.Single {
 
-    @Input private ValueNode value;
-    @OptionalInput(InputType.State) private FrameState stateAfter;
+    @Input ValueNode value;
+    @OptionalInput(InputType.State) FrameState stateAfter;
 
-    public UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, LocationIdentity locationIdentity) {
+    public static UnsafeStoreNode create(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, LocationIdentity locationIdentity) {
+        return USE_GENERATED_NODES ? new UnsafeStoreNodeGen(object, offset, value, accessKind, locationIdentity) : new UnsafeStoreNode(object, offset, value, accessKind, locationIdentity);
+    }
+
+    UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, LocationIdentity locationIdentity) {
         this(object, offset, value, accessKind, locationIdentity, null);
     }
 
-    public UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, LocationIdentity locationIdentity, FrameState stateAfter) {
+    public static UnsafeStoreNode create(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, LocationIdentity locationIdentity, FrameState stateAfter) {
+        return USE_GENERATED_NODES ? new UnsafeStoreNodeGen(object, offset, value, accessKind, locationIdentity, stateAfter) : new UnsafeStoreNode(object, offset, value, accessKind, locationIdentity,
+                        stateAfter);
+    }
+
+    UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, LocationIdentity locationIdentity, FrameState stateAfter) {
         super(StampFactory.forVoid(), object, offset, accessKind, locationIdentity);
         this.value = value;
         this.stateAfter = stateAfter;
@@ -80,8 +90,8 @@
         if (state != null && state.getState() == EscapeState.Virtual) {
             ValueNode indexValue = tool.getReplacedValue(offset());
             if (indexValue.isConstant()) {
-                long offset = indexValue.asConstant().asLong();
-                int entryIndex = state.getVirtualObject().entryIndexForOffset(offset);
+                long off = indexValue.asConstant().asLong();
+                int entryIndex = state.getVirtualObject().entryIndexForOffset(off);
                 if (entryIndex != -1) {
                     Kind entryKind = state.getVirtualObject().entryKind(entryIndex);
                     ValueNode entry = state.getEntry(entryIndex);
@@ -90,7 +100,7 @@
                         tool.delete();
                     } else {
                         if ((accessKind() == Kind.Long || accessKind() == Kind.Double) && entryKind == Kind.Int) {
-                            int nextIndex = state.getVirtualObject().entryIndexForOffset(offset + 4);
+                            int nextIndex = state.getVirtualObject().entryIndexForOffset(off + 4);
                             if (nextIndex != -1) {
                                 Kind nextKind = state.getVirtualObject().entryKind(nextIndex);
                                 if (nextKind == Kind.Int) {
@@ -108,12 +118,12 @@
 
     @Override
     protected ValueNode cloneAsFieldAccess(ResolvedJavaField field) {
-        return new StoreFieldNode(object(), field, value(), stateAfter());
+        return StoreFieldNode.create(object(), field, value(), stateAfter());
     }
 
     @Override
     protected ValueNode cloneAsArrayAccess(ValueNode location, LocationIdentity identity) {
-        return new UnsafeStoreNode(object(), location, value, accessKind(), identity);
+        return UnsafeStoreNode.create(object(), location, value, accessKind(), identity, stateAfter());
     }
 
     public FrameState getState() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,8 +23,8 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -34,11 +34,15 @@
  * The ValueAnchor instruction keeps non-CFG (floating) nodes above a certain point in the graph.
  */
 @NodeInfo(allowedUsageTypes = {InputType.Anchor, InputType.Guard})
-public final class ValueAnchorNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, Virtualizable, AnchoringNode, GuardingNode {
+public class ValueAnchorNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, Virtualizable, AnchoringNode, GuardingNode {
+
+    @OptionalInput(InputType.Guard) ValueNode anchored;
 
-    @OptionalInput(InputType.Guard) private ValueNode anchored;
+    public static ValueAnchorNode create(ValueNode value) {
+        return USE_GENERATED_NODES ? new ValueAnchorNodeGen(value) : new ValueAnchorNode(value);
+    }
 
-    public ValueAnchorNode(ValueNode value) {
+    ValueAnchorNode(ValueNode value) {
         super(StampFactory.forVoid());
         this.anchored = value;
     }
@@ -66,13 +70,13 @@
             }
         }
         if (usages().isEmpty() && next() instanceof FixedAccessNode) {
-            FixedAccessNode next = (FixedAccessNode) next();
-            if (next.getGuard() == anchored) {
+            FixedAccessNode currentNext = (FixedAccessNode) next();
+            if (currentNext.getGuard() == anchored) {
                 GraphUtil.removeFixedWithUnusedInputs(this);
                 return;
-            } else if (next.getGuard() == null && anchored instanceof GuardNode && ((GuardNode) anchored).condition() instanceof IsNullNode) {
+            } else if (currentNext.getGuard() == null && anchored instanceof GuardNode && ((GuardNode) anchored).condition() instanceof IsNullNode) {
                 // coalesce null check guards into subsequent read/write
-                next.setGuard((GuardingNode) anchored);
+                currentNext.setGuard((GuardingNode) anchored);
                 tool.addToWorkList(next());
                 return;
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.LocationNode.Location;
 import com.oracle.graal.nodes.spi.*;
@@ -32,17 +33,30 @@
 /**
  * Writes a given {@linkplain #value() value} a {@linkplain FixedAccessNode memory location}.
  */
-public final class WriteNode extends AbstractWriteNode implements LIRLowerable, Simplifiable, Virtualizable {
+@NodeInfo
+public class WriteNode extends AbstractWriteNode implements LIRLowerable, Simplifiable, Virtualizable {
 
-    public WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType) {
+    public static WriteNode create(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType) {
+        return USE_GENERATED_NODES ? new WriteNodeGen(object, value, location, barrierType) : new WriteNode(object, value, location, barrierType);
+    }
+
+    WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType) {
         super(object, value, location, barrierType);
     }
 
-    public WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean initialization) {
+    public static WriteNode create(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean initialization) {
+        return USE_GENERATED_NODES ? new WriteNodeGen(object, value, location, barrierType, initialization) : new WriteNode(object, value, location, barrierType, initialization);
+    }
+
+    WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean initialization) {
         super(object, value, location, barrierType, initialization);
     }
 
-    public WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, GuardingNode guard, boolean initialization) {
+    public static WriteNode create(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, GuardingNode guard, boolean initialization) {
+        return USE_GENERATED_NODES ? new WriteNodeGen(object, value, location, barrierType, guard, initialization) : new WriteNode(object, value, location, barrierType, guard, initialization);
+    }
+
+    WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, GuardingNode guard, boolean initialization) {
         super(object, value, location, barrierType, guard, initialization);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,15 +24,17 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
  * The {@code AbstractNewArrayNode} is used for all 1-dimensional array allocations.
  */
+@NodeInfo
 public class AbstractNewArrayNode extends AbstractNewObjectNode implements ArrayLengthProvider {
 
-    @Input private ValueNode length;
+    @Input ValueNode length;
 
     @Override
     public ValueNode length() {
@@ -41,11 +43,15 @@
 
     /**
      * Constructs a new AbstractNewArrayNode.
-     * 
+     *
      * @param stamp the stamp of the newly created array
      * @param length the node that produces the length for this allocation.
      * @param fillContents determines whether the array elements should be initialized to zero/null.
      */
+    public static AbstractNewArrayNode create(Stamp stamp, ValueNode length, boolean fillContents) {
+        return USE_GENERATED_NODES ? new AbstractNewArrayNodeGen(stamp, length, fillContents) : new AbstractNewArrayNode(stamp, length, fillContents);
+    }
+
     protected AbstractNewArrayNode(Stamp stamp, ValueNode length, boolean fillContents) {
         super(stamp, fillContents);
         this.length = length;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,6 +27,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -34,6 +35,7 @@
 /**
  * The {@code AbstractNewObjectNode} is the base class for the new instance and new array nodes.
  */
+@NodeInfo
 public class AbstractNewObjectNode extends DeoptimizingFixedWithNextNode implements Simplifiable, Lowerable {
 
     private final boolean fillContents;
@@ -44,6 +46,10 @@
      * @param stamp the stamp of the newly created object
      * @param fillContents determines if the object's contents should be initialized to zero/null.
      */
+    public static AbstractNewObjectNode create(Stamp stamp, boolean fillContents) {
+        return USE_GENERATED_NODES ? new AbstractNewObjectNodeGen(stamp, fillContents) : new AbstractNewObjectNode(stamp, fillContents);
+    }
+
     protected AbstractNewObjectNode(Stamp stamp, boolean fillContents) {
         super(stamp);
         this.fillContents = fillContents;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessArrayNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessArrayNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,14 +23,16 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
 /**
  * This the base class of all array operations.
  */
+@NodeInfo
 public abstract class AccessArrayNode extends FixedWithNextNode {
 
-    @Input private ValueNode array;
+    @Input protected ValueNode array;
 
     public ValueNode array() {
         return array;
@@ -38,7 +40,7 @@
 
     /**
      * Creates a new AccessArrayNode.
-     * 
+     *
      * @param array the instruction that produces the array object value
      */
     public AccessArrayNode(Stamp stamp, ValueNode array) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,15 +24,17 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
  * The base class of all instructions that access fields.
  */
+@NodeInfo
 public abstract class AccessFieldNode extends FixedWithNextNode implements Lowerable {
 
-    @OptionalInput private ValueNode object;
+    @OptionalInput ValueNode object;
 
     protected final ResolvedJavaField field;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -31,9 +32,10 @@
  * The {@code AccessIndexedNode} class is the base class of instructions that read or write elements
  * of an array.
  */
+@NodeInfo
 public abstract class AccessIndexedNode extends AccessArrayNode implements Lowerable {
 
-    @Input private ValueNode index;
+    @Input protected ValueNode index;
     private final Kind elementKind;
 
     public ValueNode index() {
@@ -42,7 +44,7 @@
 
     /**
      * Create an new AccessIndexedNode.
-     * 
+     *
      * @param stamp the result kind of the access
      * @param array the instruction producing the array
      * @param index the instruction producing the index
@@ -56,7 +58,7 @@
 
     /**
      * Gets the element type of the array.
-     * 
+     *
      * @return the element type
      */
     public Kind elementKind() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,7 +24,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 
@@ -37,9 +37,9 @@
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
 public abstract class AccessMonitorNode extends AbstractMemoryCheckpoint implements MemoryCheckpoint, DeoptimizingNode.DeoptBefore, DeoptimizingNode.DeoptAfter {
 
-    @OptionalInput(InputType.State) private FrameState stateBefore;
-    @Input private ValueNode object;
-    @Input(InputType.Association) private MonitorIdNode monitorId;
+    @OptionalInput(InputType.State) FrameState stateBefore;
+    @Input ValueNode object;
+    @Input(InputType.Association) MonitorIdNode monitorId;
 
     @Override
     public boolean canDeoptimize() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
@@ -32,9 +33,10 @@
 /**
  * The {@code ArrayLength} instruction gets the length of an array.
  */
-public final class ArrayLengthNode extends FixedWithNextNode implements Canonicalizable.Unary<ValueNode>, Lowerable, Virtualizable {
+@NodeInfo
+public class ArrayLengthNode extends FixedWithNextNode implements Canonicalizable.Unary<ValueNode>, Lowerable, Virtualizable {
 
-    @Input private ValueNode array;
+    @Input ValueNode array;
 
     public ValueNode array() {
         return array;
@@ -44,7 +46,11 @@
         return array;
     }
 
-    public ArrayLengthNode(ValueNode array) {
+    public static ArrayLengthNode create(ValueNode array) {
+        return USE_GENERATED_NODES ? new ArrayLengthNodeGen(array) : new ArrayLengthNode(array);
+    }
+
+    ArrayLengthNode(ValueNode array) {
         super(StampFactory.positiveInt());
         this.array = array;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,29 +23,32 @@
 package com.oracle.graal.nodes.java;
 
 import static com.oracle.graal.compiler.common.UnsafeAccess.*;
+import sun.misc.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 
-import sun.misc.*;
-
 /**
  * Represents an atomic read-and-add operation like {@link Unsafe#getAndAddInt(Object, long, int)}.
  */
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
 public class AtomicReadAndAddNode extends AbstractMemoryCheckpoint implements LIRLowerable, MemoryCheckpoint.Single {
 
-    @Input private ValueNode object;
-    @Input private ValueNode offset;
-    @Input private ValueNode delta;
+    @Input ValueNode object;
+    @Input ValueNode offset;
+    @Input ValueNode delta;
 
     private final LocationIdentity locationIdentity;
 
-    public AtomicReadAndAddNode(ValueNode object, ValueNode offset, ValueNode delta, LocationIdentity locationIdentity) {
+    public static AtomicReadAndAddNode create(ValueNode object, ValueNode offset, ValueNode delta, LocationIdentity locationIdentity) {
+        return USE_GENERATED_NODES ? new AtomicReadAndAddNodeGen(object, offset, delta, locationIdentity) : new AtomicReadAndAddNode(object, offset, delta, locationIdentity);
+    }
+
+    AtomicReadAndAddNode(ValueNode object, ValueNode offset, ValueNode delta, LocationIdentity locationIdentity) {
         super(StampFactory.forKind(delta.getKind()));
         this.object = object;
         this.offset = offset;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndWriteNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndWriteNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,29 +23,35 @@
 package com.oracle.graal.nodes.java;
 
 import static com.oracle.graal.compiler.common.UnsafeAccess.*;
+import sun.misc.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 
-import sun.misc.*;
-
 /**
  * Represents an atomic read-and-write operation like {@link Unsafe#getAndSetInt(Object, long, int)}
  * .
  */
+@NodeInfo
 public class AtomicReadAndWriteNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
 
-    @Input private ValueNode object;
-    @Input private ValueNode offset;
-    @Input private ValueNode newValue;
+    @Input ValueNode object;
+    @Input ValueNode offset;
+    @Input ValueNode newValue;
 
     private final Kind valueKind;
     private final LocationIdentity locationIdentity;
 
-    public AtomicReadAndWriteNode(ValueNode object, ValueNode offset, ValueNode newValue, Kind valueKind, LocationIdentity locationIdentity) {
+    public static AtomicReadAndWriteNode create(ValueNode object, ValueNode offset, ValueNode newValue, Kind valueKind, LocationIdentity locationIdentity) {
+        return USE_GENERATED_NODES ? new AtomicReadAndWriteNodeGen(object, offset, newValue, valueKind, locationIdentity) : new AtomicReadAndWriteNode(object, offset, newValue, valueKind,
+                        locationIdentity);
+    }
+
+    AtomicReadAndWriteNode(ValueNode object, ValueNode offset, ValueNode newValue, Kind valueKind, LocationIdentity locationIdentity) {
         super(StampFactory.forKind(newValue.getKind()));
         this.object = object;
         this.offset = offset;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -32,10 +33,11 @@
  * 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.Binary<ValueNode>, Lowerable {
+@NodeInfo
+public class CheckCastDynamicNode extends FixedWithNextNode implements Canonicalizable.Binary<ValueNode>, Lowerable {
 
-    @Input private ValueNode object;
-    @Input private ValueNode hub;
+    @Input ValueNode object;
+    @Input ValueNode hub;
 
     /**
      * Determines the exception thrown by this node if the check fails: {@link ClassCastException}
@@ -47,7 +49,11 @@
      * @param hub the type being cast to
      * @param object the object being cast
      */
-    public CheckCastDynamicNode(ValueNode hub, ValueNode object, boolean forStoreCheck) {
+    public static CheckCastDynamicNode create(ValueNode hub, ValueNode object, boolean forStoreCheck) {
+        return USE_GENERATED_NODES ? new CheckCastDynamicNodeGen(hub, object, forStoreCheck) : new CheckCastDynamicNode(hub, object, forStoreCheck);
+    }
+
+    CheckCastDynamicNode(ValueNode hub, ValueNode object, boolean forStoreCheck) {
         super(object.stamp());
         this.hub = hub;
         this.object = object;
@@ -95,7 +101,7 @@
         if (forHub.isConstant()) {
             ResolvedJavaType t = tool.getConstantReflection().asJavaType(forHub.asConstant());
             if (t != null) {
-                return new CheckCastNode(t, forObject, null, forStoreCheck);
+                return CheckCastNode.create(t, forObject, null, forStoreCheck);
             }
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -31,6 +31,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -39,9 +40,10 @@
 /**
  * Implements a type check against a compile-time known type.
  */
+@NodeInfo
 public class CheckCastNode extends FixedWithNextNode implements Canonicalizable, Simplifiable, Lowerable, Virtualizable, ValueProxy {
 
-    @Input private ValueNode object;
+    @Input ValueNode object;
     private final ResolvedJavaType type;
     private final JavaTypeProfile profile;
 
@@ -57,7 +59,11 @@
      * @param type the type being cast to
      * @param object the instruction producing the object
      */
-    public CheckCastNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile, boolean forStoreCheck) {
+    public static CheckCastNode create(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile, boolean forStoreCheck) {
+        return USE_GENERATED_NODES ? new CheckCastNodeGen(type, object, profile, forStoreCheck) : new CheckCastNode(type, object, profile, forStoreCheck);
+    }
+
+    CheckCastNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile, boolean forStoreCheck) {
         super(StampFactory.declared(type));
         assert type != null;
         this.type = type;
@@ -109,12 +115,12 @@
             condition = LogicConstantNode.contradiction(graph());
             stamp = StampFactory.declared(type);
         } else if (StampTool.isObjectNonNull(object)) {
-            condition = graph().addWithoutUnique(new InstanceOfNode(type, object, profile));
+            condition = graph().addWithoutUnique(InstanceOfNode.create(type, object, profile));
         } else {
             if (profile != null && profile.getNullSeen() == TriState.FALSE) {
-                FixedGuardNode nullCheck = graph().add(new FixedGuardNode(graph().unique(new IsNullNode(object)), UnreachedCode, InvalidateReprofile, true));
-                PiNode nullGuarded = graph().unique(new PiNode(object, object().stamp().join(StampFactory.objectNonNull()), nullCheck));
-                InstanceOfNode typeTest = graph().addWithoutUnique(new InstanceOfNode(type, nullGuarded, profile));
+                FixedGuardNode nullCheck = graph().add(FixedGuardNode.create(graph().unique(IsNullNode.create(object)), UnreachedCode, InvalidateReprofile, true));
+                PiNode nullGuarded = graph().unique(PiNode.create(object, object().stamp().join(StampFactory.objectNonNull()), nullCheck));
+                InstanceOfNode typeTest = graph().addWithoutUnique(InstanceOfNode.create(type, nullGuarded, profile));
                 graph().addBeforeFixed(this, nullCheck);
                 condition = typeTest;
                 /*
@@ -128,11 +134,11 @@
             } else {
                 // TODO (ds) replace with probability of null-seen when available
                 double shortCircuitProbability = NOT_FREQUENT_PROBABILITY;
-                InstanceOfNode typeTest = graph().addWithoutUnique(new InstanceOfNode(type, object, profile));
-                condition = LogicNode.or(graph().unique(new IsNullNode(object)), typeTest, shortCircuitProbability);
+                InstanceOfNode typeTest = graph().addWithoutUnique(InstanceOfNode.create(type, object, profile));
+                condition = LogicNode.or(graph().unique(IsNullNode.create(object)), typeTest, shortCircuitProbability);
             }
         }
-        GuardingPiNode checkedObject = graph().add(new GuardingPiNode(theValue, condition, false, forStoreCheck ? ArrayStoreException : ClassCastException, InvalidateReprofile, stamp));
+        GuardingPiNode checkedObject = graph().add(GuardingPiNode.create(theValue, condition, false, forStoreCheck ? ArrayStoreException : ClassCastException, InvalidateReprofile, stamp));
         graph().replaceFixedWithFixed(this, checkedObject);
         checkedObject.lower(tool);
     }
@@ -164,7 +170,7 @@
             if (exactType != null && !exactType.equals(type)) {
                 // Propagate more precise type information to usages of the checkcast.
                 tool.assumptions().recordConcreteSubtype(type, exactType);
-                return new CheckCastNode(exactType, object, profile, forStoreCheck);
+                return CheckCastNode.create(exactType, object, profile, forStoreCheck);
             }
         }
 
@@ -179,7 +185,7 @@
             CheckCastNode ccn = (CheckCastNode) predecessor();
             if (ccn != null && ccn.type != null && ccn == object && ccn.forStoreCheck == forStoreCheck && ccn.type.isAssignableFrom(type)) {
                 StructuredGraph graph = ccn.graph();
-                CheckCastNode newccn = graph.add(new CheckCastNode(type, ccn.object, ccn.profile, ccn.forStoreCheck));
+                CheckCastNode newccn = graph.add(CheckCastNode.create(type, ccn.object, ccn.profile, ccn.forStoreCheck));
                 graph.replaceFixedWithFixed(ccn, newccn);
                 replaceAtUsages(newccn);
                 graph.removeFixed(this);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -38,15 +38,20 @@
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
 public class CompareAndSwapNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
 
-    @Input private ValueNode object;
-    @Input private ValueNode offset;
-    @Input private ValueNode expected;
-    @Input private ValueNode newValue;
+    @Input ValueNode object;
+    @Input ValueNode offset;
+    @Input ValueNode expected;
+    @Input ValueNode newValue;
 
     private final Kind valueKind;
     private final LocationIdentity locationIdentity;
 
-    public CompareAndSwapNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, Kind valueKind, LocationIdentity locationIdentity) {
+    public static CompareAndSwapNode create(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, Kind valueKind, LocationIdentity locationIdentity) {
+        return USE_GENERATED_NODES ? new CompareAndSwapNodeGen(object, offset, expected, newValue, valueKind, locationIdentity) : new CompareAndSwapNode(object, offset, expected, newValue, valueKind,
+                        locationIdentity);
+    }
+
+    CompareAndSwapNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, Kind valueKind, LocationIdentity locationIdentity) {
         super(StampFactory.forKind(Kind.Boolean.getStackKind()));
         assert expected.stamp().isCompatible(newValue.stamp());
         this.object = object;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -30,21 +30,31 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
 /**
  * The {@code DynamicNewArrayNode} is used for allocation of arrays when the type is not a
  * compile-time constant.
  */
+@NodeInfo
 public class DynamicNewArrayNode extends AbstractNewArrayNode {
 
-    @Input private ValueNode elementType;
+    @Input ValueNode elementType;
 
-    public DynamicNewArrayNode(ValueNode elementType, ValueNode length) {
+    public static DynamicNewArrayNode create(ValueNode elementType, ValueNode length) {
+        return USE_GENERATED_NODES ? new DynamicNewArrayNodeGen(elementType, length) : new DynamicNewArrayNode(elementType, length);
+    }
+
+    DynamicNewArrayNode(ValueNode elementType, ValueNode length) {
         this(elementType, length, true);
     }
 
-    public DynamicNewArrayNode(ValueNode elementType, ValueNode length, boolean fillContents) {
+    public static DynamicNewArrayNode create(ValueNode elementType, ValueNode length, boolean fillContents) {
+        return USE_GENERATED_NODES ? new DynamicNewArrayNodeGen(elementType, length, fillContents) : new DynamicNewArrayNode(elementType, length, fillContents);
+    }
+
+    DynamicNewArrayNode(ValueNode elementType, ValueNode length, boolean fillContents) {
         super(StampFactory.objectNonNull(), length, fillContents);
         this.elementType = elementType;
     }
@@ -58,8 +68,8 @@
         if (isAlive() && elementType.isConstant()) {
             ResolvedJavaType javaType = tool.getConstantReflection().asJavaType(elementType.asConstant());
             if (javaType != null && !javaType.equals(tool.getMetaAccess().lookupJavaType(void.class))) {
-                ValueNode length = length();
-                NewArrayNode newArray = graph().add(new NewArrayNode(javaType, length.isAlive() ? length : graph().addOrUniqueWithInputs(length), fillContents()));
+                ValueNode len = length();
+                NewArrayNode newArray = graph().add(NewArrayNode.create(javaType, len.isAlive() ? len : graph().addOrUniqueWithInputs(len), fillContents()));
                 List<Node> snapshot = inputs().snapshot();
                 graph().replaceFixedWithFixed(this, newArray);
                 for (Node input : snapshot) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,13 +26,19 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
+@NodeInfo
 public class DynamicNewInstanceNode extends AbstractNewObjectNode implements Canonicalizable {
 
-    @Input private ValueNode clazz;
+    @Input ValueNode clazz;
 
-    public DynamicNewInstanceNode(ValueNode clazz, boolean fillContents) {
+    public static DynamicNewInstanceNode create(ValueNode clazz, boolean fillContents) {
+        return USE_GENERATED_NODES ? new DynamicNewInstanceNodeGen(clazz, fillContents) : new DynamicNewInstanceNode(clazz, fillContents);
+    }
+
+    DynamicNewInstanceNode(ValueNode clazz, boolean fillContents) {
         super(StampFactory.objectNonNull(), fillContents);
         this.clazz = clazz;
     }
@@ -42,7 +48,7 @@
         if (clazz.isConstant()) {
             ResolvedJavaType type = tool.getConstantReflection().asJavaType(clazz.asConstant());
             if (type != null && type.isInitialized() && !type.isArray() && !type.isInterface() && !type.isPrimitive()) {
-                return new NewInstanceNode(type, fillContents());
+                return NewInstanceNode.create(type, fillContents());
             }
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,7 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -36,7 +36,11 @@
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
 public class ExceptionObjectNode extends DispatchBeginNode implements Lowerable, MemoryCheckpoint.Single {
 
-    public ExceptionObjectNode(MetaAccessProvider metaAccess) {
+    public static ExceptionObjectNode create(MetaAccessProvider metaAccess) {
+        return USE_GENERATED_NODES ? new ExceptionObjectNodeGen(metaAccess) : new ExceptionObjectNode(metaAccess);
+    }
+
+    ExceptionObjectNode(MetaAccessProvider metaAccess) {
         super(StampFactory.declaredNonNull(metaAccess.lookupJavaType(Throwable.class)));
     }
 
@@ -53,8 +57,8 @@
              * deopts can float in between the begin node and the load exception node.
              */
             LocationIdentity locationsKilledByInvoke = ((InvokeWithExceptionNode) predecessor()).getLocationIdentity();
-            BeginNode entry = graph().add(new KillingBeginNode(locationsKilledByInvoke));
-            LoadExceptionObjectNode loadException = graph().add(new LoadExceptionObjectNode(stamp()));
+            BeginNode entry = graph().add(KillingBeginNode.create(locationsKilledByInvoke));
+            LoadExceptionObjectNode loadException = graph().add(LoadExceptionObjectNode.create(stamp()));
 
             loadException.setStateAfter(stateAfter());
             replaceAtUsages(InputType.Value, loadException);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -33,16 +34,21 @@
  * known at compile time. This is used, for instance, to intrinsify {@link Class#isInstance(Object)}
  * .
  */
-public final class InstanceOfDynamicNode extends LogicNode implements Canonicalizable.Binary<ValueNode>, Lowerable {
+@NodeInfo
+public class InstanceOfDynamicNode extends LogicNode implements Canonicalizable.Binary<ValueNode>, Lowerable {
 
-    @Input private ValueNode object;
-    @Input private ValueNode mirror;
+    @Input ValueNode object;
+    @Input ValueNode mirror;
 
     /**
      * @param mirror the {@link Class} value representing the target target type of the test
      * @param object the object being tested
      */
-    public InstanceOfDynamicNode(ValueNode mirror, ValueNode object) {
+    public static InstanceOfDynamicNode create(ValueNode mirror, ValueNode object) {
+        return USE_GENERATED_NODES ? new InstanceOfDynamicNodeGen(mirror, object) : new InstanceOfDynamicNode(mirror, object);
+    }
+
+    InstanceOfDynamicNode(ValueNode mirror, ValueNode object) {
         this.mirror = mirror;
         this.object = object;
         assert mirror.getKind() == Kind.Object : mirror.getKind();
@@ -62,7 +68,7 @@
                 if (t.isPrimitive()) {
                     return LogicConstantNode.contradiction();
                 } else {
-                    return new InstanceOfNode(t, forObject, null);
+                    return InstanceOfNode.create(t, forObject, null);
                 }
             }
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -32,6 +33,7 @@
 /**
  * The {@code InstanceOfNode} represents an instanceof test.
  */
+@NodeInfo
 public class InstanceOfNode extends UnaryOpLogicNode implements Lowerable, Virtualizable {
 
     private final ResolvedJavaType type;
@@ -43,7 +45,11 @@
      * @param type the target type of the instanceof check
      * @param object the object being tested by the instanceof
      */
-    public InstanceOfNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile) {
+    public static InstanceOfNode create(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile) {
+        return USE_GENERATED_NODES ? new InstanceOfNodeGen(type, object, profile) : new InstanceOfNode(type, object, profile);
+    }
+
+    InstanceOfNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile) {
         super(object);
         this.type = type;
         this.profile = profile;
@@ -112,7 +118,7 @@
             if (!nonNull) {
                 // the instanceof matches if the object is non-null, so return true
                 // depending on the null-ness.
-                return new LogicNegationNode(new IsNullNode(forValue));
+                return LogicNegationNode.create(IsNullNode.create(forValue));
             }
         }
         return null;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,12 +23,18 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public class LoadExceptionObjectNode extends AbstractStateSplit implements Lowerable {
 
-    public LoadExceptionObjectNode(Stamp stamp) {
+    public static LoadExceptionObjectNode create(Stamp stamp) {
+        return USE_GENERATED_NODES ? new LoadExceptionObjectNodeGen(stamp) : new LoadExceptionObjectNode(stamp);
+    }
+
+    LoadExceptionObjectNode(Stamp stamp) {
         super(stamp);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,8 +26,8 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -37,7 +37,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.Unary<ValueNode>, VirtualizableRoot {
+public class LoadFieldNode extends AccessFieldNode implements Canonicalizable.Unary<ValueNode>, VirtualizableRoot {
 
     /**
      * Creates a new LoadFieldNode instance.
@@ -45,7 +45,11 @@
      * @param object the receiver object
      * @param field the compiler interface field
      */
-    public LoadFieldNode(ValueNode object, ResolvedJavaField field) {
+    public static LoadFieldNode create(ValueNode object, ResolvedJavaField field) {
+        return USE_GENERATED_NODES ? new LoadFieldNodeGen(object, field) : new LoadFieldNode(object, field);
+    }
+
+    protected LoadFieldNode(ValueNode object, ResolvedJavaField field) {
         super(createStamp(field), object, field);
     }
 
@@ -78,7 +82,7 @@
             }
         }
         if (!isStatic() && forObject.isNullConstant()) {
-            return new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.NullCheckException);
+            return DeoptimizeNode.create(DeoptimizationAction.None, DeoptimizationReason.NullCheckException);
         }
         return this;
     }
@@ -114,7 +118,7 @@
             for (int i = 0; i < phi.valueCount(); i++) {
                 constantNodes[i] = ConstantNode.forConstant(constants[i], metaAccess);
             }
-            return new ValuePhiNode(stamp(), phi.merge(), constantNodes);
+            return ValuePhiNode.create(stamp(), phi.merge(), constantNodes);
         }
         return null;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -31,7 +32,8 @@
 /**
  * The {@code LoadIndexedNode} represents a read from an element of an array.
  */
-public final class LoadIndexedNode extends AccessIndexedNode implements Virtualizable {
+@NodeInfo
+public class LoadIndexedNode extends AccessIndexedNode implements Virtualizable {
 
     /**
      * Creates a new LoadIndexedNode.
@@ -40,7 +42,11 @@
      * @param index the instruction producing the index
      * @param elementKind the element type
      */
-    public LoadIndexedNode(ValueNode array, ValueNode index, Kind elementKind) {
+    public static LoadIndexedNode create(ValueNode array, ValueNode index, Kind elementKind) {
+        return USE_GENERATED_NODES ? new LoadIndexedNodeGen(array, index, elementKind) : new LoadIndexedNode(array, index, elementKind);
+    }
+
+    LoadIndexedNode(ValueNode array, ValueNode index, Kind elementKind) {
         super(createStamp(array, elementKind), array, index, elementKind);
     }
 
@@ -63,9 +69,9 @@
         State arrayState = tool.getObjectState(array());
         if (arrayState != null && arrayState.getState() == EscapeState.Virtual) {
             ValueNode indexValue = tool.getReplacedValue(index());
-            int index = indexValue.isConstant() ? indexValue.asConstant().asInt() : -1;
-            if (index >= 0 && index < arrayState.getVirtualObject().entryCount()) {
-                tool.replaceWith(arrayState.getEntry(index));
+            int idx = indexValue.isConstant() ? indexValue.asConstant().asInt() : -1;
+            if (idx >= 0 && idx < arrayState.getVirtualObject().entryCount()) {
+                tool.replaceWith(arrayState.getEntry(idx));
             }
         }
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredAtomicReadAndWriteNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredAtomicReadAndWriteNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,14 +22,14 @@
  */
 package com.oracle.graal.nodes.java;
 
+import sun.misc.*;
+
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 
-import sun.misc.*;
-
 /**
  * Represents the lowered version of an atomic read-and-write operation like
  * {@link Unsafe#getAndSetInt(Object, long, int)} .
@@ -37,10 +37,14 @@
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
 public class LoweredAtomicReadAndWriteNode extends FixedAccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single {
 
-    @Input private ValueNode newValue;
-    @OptionalInput(InputType.State) private FrameState stateAfter;
+    @Input ValueNode newValue;
+    @OptionalInput(InputType.State) FrameState stateAfter;
 
-    public LoweredAtomicReadAndWriteNode(ValueNode object, LocationNode location, ValueNode newValue, BarrierType barrierType) {
+    public static LoweredAtomicReadAndWriteNode create(ValueNode object, LocationNode location, ValueNode newValue, BarrierType barrierType) {
+        return USE_GENERATED_NODES ? new LoweredAtomicReadAndWriteNodeGen(object, location, newValue, barrierType) : new LoweredAtomicReadAndWriteNode(object, location, newValue, barrierType);
+    }
+
+    LoweredAtomicReadAndWriteNode(ValueNode object, LocationNode location, ValueNode newValue, BarrierType barrierType) {
         super(object, location, newValue.stamp().unrestricted(), barrierType);
         this.newValue = newValue;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,7 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -35,9 +35,9 @@
 @NodeInfo(allowedUsageTypes = {InputType.Value, InputType.Memory})
 public class LoweredCompareAndSwapNode extends FixedAccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single {
 
-    @Input private ValueNode expectedValue;
-    @Input private ValueNode newValue;
-    @OptionalInput(InputType.State) private FrameState stateAfter;
+    @Input ValueNode expectedValue;
+    @Input ValueNode newValue;
+    @OptionalInput(InputType.State) FrameState stateAfter;
 
     public FrameState stateAfter() {
         return stateAfter;
@@ -61,7 +61,12 @@
         return newValue;
     }
 
-    public LoweredCompareAndSwapNode(ValueNode object, LocationNode location, ValueNode expectedValue, ValueNode newValue, BarrierType barrierType) {
+    public static LoweredCompareAndSwapNode create(ValueNode object, LocationNode location, ValueNode expectedValue, ValueNode newValue, BarrierType barrierType) {
+        return USE_GENERATED_NODES ? new LoweredCompareAndSwapNodeGen(object, location, expectedValue, newValue, barrierType) : new LoweredCompareAndSwapNode(object, location, expectedValue,
+                        newValue, barrierType);
+    }
+
+    LoweredCompareAndSwapNode(ValueNode object, LocationNode location, ValueNode expectedValue, ValueNode newValue, BarrierType barrierType) {
         super(object, location, StampFactory.forKind(Kind.Boolean.getStackKind()), barrierType);
         assert expectedValue.getKind() == newValue.getKind();
         this.expectedValue = expectedValue;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,16 +26,22 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 
+@NodeInfo
 public class MethodCallTargetNode extends CallTargetNode implements IterableNodeType, Canonicalizable {
     private final JavaType returnType;
 
     /**
      * @param arguments
      */
-    public MethodCallTargetNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType) {
+    public static MethodCallTargetNode create(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType) {
+        return USE_GENERATED_NODES ? new MethodCallTargetNodeGen(invokeKind, targetMethod, arguments, returnType) : new MethodCallTargetNode(invokeKind, targetMethod, arguments, returnType);
+    }
+
+    MethodCallTargetNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType) {
         super(arguments, targetMethod, invokeKind);
         this.returnType = returnType;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -31,14 +32,19 @@
 /**
  * The {@code MonitorEnterNode} represents the acquisition of a monitor.
  */
-public final class MonitorEnterNode extends AccessMonitorNode implements Virtualizable, Lowerable, IterableNodeType, MonitorEnter, MemoryCheckpoint.Single {
+@NodeInfo
+public class MonitorEnterNode extends AccessMonitorNode implements Virtualizable, Lowerable, IterableNodeType, MonitorEnter, MemoryCheckpoint.Single {
 
     /**
      * Creates a new MonitorEnterNode.
-     * 
+     *
      * @param object the instruction producing the object
      */
-    public MonitorEnterNode(ValueNode object, MonitorIdNode monitorId) {
+    public static MonitorEnterNode create(ValueNode object, MonitorIdNode monitorId) {
+        return USE_GENERATED_NODES ? new MonitorEnterNodeGen(object, monitorId) : new MonitorEnterNode(object, monitorId);
+    }
+
+    MonitorEnterNode(ValueNode object, MonitorIdNode monitorId) {
         super(object, monitorId);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -35,14 +36,19 @@
  * a synchronized method, then the return value of the method will be referenced, so that it will be
  * materialized before releasing the monitor.
  */
-public final class MonitorExitNode extends AccessMonitorNode implements Virtualizable, Simplifiable, Lowerable, IterableNodeType, MonitorExit, MemoryCheckpoint.Single {
+@NodeInfo
+public class MonitorExitNode extends AccessMonitorNode implements Virtualizable, Simplifiable, Lowerable, IterableNodeType, MonitorExit, MemoryCheckpoint.Single {
 
-    @OptionalInput private ValueNode escapedReturnValue;
+    @OptionalInput ValueNode escapedReturnValue;
 
     /**
      * Creates a new MonitorExitNode.
      */
-    public MonitorExitNode(ValueNode object, MonitorIdNode monitorId, ValueNode escapedReturnValue) {
+    public static MonitorExitNode create(ValueNode object, MonitorIdNode monitorId, ValueNode escapedReturnValue) {
+        return USE_GENERATED_NODES ? new MonitorExitNodeGen(object, monitorId, escapedReturnValue) : new MonitorExitNode(object, monitorId, escapedReturnValue);
+    }
+
+    MonitorExitNode(ValueNode object, MonitorIdNode monitorId, ValueNode escapedReturnValue) {
         super(object, monitorId);
         this.escapedReturnValue = escapedReturnValue;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -37,7 +38,11 @@
 
     private int lockDepth;
 
-    public MonitorIdNode(int lockDepth) {
+    public static MonitorIdNode create(int lockDepth) {
+        return USE_GENERATED_NODES ? new MonitorIdNodeGen(lockDepth) : new MonitorIdNode(lockDepth);
+    }
+
+    MonitorIdNode(int lockDepth) {
         super(StampFactory.forVoid());
         this.lockDepth = lockDepth;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -35,6 +36,7 @@
  * The {@code NewArrayNode} is used for all array allocations where the element type is know at
  * compile time.
  */
+@NodeInfo
 public class NewArrayNode extends AbstractNewArrayNode implements VirtualizableAllocation {
 
     /**
@@ -45,7 +47,11 @@
      * @param length the node that produces the length for this allocation.
      * @param fillContents determines whether the array elements should be initialized to zero/null.
      */
-    public NewArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents) {
+    public static NewArrayNode create(ResolvedJavaType elementType, ValueNode length, boolean fillContents) {
+        return USE_GENERATED_NODES ? new NewArrayNodeGen(elementType, length, fillContents) : new NewArrayNode(elementType, length, fillContents);
+    }
+
+    NewArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents) {
         super(StampFactory.exactNonNull(elementType.getArrayClass()), length, fillContents);
     }
 
@@ -75,7 +81,7 @@
                 for (int i = 0; i < constantLength; i++) {
                     state[i] = defaultForKind;
                 }
-                VirtualObjectNode virtualObject = new VirtualArrayNode(elementType(), constantLength);
+                VirtualObjectNode virtualObject = VirtualArrayNode.create(elementType(), constantLength);
                 tool.createVirtualObject(virtualObject, state, Collections.<MonitorIdNode> emptyList());
                 tool.replaceWithVirtual(virtualObject);
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,7 +27,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.virtual.*;
@@ -47,7 +47,11 @@
      * @param fillContents determines whether the new object's fields should be initialized to
      *            zero/null.
      */
-    public NewInstanceNode(ResolvedJavaType type, boolean fillContents) {
+    public static NewInstanceNode create(ResolvedJavaType type, boolean fillContents) {
+        return USE_GENERATED_NODES ? new NewInstanceNodeGen(type, fillContents) : new NewInstanceNode(type, fillContents);
+    }
+
+    NewInstanceNode(ResolvedJavaType type, boolean fillContents) {
         super(StampFactory.exactNonNull(type), fillContents);
         assert !type.isArray() && !type.isInterface() && !type.isPrimitive();
         this.instanceClass = type;
@@ -69,7 +73,7 @@
          * they're excluded from escape analysis.
          */
         if (!tool.getMetaAccessProvider().lookupJavaType(Reference.class).isAssignableFrom(instanceClass)) {
-            VirtualInstanceNode virtualObject = new VirtualInstanceNode(instanceClass(), true);
+            VirtualInstanceNode virtualObject = VirtualInstanceNode.create(instanceClass(), true);
             ResolvedJavaField[] fields = virtualObject.getFields();
             ValueNode[] state = new ValueNode[fields.length];
             for (int i = 0; i < state.length; i++) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,15 +25,17 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
  * The {@code NewMultiArrayNode} represents an allocation of a multi-dimensional object array.
  */
+@NodeInfo
 public class NewMultiArrayNode extends DeoptimizingFixedWithNextNode implements Lowerable, ArrayLengthProvider {
 
-    @Input private final NodeInputList<ValueNode> dimensions;
+    @Input NodeInputList<ValueNode> dimensions;
     private final ResolvedJavaType type;
 
     public ValueNode dimension(int index) {
@@ -54,7 +56,11 @@
      * @param type the element type of the array
      * @param dimensions the node which produce the dimensions for this array
      */
-    public NewMultiArrayNode(ResolvedJavaType type, ValueNode[] dimensions) {
+    public static NewMultiArrayNode create(ResolvedJavaType type, ValueNode[] dimensions) {
+        return USE_GENERATED_NODES ? new NewMultiArrayNodeGen(type, dimensions) : new NewMultiArrayNode(type, dimensions);
+    }
+
+    NewMultiArrayNode(ResolvedJavaType type, ValueNode[] dimensions) {
         super(StampFactory.exactNonNull(type));
         this.type = type;
         this.dimensions = new NodeInputList<>(this, dimensions);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,8 +26,8 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -35,12 +35,17 @@
  * This node is used to perform the finalizer registration at the end of the java.lang.Object
  * constructor.
  */
-public final class RegisterFinalizerNode extends AbstractStateSplit implements Canonicalizable.Unary<ValueNode>, LIRLowerable, Virtualizable, DeoptimizingNode.DeoptAfter {
+@NodeInfo
+public class RegisterFinalizerNode extends AbstractStateSplit implements Canonicalizable.Unary<ValueNode>, LIRLowerable, Virtualizable, DeoptimizingNode.DeoptAfter {
+
+    @OptionalInput(InputType.State) FrameState deoptState;
+    @Input ValueNode value;
 
-    @OptionalInput(InputType.State) private FrameState deoptState;
-    @Input private ValueNode value;
+    public static RegisterFinalizerNode create(ValueNode value) {
+        return USE_GENERATED_NODES ? new RegisterFinalizerNodeGen(value) : new RegisterFinalizerNode(value);
+    }
 
-    public RegisterFinalizerNode(ValueNode value) {
+    RegisterFinalizerNode(ValueNode value) {
         super(StampFactory.forVoid());
         this.value = value;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,24 +25,32 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
  * A SelfReplacingMethodCallTargetNode replaces itself in the graph when being lowered with a
  * {@link MethodCallTargetNode} that calls the stored replacement target method.
- * 
+ *
  * This node is used for method handle call nodes which have a constant call target but are not
  * inlined.
  */
+@NodeInfo
 public class SelfReplacingMethodCallTargetNode extends MethodCallTargetNode implements Lowerable {
 
     // Replacement method data
     private final ResolvedJavaMethod replacementTargetMethod;
     private final JavaType replacementReturnType;
-    @Input private final NodeInputList<ValueNode> replacementArguments;
+    @Input NodeInputList<ValueNode> replacementArguments;
 
-    public SelfReplacingMethodCallTargetNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType, ResolvedJavaMethod replacementTargetMethod,
+    public static SelfReplacingMethodCallTargetNode create(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType,
+                    ResolvedJavaMethod replacementTargetMethod, ValueNode[] replacementArguments, JavaType replacementReturnType) {
+        return USE_GENERATED_NODES ? new SelfReplacingMethodCallTargetNodeGen(invokeKind, targetMethod, arguments, returnType, replacementTargetMethod, replacementArguments, replacementReturnType)
+                        : new SelfReplacingMethodCallTargetNode(invokeKind, targetMethod, arguments, returnType, replacementTargetMethod, replacementArguments, replacementReturnType);
+    }
+
+    SelfReplacingMethodCallTargetNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType, ResolvedJavaMethod replacementTargetMethod,
                     ValueNode[] replacementArguments, JavaType replacementReturnType) {
         super(invokeKind, targetMethod, arguments, returnType);
         this.replacementTargetMethod = replacementTargetMethod;
@@ -66,7 +74,7 @@
     public void lower(LoweringTool tool) {
         InvokeKind invokeKind = replacementTargetMethod.isStatic() ? InvokeKind.Static : InvokeKind.Special;
         MethodCallTargetNode replacement = graph().add(
-                        new MethodCallTargetNode(invokeKind, replacementTargetMethod, replacementArguments.toArray(new ValueNode[replacementArguments.size()]), replacementReturnType));
+                        MethodCallTargetNode.create(invokeKind, replacementTargetMethod, replacementArguments.toArray(new ValueNode[replacementArguments.size()]), replacementReturnType));
 
         // Replace myself...
         this.replaceAndDelete(replacement);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,7 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.virtual.*;
@@ -33,10 +33,10 @@
  * The {@code StoreFieldNode} represents a write to a static or instance field.
  */
 @NodeInfo(nameTemplate = "StoreField#{p#field/s}")
-public final class StoreFieldNode extends AccessFieldNode implements StateSplit, VirtualizableRoot {
+public class StoreFieldNode extends AccessFieldNode implements StateSplit, VirtualizableRoot {
 
-    @Input private ValueNode value;
-    @OptionalInput(InputType.State) private FrameState stateAfter;
+    @Input ValueNode value;
+    @OptionalInput(InputType.State) FrameState stateAfter;
 
     public FrameState stateAfter() {
         return stateAfter;
@@ -63,12 +63,20 @@
      * @param field the compiler interface field
      * @param value the node representing the value to store to the field
      */
-    public StoreFieldNode(ValueNode object, ResolvedJavaField field, ValueNode value) {
+    public static StoreFieldNode create(ValueNode object, ResolvedJavaField field, ValueNode value) {
+        return USE_GENERATED_NODES ? new StoreFieldNodeGen(object, field, value) : new StoreFieldNode(object, field, value);
+    }
+
+    StoreFieldNode(ValueNode object, ResolvedJavaField field, ValueNode value) {
         super(StampFactory.forVoid(), object, field);
         this.value = value;
     }
 
-    public StoreFieldNode(ValueNode object, ResolvedJavaField field, ValueNode value, FrameState stateAfter) {
+    public static StoreFieldNode create(ValueNode object, ResolvedJavaField field, ValueNode value, FrameState stateAfter) {
+        return USE_GENERATED_NODES ? new StoreFieldNodeGen(object, field, value, stateAfter) : new StoreFieldNode(object, field, value, stateAfter);
+    }
+
+    StoreFieldNode(ValueNode object, ResolvedJavaField field, ValueNode value, FrameState stateAfter) {
         super(StampFactory.forVoid(), object, field);
         this.value = value;
         this.stateAfter = stateAfter;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,7 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -32,10 +32,11 @@
 /**
  * The {@code StoreIndexedNode} represents a write to an array element.
  */
-public final class StoreIndexedNode extends AccessIndexedNode implements StateSplit, Lowerable, Virtualizable {
+@NodeInfo
+public class StoreIndexedNode extends AccessIndexedNode implements StateSplit, Lowerable, Virtualizable {
 
-    @Input private ValueNode value;
-    @OptionalInput(InputType.State) private FrameState stateAfter;
+    @Input ValueNode value;
+    @OptionalInput(InputType.State) FrameState stateAfter;
 
     public FrameState stateAfter() {
         return stateAfter;
@@ -63,7 +64,11 @@
      * @param elementKind the element type
      * @param value the value to store into the array
      */
-    public StoreIndexedNode(ValueNode array, ValueNode index, Kind elementKind, ValueNode value) {
+    public static StoreIndexedNode create(ValueNode array, ValueNode index, Kind elementKind, ValueNode value) {
+        return USE_GENERATED_NODES ? new StoreIndexedNodeGen(array, index, elementKind, value) : new StoreIndexedNode(array, index, elementKind, value);
+    }
+
+    StoreIndexedNode(ValueNode array, ValueNode index, Kind elementKind, ValueNode value) {
         super(StampFactory.forVoid(), array, index, elementKind);
         this.value = value;
     }
@@ -73,12 +78,12 @@
         State arrayState = tool.getObjectState(array());
         if (arrayState != null && arrayState.getState() == EscapeState.Virtual) {
             ValueNode indexValue = tool.getReplacedValue(index());
-            int index = indexValue.isConstant() ? indexValue.asConstant().asInt() : -1;
-            if (index >= 0 && index < arrayState.getVirtualObject().entryCount()) {
+            int idx = indexValue.isConstant() ? indexValue.asConstant().asInt() : -1;
+            if (idx >= 0 && idx < arrayState.getVirtualObject().entryCount()) {
                 ResolvedJavaType componentType = arrayState.getVirtualObject().type().getComponentType();
                 if (componentType.isPrimitive() || StampTool.isObjectAlwaysNull(value) || componentType.getSuperclass() == null ||
                                 (StampTool.typeOrNull(value) != null && componentType.isAssignableFrom(StampTool.typeOrNull(value)))) {
-                    tool.setVirtualEntry(arrayState, index, value(), false);
+                    tool.setVirtualEntry(arrayState, idx, value(), false);
                     tool.delete();
                 }
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -28,6 +28,7 @@
 import com.oracle.graal.api.meta.ResolvedJavaType.Representation;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -37,7 +38,8 @@
  * The {@code TypeSwitchNode} performs a lookup based on the type of the input value. The type
  * comparison is an exact type comparison, not an instanceof.
  */
-public final class TypeSwitchNode extends SwitchNode implements LIRLowerable, Simplifiable {
+@NodeInfo
+public class TypeSwitchNode extends SwitchNode implements LIRLowerable, Simplifiable {
 
     private final ResolvedJavaType[] keys;
 
@@ -51,7 +53,11 @@
      * @param keyProbabilities the probabilities of the keys
      * @param keySuccessors the successor index for each key
      */
-    public TypeSwitchNode(ValueNode value, BeginNode[] successors, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) {
+    public static TypeSwitchNode create(ValueNode value, BeginNode[] successors, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) {
+        return USE_GENERATED_NODES ? new TypeSwitchNodeGen(value, successors, keys, keyProbabilities, keySuccessors) : new TypeSwitchNode(value, successors, keys, keyProbabilities, keySuccessors);
+    }
+
+    TypeSwitchNode(ValueNode value, BeginNode[] successors, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) {
         super(value, successors, keySuccessors, keyProbabilities);
         assert successors.length <= keys.length + 1;
         assert keySuccessors.length == keyProbabilities.length;
@@ -199,7 +205,7 @@
                     }
 
                     BeginNode[] successorsArray = newSuccessors.toArray(new BeginNode[newSuccessors.size()]);
-                    TypeSwitchNode newSwitch = graph().add(new TypeSwitchNode(value(), successorsArray, newKeys, newKeyProbabilities, newKeySuccessors));
+                    TypeSwitchNode newSwitch = graph().add(TypeSwitchNode.create(value(), successorsArray, newKeys, newKeyProbabilities, newKeySuccessors));
                     ((FixedWithNextNode) predecessor()).setNext(newSwitch);
                     GraphUtil.killWithUnusedFloatingInputs(this);
                 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,7 +23,7 @@
 package com.oracle.graal.nodes.virtual;
 
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -32,12 +32,17 @@
  * Selects one object from a {@link CommitAllocationNode}. The object is identified by its
  * {@link VirtualObjectNode}.
  */
+@NodeInfo
 public class AllocatedObjectNode extends FloatingNode implements Virtualizable, ArrayLengthProvider {
 
-    @Input private VirtualObjectNode virtualObject;
-    @Input(InputType.Extension) private CommitAllocationNode commit;
+    @Input VirtualObjectNode virtualObject;
+    @Input(InputType.Extension) CommitAllocationNode commit;
 
-    public AllocatedObjectNode(VirtualObjectNode virtualObject) {
+    public static AllocatedObjectNode create(VirtualObjectNode virtualObject) {
+        return USE_GENERATED_NODES ? new AllocatedObjectNodeGen(virtualObject) : new AllocatedObjectNode(virtualObject);
+    }
+
+    AllocatedObjectNode(VirtualObjectNode virtualObject) {
         super(StampFactory.exactNonNull(virtualObject.type()));
         this.virtualObject = virtualObject;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,19 +27,24 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(nameTemplate = "Alloc {i#virtualObjects}", allowedUsageTypes = {InputType.Extension})
-public final class CommitAllocationNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Simplifiable {
+public class CommitAllocationNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Simplifiable {
 
-    @Input private final NodeInputList<VirtualObjectNode> virtualObjects = new NodeInputList<>(this);
-    @Input private final NodeInputList<ValueNode> values = new NodeInputList<>(this);
-    @Input(InputType.Association) private final NodeInputList<MonitorIdNode> locks = new NodeInputList<>(this);
+    @Input NodeInputList<VirtualObjectNode> virtualObjects = new NodeInputList<>(this);
+    @Input NodeInputList<ValueNode> values = new NodeInputList<>(this);
+    @Input(InputType.Association) NodeInputList<MonitorIdNode> locks = new NodeInputList<>(this);
     private ArrayList<Integer> lockIndexes = new ArrayList<>(Arrays.asList(0));
 
-    public CommitAllocationNode() {
+    public static CommitAllocationNode create() {
+        return USE_GENERATED_NODES ? new CommitAllocationNodeGen() : new CommitAllocationNode();
+    }
+
+    CommitAllocationNode() {
         super(StampFactory.forVoid());
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EscapeObjectState.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EscapeObjectState.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,11 +23,13 @@
 package com.oracle.graal.nodes.virtual;
 
 import com.oracle.graal.graph.Node.ValueNumberable;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
+@NodeInfo
 public abstract class EscapeObjectState extends VirtualState implements ValueNumberable {
 
-    @Input private VirtualObjectNode object;
+    @Input protected VirtualObjectNode object;
 
     public VirtualObjectNode object() {
         return object;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,7 +25,7 @@
 import sun.misc.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -35,7 +35,11 @@
     private final ResolvedJavaType componentType;
     private final int length;
 
-    public VirtualArrayNode(ResolvedJavaType componentType, int length) {
+    public static VirtualArrayNode create(ResolvedJavaType componentType, int length) {
+        return USE_GENERATED_NODES ? new VirtualArrayNodeGen(componentType, length) : new VirtualArrayNode(componentType, length);
+    }
+
+    VirtualArrayNode(ResolvedJavaType componentType, int length) {
         super(componentType.getArrayClass(), true);
         this.componentType = componentType;
         this.length = length;
@@ -137,12 +141,12 @@
 
     @Override
     public VirtualArrayNode duplicate() {
-        return new VirtualArrayNode(componentType, length);
+        return VirtualArrayNode.create(componentType, length);
     }
 
     @Override
     public ValueNode getMaterializedRepresentation(FixedNode fixed, ValueNode[] entries, LockState locks) {
-        return new AllocatedObjectNode(this);
+        return AllocatedObjectNode.create(this);
     }
 
     public ValueNode length() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualBoxingNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualBoxingNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,27 +23,33 @@
 package com.oracle.graal.nodes.virtual;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 
+@NodeInfo
 public class VirtualBoxingNode extends VirtualInstanceNode {
 
     private final Kind boxingKind;
 
-    public VirtualBoxingNode(ResolvedJavaType type, Kind boxingKind) {
+    public static VirtualBoxingNode create(ResolvedJavaType type, Kind boxingKind) {
+        return USE_GENERATED_NODES ? new VirtualBoxingNodeGen(type, boxingKind) : new VirtualBoxingNode(type, boxingKind);
+    }
+
+    VirtualBoxingNode(ResolvedJavaType type, Kind boxingKind) {
         super(type, false);
         this.boxingKind = boxingKind;
     }
 
     @Override
     public VirtualBoxingNode duplicate() {
-        return new VirtualBoxingNode(type(), boxingKind);
+        return VirtualBoxingNode.create(type(), boxingKind);
     }
 
     @Override
     public ValueNode getMaterializedRepresentation(FixedNode fixed, ValueNode[] entries, LockState locks) {
         assert entries.length == 1;
         assert locks == null;
-        return new BoxNode(entries[0], type(), boxingKind);
+        return BoxNode.create(entries[0], type(), boxingKind);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,7 +23,7 @@
 package com.oracle.graal.nodes.virtual;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
 @NodeInfo(nameTemplate = "VirtualInstance {p#type/s}")
@@ -32,11 +32,19 @@
     private final ResolvedJavaType type;
     private final ResolvedJavaField[] fields;
 
-    public VirtualInstanceNode(ResolvedJavaType type, boolean hasIdentity) {
+    public static VirtualInstanceNode create(ResolvedJavaType type, boolean hasIdentity) {
+        return USE_GENERATED_NODES ? new VirtualInstanceNodeGen(type, hasIdentity) : new VirtualInstanceNode(type, hasIdentity);
+    }
+
+    VirtualInstanceNode(ResolvedJavaType type, boolean hasIdentity) {
         this(type, type.getInstanceFields(true), hasIdentity);
     }
 
-    public VirtualInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields, boolean hasIdentity) {
+    public static VirtualInstanceNode create(ResolvedJavaType type, ResolvedJavaField[] fields, boolean hasIdentity) {
+        return USE_GENERATED_NODES ? new VirtualInstanceNodeGen(type, fields, hasIdentity) : new VirtualInstanceNode(type, fields, hasIdentity);
+    }
+
+    protected VirtualInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields, boolean hasIdentity) {
         super(type, hasIdentity);
         this.type = type;
         this.fields = fields;
@@ -97,11 +105,11 @@
 
     @Override
     public VirtualInstanceNode duplicate() {
-        return new VirtualInstanceNode(type, fields, super.hasIdentity());
+        return VirtualInstanceNode.create(type, fields, super.hasIdentity());
     }
 
     @Override
     public ValueNode getMaterializedRepresentation(FixedNode fixed, ValueNode[] entries, LockState locks) {
-        return new AllocatedObjectNode(this);
+        return AllocatedObjectNode.create(this);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,9 +25,11 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public abstract class VirtualObjectNode extends ValueNode implements LIRLowerable, IterableNodeType {
 
     private boolean hasIdentity;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/DerivedOptionValue.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 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.options;
+
+import java.util.function.*;
+
+import com.oracle.graal.options.OptionValue.OverrideScope;
+
+/**
+ * A cached value that needs to be recomputed when an option changes.
+ */
+public class DerivedOptionValue<T> {
+
+    private final T initialValue;
+    private final Supplier<T> supplier;
+
+    public DerivedOptionValue(Supplier<T> supplier) {
+        this.supplier = supplier;
+        assert OptionValue.overrideScopes.get() == null : "derived option value should be initialized outside any override scope";
+        this.initialValue = createValue();
+    }
+
+    public T getValue() {
+        OverrideScope overrideScope = OptionValue.overrideScopes.get();
+        if (overrideScope != null) {
+            return overrideScope.getDerived(this);
+        } else {
+            return initialValue;
+        }
+    }
+
+    T createValue() {
+        return supplier.get();
+    }
+}
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java	Mon Aug 25 21:15:59 2014 -0700
@@ -39,7 +39,7 @@
  * retrieved as follows:
  *
  * <pre>
- * ServiceLoader&lt;Options&gt; sl = ServiceLoader.loadInstalled(Options.class);
+ * ServiceLoader&lt;Options&gt; sl = ServiceLoader.load(Options.class);
  * for (Options opts : sl) {
  *     for (OptionDescriptor desc : sl) {
  *         // use desc
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java	Mon Aug 25 21:15:59 2014 -0700
@@ -128,7 +128,7 @@
         return new MultipleOverridesScope(current, map);
     }
 
-    private static final ThreadLocal<OverrideScope> overrideScopes = new ThreadLocal<>();
+    static final ThreadLocal<OverrideScope> overrideScopes = new ThreadLocal<>();
 
     /**
      * The raw option value.
@@ -252,6 +252,22 @@
      * {@link OptionValue#override(OptionValue, Object)} or {@link OptionValue#override(Map)}.
      */
     public abstract static class OverrideScope implements AutoCloseable {
+
+        private Map<DerivedOptionValue<?>, Object> derivedCache = null;
+
+        public <T> T getDerived(DerivedOptionValue<T> key) {
+            if (derivedCache == null) {
+                derivedCache = new HashMap<>();
+            }
+            @SuppressWarnings("unchecked")
+            T ret = (T) derivedCache.get(key);
+            if (ret == null) {
+                ret = key.createValue();
+                derivedCache.put(key, ret);
+            }
+            return ret;
+        }
+
         abstract void addToInherited(Map<OptionValue<?>, Object> inherited);
 
         abstract <T> T getOverride(OptionValue<T> option);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -29,6 +29,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.util.*;
@@ -212,7 +213,7 @@
         }
 
         public static boolean tryGlobalValueNumbering(Node node, NodeClass nodeClass) {
-            if (nodeClass.valueNumberable() && !nodeClass.isLeafNode()) {
+            if (nodeClass.valueNumberable() && !node.isLeafNode()) {
                 Node newNode = node.graph().findDuplicate(node);
                 if (newNode != null) {
                     assert !(node instanceof FixedNode || newNode instanceof FixedNode);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -716,9 +716,9 @@
                     PiNode piNode;
                     if (isNull) {
                         ConstantNode nullObject = ConstantNode.defaultForKind(Kind.Object, graph);
-                        piNode = graph.unique(new PiNode(nullObject, StampFactory.forConstant(nullObject.getValue(), metaAccess), replacementAnchor.asNode()));
+                        piNode = graph.unique(PiNode.create(nullObject, StampFactory.forConstant(nullObject.getValue(), metaAccess), replacementAnchor.asNode()));
                     } else {
-                        piNode = graph.unique(new PiNode(object, StampFactory.declared(type, nonNull), replacementAnchor.asNode()));
+                        piNode = graph.unique(PiNode.create(object, StampFactory.declared(type, nonNull), replacementAnchor.asNode()));
                     }
                     checkCast.replaceAtUsages(piNode);
                     graph.removeFixed(checkCast);
@@ -770,7 +770,7 @@
 
                 if (replacement != null) {
                     if (replacementAnchor != null && !(replacementAnchor instanceof BeginNode)) {
-                        ValueAnchorNode anchor = graph.add(new ValueAnchorNode(replacementAnchor));
+                        ValueAnchorNode anchor = graph.add(ValueAnchorNode.create(replacementAnchor));
                         graph.addBeforeFixed(ifNode, anchor);
                     }
                     for (Node n : survivingSuccessor.usages().snapshot()) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -122,7 +122,7 @@
             IfNode ifNode = (IfNode) deoptBegin.predecessor();
             BeginNode otherBegin = ifNode.trueSuccessor();
             LogicNode conditionNode = ifNode.condition();
-            FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deoptReason, deoptAction, deoptBegin == ifNode.trueSuccessor()));
+            FixedGuardNode guard = graph.add(FixedGuardNode.create(conditionNode, deoptReason, deoptAction, deoptBegin == ifNode.trueSuccessor()));
             FixedWithNextNode pred = (FixedWithNextNode) ifNode.predecessor();
             BeginNode survivingSuccessor;
             if (deoptBegin == ifNode.trueSuccessor()) {
@@ -160,7 +160,7 @@
         FixedNode next = deoptPred.next();
 
         if (!(next instanceof DeoptimizeNode)) {
-            DeoptimizeNode newDeoptNode = graph.add(new DeoptimizeNode(deoptAction, deoptReason));
+            DeoptimizeNode newDeoptNode = graph.add(DeoptimizeNode.create(deoptAction, deoptReason));
             deoptPred.setNext(newDeoptNode);
             assert deoptPred == newDeoptNode.predecessor();
             GraphUtil.killCFG(next);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -55,10 +55,10 @@
                     }
                     MergeNode merge;
                     if (target instanceof AbstractDeoptimizeNode) {
-                        merge = graph.add(new MergeNode());
-                        EndNode firstEnd = graph.add(new EndNode());
-                        reasonActionPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(Kind.Int), merge));
-                        speculationPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(Kind.Object), merge));
+                        merge = graph.add(MergeNode.create());
+                        EndNode firstEnd = graph.add(EndNode.create());
+                        reasonActionPhi = graph.addWithoutUnique(ValuePhiNode.create(StampFactory.forKind(Kind.Int), merge));
+                        speculationPhi = graph.addWithoutUnique(ValuePhiNode.create(StampFactory.forKind(Kind.Object), merge));
                         merge.addForwardEnd(firstEnd);
                         reasonActionPhi.addInput(((AbstractDeoptimizeNode) target).getActionAndReason(context.getMetaAccess()));
                         speculationPhi.addInput(((AbstractDeoptimizeNode) target).getSpeculation(context.getMetaAccess()));
@@ -66,14 +66,14 @@
 
                         exitLoops((AbstractDeoptimizeNode) target, firstEnd, cfg);
 
-                        merge.setNext(graph.add(new DynamicDeoptimizeNode(reasonActionPhi, speculationPhi)));
+                        merge.setNext(graph.add(DynamicDeoptimizeNode.create(reasonActionPhi, speculationPhi)));
                         obsoletes = new LinkedList<>();
                         obsoletes.add((AbstractDeoptimizeNode) target);
                         target = merge;
                     } else {
                         merge = (MergeNode) target;
                     }
-                    EndNode newEnd = graph.add(new EndNode());
+                    EndNode newEnd = graph.add(EndNode.create());
                     merge.addForwardEnd(newEnd);
                     reasonActionPhi.addInput(deopt.getActionAndReason(context.getMetaAccess()));
                     speculationPhi.addInput(deopt.getSpeculation(context.getMetaAccess()));
@@ -95,7 +95,7 @@
         Block block = cfg.blockFor(deopt);
         Loop<Block> loop = block.getLoop();
         while (loop != null) {
-            end.graph().addBeforeFixed(end, end.graph().add(new LoopExitNode((LoopBeginNode) loop.getHeader().getBeginNode())));
+            end.graph().addBeforeFixed(end, end.graph().add(LoopExitNode.create((LoopBeginNode) loop.getHeader().getBeginNode())));
             loop = loop.getParent();
         }
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -72,16 +72,16 @@
         }
         ifNode.clearSuccessors();
         Graph graph = ifNode.graph();
-        MergeNode trueTargetMerge = graph.add(new MergeNode());
+        MergeNode trueTargetMerge = graph.add(MergeNode.create());
         trueTargetMerge.setNext(trueTarget);
-        EndNode firstTrueEnd = graph.add(new EndNode());
-        EndNode secondTrueEnd = graph.add(new EndNode());
+        EndNode firstTrueEnd = graph.add(EndNode.create());
+        EndNode secondTrueEnd = graph.add(EndNode.create());
         trueTargetMerge.addForwardEnd(firstTrueEnd);
         trueTargetMerge.addForwardEnd(secondTrueEnd);
         BeginNode firstTrueTarget = BeginNode.begin(firstTrueEnd);
         BeginNode secondTrueTarget = BeginNode.begin(secondTrueEnd);
-        BeginNode secondIf = BeginNode.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));
+        BeginNode secondIf = BeginNode.begin(graph.add(IfNode.create(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfProbability)));
+        IfNode firstIf = graph.add(IfNode.create(x, xNegated ? secondIf : firstTrueTarget, xNegated ? firstTrueTarget : secondIf, firstIfProbability));
         ifNode.replaceAtPredecessor(firstIf);
         ifNode.safeDelete();
     }
@@ -90,8 +90,8 @@
         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 ? secondConditional : trueTarget, xNegated ? trueTarget : secondConditional));
+        ConditionalNode secondConditional = graph.unique(ConditionalNode.create(y, yNegated ? falseTarget : trueTarget, yNegated ? trueTarget : falseTarget));
+        ConditionalNode firstConditional = graph.unique(ConditionalNode.create(x, xNegated ? secondConditional : trueTarget, xNegated ? trueTarget : secondConditional));
         conditional.replaceAndDelete(firstConditional);
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -186,7 +186,7 @@
                     } else {
                         MemoryPhiNode phi = null;
                         if (existingPhis == null || (phi = existingPhis.remove(key)) == null) {
-                            phi = merge.graph().addWithoutUnique(new MemoryPhiNode(merge, key));
+                            phi = merge.graph().addWithoutUnique(MemoryPhiNode.create(merge, key));
                         }
                         for (int j = 0; j < mergedStatesCount; j++) {
                             phi.addInput(ValueNodeUtil.asNode(merged));
@@ -291,7 +291,7 @@
             assert MemoryCheckpoint.TypeAssertion.correctType(node) : node;
 
             if (createMemoryMapNodes && node instanceof ReturnNode) {
-                ((ReturnNode) node).setMemoryMap(node.graph().unique(new MemoryMapNode(state.lastMemorySnapshot)));
+                ((ReturnNode) node).setMemoryMap(node.graph().unique(MemoryMapNode.create(state.lastMemorySnapshot)));
             }
             return state;
         }
@@ -331,7 +331,7 @@
                 ValueAnchorNode anchor = null;
                 GuardingNode guard = accessNode.getGuard();
                 if (guard != null) {
-                    anchor = graph.add(new ValueAnchorNode(guard.asNode()));
+                    anchor = graph.add(ValueAnchorNode.create(guard.asNode()));
                     graph.addAfterFixed(accessNode, anchor);
                 }
                 graph.replaceFixedWithFloating(accessNode, floatingNode);
@@ -385,7 +385,7 @@
 
             for (LocationIdentity location : modifiedLocations) {
                 if (!updateExistingPhis || !phis.containsKey(location)) {
-                    MemoryPhiNode phi = loop.graph().addWithoutUnique(new MemoryPhiNode(loop, location));
+                    MemoryPhiNode phi = loop.graph().addWithoutUnique(MemoryPhiNode.create(loop, location));
                     phi.addInput(ValueNodeUtil.asNode(initialState.getLastLocationAccess(location)));
                     phis.put(location, phi);
                 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -162,9 +162,9 @@
 
         private void lowerToIf(GuardNode guard) {
             StructuredGraph graph = guard.graph();
-            BeginNode fastPath = graph.add(new BeginNode());
+            BeginNode fastPath = graph.add(BeginNode.create());
             @SuppressWarnings("deprecation")
-            DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.action(), guard.reason(), useGuardIdAsDebugId ? guard.getId() : 0, guard.getSpeculation(), null));
+            DeoptimizeNode deopt = graph.add(DeoptimizeNode.create(guard.action(), guard.reason(), useGuardIdAsDebugId ? guard.getId() : 0, guard.getSpeculation(), null));
             BeginNode deoptBranch = BeginNode.begin(deopt);
             BeginNode trueSuccessor;
             BeginNode falseSuccessor;
@@ -176,7 +176,7 @@
                 trueSuccessor = fastPath;
                 falseSuccessor = deoptBranch;
             }
-            IfNode ifNode = graph.add(new IfNode(guard.condition(), trueSuccessor, falseSuccessor, trueSuccessor == fastPath ? 1 : 0));
+            IfNode ifNode = graph.add(IfNode.create(guard.condition(), trueSuccessor, falseSuccessor, trueSuccessor == fastPath ? 1 : 0));
             guard.replaceAndDelete(fastPath);
             insert(ifNode, fastPath);
         }
@@ -185,7 +185,7 @@
             Loop<Block> loop = block.getLoop();
             StructuredGraph graph = deopt.graph();
             while (loop != null) {
-                LoopExitNode exit = graph.add(new LoopExitNode((LoopBeginNode) loop.getHeader().getBeginNode()));
+                LoopExitNode exit = graph.add(LoopExitNode.create((LoopBeginNode) loop.getHeader().getBeginNode()));
                 graph.addBeforeFixed(deopt, exit);
                 loop = loop.getParent();
             }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -37,7 +37,7 @@
         if (GenLoopSafepoints.getValue()) {
             for (LoopEndNode loopEndNode : graph.getNodes(LoopEndNode.class)) {
                 if (loopEndNode.canSafepoint()) {
-                    SafepointNode safepointNode = graph.add(new SafepointNode());
+                    SafepointNode safepointNode = graph.add(SafepointNode.create());
                     graph.addBeforeFixed(loopEndNode, safepointNode);
                 }
             }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -32,6 +32,7 @@
 import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.cfg.*;
@@ -46,6 +47,34 @@
  */
 public class LoweringPhase extends BasePhase<PhaseContext> {
 
+    @NodeInfo
+    static class DummyGuardHandle extends ValueNode implements GuardedNode {
+        @Input(InputType.Guard) GuardingNode guard;
+
+        public static DummyGuardHandle create(GuardingNode guard) {
+            return USE_GENERATED_NODES ? new LoweringPhase_DummyGuardHandleGen(guard) : new DummyGuardHandle(guard);
+        }
+
+        protected DummyGuardHandle(GuardingNode guard) {
+            super(StampFactory.forVoid());
+            this.guard = guard;
+        }
+
+        public GuardingNode getGuard() {
+            return guard;
+        }
+
+        public void setGuard(GuardingNode guard) {
+            updateUsagesInterface(this.guard, guard);
+            this.guard = guard;
+        }
+
+        @Override
+        public ValueNode asNode() {
+            return this;
+        }
+    }
+
     final class LoweringToolImpl implements LoweringTool {
 
         private final PhaseContext context;
@@ -102,30 +131,6 @@
             return context.getAssumptions();
         }
 
-        private class DummyGuardHandle extends ValueNode implements GuardedNode {
-            @Input(InputType.Guard) private GuardingNode guard;
-
-            public DummyGuardHandle(GuardingNode guard) {
-                super(StampFactory.forVoid());
-                this.guard = guard;
-            }
-
-            public GuardingNode getGuard() {
-                return guard;
-            }
-
-            public void setGuard(GuardingNode guard) {
-                updateUsagesInterface(this.guard, guard);
-                this.guard = guard;
-            }
-
-            @Override
-            public ValueNode asNode() {
-                return this;
-            }
-
-        }
-
         @Override
         public GuardingNode createGuard(FixedNode before, LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
             if (OptEliminateGuards.getValue()) {
@@ -137,13 +142,13 @@
             }
             StructuredGraph graph = before.graph();
             if (condition.graph().getGuardsStage().ordinal() >= StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal()) {
-                FixedGuardNode fixedGuard = graph.add(new FixedGuardNode(condition, deoptReason, action, negated));
+                FixedGuardNode fixedGuard = graph.add(FixedGuardNode.create(condition, deoptReason, action, negated));
                 graph.addBeforeFixed(before, fixedGuard);
-                DummyGuardHandle handle = graph.add(new DummyGuardHandle(fixedGuard));
+                DummyGuardHandle handle = graph.add(DummyGuardHandle.create(fixedGuard));
                 fixedGuard.lower(this);
                 return handle.getGuard();
             } else {
-                GuardNode newGuard = graph.unique(new GuardNode(condition, guardAnchor, deoptReason, action, negated, Constant.NULL_OBJECT));
+                GuardNode newGuard = graph.unique(GuardNode.create(condition, guardAnchor, deoptReason, action, negated, Constant.NULL_OBJECT));
                 if (OptEliminateGuards.getValue()) {
                     activeGuards.markAndGrow(newGuard);
                 }
@@ -336,7 +341,7 @@
                         // FixedWithNextNode is followed by some kind of BeginNode.
                         // For example the when a FixedGuard followed by a loop exit is lowered to a
                         // control-split + deopt.
-                        BeginNode begin = node.graph().add(new BeginNode());
+                        BeginNode begin = node.graph().add(BeginNode.create());
                         nextLastFixed.replaceFirstSuccessor(nextNode, begin);
                         begin.setNext(nextNode);
                         nextLastFixed = begin;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -110,7 +110,7 @@
 
             if (otherGuards.size() == successorCount - 1) {
                 BeginNode anchor = computeOptimalAnchor(cfg.get(), BeginNode.prevBegin(controlSplit));
-                GuardNode newGuard = controlSplit.graph().unique(new GuardNode(guard.condition(), anchor, guard.reason(), guard.action(), guard.negated(), guard.getSpeculation()));
+                GuardNode newGuard = controlSplit.graph().unique(GuardNode.create(guard.condition(), anchor, guard.reason(), guard.action(), guard.negated(), guard.getSpeculation()));
                 for (GuardNode otherGuard : otherGuards) {
                     otherGuard.replaceAndDelete(newGuard);
                 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -34,7 +34,7 @@
 import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.NodeClass.NodeClassIterator;
-import com.oracle.graal.graph.NodeClass.Position;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.VirtualState.NodeClosure;
 import com.oracle.graal.nodes.extended.*;
@@ -61,8 +61,13 @@
 
     private final CanonicalizerPhase canonicalizer;
 
-    private static final class DummyAnchorNode extends FixedWithNextNode implements GuardingNode {
-        public DummyAnchorNode() {
+    @NodeInfo
+    static class DummyAnchorNode extends FixedWithNextNode implements GuardingNode {
+        public static DummyAnchorNode create() {
+            return USE_GENERATED_NODES ? new TailDuplicationPhase_DummyAnchorNodeGen() : new DummyAnchorNode();
+        }
+
+        protected DummyAnchorNode() {
             super(StampFactory.forVoid());
         }
     }
@@ -337,7 +342,7 @@
          * @return The new {@link ValueAnchorNode} that was created.
          */
         private DummyAnchorNode addValueAnchor() {
-            DummyAnchorNode anchor = graph.add(new DummyAnchorNode());
+            DummyAnchorNode anchor = graph.add(DummyAnchorNode.create());
             graph.addAfterFixed(merge, anchor);
             merge.replaceAtUsages(InputType.Guard, anchor);
             merge.replaceAtUsages(InputType.Anchor, anchor);
@@ -447,8 +452,8 @@
          * @return The newly created end node.
          */
         private AbstractEndNode createNewMerge(FixedNode successor, FrameState stateAfterMerge) {
-            MergeNode newBottomMerge = graph.add(new MergeNode());
-            AbstractEndNode newBottomEnd = graph.add(new EndNode());
+            MergeNode newBottomMerge = graph.add(MergeNode.create());
+            AbstractEndNode newBottomEnd = graph.add(EndNode.create());
             newBottomMerge.addForwardEnd(newBottomEnd);
             newBottomMerge.setStateAfter(stateAfterMerge);
             ((FixedWithNextNode) successor.predecessor()).setNext(newBottomEnd);
@@ -522,7 +527,7 @@
                                     ValueNode node = (ValueNode) duplicated;
                                     PhiNode newPhi = bottomPhis.get(node);
                                     if (newPhi == null) {
-                                        newPhi = graph.addWithoutUnique(new ValuePhiNode(node.stamp().unrestricted(), newBottomMerge));
+                                        newPhi = graph.addWithoutUnique(ValuePhiNode.create(node.stamp().unrestricted(), newBottomMerge));
                                         bottomPhis.put(node, newPhi);
                                         newPhi.addInput(node);
                                     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,6 +27,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
 import com.oracle.graal.nodes.calc.*;
@@ -161,7 +162,7 @@
         IsNullNode isNullNode = (IsNullNode) condition;
         BeginNode nonTrappingContinuation = ifNode.falseSuccessor();
         BeginNode trappingContinuation = ifNode.trueSuccessor();
-        NullCheckNode trappingNullCheck = deopt.graph().add(new NullCheckNode(isNullNode.getValue()));
+        NullCheckNode trappingNullCheck = deopt.graph().add(NullCheckNode.create(isNullNode.getValue()));
         trappingNullCheck.setStateBefore(deopt.stateBefore());
         deopt.graph().replaceSplit(ifNode, trappingNullCheck, nonTrappingContinuation);
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/BaseReduction.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/BaseReduction.java	Mon Aug 25 21:15:59 2014 -0700
@@ -97,7 +97,7 @@
             metricUnconditionalDeoptInserted.increment();
             StructuredGraph graph = fixed.graph();
             // have to insert a FixedNode other than a ControlSinkNode
-            FixedGuardNode buckStopsHere = graph.add(new FixedGuardNode(falseConstant, deoptReason, DeoptimizationAction.None));
+            FixedGuardNode buckStopsHere = graph.add(FixedGuardNode.create(falseConstant, deoptReason, DeoptimizationAction.None));
             if (goesBeforeFixed) {
                 fixed.replaceAtPredecessor(buckStopsHere);
             } else {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CheckCastReduction.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CheckCastReduction.java	Mon Aug 25 21:15:59 2014 -0700
@@ -231,7 +231,7 @@
              * (1 of 3) definitely-non-null
              */
             // addWithoutUnique for the same reason as in CheckCastNode.lower()
-            condition = graph.addWithoutUnique(new InstanceOfNode(toType, subject, profile));
+            condition = graph.addWithoutUnique(InstanceOfNode.create(toType, subject, profile));
             reasoner.added.add(condition);
             resultStamp = FlowUtil.asNonNullStamp(resultStamp);
             // TODO fix in CheckCastNode.lower()
@@ -240,15 +240,15 @@
                 /*
                  * (2 of 3) null-not-seen-in-profiling
                  */
-                IsNullNode isNN = graph.unique(new IsNullNode(subject));
+                IsNullNode isNN = graph.unique(IsNullNode.create(subject));
                 reasoner.added.add(isNN);
-                FixedGuardNode nullCheck = graph.add(new FixedGuardNode(isNN, UnreachedCode, InvalidateReprofile, true));
+                FixedGuardNode nullCheck = graph.add(FixedGuardNode.create(isNN, UnreachedCode, InvalidateReprofile, true));
                 graph.addBeforeFixed(checkCast, nullCheck);
                 // not calling wrapInPiNode() because we don't want to rememberSubstitution()
-                PiNode nonNullGuarded = graph.unique(new PiNode(subject, FlowUtil.asNonNullStamp(subjectStamp), nullCheck));
+                PiNode nonNullGuarded = graph.unique(PiNode.create(subject, FlowUtil.asNonNullStamp(subjectStamp), nullCheck));
                 reasoner.added.add(nonNullGuarded);
                 // addWithoutUnique for the same reason as in CheckCastNode.lower()
-                condition = graph.addWithoutUnique(new InstanceOfNode(toType, nonNullGuarded, profile));
+                condition = graph.addWithoutUnique(InstanceOfNode.create(toType, nonNullGuarded, profile));
                 reasoner.added.add(condition);
                 resultStamp = FlowUtil.asNonNullStamp(resultStamp);
             } else {
@@ -256,9 +256,9 @@
                  * (3 of 3) runtime-null-check-needed
                  */
                 // addWithoutUnique for the same reason as in CheckCastNode.lower()
-                InstanceOfNode typeTest = graph.addWithoutUnique(new InstanceOfNode(toType, subject, profile));
+                InstanceOfNode typeTest = graph.addWithoutUnique(InstanceOfNode.create(toType, subject, profile));
                 reasoner.added.add(typeTest);
-                LogicNode nullTest = graph.unique(new IsNullNode(subject));
+                LogicNode nullTest = graph.unique(IsNullNode.create(subject));
                 reasoner.added.add(nullTest);
                 // TODO (ds) replace with probability of null-seen when available
                 final double shortCircuitProbability = NOT_FREQUENT_PROBABILITY;
@@ -271,7 +271,7 @@
          * Add a cast-guard (checking only what needs to be checked) and a PiNode (to be used in
          * place of the CheckCastNode).
          */
-        FixedGuardNode castGuard = graph.add(new FixedGuardNode(condition, checkCast.isForStoreCheck() ? ArrayStoreException : ClassCastException, InvalidateReprofile));
+        FixedGuardNode castGuard = graph.add(FixedGuardNode.create(condition, checkCast.isForStoreCheck() ? ArrayStoreException : ClassCastException, InvalidateReprofile));
         graph.addBeforeFixed(checkCast, castGuard);
 
         assert FlowUtil.isLegalObjectStamp(resultStamp);
@@ -280,7 +280,7 @@
 
         if (!FlowUtil.lacksUsages(checkCast)) {
             // not calling wrapInPiNode() because we don't want to rememberSubstitution()
-            PiNode checkedObject = graph.unique(new PiNode(subject, resultStamp, castGuard));
+            PiNode checkedObject = graph.unique(PiNode.create(subject, resultStamp, castGuard));
             reasoner.added.add(checkedObject);
             assert !precisionLoss(originalCheckCastObject, checkedObject);
             assert !precisionLoss(subject, checkedObject);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java	Mon Aug 25 21:15:59 2014 -0700
@@ -46,8 +46,8 @@
  * Such evaluator comes handy when visiting a {@link com.oracle.graal.nodes.FixedNode} N, just
  * before updating the state for N. At the pre-state, an {@link EquationalReasoner} can be used to
  * reduce N's inputs (actually only those inputs of Value and Condition
- * {@link com.oracle.graal.graph.InputType InputType}). For an explanation of where it's warranted
- * to replace "old input" with "reduced input", see the inline comments in method
+ * {@link com.oracle.graal.nodeinfo.InputType InputType}). For an explanation of where it's
+ * warranted to replace "old input" with "reduced input", see the inline comments in method
  * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node n) deverbosify(Node n)}
  * </p>
  *
@@ -664,7 +664,7 @@
         try (Debug.Scope s = Debug.scope("Downcast", payload)) {
             assert payload != anchor : payload.graph().toString();
             metricDowncasting.increment();
-            PiNode result = graph.unique(new PiNode(payload, newStamp, anchor.asNode()));
+            PiNode result = graph.unique(PiNode.create(payload, newStamp, anchor.asNode()));
             // we've possibly got a new node in the graph --- bookkeeping is in order.
             added.add(result);
             if (remember) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java	Mon Aug 25 21:15:59 2014 -0700
@@ -499,9 +499,9 @@
          * state-tracking. TODO the assumption here is that the code emitted for the resulting
          * FixedGuardNode is as efficient as for NullCheckNode.
          */
-        IsNullNode isNN = graph.unique(new IsNullNode(object));
+        IsNullNode isNN = graph.unique(IsNullNode.create(object));
         reasoner.added.add(isNN);
-        FixedGuardNode nullCheck = graph.add(new FixedGuardNode(isNN, UnreachedCode, InvalidateReprofile, true));
+        FixedGuardNode nullCheck = graph.add(FixedGuardNode.create(isNN, UnreachedCode, InvalidateReprofile, true));
         graph.replaceFixedWithFixed(ncn, nullCheck);
 
         state.trackNN(object, nullCheck);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,18 +22,13 @@
  */
 package com.oracle.graal.phases.common.cfs;
 
-import com.oracle.graal.api.meta.ResolvedJavaType;
-import com.oracle.graal.graph.InputType;
-import com.oracle.graal.graph.Node;
-import com.oracle.graal.graph.NodeClass;
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.compiler.common.type.ObjectStamp;
-import com.oracle.graal.compiler.common.type.Stamp;
-import com.oracle.graal.compiler.common.type.StampFactory;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
 
 public class FlowUtil {
 
@@ -236,7 +231,7 @@
         ArrayList<ValueNode> result = null;
         NodeClass.NodeClassIterator iter = n.inputs().iterator();
         while (iter.hasNext()) {
-            NodeClass.Position pos = iter.nextPosition();
+            Position pos = iter.nextPosition();
             InputType inputType = pos.getInputType(n);
             boolean isReducibleInput = (inputType == InputType.Value || inputType == InputType.Condition);
             if (isReducibleInput) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/GuardingPiReduction.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/GuardingPiReduction.java	Mon Aug 25 21:15:59 2014 -0700
@@ -141,7 +141,7 @@
          * FixedGuardNode allows tracking the condition via a GuardingNode, thus potentially
          * triggering simplifications down the road.
          */
-        FixedGuardNode fixedGuard = graph.add(new FixedGuardNode(envelope.condition(), envelope.getReason(), envelope.getAction(), envelope.isNegated()));
+        FixedGuardNode fixedGuard = graph.add(FixedGuardNode.create(envelope.condition(), envelope.getReason(), envelope.getAction(), envelope.isNegated()));
         graph.addBeforeFixed(envelope, fixedGuard);
 
         /*
@@ -152,7 +152,7 @@
 
         if (!FlowUtil.lacksUsages(envelope)) {
             // not calling wrapInPiNode() because we don't want to rememberSubstitution()
-            PiNode replacement = graph.unique(new PiNode(envelope.object(), envelope.stamp(), fixedGuard));
+            PiNode replacement = graph.unique(PiNode.create(envelope.object(), envelope.stamp(), fixedGuard));
             reasoner.added.add(replacement);
             // before removing the GuardingPiNode replace its usages
             envelope.replaceAtUsages(replacement);
@@ -182,8 +182,8 @@
      * Provided a condition as above can be reduced to a constant (and an anchor obtained in the
      * process), this method replaces all usages of the
      * {@link com.oracle.graal.nodes.GuardingPiNode} (necessarily of
-     * {@link com.oracle.graal.graph.InputType#Value}) with a {@link com.oracle.graal.nodes.PiNode}
-     * that wraps the payload and the anchor in question.
+     * {@link com.oracle.graal.nodeinfo.InputType#Value}) with a
+     * {@link com.oracle.graal.nodes.PiNode} that wraps the payload and the anchor in question.
      * </p>
      * 
      * <p>
@@ -281,7 +281,7 @@
                  * TODO The GuardingPiNode has an outgoing stamp whose narrowing goes beyond what
                  * the condition checks. That's suspicious.
                  */
-                PiNode replacement = graph.unique(new PiNode(payload, envelope.stamp()));
+                PiNode replacement = graph.unique(PiNode.create(payload, envelope.stamp()));
                 reasoner.added.add(replacement);
                 removeGuardingPiNode(envelope, replacement);
                 return true;
@@ -295,7 +295,7 @@
         Witness w = state.typeInfo(payload);
         GuardingNode nonNullAnchor = (w != null && w.isNonNull()) ? w.guard() : null;
         if (nonNullAnchor != null) {
-            PiNode replacement = graph.unique(new PiNode(payload, envelope.stamp(), nonNullAnchor.asNode()));
+            PiNode replacement = graph.unique(PiNode.create(payload, envelope.stamp(), nonNullAnchor.asNode()));
             reasoner.added.add(replacement);
             removeGuardingPiNode(envelope, replacement);
             return true;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,6 +27,7 @@
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.compiler.common.type.StampFactory.*;
 
+import java.lang.reflect.*;
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
@@ -37,7 +38,7 @@
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Graph.DuplicationReplacement;
-import com.oracle.graal.graph.Node.Verbosity;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.calc.*;
@@ -175,7 +176,7 @@
 
     public static void replaceInvokeCallTarget(Invoke invoke, StructuredGraph graph, InvokeKind invokeKind, ResolvedJavaMethod targetMethod) {
         MethodCallTargetNode oldCallTarget = (MethodCallTargetNode) invoke.callTarget();
-        MethodCallTargetNode newCallTarget = graph.add(new MethodCallTargetNode(invokeKind, targetMethod, oldCallTarget.arguments().toArray(new ValueNode[0]), oldCallTarget.returnType()));
+        MethodCallTargetNode newCallTarget = graph.add(MethodCallTargetNode.create(invokeKind, targetMethod, oldCallTarget.arguments().toArray(new ValueNode[0]), oldCallTarget.returnType()));
         invoke.asNode().replaceFirstInput(oldCallTarget, newCallTarget);
     }
 
@@ -185,7 +186,7 @@
 
     private static GuardedValueNode createAnchoredReceiver(StructuredGraph graph, GuardingNode anchor, ValueNode receiver, Stamp stamp) {
         // to avoid that floating reads on receiver fields float above the type check
-        return graph.unique(new GuardedValueNode(receiver, anchor, stamp));
+        return graph.unique(GuardedValueNode.create(receiver, anchor, stamp));
     }
 
     /**
@@ -301,7 +302,7 @@
             // get rid of memory kill
             BeginNode begin = invokeWithException.next();
             if (begin instanceof KillingBeginNode) {
-                BeginNode newBegin = new BeginNode();
+                BeginNode newBegin = BeginNode.create();
                 graph.addAfterFixed(begin, graph.add(newBegin));
                 begin.replaceAtUsages(newBegin);
                 graph.removeFixed(begin);
@@ -309,7 +310,7 @@
         } else {
             if (unwindNode != null) {
                 UnwindNode unwindDuplicate = (UnwindNode) duplicates.get(unwindNode);
-                DeoptimizeNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler));
+                DeoptimizeNode deoptimizeNode = graph.add(DeoptimizeNode.create(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler));
                 unwindDuplicate.replaceAndDelete(deoptimizeNode);
             }
         }
@@ -340,7 +341,7 @@
                 for (ReturnNode returnNode : returnNodes) {
                     returnDuplicates.add((ReturnNode) duplicates.get(returnNode));
                 }
-                MergeNode merge = graph.add(new MergeNode());
+                MergeNode merge = graph.add(MergeNode.create());
                 merge.setStateAfter(stateAfter);
                 ValueNode returnValue = mergeReturns(merge, returnDuplicates, canonicalizedNodes);
                 invokeNode.replaceAtUsages(returnValue);
@@ -385,7 +386,7 @@
                      * return value (top of stack)
                      */
                     FrameState stateAfterReturn = stateAtReturn;
-                    if (invokeReturnKind != Kind.Void && (alwaysDuplicateStateAfter || frameState.stackSize() > 0 && stateAfterReturn.stackAt(0) != frameState.stackAt(0))) {
+                    if (invokeReturnKind != Kind.Void && (alwaysDuplicateStateAfter || (frameState.stackSize() > 0 && stateAfterReturn.stackAt(0) != frameState.stackAt(0)))) {
                         stateAfterReturn = stateAtReturn.duplicateModified(invokeReturnKind, frameState.stackAt(0));
                     }
                     frameState.replaceAndDelete(stateAfterReturn);
@@ -442,12 +443,12 @@
                         MergeNode merge = (MergeNode) fixedStateSplit;
                         while (merge.isAlive()) {
                             AbstractEndNode end = merge.forwardEnds().first();
-                            DeoptimizeNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler));
+                            DeoptimizeNode deoptimizeNode = graph.add(DeoptimizeNode.create(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler));
                             end.replaceAtPredecessor(deoptimizeNode);
                             GraphUtil.killCFG(end);
                         }
                     } else {
-                        FixedNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler));
+                        FixedNode deoptimizeNode = graph.add(DeoptimizeNode.create(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler));
                         if (fixedStateSplit instanceof BeginNode) {
                             deoptimizeNode = BeginNode.begin(deoptimizeNode);
                         }
@@ -464,12 +465,12 @@
 
         for (ReturnNode returnNode : returnNodes) {
             // create and wire up a new EndNode
-            EndNode endNode = merge.graph().add(new EndNode());
+            EndNode endNode = merge.graph().add(EndNode.create());
             merge.addForwardEnd(endNode);
 
             if (returnNode.result() != null) {
                 if (returnValuePhi == null) {
-                    returnValuePhi = merge.graph().addWithoutUnique(new ValuePhiNode(returnNode.result().stamp().unrestricted(), merge));
+                    returnValuePhi = merge.graph().addWithoutUnique(ValuePhiNode.create(returnNode.result().stamp().unrestricted(), merge));
                     if (canonicalizedNodes != null) {
                         canonicalizedNodes.add(returnValuePhi);
                     }
@@ -501,9 +502,9 @@
         StructuredGraph graph = callTarget.graph();
         ValueNode firstParam = callTarget.arguments().get(0);
         if (firstParam.getKind() == Kind.Object && !StampTool.isObjectNonNull(firstParam)) {
-            IsNullNode condition = graph.unique(new IsNullNode(firstParam));
+            IsNullNode condition = graph.unique(IsNullNode.create(firstParam));
             Stamp stamp = firstParam.stamp().join(objectNonNull());
-            GuardingPiNode nonNullReceiver = graph.add(new GuardingPiNode(firstParam, condition, true, NullCheckException, InvalidateReprofile, stamp));
+            GuardingPiNode nonNullReceiver = graph.add(GuardingPiNode.create(firstParam, condition, true, NullCheckException, InvalidateReprofile, stamp));
             graph.addBeforeFixed(invoke.asNode(), nonNullReceiver);
             callTarget.replaceFirstInput(firstParam, nonNullReceiver);
             return nonNullReceiver;
@@ -546,7 +547,8 @@
 
     private static FixedWithNextNode createMacroNodeInstance(Class<? extends FixedWithNextNode> macroNodeClass, Invoke invoke) throws GraalInternalError {
         try {
-            return macroNodeClass.getConstructor(Invoke.class).newInstance(invoke);
+            Method factory = macroNodeClass.getDeclaredMethod("create", Invoke.class);
+            return (FixedWithNextNode) factory.invoke(null, invoke);
         } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
             throw new GraalGraphInternalError(e).addContext(invoke.asNode()).addContext("macroSubstitution", macroNodeClass);
         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Mon Aug 25 21:15:59 2014 -0700
@@ -172,12 +172,12 @@
 
         ValueNode originalReceiver = ((MethodCallTargetNode) invoke.callTarget()).receiver();
         // setup merge and phi nodes for results and exceptions
-        MergeNode returnMerge = graph.add(new MergeNode());
+        MergeNode returnMerge = graph.add(MergeNode.create());
         returnMerge.setStateAfter(invoke.stateAfter());
 
         PhiNode returnValuePhi = null;
         if (invoke.asNode().getKind() != Kind.Void) {
-            returnValuePhi = graph.addWithoutUnique(new ValuePhiNode(invoke.asNode().stamp().unrestricted(), returnMerge));
+            returnValuePhi = graph.addWithoutUnique(ValuePhiNode.create(invoke.asNode().stamp().unrestricted(), returnMerge));
         }
 
         MergeNode exceptionMerge = null;
@@ -186,11 +186,11 @@
             InvokeWithExceptionNode invokeWithException = (InvokeWithExceptionNode) invoke;
             ExceptionObjectNode exceptionEdge = (ExceptionObjectNode) invokeWithException.exceptionEdge();
 
-            exceptionMerge = graph.add(new MergeNode());
+            exceptionMerge = graph.add(MergeNode.create());
 
             FixedNode exceptionSux = exceptionEdge.next();
             graph.addBeforeFixed(exceptionSux, exceptionMerge);
-            exceptionObjectPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(Kind.Object), exceptionMerge));
+            exceptionObjectPhi = graph.addWithoutUnique(ValuePhiNode.create(StampFactory.forKind(Kind.Object), exceptionMerge));
             exceptionMerge.setStateAfter(exceptionEdge.stateAfter().duplicateModified(invoke.stateAfter().bci, true, Kind.Object, exceptionObjectPhi));
         }
 
@@ -205,7 +205,7 @@
         if (shouldFallbackToInvoke()) {
             unknownTypeSux = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, false);
         } else {
-            unknownTypeSux = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated));
+            unknownTypeSux = graph.add(DeoptimizeNode.create(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated));
         }
         successors[successors.length - 1] = BeginNode.begin(unknownTypeSux);
 
@@ -329,7 +329,7 @@
     private Collection<Node> inlineSingleMethod(StructuredGraph graph, MetaAccessProvider metaAccess, Assumptions assumptions) {
         assert concretes.size() == 1 && inlineableElements.length == 1 && ptypes.size() > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0;
 
-        BeginNode calleeEntryNode = graph.add(new BeginNode());
+        BeginNode calleeEntryNode = graph.add(BeginNode.create());
 
         BeginNode unknownTypeSux = createUnknownTypeSuccessor(graph);
         BeginNode[] successors = new BeginNode[]{calleeEntryNode, unknownTypeSux};
@@ -344,7 +344,7 @@
         assert ptypes.size() >= 1;
         ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke);
         Kind hubKind = ((MethodCallTargetNode) invoke.callTarget()).targetMethod().getDeclaringClass().getEncoding(ResolvedJavaType.Representation.ObjectHub).getKind();
-        LoadHubNode hub = graph.unique(new LoadHubNode(nonNullReceiver, hubKind));
+        LoadHubNode hub = graph.unique(LoadHubNode.create(nonNullReceiver, hubKind));
 
         if (!invokeIsOnlySuccessor && chooseMethodDispatch()) {
             assert successors.length == concretes.size() + 1;
@@ -375,9 +375,9 @@
             ResolvedJavaType receiverType = invoke.getReceiverType();
             FixedNode lastSucc = successors[concretes.size()];
             for (int i = concretes.size() - 1; i >= 0; --i) {
-                LoadMethodNode method = graph.add(new LoadMethodNode(concretes.get(i), receiverType, hub, constantMethods[i].getKind()));
+                LoadMethodNode method = graph.add(LoadMethodNode.create(concretes.get(i), receiverType, hub, constantMethods[i].getKind()));
                 CompareNode methodCheck = CompareNode.createCompareNode(graph, Condition.EQ, method, constantMethods[i]);
-                IfNode ifNode = graph.add(new IfNode(methodCheck, successors[i], lastSucc, probability[i]));
+                IfNode ifNode = graph.add(IfNode.create(methodCheck, successors[i], lastSucc, probability[i]));
                 method.setNext(ifNode);
                 lastSucc = method;
             }
@@ -408,7 +408,7 @@
             keyProbabilities[i] /= totalProbability;
         }
 
-        TypeSwitchNode typeSwitch = graph.add(new TypeSwitchNode(hub, successors, keys, keyProbabilities, keySuccessors));
+        TypeSwitchNode typeSwitch = graph.add(TypeSwitchNode.create(hub, successors, keys, keyProbabilities, keySuccessors));
         FixedWithNextNode pred = (FixedWithNextNode) invoke.asNode().predecessor();
         pred.setNext(typeSwitch);
         return false;
@@ -462,10 +462,10 @@
     private static BeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, MergeNode returnMerge, PhiNode returnValuePhi, MergeNode exceptionMerge, PhiNode exceptionObjectPhi,
                     boolean useForInlining) {
         Invoke duplicatedInvoke = duplicateInvokeForInlining(graph, invoke, exceptionMerge, exceptionObjectPhi, useForInlining);
-        BeginNode calleeEntryNode = graph.add(new BeginNode());
+        BeginNode calleeEntryNode = graph.add(BeginNode.create());
         calleeEntryNode.setNext(duplicatedInvoke.asNode());
 
-        AbstractEndNode endNode = graph.add(new EndNode());
+        AbstractEndNode endNode = graph.add(EndNode.create());
         duplicatedInvoke.setNext(endNode);
         returnMerge.addForwardEnd(endNode);
 
@@ -500,7 +500,7 @@
             // set new state (pop old exception object, push new one)
             newExceptionEdge.setStateAfter(stateAfterException.duplicateModified(stateAfterException.bci, stateAfterException.rethrowException(), Kind.Object, newExceptionEdge));
 
-            AbstractEndNode endNode = graph.add(new EndNode());
+            AbstractEndNode endNode = graph.add(EndNode.create());
             newExceptionEdge.setNext(endNode);
             exceptionMerge.addForwardEnd(endNode);
             exceptionObjectPhi.addInput(newExceptionEdge);
@@ -538,7 +538,7 @@
     }
 
     private void devirtualizeWithTypeSwitch(StructuredGraph graph, InvokeKind kind, ResolvedJavaMethod target, MetaAccessProvider metaAccess) {
-        BeginNode invocationEntry = graph.add(new BeginNode());
+        BeginNode invocationEntry = graph.add(BeginNode.create());
         BeginNode unknownTypeSux = createUnknownTypeSuccessor(graph);
         BeginNode[] successors = new BeginNode[]{invocationEntry, unknownTypeSux};
         createDispatchOnTypeBeforeInvoke(graph, successors, true, metaAccess);
@@ -551,7 +551,7 @@
     }
 
     private static BeginNode createUnknownTypeSuccessor(StructuredGraph graph) {
-        return BeginNode.begin(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated)));
+        return BeginNode.begin(graph.add(DeoptimizeNode.create(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated)));
     }
 
     @Override
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java	Mon Aug 25 21:15:59 2014 -0700
@@ -104,10 +104,10 @@
     private void createGuard(StructuredGraph graph, MetaAccessProvider metaAccess) {
         ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke);
         ConstantNode typeHub = ConstantNode.forConstant(type.getEncoding(ResolvedJavaType.Representation.ObjectHub), metaAccess, graph);
-        LoadHubNode receiverHub = graph.unique(new LoadHubNode(nonNullReceiver, typeHub.getKind()));
+        LoadHubNode receiverHub = graph.unique(LoadHubNode.create(nonNullReceiver, typeHub.getKind()));
 
         CompareNode typeCheck = CompareNode.createCompareNode(graph, Condition.EQ, receiverHub, typeHub);
-        FixedGuardNode guard = graph.add(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile));
+        FixedGuardNode guard = graph.add(FixedGuardNode.create(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile));
         assert invoke.predecessor() != null;
 
         ValueNode anchoredReceiver = InliningUtil.createAnchoredReceiver(graph, guard, type, nonNullReceiver, true);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/ComputeInliningRelevance.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/ComputeInliningRelevance.java	Mon Aug 25 21:15:59 2014 -0700
@@ -116,7 +116,7 @@
                         parent = loops.get(null);
                         break;
                     } else {
-                        assert current.getClass() == MergeNode.class : current;
+                        assert current.getClass() == MergeNode.getGenClass() : current;
                         // follow any path upwards - it doesn't matter which one
                         current = ((MergeNode) current).forwardEndAt(0);
                     }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -33,7 +33,7 @@
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.Verbosity;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java	Mon Aug 25 21:15:59 2014 -0700
@@ -83,26 +83,19 @@
             }
         }
 
-        if (CompilerConfiguration.getValue().equals("")) {
-            if (nonBasicCount == 1) {
-                /*
-                 * There is exactly one non-basic configuration. We use this one as default.
-                 */
-                defaultConfiguration = nonBasic;
-            } else {
-                /*
-                 * There is either no extended configuration available, or more than one. In that
-                 * case, default to "basic".
-                 */
-                defaultConfiguration = basic;
-                if (defaultConfiguration == null) {
-                    throw new GraalInternalError("unable to find basic compiler configuration");
-                }
-            }
+        if (nonBasicCount == 1) {
+            /*
+             * There is exactly one non-basic configuration. We use this one as default.
+             */
+            defaultConfiguration = nonBasic;
         } else {
-            defaultConfiguration = configurations.get(CompilerConfiguration.getValue());
+            /*
+             * There is either no extended configuration available, or more than one. In that case,
+             * default to "basic".
+             */
+            defaultConfiguration = basic;
             if (defaultConfiguration == null) {
-                throw new GraalInternalError("unknown compiler configuration: " + CompilerConfiguration.getValue());
+                throw new GraalInternalError("unable to find basic compiler configuration");
             }
         }
     }
@@ -120,7 +113,12 @@
     }
 
     public static Suites createDefaultSuites() {
-        return new Suites(defaultConfiguration);
+        String selected = CompilerConfiguration.getValue();
+        if (selected.equals("")) {
+            return new Suites(defaultConfiguration);
+        } else {
+            return createSuites(selected);
+        }
     }
 
     public static Suites createSuites(String name) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyNoNodeClassLiteralIdentityTests.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.verify;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.tiers.*;
+
+/**
+ * Since only {@linkplain GeneratedNode generated} {@link Node} types can be instantiated (which is
+ * checked by an assertion in {@link Node#Node()}), any identity test of a node's
+ * {@linkplain Object#getClass() class} against a class literal of a non-generated node types will
+ * always return false. Instead, a static {@code getGenClass()} helper method should be used for
+ * such identity tests. For example, instead of:
+ *
+ * <pre>
+ *     if (operation.getClass() == IntegerAddNode.class) { ... }
+ * </pre>
+ *
+ * this should be used:
+ *
+ * <pre>
+ *     if (operation.getClass() == IntegerAddNode.getGenClass()) { ... }
+ * </pre>
+ *
+ * This phase verifies there are no identity tests against class literals for non-generated Node
+ * types.
+ */
+public class VerifyNoNodeClassLiteralIdentityTests extends VerifyPhase<PhaseContext> {
+
+    @Override
+    protected boolean verify(StructuredGraph graph, PhaseContext context) {
+        Map<String, String> errors = new HashMap<>();
+
+        for (ConstantNode c : ConstantNode.getConstantNodes(graph)) {
+            ResolvedJavaType nodeClassType = context.getMetaAccess().lookupJavaType(Node.class);
+            ResolvedJavaType nodeType = context.getConstantReflection().asJavaType(c.asConstant());
+            if (nodeType != null && nodeClassType.isAssignableFrom(nodeType)) {
+                NodeIterable<Node> usages = c.usages();
+                for (Node n : usages) {
+                    if (!(n instanceof ObjectEqualsNode)) {
+                        continue;
+                    }
+                    String loc = GraphUtil.approxSourceLocation(n);
+                    if (loc == null) {
+                        loc = graph.method().asStackTraceElement(0).toString() + "  " + n;
+                    }
+                    errors.put(nodeType.toJavaName(false), loc);
+                }
+            }
+        }
+        if (errors.isEmpty()) {
+            return true;
+        }
+        Formatter f = new Formatter();
+        boolean first = true;
+        for (Map.Entry<String, String> e : errors.entrySet()) {
+            if (!first) {
+                f.format("%n");
+            } else {
+                first = false;
+            }
+            f.format("Found illegal use of Node class literal %s near:%n    %s", e.getKey(), e.getValue());
+        }
+        throw new VerificationError(f.toString());
+    }
+}
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Mon Aug 25 21:15:59 2014 -0700
@@ -34,7 +34,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.NodeClass.Position;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.graph.*;
@@ -299,14 +298,14 @@
             Collection<Position> directInputPositions = nodeClass.getFirstLevelInputPositions();
             writeShort((char) directInputPositions.size());
             for (Position pos : directInputPositions) {
-                writeByte(pos.getSubIndex() == NodeClass.NOT_ITERABLE ? 0 : 1);
+                writeByte(pos.getSubIndex() == Node.NOT_ITERABLE ? 0 : 1);
                 writePoolObject(nodeClass.getName(pos));
                 writePoolObject(nodeClass.getInputType(pos));
             }
             Collection<Position> directSuccessorPositions = nodeClass.getFirstLevelSuccessorPositions();
             writeShort((char) directSuccessorPositions.size());
             for (Position pos : directSuccessorPositions) {
-                writeByte(pos.getSubIndex() == NodeClass.NOT_ITERABLE ? 0 : 1);
+                writeByte(pos.getSubIndex() == Node.NOT_ITERABLE ? 0 : 1);
                 writePoolObject(nodeClass.getName(pos));
             }
         } else if (object instanceof ResolvedJavaMethod) {
@@ -440,7 +439,7 @@
     private void writeEdges(Node node, Collection<Position> positions) throws IOException {
         NodeClass nodeClass = node.getNodeClass();
         for (Position pos : positions) {
-            if (pos.getSubIndex() == NodeClass.NOT_ITERABLE) {
+            if (pos.getSubIndex() == Node.NOT_ITERABLE) {
                 Node edge = nodeClass.get(node, pos);
                 writeNodeRef(edge);
             } else {
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Mon Aug 25 21:15:59 2014 -0700
@@ -34,12 +34,11 @@
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.graph.NodeClass.NodeClassIterator;
-import com.oracle.graal.graph.NodeClass.Position;
 import com.oracle.graal.java.*;
 import com.oracle.graal.java.BciBlockMapping.BciBlock;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.cfg.*;
@@ -459,7 +458,7 @@
             out.printf("nr %4d ", inst.id()).print(COLUMN_END);
 
             final StringBuilder stateString = new StringBuilder();
-            inst.forEachState(new LIRInstruction.StateProcedure() {
+            inst.forEachState(new StateProcedure() {
 
                 @Override
                 protected void doState(LIRFrameState state) {
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Mon Aug 25 21:15:59 2014 -0700
@@ -30,10 +30,9 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.graph.NodeClass.NodeClassIterator;
-import com.oracle.graal.graph.NodeClass.Position;
 import com.oracle.graal.java.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.schedule.*;
@@ -175,9 +174,9 @@
                     printProperty(bit, "true");
                 }
             }
-            if (node.getClass() == BeginNode.class) {
+            if (node.getClass() == BeginNode.getGenClass()) {
                 printProperty("shortName", "B");
-            } else if (node.getClass() == AbstractEndNode.class) {
+            } else if (node.getClass() == EndNode.getGenClass()) {
                 printProperty("shortName", "E");
             }
             if (node.predecessor() != null) {
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java	Mon Aug 25 21:15:59 2014 -0700
@@ -182,7 +182,7 @@
 
             Arguments args = new Arguments(key, graph.getGuardsStage(), tool.getLoweringStage());
             args.add("input", convert.getValue());
-            args.add("result", graph.unique(new AMD64FloatConvertNode(convert.stamp(), convert.getOp(), convert.getValue())));
+            args.add("result", graph.unique(AMD64FloatConvertNode.create(convert.stamp(), convert.getOp(), convert.getValue())));
 
             SnippetTemplate template = template(args);
             Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.getOp(), graph, convert, template, args);
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -28,6 +28,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -37,11 +38,16 @@
  * of the {@link FloatConvertNode} which, on AMD64 needs a {@link AMD64FloatConvertNode} plus some
  * fixup code that handles the corner cases that differ between AMD64 and Java.
  */
+@NodeInfo
 public class AMD64FloatConvertNode extends UnaryNode implements ArithmeticLIRLowerable {
 
     private final FloatConvert op;
 
-    public AMD64FloatConvertNode(Stamp stamp, FloatConvert op, ValueNode value) {
+    public static AMD64FloatConvertNode create(Stamp stamp, FloatConvert op, ValueNode value) {
+        return USE_GENERATED_NODES ? new AMD64FloatConvertNodeGen(stamp, op, value) : new AMD64FloatConvertNode(stamp, op, value);
+    }
+
+    protected AMD64FloatConvertNode(Stamp stamp, FloatConvert op, ValueNode value) {
         super(stamp, value);
         this.op = op;
     }
--- a/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -30,6 +30,7 @@
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.hsail.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -37,12 +38,13 @@
 /**
  * This node implements HSAIL intrinsics for specific {@link Math} routines.
  */
+@NodeInfo
 public class HSAILMathIntrinsicsNode extends FloatingNode implements Canonicalizable, ArithmeticLIRLowerable {
 
     /**
      * The parameter passed to the math operation that this node represents.
      */
-    @Input private ValueNode param;
+    @Input ValueNode param;
 
     /**
      * The math operation that this Node represents.
@@ -73,7 +75,11 @@
      * @param x the argument to the math operation
      * @param op the math operation
      */
-    public HSAILMathIntrinsicsNode(ValueNode x, HSAILArithmetic op) {
+    public static HSAILMathIntrinsicsNode create(ValueNode x, HSAILArithmetic op) {
+        return USE_GENERATED_NODES ? new HSAILMathIntrinsicsNodeGen(x, op) : new HSAILMathIntrinsicsNode(x, op);
+    }
+
+    protected HSAILMathIntrinsicsNode(ValueNode x, HSAILArithmetic op) {
         super(StampFactory.forKind(x.getKind()));
         this.param = x;
         this.operation = op;
--- a/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/JStrictMath.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/JStrictMath.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,13 +23,12 @@
 
 package com.oracle.graal.replacements.hsail;
 
-import java.util.Random;
+import java.util.*;
+
+import sun.misc.*;
 
 import com.oracle.graal.api.replacements.*;
 
-import sun.misc.FpUtils;
-import sun.misc.DoubleConsts;
-
 /**
  * This class contains methods for performing basic numeric operations such as the elementary
  * exponential, logarithm, square root, and trigonometric functions. It is a Java port of the native
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -72,7 +72,7 @@
         }
 
         // Force compilation
-        InstalledCode code = getCode(getMetaAccess().lookupJavaMethod(testMethod), parse(testMethod));
+        InstalledCode code = getCode(getMetaAccess().lookupJavaMethod(testMethod), parseEager(testMethod));
         assert optional || code != null;
 
         for (int i = 0; i < args1.length; i++) {
@@ -374,7 +374,7 @@
 
     @Test
     public void testCanonicalLength() {
-        StructuredGraph graph = parse("testCanonicalLengthSnippet");
+        StructuredGraph graph = parseEager("testCanonicalLengthSnippet");
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
         new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
@@ -391,7 +391,7 @@
 
     @Test
     public void testCanonicalEqual() {
-        StructuredGraph graph = parse("testCanonicalEqualSnippet");
+        StructuredGraph graph = parseEager("testCanonicalEqualSnippet");
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
         new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
@@ -406,7 +406,7 @@
 
     @Test
     public void testVirtualEqual() {
-        StructuredGraph graph = parse("testVirtualEqualSnippet");
+        StructuredGraph graph = parseEager("testVirtualEqualSnippet");
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
         new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
@@ -425,7 +425,7 @@
 
     @Test
     public void testVirtualNotEqual() {
-        StructuredGraph graph = parse("testVirtualNotEqualSnippet");
+        StructuredGraph graph = parseEager("testVirtualNotEqualSnippet");
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
         new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -247,7 +247,7 @@
      * @return the returned value or null if {@code expectedClass} is not found in the graph.
      */
     private ValueNode parseAndInline(String name, Class<? extends ValueNode> expectedClass) {
-        StructuredGraph graph = parse(name);
+        StructuredGraph graph = parseEager(name);
         HighTierContext context = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE);
         CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
         canonicalizer.apply(graph, context);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -37,7 +37,7 @@
     protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) {
         CheckCastNode ccn = graph.getNodes().filter(CheckCastNode.class).first();
         if (ccn != null) {
-            CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.type(), ccn.object(), profile, false));
+            CheckCastNode ccnNew = graph.add(CheckCastNode.create(ccn.type(), ccn.object(), profile, false));
             graph.replaceFixedWithFixed(ccn, ccnNew);
         }
     }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -41,8 +41,8 @@
     }
 
     @Override
-    protected StructuredGraph parse(Method m) {
-        StructuredGraph graph = super.parse(m);
+    protected StructuredGraph parseEager(Method m) {
+        StructuredGraph graph = super.parseEager(m);
         int handlers = graph.getNodes().filter(ExceptionObjectNode.class).count();
         Assert.assertEquals(1, handlers);
         return graph;
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -50,7 +50,7 @@
     protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) {
         InstanceOfNode ion = graph.getNodes().filter(InstanceOfNode.class).first();
         if (ion != null) {
-            InstanceOfNode ionNew = graph.unique(new InstanceOfNode(ion.type(), ion.getValue(), profile));
+            InstanceOfNode ionNew = graph.unique(InstanceOfNode.create(ion.type(), ion.getValue(), profile));
             graph.replaceFloating(ion, ionNew);
         }
     }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -44,7 +44,7 @@
 
     protected StructuredGraph test(final String snippet) {
         try (Scope s = Debug.scope("MethodSubstitutionTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) {
-            StructuredGraph graph = parse(snippet);
+            StructuredGraph graph = parseEager(snippet);
             Assumptions assumptions = new Assumptions(true);
             HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
             Debug.dump(graph, "Graph");
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewMultiArrayTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewMultiArrayTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -63,7 +63,7 @@
                 dimensionNodes[i] = ConstantNode.forInt(dimensions[i], graph);
             }
 
-            NewMultiArrayNode repl = graph.add(new NewMultiArrayNode(arrayType, dimensionNodes));
+            NewMultiArrayNode repl = graph.add(NewMultiArrayNode.create(arrayType, dimensionNodes));
             graph.replaceFixedWithFixed(node, repl);
             forceCompile = true;
         }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -53,7 +53,7 @@
     private static final ThreadLocal<SnippetInliningPolicy> inliningPolicy = new ThreadLocal<>();
 
     @Override
-    protected StructuredGraph parse(Method m) {
+    protected StructuredGraph parseEager(Method m) {
         ResolvedJavaMethod resolvedMethod = getMetaAccess().lookupJavaMethod(m);
         return installer.makeGraph(resolvedMethod, null, inliningPolicy.get(), FrameStateProcessing.CollapseFrameForSingleSideEffect);
     }
@@ -61,42 +61,42 @@
     @Test
     public void testRead1() {
         for (Kind kind : KINDS) {
-            assertRead(parse("read" + kind.name() + "1"), kind, true, ID);
+            assertRead(parseEager("read" + kind.name() + "1"), kind, true, ID);
         }
     }
 
     @Test
     public void testRead2() {
         for (Kind kind : KINDS) {
-            assertRead(parse("read" + kind.name() + "2"), kind, true, ID);
+            assertRead(parseEager("read" + kind.name() + "2"), kind, true, ID);
         }
     }
 
     @Test
     public void testRead3() {
         for (Kind kind : KINDS) {
-            assertRead(parse("read" + kind.name() + "3"), kind, true, LocationIdentity.ANY_LOCATION);
+            assertRead(parseEager("read" + kind.name() + "3"), kind, true, LocationIdentity.ANY_LOCATION);
         }
     }
 
     @Test
     public void testWrite1() {
         for (Kind kind : KINDS) {
-            assertWrite(parse("write" + kind.name() + "1"), kind, true, ID);
+            assertWrite(parseEager("write" + kind.name() + "1"), kind, true, ID);
         }
     }
 
     @Test
     public void testWrite2() {
         for (Kind kind : KINDS) {
-            assertWrite(parse("write" + kind.name() + "2"), kind, true, ID);
+            assertWrite(parseEager("write" + kind.name() + "2"), kind, true, ID);
         }
     }
 
     @Test
     public void testWrite3() {
         for (Kind kind : KINDS) {
-            assertWrite(parse("write" + kind.name() + "3"), kind, true, LocationIdentity.ANY_LOCATION);
+            assertWrite(parseEager("write" + kind.name() + "3"), kind, true, LocationIdentity.ANY_LOCATION);
         }
     }
 
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -59,7 +59,7 @@
     private static final ThreadLocal<SnippetInliningPolicy> inliningPolicy = new ThreadLocal<>();
 
     @Override
-    protected StructuredGraph parse(Method m) {
+    protected StructuredGraph parseEager(Method m) {
         ResolvedJavaMethod resolvedMethod = getMetaAccess().lookupJavaMethod(m);
         return installer.makeGraph(resolvedMethod, null, inliningPolicy.get(), FrameStateProcessing.CollapseFrameForSingleSideEffect);
     }
@@ -67,42 +67,42 @@
     @Test
     public void testRead1() {
         for (Kind kind : KINDS) {
-            assertRead(parse("read" + kind.name() + "1"), kind, true, ID);
+            assertRead(parseEager("read" + kind.name() + "1"), kind, true, ID);
         }
     }
 
     @Test
     public void testRead2() {
         for (Kind kind : KINDS) {
-            assertRead(parse("read" + kind.name() + "2"), kind, true, ID);
+            assertRead(parseEager("read" + kind.name() + "2"), kind, true, ID);
         }
     }
 
     @Test
     public void testRead3() {
         for (Kind kind : KINDS) {
-            assertRead(parse("read" + kind.name() + "3"), kind, true, LocationIdentity.ANY_LOCATION);
+            assertRead(parseEager("read" + kind.name() + "3"), kind, true, LocationIdentity.ANY_LOCATION);
         }
     }
 
     @Test
     public void testWrite1() {
         for (Kind kind : KINDS) {
-            assertWrite(parse("write" + kind.name() + "1"), kind, true, ID);
+            assertWrite(parseEager("write" + kind.name() + "1"), kind, true, ID);
         }
     }
 
     @Test
     public void testWrite2() {
         for (Kind kind : KINDS) {
-            assertWrite(parse("write" + kind.name() + "2"), kind, true, ID);
+            assertWrite(parseEager("write" + kind.name() + "2"), kind, true, ID);
         }
     }
 
     @Test
     public void testWrite3() {
         for (Kind kind : KINDS) {
-            assertWrite(parse("write" + kind.name() + "3"), kind, true, LocationIdentity.ANY_LOCATION);
+            assertWrite(parseEager("write" + kind.name() + "3"), kind, true, LocationIdentity.ANY_LOCATION);
         }
     }
 
@@ -407,7 +407,7 @@
         Assumptions assumptions = new Assumptions(true);
         HighTierContext context = new HighTierContext(getProviders(), assumptions, null, null, OptimisticOptimizations.ALL);
 
-        StructuredGraph graph = parse(snippetName);
+        StructuredGraph graph = parseEager(snippetName);
         new CanonicalizerPhase(false).apply(graph, context);
         Assert.assertEquals(expectedWordCasts, graph.getNodes().filter(WordCastNode.class).count());
     }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -94,7 +94,7 @@
         }
 
         // Force compilation
-        InstalledCode code = getCode(getMetaAccess().lookupJavaMethod(testMethod), parse(testMethod));
+        InstalledCode code = getCode(getMetaAccess().lookupJavaMethod(testMethod), parseEager(testMethod));
         assert optional || code != null;
         for (Object l : args) {
             // Verify that the original method and the substitution produce the same value
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StringSubstitutionsTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StringSubstitutionsTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -66,7 +66,7 @@
         }
 
         // Force compilation
-        InstalledCode code = getCode(getMetaAccess().lookupJavaMethod(testMethod), parse(testMethod));
+        InstalledCode code = getCode(getMetaAccess().lookupJavaMethod(testMethod), parseEager(testMethod));
         assert optional || code != null;
 
         for (int i = 0; i < args1.length; i++) {
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/UnsafeSubstitutionsTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/UnsafeSubstitutionsTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -62,7 +62,7 @@
         Method testMethod = getMethod(testMethodName);
 
         // Force compilation
-        InstalledCode code = getCode(getMetaAccess().lookupJavaMethod(testMethod), parse(testMethod));
+        InstalledCode code = getCode(getMetaAccess().lookupJavaMethod(testMethod), parseEager(testMethod));
         assert code != null;
 
         // Verify that the original method and the substitution produce the same value
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -49,7 +49,7 @@
     private static final ThreadLocal<SnippetInliningPolicy> inliningPolicy = new ThreadLocal<>();
 
     @Override
-    protected StructuredGraph parse(Method m) {
+    protected StructuredGraph parseEager(Method m) {
         ResolvedJavaMethod resolvedMethod = getMetaAccess().lookupJavaMethod(m);
         return installer.makeGraph(resolvedMethod, null, inliningPolicy.get(), FrameStateProcessing.CollapseFrameForSingleSideEffect);
     }
--- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/AbstractVerifier.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/AbstractVerifier.java	Mon Aug 25 21:15:59 2014 -0700
@@ -44,7 +44,7 @@
     @SuppressWarnings("unchecked")
     protected static <T> T resolveAnnotationValue(Class<T> expectedType, AnnotationValue value) {
         if (value == null) {
-            throw new NullPointerException("Value must not be null.");
+            return null;
         }
         Object unboxedValue = value.getValue();
         if (unboxedValue != null) {
--- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java	Mon Aug 25 21:15:59 2014 -0700
@@ -94,7 +94,7 @@
                 env.getMessager().printMessage(Kind.ERROR, String.format("Cannot make @NodeIntrinsic for abstract node class %s.", nodeClass.getSimpleName()), element, annotation);
             } else {
                 TypeMirror[] constructorSignature = constructorSignature(intrinsicMethod);
-                findConstructor(nodeClass, constructorSignature, intrinsicMethod, annotation);
+                findFactory(nodeClass, constructorSignature, intrinsicMethod, annotation);
             }
         } else {
             env.getMessager().printMessage(Kind.ERROR, String.format("The class %s is not a Node subclass.", nodeClass.getSimpleName()), element, annotation);
@@ -122,37 +122,40 @@
         return parameters;
     }
 
-    private void findConstructor(TypeElement nodeClass, TypeMirror[] signature, ExecutableElement intrinsicMethod, AnnotationMirror intrinsicAnnotation) {
-        List<ExecutableElement> constructors = ElementFilter.constructorsIn(nodeClass.getEnclosedElements());
+    private void findFactory(TypeElement nodeClass, TypeMirror[] signature, ExecutableElement intrinsicMethod, AnnotationMirror intrinsicAnnotation) {
+        List<ExecutableElement> methods = ElementFilter.methodsIn(nodeClass.getEnclosedElements());
         List<String> failureReasons = new ArrayList<>();
 
-        nextConstructor: for (ExecutableElement constructor : constructors) {
+        nextMethod: for (ExecutableElement method : methods) {
+            if (!method.getSimpleName().contentEquals("create") || !method.getModifiers().contains(Modifier.STATIC)) {
+                continue;
+            }
             int sIdx = 0;
-            int cIdx = 0;
-            while (cIdx < constructor.getParameters().size()) {
-                VariableElement parameter = constructor.getParameters().get(cIdx++);
+            int mIdx = 0;
+            while (mIdx < method.getParameters().size()) {
+                VariableElement parameter = method.getParameters().get(mIdx++);
                 if (parameter.getAnnotation(InjectedNodeParameter.class) != null) {
                     // skip injected parameters
                     continue;
                 }
 
                 TypeMirror paramType = parameter.asType();
-                if (cIdx == constructor.getParameters().size() && paramType.getKind() == TypeKind.ARRAY) {
-                    // last argument of constructor is varargs, match remaining intrinsic arguments
+                if (mIdx == method.getParameters().size() && paramType.getKind() == TypeKind.ARRAY) {
+                    // last argument of method is varargs, match remaining intrinsic arguments
                     TypeMirror varargsType = ((ArrayType) paramType).getComponentType();
                     while (sIdx < signature.length) {
                         if (!isTypeCompatible(varargsType, signature[sIdx++])) {
-                            failureReasons.add(String.format("Constructor %s failed because the types of argument %d are incompatible: %s != %s", constructor, sIdx, varargsType, signature[sIdx - 1]));
-                            continue nextConstructor;
+                            failureReasons.add(String.format("Factory method %s failed because the types of argument %d are incompatible: %s != %s", method, sIdx, varargsType, signature[sIdx - 1]));
+                            continue nextMethod;
                         }
                     }
                 } else if (sIdx >= signature.length) {
                     // too many arguments in intrinsic method
-                    failureReasons.add(String.format("Too many arguments for %s", constructor));
-                    continue nextConstructor;
+                    failureReasons.add(String.format("Too many arguments for %s", method));
+                    continue nextMethod;
                 } else if (!isTypeCompatible(paramType, signature[sIdx++])) {
-                    failureReasons.add(String.format("Constructor %s failed because the types of argument %d are incompatible: %s != %s", constructor, sIdx, paramType, signature[sIdx - 1]));
-                    continue nextConstructor;
+                    failureReasons.add(String.format("Factory method %s failed because the types of argument %d are incompatible: %s != %s", method, sIdx, paramType, signature[sIdx - 1]));
+                    continue nextMethod;
                 }
             }
 
@@ -162,12 +165,12 @@
             }
 
             // too many arguments in constructor
-            failureReasons.add(String.format("Not enough arguments for %s", constructor));
+            failureReasons.add(String.format("Not enough arguments for %s", method));
         }
 
         // not found
         if (failureReasons.isEmpty()) {
-            env.getMessager().printMessage(Kind.ERROR, "Could not find matching constructor for node intrinsic.", intrinsicMethod, intrinsicAnnotation);
+            env.getMessager().printMessage(Kind.ERROR, "Could not find matching factory method for node intrinsic.", intrinsicMethod, intrinsicAnnotation);
         } else {
             for (String reason : failureReasons) {
                 env.getMessager().printMessage(Kind.ERROR, reason, intrinsicMethod, intrinsicAnnotation);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -228,7 +228,7 @@
             assert bci == AFTER_BCI || bci == AFTER_EXCEPTION_BCI || bci == INVALID_FRAMESTATE_BCI;
             FrameState currentStateAfter = node.stateAfter();
             if (currentStateAfter != null || !replaceOnly) {
-                node.setStateAfter(graph.add(new FrameState(bci)));
+                node.setStateAfter(graph.add(FrameState.create(bci)));
                 if (currentStateAfter != null && currentStateAfter.usages().isEmpty()) {
                     GraphUtil.killWithUnusedFloatingInputs(currentStateAfter);
                 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java	Mon Aug 25 21:15:59 2014 -0700
@@ -113,7 +113,7 @@
         ConstantLocationNode location = createFieldLocation(graph, field, false);
         assert location != null : "Field that is loaded must not be eliminated";
 
-        ReadNode memoryRead = graph.add(new ReadNode(object, location, loadStamp, fieldLoadBarrierType(field)));
+        ReadNode memoryRead = graph.add(ReadNode.create(object, location, loadStamp, fieldLoadBarrierType(field)));
         ValueNode readValue = implicitLoadConvert(graph, field.getKind(), memoryRead);
         loadField.replaceAtUsages(readValue);
         graph.replaceFixed(loadField, memoryRead);
@@ -121,9 +121,9 @@
         memoryRead.setGuard(createNullCheck(object, memoryRead, tool));
 
         if (loadField.isVolatile()) {
-            MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ));
+            MembarNode preMembar = graph.add(MembarNode.create(JMM_PRE_VOLATILE_READ));
             graph.addBeforeFixed(memoryRead, preMembar);
-            MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_READ));
+            MembarNode postMembar = graph.add(MembarNode.create(JMM_POST_VOLATILE_READ));
             graph.addAfterFixed(memoryRead, postMembar);
         }
     }
@@ -141,15 +141,15 @@
             graph.removeFixed(storeField);
             return;
         }
-        WriteNode memoryWrite = graph.add(new WriteNode(object, value, location, fieldStoreBarrierType(storeField.field())));
+        WriteNode memoryWrite = graph.add(WriteNode.create(object, value, location, fieldStoreBarrierType(storeField.field())));
         memoryWrite.setStateAfter(storeField.stateAfter());
         graph.replaceFixedWithFixed(storeField, memoryWrite);
         memoryWrite.setGuard(createNullCheck(object, memoryWrite, tool));
 
         if (storeField.isVolatile()) {
-            MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE));
+            MembarNode preMembar = graph.add(MembarNode.create(JMM_PRE_VOLATILE_WRITE));
             graph.addBeforeFixed(memoryWrite, preMembar);
-            MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_WRITE));
+            MembarNode postMembar = graph.add(MembarNode.create(JMM_POST_VOLATILE_WRITE));
             graph.addAfterFixed(memoryWrite, postMembar);
         }
     }
@@ -160,7 +160,7 @@
         LocationNode location = createArrayLocation(graph, elementKind, loadIndexed.index(), false);
         Stamp loadStamp = loadStamp(loadIndexed.stamp(), elementKind);
 
-        ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), location, loadStamp, BarrierType.NONE));
+        ReadNode memoryRead = graph.add(ReadNode.create(loadIndexed.array(), location, loadStamp, BarrierType.NONE));
         ValueNode readValue = implicitLoadConvert(graph, elementKind, memoryRead);
 
         memoryRead.setGuard(createBoundsCheck(loadIndexed, tool));
@@ -184,20 +184,20 @@
             if (arrayType != null && StampTool.isExactType(array)) {
                 ResolvedJavaType elementType = arrayType.getComponentType();
                 if (!elementType.isJavaLangObject()) {
-                    checkCastNode = graph.add(new CheckCastNode(elementType, value, null, true));
+                    checkCastNode = graph.add(CheckCastNode.create(elementType, value, null, true));
                     graph.addBeforeFixed(storeIndexed, checkCastNode);
                     value = checkCastNode;
                 }
             } else {
                 ValueNode arrayClass = createReadHub(graph, array, boundsCheck);
                 ValueNode componentHub = createReadArrayComponentHub(graph, arrayClass, storeIndexed);
-                checkCastNode = graph.add(new CheckCastDynamicNode(componentHub, value, true));
+                checkCastNode = graph.add(CheckCastDynamicNode.create(componentHub, value, true));
                 graph.addBeforeFixed(storeIndexed, checkCastNode);
                 value = checkCastNode;
             }
         }
 
-        WriteNode memoryWrite = graph.add(new WriteNode(array, implicitStoreConvert(graph, elementKind, value), location, arrayStoreBarrierType(storeIndexed.elementKind())));
+        WriteNode memoryWrite = graph.add(WriteNode.create(array, implicitStoreConvert(graph, elementKind, value), location, arrayStoreBarrierType(storeIndexed.elementKind())));
         memoryWrite.setGuard(boundsCheck);
         memoryWrite.setStateAfter(storeIndexed.stateAfter());
         graph.replaceFixedWithFixed(storeIndexed, memoryWrite);
@@ -213,7 +213,7 @@
         ValueNode array = arrayLengthNode.array();
         ConstantLocationNode location = ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, arrayLengthOffset(), graph);
 
-        ReadNode arrayLengthRead = graph.add(new ReadNode(array, location, StampFactory.positiveInt(), BarrierType.NONE));
+        ReadNode arrayLengthRead = graph.add(ReadNode.create(array, location, StampFactory.positiveInt(), BarrierType.NONE));
         arrayLengthRead.setGuard(createNullCheck(array, arrayLengthNode, tool));
         graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead);
     }
@@ -235,7 +235,7 @@
         ValueNode expectedValue = implicitStoreConvert(graph, valueKind, cas.expected());
         ValueNode newValue = implicitStoreConvert(graph, valueKind, cas.newValue());
 
-        LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(cas.object(), location, expectedValue, newValue, compareAndSwapBarrierType(cas)));
+        LoweredCompareAndSwapNode atomicNode = graph.add(LoweredCompareAndSwapNode.create(cas.object(), location, expectedValue, newValue, compareAndSwapBarrierType(cas)));
         atomicNode.setStateAfter(cas.stateAfter());
         graph.replaceFixedWithFixed(cas, atomicNode);
     }
@@ -247,7 +247,7 @@
 
         ValueNode newValue = implicitStoreConvert(graph, valueKind, n.newValue());
 
-        LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(n.object(), location, newValue, atomicReadAndWriteBarrierType(n)));
+        LoweredAtomicReadAndWriteNode memoryRead = graph.add(LoweredAtomicReadAndWriteNode.create(n.object(), location, newValue, atomicReadAndWriteBarrierType(n)));
         memoryRead.setStateAfter(n.stateAfter());
 
         ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead);
@@ -258,7 +258,7 @@
     protected void lowerUnsafeLoadNode(UnsafeLoadNode load, @SuppressWarnings("unused") LoweringTool tool) {
         StructuredGraph graph = load.graph();
         if (load.getGuardingCondition() != null) {
-            ConditionAnchorNode valueAnchorNode = graph.add(new ConditionAnchorNode(load.getGuardingCondition()));
+            ConditionAnchorNode valueAnchorNode = graph.add(ConditionAnchorNode.create(load.getGuardingCondition()));
             ReadNode memoryRead = createUnsafeRead(graph, load, valueAnchorNode);
             graph.replaceFixedWithFixed(load, valueAnchorNode);
             graph.addAfterFixed(valueAnchorNode, memoryRead);
@@ -275,9 +275,17 @@
     protected ReadNode createUnsafeRead(StructuredGraph graph, UnsafeLoadNode load, GuardingNode guard) {
         boolean compressible = load.accessKind() == Kind.Object;
         Kind readKind = load.accessKind();
-        LocationNode location = createLocation(load);
+        ValueNode[] base = null;
+        ValueNode object = load.object();
+        if (object.isConstant() && object.asConstant().isDefaultForKind()) {
+            base = new ValueNode[1];
+        }
+        LocationNode location = createLocation(load, base);
+        if (base != null && base[0] != null) {
+            object = base[0];
+        }
         Stamp loadStamp = loadStamp(load.stamp(), readKind, compressible);
-        ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, loadStamp, guard, BarrierType.NONE));
+        ReadNode memoryRead = graph.add(ReadNode.create(object, location, loadStamp, guard, BarrierType.NONE));
         ValueNode readValue = implicitLoadConvert(graph, readKind, memoryRead, compressible);
         load.replaceAtUsages(readValue);
         return memoryRead;
@@ -285,12 +293,19 @@
 
     protected void lowerUnsafeStoreNode(UnsafeStoreNode store) {
         StructuredGraph graph = store.graph();
-        LocationNode location = createLocation(store);
         ValueNode object = store.object();
+        ValueNode[] base = null;
+        if (object.isConstant() && object.asConstant().isDefaultForKind()) {
+            base = new ValueNode[1];
+        }
+        LocationNode location = createLocation(store, base);
+        if (base != null && base[0] != null) {
+            object = base[0];
+        }
         boolean compressible = store.value().getKind() == Kind.Object;
         Kind valueKind = store.accessKind();
         ValueNode value = implicitStoreConvert(graph, valueKind, store.value(), compressible);
-        WriteNode write = graph.add(new WriteNode(object, value, location, unsafeStoreBarrierType(store)));
+        WriteNode write = graph.add(WriteNode.create(object, value, location, unsafeStoreBarrierType(store)));
         write.setStateAfter(store.stateAfter());
         graph.replaceFixedWithFixed(store, write);
     }
@@ -300,7 +315,7 @@
         Kind valueKind = read.location().getValueKind();
         Stamp loadStamp = loadStamp(read.stamp(), valueKind, read.isCompressible());
 
-        ReadNode memoryRead = graph.add(new ReadNode(read.object(), read.location(), loadStamp, read.getBarrierType()));
+        ReadNode memoryRead = graph.add(ReadNode.create(read.object(), read.location(), loadStamp, read.getBarrierType()));
         ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead, read.isCompressible());
         memoryRead.setGuard(read.getGuard());
         read.replaceAtUsages(readValue);
@@ -312,7 +327,7 @@
         Kind valueKind = write.location().getValueKind();
         ValueNode value = implicitStoreConvert(graph, valueKind, write.value(), write.isCompressible());
 
-        WriteNode memoryWrite = graph.add(new WriteNode(write.object(), value, write.location(), write.getBarrierType(), write.isInitialization()));
+        WriteNode memoryWrite = graph.add(WriteNode.create(write.object(), value, write.location(), write.getBarrierType(), write.isInitialization()));
         memoryWrite.setStateAfter(write.stateAfter());
         graph.replaceFixedWithFixed(write, memoryWrite);
         memoryWrite.setGuard(write.getGuard());
@@ -331,9 +346,9 @@
                 int entryCount = virtual.entryCount();
                 AbstractNewObjectNode newObject;
                 if (virtual instanceof VirtualInstanceNode) {
-                    newObject = graph.add(new NewInstanceNode(virtual.type(), true));
+                    newObject = graph.add(NewInstanceNode.create(virtual.type(), true));
                 } else {
-                    newObject = graph.add(new NewArrayNode(((VirtualArrayNode) virtual).componentType(), ConstantNode.forInt(entryCount, graph), true));
+                    newObject = graph.add(NewArrayNode.create(((VirtualArrayNode) virtual).componentType(), ConstantNode.forInt(entryCount, graph), true));
                 }
                 recursiveLowerings.add(newObject);
                 graph.addBeforeFixed(commit, newObject);
@@ -368,7 +383,7 @@
                             barrierType = arrayInitializationBarrier(entryKind);
                         }
                         if (location != null) {
-                            WriteNode write = new WriteNode(newObject, implicitStoreConvert(graph, entryKind, value), location, barrierType);
+                            WriteNode write = WriteNode.create(newObject, implicitStoreConvert(graph, entryKind, value), location, barrierType);
                             graph.addAfterFixed(newObject, graph.add(write));
                         }
                     }
@@ -400,7 +415,7 @@
                                 barrierType = BarrierType.PRECISE;
                             }
                             if (location != null) {
-                                WriteNode write = new WriteNode(newObject, implicitStoreConvert(graph, Kind.Object, allocValue), location, barrierType);
+                                WriteNode write = WriteNode.create(newObject, implicitStoreConvert(graph, Kind.Object, allocValue), location, barrierType);
                                 graph.addBeforeFixed(commit, graph.add(write));
                             }
                         }
@@ -421,13 +436,13 @@
     public static void finishAllocatedObjects(LoweringTool tool, CommitAllocationNode commit, ValueNode[] allocations) {
         StructuredGraph graph = commit.graph();
         for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
-            FixedValueAnchorNode anchor = graph.add(new FixedValueAnchorNode(allocations[objIndex]));
+            FixedValueAnchorNode anchor = graph.add(FixedValueAnchorNode.create(allocations[objIndex]));
             allocations[objIndex] = anchor;
             graph.addBeforeFixed(commit, anchor);
         }
         for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
             for (MonitorIdNode monitorId : commit.getLocks(objIndex)) {
-                MonitorEnterNode enter = graph.add(new MonitorEnterNode(allocations[objIndex], monitorId));
+                MonitorEnterNode enter = graph.add(MonitorEnterNode.create(allocations[objIndex], monitorId));
                 graph.addBeforeFixed(commit, enter);
                 enter.lower(tool);
             }
@@ -528,10 +543,10 @@
         switch (kind) {
             case Byte:
             case Short:
-                return graph.unique(new SignExtendNode(value, 32));
+                return graph.unique(SignExtendNode.create(value, 32));
             case Boolean:
             case Char:
-                return graph.unique(new ZeroExtendNode(value, 32));
+                return graph.unique(ZeroExtendNode.create(value, 32));
         }
         return value;
     }
@@ -544,10 +559,10 @@
         switch (kind) {
             case Boolean:
             case Byte:
-                return graph.unique(new NarrowNode(value, 8));
+                return graph.unique(NarrowNode.create(value, 8));
             case Char:
             case Short:
-                return graph.unique(new NarrowNode(value, 16));
+                return graph.unique(NarrowNode.create(value, 16));
         }
         return value;
     }
@@ -566,11 +581,26 @@
         }
     }
 
-    protected LocationNode createLocation(UnsafeAccessNode access) {
-        return createLocation(access.offset(), access.getLocationIdentity(), access.accessKind());
+    protected LocationNode createLocation(UnsafeAccessNode access, ValueNode[] base) {
+        return createLocation(access.offset(), access.getLocationIdentity(), access.accessKind(), base);
     }
 
     protected LocationNode createLocation(ValueNode offsetNode, LocationIdentity locationIdentity, Kind accessKind) {
+        return createLocation(offsetNode, locationIdentity, accessKind, null);
+    }
+
+    /**
+     * Try to unpack the operations in offsetNode into a LocationNode, taking advantage of
+     * addressing modes if possible.
+     *
+     * @param offsetNode the computed offset into the base of the memory operation
+     * @param locationIdentity
+     * @param accessKind
+     * @param base if non-null try to find a value that can be used as the base of the memory
+     *            operation and return it as base[0]
+     * @return the newly created LocationNode
+     */
+    protected LocationNode createLocation(ValueNode offsetNode, LocationIdentity locationIdentity, Kind accessKind, ValueNode[] base) {
         ValueNode offset = offsetNode;
         if (offset.isConstant()) {
             long offsetValue = offset.asConstant().asLong();
@@ -594,7 +624,27 @@
                 offset = integerAddNode.getX();
             }
         }
-
+        if (base != null && signExtend == false && offset instanceof IntegerAddNode) {
+            /*
+             * Try to decompose the operation into base plus offset so the base can go into a new
+             * node. Prefer the unshifted side of an add as the base.
+             */
+            IntegerAddNode integerAddNode = (IntegerAddNode) offset;
+            if (integerAddNode.getY() instanceof LeftShiftNode) {
+                base[0] = integerAddNode.getX();
+                offset = integerAddNode.getY();
+            } else {
+                base[0] = integerAddNode.getY();
+                offset = integerAddNode.getX();
+            }
+            if (offset instanceof IntegerAddNode) {
+                integerAddNode = (IntegerAddNode) offset;
+                if (integerAddNode.getY() instanceof ConstantNode) {
+                    displacement = integerAddNode.getY().asConstant().asLong();
+                    offset = integerAddNode.getX();
+                }
+            }
+        }
         if (offset instanceof LeftShiftNode) {
             LeftShiftNode leftShiftNode = (LeftShiftNode) offset;
             if (leftShiftNode.getY() instanceof ConstantNode) {
@@ -613,7 +663,7 @@
         }
         if (signExtend) {
             // If we were using sign extended values before restore the sign extension.
-            offset = offset.graph().addOrUnique(new SignExtendNode(offset, 64));
+            offset = offset.graph().addOrUnique(SignExtendNode.create(offset, 64));
         }
         return IndexedLocationNode.create(locationIdentity, accessKind, displacement, offset, offset.graph(), indexScaling);
     }
@@ -629,7 +679,7 @@
         ValueNode arrayLength = readArrayLength(array, tool.getConstantReflection());
         if (arrayLength == null) {
             Stamp stamp = StampFactory.positiveInt();
-            ReadNode readArrayLength = graph.add(new ReadNode(array, ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, arrayLengthOffset(), graph), stamp, BarrierType.NONE));
+            ReadNode readArrayLength = graph.add(ReadNode.create(array, ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, arrayLengthOffset(), graph), stamp, BarrierType.NONE));
             graph.addBeforeFixed(n, readArrayLength);
             readArrayLength.setGuard(createNullCheck(array, readArrayLength, tool));
             arrayLength = readArrayLength;
@@ -646,14 +696,14 @@
             }
         }
 
-        return tool.createGuard(n, graph.unique(new IntegerBelowNode(n.index(), arrayLength)), BoundsCheckException, InvalidateReprofile);
+        return tool.createGuard(n, graph.unique(IntegerBelowNode.create(n.index(), arrayLength)), BoundsCheckException, InvalidateReprofile);
     }
 
     protected GuardingNode createNullCheck(ValueNode object, FixedNode before, LoweringTool tool) {
         if (StampTool.isObjectNonNull(object)) {
             return null;
         }
-        return tool.createGuard(before, before.graph().unique(new IsNullNode(object)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true);
+        return tool.createGuard(before, before.graph().unique(IsNullNode.create(object)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true);
     }
 
     @Override
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java	Mon Aug 25 21:15:59 2014 -0700
@@ -131,7 +131,7 @@
         JavaType returnType = signature.getReturnType(null);
         assert checkArgs(method, args);
         MethodCallTargetNode callTarget = graph.add(createMethodCallTarget(invokeKind, method, args, returnType, bci));
-        InvokeNode invoke = append(new InvokeNode(callTarget, bci));
+        InvokeNode invoke = append(InvokeNode.create(callTarget, bci));
 
         if (frameStateBuilder != null) {
             if (invoke.getKind() != Kind.Void) {
@@ -146,7 +146,7 @@
     }
 
     protected MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, JavaType returnType, @SuppressWarnings("unused") int bci) {
-        return new MethodCallTargetNode(invokeKind, targetMethod, args, returnType);
+        return MethodCallTargetNode.create(invokeKind, targetMethod, args, returnType);
     }
 
     /**
@@ -246,9 +246,9 @@
      * @param trueProbability The estimated probability the the condition is true
      */
     public void startIf(LogicNode condition, double trueProbability) {
-        BeginNode thenSuccessor = graph.add(new BeginNode());
-        BeginNode elseSuccessor = graph.add(new BeginNode());
-        append(new IfNode(condition, thenSuccessor, elseSuccessor, trueProbability));
+        BeginNode thenSuccessor = graph.add(BeginNode.create());
+        BeginNode elseSuccessor = graph.add(BeginNode.create());
+        append(IfNode.create(condition, thenSuccessor, elseSuccessor, trueProbability));
         lastFixedNode = null;
 
         IfStructure s = new IfStructure();
@@ -298,12 +298,12 @@
 
         if (thenPart != null && elsePart != null) {
             /* Both parts are alive, we need a real merge. */
-            EndNode thenEnd = graph.add(new EndNode());
+            EndNode thenEnd = graph.add(EndNode.create());
             graph.addAfterFixed(thenPart, thenEnd);
-            EndNode elseEnd = graph.add(new EndNode());
+            EndNode elseEnd = graph.add(EndNode.create());
             graph.addAfterFixed(elsePart, elseEnd);
 
-            MergeNode merge = graph.add(new MergeNode());
+            MergeNode merge = graph.add(MergeNode.create());
             merge.addForwardEnd(thenEnd);
             merge.addForwardEnd(elseEnd);
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Mon Aug 25 21:15:59 2014 -0700
@@ -160,7 +160,7 @@
                 // Can simply use the phi result if the same materialized values are expected.
                 return result;
             } else {
-                return graph.unique(new ConditionalNode(asCondition(trueValue), t, f));
+                return graph.unique(ConditionalNode.create(asCondition(trueValue), t, f));
             }
         }
     }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -85,15 +85,15 @@
 
             ResolvedJavaType[] parameterTypes = resolveJavaTypes(target.toParameterTypes(), declaringClass);
 
-            // Prepare the arguments for the reflective constructor call on the node class.
-            Constant[] nodeConstructorArguments = prepareArguments(methodCallTargetNode, parameterTypes, target, false);
-            if (nodeConstructorArguments == null) {
+            // Prepare the arguments for the reflective factory method call on the node class.
+            Constant[] nodeFactoryArguments = prepareArguments(methodCallTargetNode, parameterTypes, target, false);
+            if (nodeFactoryArguments == null) {
                 return false;
             }
 
             // Create the new node instance.
             ResolvedJavaType c = getNodeClass(target, intrinsic);
-            Node newInstance = createNodeInstance(graph, c, parameterTypes, methodCallTargetNode.invoke().asNode().stamp(), intrinsic.setStampFromReturnType(), nodeConstructorArguments);
+            Node newInstance = createNodeInstance(graph, c, parameterTypes, methodCallTargetNode.invoke().asNode().stamp(), intrinsic.setStampFromReturnType(), nodeFactoryArguments);
 
             // Replace the invoke with the new node.
             newInstance = graph.addOrUnique(newInstance);
@@ -150,7 +150,7 @@
 
     /**
      * 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.
+     * to a reflective invocation of a Java 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}
@@ -209,35 +209,38 @@
     }
 
     private Node createNodeInstance(StructuredGraph graph, ResolvedJavaType nodeClass, ResolvedJavaType[] parameterTypes, Stamp invokeStamp, boolean setStampFromReturnType,
-                    Constant[] nodeConstructorArguments) {
-        ResolvedJavaMethod constructor = null;
+                    Constant[] nodeFactoryArguments) {
+        ResolvedJavaMethod factory = null;
         Constant[] arguments = null;
 
-        for (ResolvedJavaMethod c : nodeClass.getDeclaredConstructors()) {
-            Constant[] match = match(graph, c, parameterTypes, nodeConstructorArguments);
+        for (ResolvedJavaMethod m : nodeClass.getDeclaredMethods()) {
+            if (m.getName().equals("create") && !m.isSynthetic()) {
+                Constant[] match = match(graph, m, parameterTypes, nodeFactoryArguments);
 
-            if (match != null) {
-                if (constructor == null) {
-                    constructor = c;
-                    arguments = match;
-                } else {
-                    throw new GraalInternalError("Found multiple constructors in %s compatible with signature %s: %s, %s", nodeClass.toJavaName(), sigString(parameterTypes), constructor, c);
+                if (match != null) {
+                    if (factory == null) {
+                        factory = m;
+                        arguments = match;
+                    } else {
+                        throw new GraalInternalError("Found multiple factory methods in %s compatible with signature %s: %s, %s", nodeClass.toJavaName(), sigString(parameterTypes),
+                                        factory.format("%n(%p)%r"), m.format("%n(%p)%r"));
+                    }
                 }
             }
         }
-        if (constructor == null) {
-            throw new GraalInternalError("Could not find constructor in %s compatible with signature %s", nodeClass.toJavaName(), sigString(parameterTypes));
+        if (factory == null) {
+            throw new GraalInternalError("Could not find factory method in %s compatible with signature %s", nodeClass.toJavaName(), sigString(parameterTypes));
         }
 
         try {
-            ValueNode intrinsicNode = (ValueNode) snippetReflection.asObject(constructor.newInstance(arguments));
+            ValueNode intrinsicNode = (ValueNode) snippetReflection.asObject(factory.invoke(null, arguments));
 
             if (setStampFromReturnType) {
                 intrinsicNode.setStamp(invokeStamp);
             }
             return intrinsicNode;
         } catch (Exception e) {
-            throw new RuntimeException(constructor + Arrays.toString(nodeConstructorArguments), e);
+            throw new RuntimeException(factory + Arrays.toString(nodeFactoryArguments), e);
         }
     }
 
@@ -261,14 +264,14 @@
         return false;
     }
 
-    private Constant[] match(StructuredGraph graph, ResolvedJavaMethod c, ResolvedJavaType[] parameterTypes, Constant[] nodeConstructorArguments) {
+    private Constant[] match(StructuredGraph graph, ResolvedJavaMethod m, ResolvedJavaType[] parameterTypes, Constant[] nodeFactoryArguments) {
         Constant[] arguments = null;
         Constant[] injected = null;
 
-        ResolvedJavaType[] signature = resolveJavaTypes(c.getSignature().toParameterTypes(null), c.getDeclaringClass());
+        ResolvedJavaType[] signature = resolveJavaTypes(m.getSignature().toParameterTypes(null), m.getDeclaringClass());
         MetaAccessProvider metaAccess = providers.getMetaAccess();
         for (int i = 0; i < signature.length; i++) {
-            if (c.getParameterAnnotation(InjectedNodeParameter.class, i) != null) {
+            if (m.getParameterAnnotation(InjectedNodeParameter.class, i) != null) {
                 injected = injected == null ? new Constant[1] : Arrays.copyOf(injected, injected.length + 1);
                 if (signature[i].equals(metaAccess.lookupJavaType(MetaAccessProvider.class))) {
                     injected[injected.length - 1] = snippetReflection.forObject(metaAccess);
@@ -279,24 +282,24 @@
                 } else if (signature[i].equals(metaAccess.lookupJavaType(SnippetReflectionProvider.class))) {
                     injected[injected.length - 1] = snippetReflection.forObject(snippetReflection);
                 } else {
-                    throw new GraalInternalError("Cannot handle injected argument of type %s in %s", signature[i].toJavaName(), c.format("%H.%n(%p)"));
+                    throw new GraalInternalError("Cannot handle injected argument of type %s in %s", signature[i].toJavaName(), m.format("%H.%n(%p)"));
                 }
             } else {
                 if (i > 0) {
                     // Chop injected arguments from signature
                     signature = Arrays.copyOfRange(signature, i, signature.length);
                 }
-                assert !containsInjected(c, i, signature.length);
+                assert !containsInjected(m, i, signature.length);
                 break;
             }
         }
 
         if (Arrays.equals(parameterTypes, signature)) {
             // Exact match
-            arguments = nodeConstructorArguments;
+            arguments = nodeFactoryArguments;
 
         } else if (signature.length > 0 && signature[signature.length - 1].isArray()) {
-            // Last constructor parameter is an array, so check if we have a vararg match
+            // Last parameter is an array, so check if we have a vararg match
             int fixedArgs = signature.length - 1;
             if (parameterTypes.length < fixedArgs) {
                 return null;
@@ -309,17 +312,17 @@
 
             ResolvedJavaType componentType = signature[fixedArgs].getComponentType();
             assert componentType != null;
-            for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) {
+            for (int i = fixedArgs; i < nodeFactoryArguments.length; i++) {
                 if (!parameterTypes[i].equals(componentType)) {
                     return null;
                 }
             }
-            arguments = Arrays.copyOf(nodeConstructorArguments, fixedArgs + 1);
-            arguments[fixedArgs] = componentType.newArray(nodeConstructorArguments.length - fixedArgs);
+            arguments = Arrays.copyOf(nodeFactoryArguments, fixedArgs + 1);
+            arguments[fixedArgs] = componentType.newArray(nodeFactoryArguments.length - fixedArgs);
 
             Object varargs = snippetReflection.asObject(arguments[fixedArgs]);
-            for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) {
-                Array.set(varargs, i - fixedArgs, snippetReflection.asBoxedValue(nodeConstructorArguments[i]));
+            for (int i = fixedArgs; i < nodeFactoryArguments.length; i++) {
+                Array.set(varargs, i - fixedArgs, snippetReflection.asBoxedValue(nodeFactoryArguments[i]));
             }
         } else {
             return null;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Mon Aug 25 21:15:59 2014 -0700
@@ -36,12 +36,13 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.debug.internal.*;
+import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.java.*;
 import com.oracle.graal.java.GraphBuilderPhase.Instance;
 import com.oracle.graal.nodes.*;
@@ -428,6 +429,20 @@
     }
 
     /**
+     * Calls in snippets to methods matching one of these filters are elided. Only void methods are
+     * considered for elision.
+     */
+    private static final MethodFilter[] MethodsElidedInSnippets = getMethodsElidedInSnippets();
+
+    private static MethodFilter[] getMethodsElidedInSnippets() {
+        String commaSeparatedPatterns = System.getProperty("graal.MethodsElidedInSnippets");
+        if (commaSeparatedPatterns != null) {
+            return MethodFilter.parse(commaSeparatedPatterns);
+        }
+        return null;
+    }
+
+    /**
      * Creates and preprocesses a graph for a replacement.
      */
     protected class GraphMaker {
@@ -554,7 +569,12 @@
             final StructuredGraph graph = new StructuredGraph(methodToParse);
             try (Scope s = Debug.scope("buildInitialGraph", graph)) {
                 MetaAccessProvider metaAccess = providers.getMetaAccess();
-                createGraphBuilder(metaAccess, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(graph);
+
+                if (MethodsElidedInSnippets != null && methodToParse.getSignature().getReturnKind() == Kind.Void && MethodFilter.matches(MethodsElidedInSnippets, methodToParse)) {
+                    graph.addAfterFixed(graph.start(), graph.add(ReturnNode.create(null)));
+                } else {
+                    createGraphBuilder(metaAccess, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(graph);
+                }
                 new WordTypeVerificationPhase(metaAccess, snippetReflection, target.wordKind).apply(graph);
                 new WordTypeRewriterPhase(metaAccess, snippetReflection, target.wordKind).apply(graph);
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,6 +23,7 @@
 package com.oracle.graal.replacements;
 
 import java.lang.annotation.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.replacements.nodes.*;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Mon Aug 25 21:15:59 2014 -0700
@@ -45,8 +45,9 @@
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.graph.Graph.Mark;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node;
 import com.oracle.graal.loop.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
 import com.oracle.graal.nodes.calc.*;
@@ -354,11 +355,16 @@
         }
     }
 
+    @NodeInfo
     static class VarargsPlaceholderNode extends FloatingNode implements ArrayLengthProvider {
 
         final Varargs varargs;
 
-        public VarargsPlaceholderNode(Varargs varargs, MetaAccessProvider metaAccess) {
+        public static VarargsPlaceholderNode create(Varargs varargs, MetaAccessProvider metaAccess) {
+            return USE_GENERATED_NODES ? new SnippetTemplate_VarargsPlaceholderNodeGen(varargs, metaAccess) : new VarargsPlaceholderNode(varargs, metaAccess);
+        }
+
+        protected VarargsPlaceholderNode(Varargs varargs, MetaAccessProvider metaAccess) {
             super(StampFactory.exactNonNull(metaAccess.lookupJavaType(varargs.componentType).getArrayClass()));
             this.varargs = varargs;
         }
@@ -545,7 +551,7 @@
                 nodeReplacements.put(snippetGraph.getParameter(i), ConstantNode.forConstant(constantArg, metaAccess, snippetCopy));
             } else if (args.info.isVarargsParameter(i)) {
                 Varargs varargs = (Varargs) args.values[i];
-                VarargsPlaceholderNode placeholder = snippetCopy.unique(new VarargsPlaceholderNode(varargs, providers.getMetaAccess()));
+                VarargsPlaceholderNode placeholder = snippetCopy.unique(VarargsPlaceholderNode.create(varargs, providers.getMetaAccess()));
                 nodeReplacements.put(snippetGraph.getParameter(i), placeholder);
                 placeholders[i] = placeholder;
             }
@@ -573,7 +579,7 @@
                     assert parameterCount < 10000;
                     int idx = (i + 1) * 10000 + j;
                     assert idx >= parameterCount : "collision in parameter numbering";
-                    ParameterNode local = snippetCopy.unique(new ParameterNode(idx, stamp));
+                    ParameterNode local = snippetCopy.unique(ParameterNode.create(idx, stamp));
                     params[j] = local;
                 }
                 parameters[i] = params;
@@ -584,7 +590,7 @@
                     if (usage instanceof LoadIndexedNode) {
                         LoadIndexedNode loadIndexed = (LoadIndexedNode) usage;
                         Debug.dump(snippetCopy, "Before replacing %s", loadIndexed);
-                        LoadSnippetVarargParameterNode loadSnippetParameter = snippetCopy.add(new LoadSnippetVarargParameterNode(params, loadIndexed.index(), loadIndexed.stamp()));
+                        LoadSnippetVarargParameterNode loadSnippetParameter = snippetCopy.add(LoadSnippetVarargParameterNode.create(params, loadIndexed.index(), loadIndexed.stamp()));
                         snippetCopy.replaceFixedWithFixed(loadIndexed, loadSnippetParameter);
                         Debug.dump(snippetCopy, "After replacing %s", loadIndexed);
                     } else if (usage instanceof StoreIndexedNode) {
@@ -670,7 +676,7 @@
 
         new FloatingReadPhase(false, true, false).apply(snippetCopy);
 
-        MemoryAnchorNode memoryAnchor = snippetCopy.add(new MemoryAnchorNode());
+        MemoryAnchorNode memoryAnchor = snippetCopy.add(MemoryAnchorNode.create());
         snippetCopy.start().replaceAtUsages(InputType.Memory, memoryAnchor);
 
         this.snippet = snippetCopy;
@@ -689,12 +695,12 @@
         } else if (returnNodes.size() == 1) {
             this.returnNode = returnNodes.get(0);
         } else {
-            MergeNode merge = snippet.add(new MergeNode());
+            MergeNode merge = snippet.add(MergeNode.create());
             List<MemoryMapNode> memMaps = returnNodes.stream().map(n -> n.getMemoryMap()).collect(Collectors.toList());
             ValueNode returnValue = InliningUtil.mergeReturns(merge, returnNodes, null);
-            this.returnNode = snippet.add(new ReturnNode(returnValue));
+            this.returnNode = snippet.add(ReturnNode.create(returnValue));
             MemoryMapImpl mmap = FloatingReadPhase.mergeMemoryMaps(merge, memMaps, false);
-            MemoryMapNode memoryMap = snippet.unique(new MemoryMapNode(mmap.getMap()));
+            MemoryMapNode memoryMap = snippet.unique(MemoryMapNode.create(mmap.getMap()));
             this.returnNode.setMemoryMap(memoryMap);
             for (MemoryMapNode mm : memMaps) {
                 if (mm != memoryMap && mm.isAlive()) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,28 +26,35 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
 
 /**
  * Compares two arrays with the same length.
  */
-public class ArrayEqualsNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable, Virtualizable {
+@NodeInfo
+public class ArrayEqualsNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable, Virtualizable, MemoryAccess {
 
     /** {@link Kind} of the arrays to compare. */
     private final Kind kind;
 
     /** One array to be tested for equality. */
-    @Input private ValueNode array1;
+    @Input ValueNode array1;
 
     /** The other array to be tested for equality. */
-    @Input private ValueNode array2;
+    @Input ValueNode array2;
 
     /** Length of both arrays. */
-    @Input private ValueNode length;
+    @Input ValueNode length;
 
-    public ArrayEqualsNode(ValueNode array1, ValueNode array2, ValueNode length) {
+    public static ArrayEqualsNode create(ValueNode array1, ValueNode array2, ValueNode length) {
+        return USE_GENERATED_NODES ? new ArrayEqualsNodeGen(array1, array2, length) : new ArrayEqualsNode(array1, array2, length);
+    }
+
+    protected ArrayEqualsNode(ValueNode array1, ValueNode array2, ValueNode length) {
         super(StampFactory.forKind(Kind.Boolean));
 
         assert array1.stamp().equals(array2.stamp());
@@ -132,4 +139,8 @@
         Value result = gen.getLIRGeneratorTool().emitArrayEquals(kind, gen.operand(array1), gen.operand(array2), gen.operand(length));
         gen.setResult(this, result);
     }
+
+    public LocationIdentity getLocationIdentity() {
+        return NamedLocationIdentity.getArrayLocation(kind);
+    }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/AssertionNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/AssertionNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -34,14 +35,19 @@
  * fail if this has not happened by the time the node is lowered to LIR, while runtime assertions
  * may need to insert a check.
  */
+@NodeInfo
 public class AssertionNode extends FixedWithNextNode implements Lowerable, Canonicalizable, LIRLowerable {
 
-    @Input private ValueNode value;
+    @Input ValueNode value;
 
     private final boolean compileTimeAssertion;
     private final String message;
 
-    public AssertionNode(boolean compileTimeAssertion, ValueNode value, String message) {
+    public static AssertionNode create(boolean compileTimeAssertion, ValueNode value, String message) {
+        return USE_GENERATED_NODES ? new AssertionNodeGen(compileTimeAssertion, value, message) : new AssertionNode(compileTimeAssertion, value, message);
+    }
+
+    protected AssertionNode(boolean compileTimeAssertion, ValueNode value, String message) {
         super(StampFactory.forVoid());
         this.value = value;
         this.compileTimeAssertion = compileTimeAssertion;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,13 +25,19 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public class BitCountNode extends UnaryNode implements LIRLowerable {
 
-    public BitCountNode(ValueNode value) {
+    public static BitCountNode create(ValueNode value) {
+        return USE_GENERATED_NODES ? new BitCountNodeGen(value) : new BitCountNode(value);
+    }
+
+    protected BitCountNode(ValueNode value) {
         super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value);
         assert value.getKind() == Kind.Int || value.getKind() == Kind.Long;
     }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -33,9 +34,14 @@
  * Determines the index of the least significant "1" bit. Note that the result is undefined if the
  * input is zero.
  */
+@NodeInfo
 public class BitScanForwardNode extends UnaryNode implements LIRLowerable {
 
-    public BitScanForwardNode(ValueNode value) {
+    public static BitScanForwardNode create(ValueNode value) {
+        return USE_GENERATED_NODES ? new BitScanForwardNodeGen(value) : new BitScanForwardNode(value);
+    }
+
+    protected BitScanForwardNode(ValueNode value) {
         super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value);
         assert value.getKind() == Kind.Int || value.getKind() == Kind.Long;
     }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -33,9 +34,14 @@
  * Determines the index of the most significant "1" bit. Note that the result is undefined if the
  * input is zero.
  */
+@NodeInfo
 public class BitScanReverseNode extends UnaryNode implements LIRLowerable {
 
-    public BitScanReverseNode(ValueNode value) {
+    public static BitScanReverseNode create(ValueNode value) {
+        return USE_GENERATED_NODES ? new BitScanReverseNodeGen(value) : new BitScanReverseNode(value);
+    }
+
+    protected BitScanReverseNode(ValueNode value) {
         super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value);
         assert value.getKind() == Kind.Int || value.getKind() == Kind.Long;
     }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.HeapAccess.BarrierType;
 import com.oracle.graal.nodes.extended.*;
@@ -33,15 +34,21 @@
  * A special purpose store node that differs from {@link UnsafeStoreNode} in that it is not a
  * {@link StateSplit} and does not include a write barrier.
  */
+@NodeInfo
 public class DirectObjectStoreNode extends FixedWithNextNode implements Lowerable {
 
-    @Input private ValueNode object;
-    @Input private ValueNode value;
-    @Input private ValueNode offset;
+    @Input ValueNode object;
+    @Input ValueNode value;
+    @Input ValueNode offset;
     private final int displacement;
     private final LocationIdentity locationIdentity;
 
-    public DirectObjectStoreNode(ValueNode object, int displacement, ValueNode offset, ValueNode value, LocationIdentity locationIdentity) {
+    public static DirectObjectStoreNode create(ValueNode object, int displacement, ValueNode offset, ValueNode value, LocationIdentity locationIdentity) {
+        return USE_GENERATED_NODES ? new DirectObjectStoreNodeGen(object, displacement, offset, value, locationIdentity) : new DirectObjectStoreNode(object, displacement, offset, value,
+                        locationIdentity);
+    }
+
+    protected DirectObjectStoreNode(ValueNode object, int displacement, ValueNode offset, ValueNode value, LocationIdentity locationIdentity) {
         super(StampFactory.forVoid());
         this.object = object;
         this.value = value;
@@ -59,7 +66,7 @@
     @Override
     public void lower(LoweringTool tool) {
         IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, value.getKind(), displacement, offset, graph(), 1);
-        JavaWriteNode write = graph().add(new JavaWriteNode(object, value, location, BarrierType.NONE, value.getKind() == Kind.Object, false));
+        JavaWriteNode write = graph().add(JavaWriteNode.create(object, value, location, BarrierType.NONE, value.getKind() == Kind.Object, false));
         graph().replaceFixedWithFixed(this, write);
 
         tool.getLowerer().lower(write, tool);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -34,12 +35,17 @@
  * A special purpose store node that differs from {@link UnsafeStoreNode} in that it is not a
  * {@link StateSplit} and takes a computed address instead of an object.
  */
+@NodeInfo
 public class DirectReadNode extends FixedWithNextNode implements LIRLowerable {
 
-    @Input private ValueNode address;
+    @Input protected ValueNode address;
     private final Kind readKind;
 
-    public DirectReadNode(ValueNode address, Kind readKind) {
+    public static DirectReadNode create(ValueNode address, Kind readKind) {
+        return USE_GENERATED_NODES ? new DirectReadNodeGen(address, readKind) : new DirectReadNode(address, readKind);
+    }
+
+    protected DirectReadNode(ValueNode address, Kind readKind) {
         super(StampFactory.forKind(readKind));
         this.address = address;
         this.readKind = readKind;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -34,13 +35,18 @@
  * A special purpose store node that differs from {@link UnsafeStoreNode} in that it is not a
  * {@link StateSplit} and takes a computed address instead of an object.
  */
+@NodeInfo
 public class DirectStoreNode extends FixedWithNextNode implements LIRLowerable {
 
-    @Input private ValueNode address;
-    @Input private ValueNode value;
+    @Input protected ValueNode address;
+    @Input protected ValueNode value;
     private final Kind kind;
 
-    public DirectStoreNode(ValueNode address, ValueNode value, Kind kind) {
+    public static DirectStoreNode create(ValueNode address, ValueNode value, Kind kind) {
+        return USE_GENERATED_NODES ? new DirectStoreNodeGen(address, value, kind) : new DirectStoreNode(address, value, kind);
+    }
+
+    protected DirectStoreNode(ValueNode address, ValueNode value, Kind kind) {
         super(StampFactory.forVoid());
         this.address = address;
         this.value = value;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ExplodeLoopNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ExplodeLoopNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,36 +26,42 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.Snippet.VarargsParameter;
 
 /**
  * Placeholder node to denote to snippet preparation that the following loop must be completely
  * unrolled.
- * 
+ *
  * @see VarargsParameter
  */
-public final class ExplodeLoopNode extends FixedWithNextNode {
+@NodeInfo
+public class ExplodeLoopNode extends FixedWithNextNode {
 
-    public ExplodeLoopNode() {
+    public static ExplodeLoopNode create() {
+        return USE_GENERATED_NODES ? new ExplodeLoopNodeGen() : new ExplodeLoopNode();
+    }
+
+    protected ExplodeLoopNode() {
         super(StampFactory.forVoid());
     }
 
     public LoopBeginNode findLoopBegin() {
-        Node next = next();
+        Node currentNext = next();
         ArrayList<Node> succs = new ArrayList<>();
-        while (!(next instanceof LoopBeginNode)) {
-            assert next != null : "cannot find loop after " + this;
-            for (Node n : next.cfgSuccessors()) {
+        while (!(currentNext instanceof LoopBeginNode)) {
+            assert currentNext != null : "cannot find loop after " + this;
+            for (Node n : currentNext.cfgSuccessors()) {
                 succs.add(n);
             }
             if (succs.size() == 1) {
-                next = succs.get(0);
+                currentNext = succs.get(0);
             } else {
                 return null;
             }
         }
-        return (LoopBeginNode) next;
+        return (LoopBeginNode) currentNext;
     }
 
     /**
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/LoadSnippetVarargParameterNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/LoadSnippetVarargParameterNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,19 +25,25 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.Snippet.VarargsParameter;
 
 /**
  * Implements the semantics of {@link VarargsParameter}.
  */
-public final class LoadSnippetVarargParameterNode extends FixedWithNextNode implements Canonicalizable {
+@NodeInfo
+public class LoadSnippetVarargParameterNode extends FixedWithNextNode implements Canonicalizable {
 
-    @Input private ValueNode index;
+    @Input ValueNode index;
 
-    @Input private final NodeInputList<ParameterNode> parameters;
+    @Input NodeInputList<ParameterNode> parameters;
 
-    public LoadSnippetVarargParameterNode(ParameterNode[] locals, ValueNode index, Stamp stamp) {
+    public static LoadSnippetVarargParameterNode create(ParameterNode[] locals, ValueNode index, Stamp stamp) {
+        return USE_GENERATED_NODES ? new LoadSnippetVarargParameterNodeGen(locals, index, stamp) : new LoadSnippetVarargParameterNode(locals, index, stamp);
+    }
+
+    protected LoadSnippetVarargParameterNode(ParameterNode[] locals, ValueNode index, Stamp stamp) {
         super(stamp);
         this.index = index;
         this.parameters = new NodeInputList<>(this, locals);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -30,8 +30,9 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
@@ -55,15 +56,20 @@
  * possible if the macro node is a {@link MacroStateSplitNode}.</li>
  * </ul>
  */
+@NodeInfo
 public class MacroNode extends FixedWithNextNode implements Lowerable {
 
-    @Input protected final NodeInputList<ValueNode> arguments;
+    @Input protected NodeInputList<ValueNode> arguments;
 
     private final int bci;
     private final ResolvedJavaMethod targetMethod;
     private final JavaType returnType;
     private final InvokeKind invokeKind;
 
+    public static MacroNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new MacroNodeGen(invoke) : new MacroNode(invoke);
+    }
+
     protected MacroNode(Invoke invoke) {
         super(StampFactory.forKind(((MethodCallTargetNode) invoke.callTarget()).targetMethod().getSignature().getReturnKind()));
         MethodCallTargetNode methodCallTarget = (MethodCallTargetNode) invoke.callTarget();
@@ -182,8 +188,8 @@
     }
 
     protected InvokeNode createInvoke() {
-        MethodCallTargetNode callTarget = graph().add(new MethodCallTargetNode(invokeKind, targetMethod, arguments.toArray(new ValueNode[arguments.size()]), returnType));
-        InvokeNode invoke = graph().add(new InvokeNode(callTarget, bci));
+        MethodCallTargetNode callTarget = graph().add(MethodCallTargetNode.create(invokeKind, targetMethod, arguments.toArray(new ValueNode[arguments.size()]), returnType));
+        InvokeNode invoke = graph().add(InvokeNode.create(callTarget, bci));
         if (stateAfter() != null) {
             invoke.setStateAfter(stateAfter().duplicate());
             if (getKind() != Kind.Void) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroStateSplitNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroStateSplitNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,7 +25,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
@@ -34,9 +34,14 @@
  * This is an extension of {@link MacroNode} that is a {@link StateSplit} and a
  * {@link MemoryCheckpoint}.
  */
+@NodeInfo
 public class MacroStateSplitNode extends MacroNode implements StateSplit, MemoryCheckpoint.Single {
 
-    @OptionalInput(InputType.State) private FrameState stateAfter;
+    @OptionalInput(InputType.State) protected FrameState stateAfter;
+
+    public static MacroStateSplitNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new MacroStateSplitNodeGen(invoke) : new MacroStateSplitNode(invoke);
+    }
 
     protected MacroStateSplitNode(Invoke invoke) {
         super(invoke);
@@ -70,7 +75,7 @@
             }
             assert invoke.stateAfter().bci == BytecodeFrame.AFTER_BCI;
             // Here we need to fix the bci of the invoke
-            InvokeNode newInvoke = snippetGraph.add(new InvokeNode(invoke.callTarget(), getBci()));
+            InvokeNode newInvoke = snippetGraph.add(InvokeNode.create(invoke.callTarget(), getBci()));
             newInvoke.setStateAfter(invoke.stateAfter());
             snippetGraph.replaceFixedWithFixed((InvokeNode) invoke.asNode(), newInvoke);
         }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,10 +27,12 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public class MathIntrinsicNode extends UnaryNode implements ArithmeticLIRLowerable {
 
     private final Operation operation;
@@ -49,7 +51,11 @@
         return operation;
     }
 
-    public MathIntrinsicNode(ValueNode value, Operation op) {
+    public static MathIntrinsicNode create(ValueNode value, Operation op) {
+        return USE_GENERATED_NODES ? new MathIntrinsicNodeGen(value, op) : new MathIntrinsicNode(value, op);
+    }
+
+    protected MathIntrinsicNode(ValueNode value, Operation op) {
         super(StampFactory.forKind(Kind.Double), value);
         assert value.stamp() instanceof FloatStamp && PrimitiveStamp.getBits(value.stamp()) == 64;
         this.operation = op;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -32,7 +33,11 @@
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
 public class MemoryAnchorNode extends FixedWithNextNode implements LIRLowerable, MemoryNode, Canonicalizable {
 
-    public MemoryAnchorNode() {
+    public static MemoryAnchorNode create() {
+        return USE_GENERATED_NODES ? new MemoryAnchorNodeGen() : new MemoryAnchorNode();
+    }
+
+    protected MemoryAnchorNode() {
         super(StampFactory.forVoid());
     }
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/PureFunctionMacroNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/PureFunctionMacroNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,12 +25,14 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
 /**
  * This node class can be used to create {@link MacroNode}s for simple pure functions like
  * {@link System#identityHashCode(Object)}.
  */
+@NodeInfo
 public abstract class PureFunctionMacroNode extends MacroStateSplitNode implements Canonicalizable {
 
     public PureFunctionMacroNode(Invoke invoke) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,7 +25,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -33,7 +33,7 @@
  * Access the value of a specific register.
  */
 @NodeInfo(nameTemplate = "ReadRegister %{p#register}")
-public final class ReadRegisterNode extends FixedWithNextNode implements LIRLowerable {
+public class ReadRegisterNode extends FixedWithNextNode implements LIRLowerable {
 
     /**
      * The fixed register to access.
@@ -53,7 +53,11 @@
      */
     private final boolean incoming;
 
-    public ReadRegisterNode(Register register, Kind kind, boolean directUse, boolean incoming) {
+    public static ReadRegisterNode create(Register register, Kind kind, boolean directUse, boolean incoming) {
+        return USE_GENERATED_NODES ? new ReadRegisterNodeGen(register, kind, directUse, incoming) : new ReadRegisterNode(register, kind, directUse, incoming);
+    }
+
+    protected ReadRegisterNode(Register register, Kind kind, boolean directUse, boolean incoming) {
         super(StampFactory.forKind(kind));
         assert register != null;
         this.register = register;
@@ -65,7 +69,11 @@
      * Constructor to be used by node intrinsics where the stamp is inferred from the intrinsic
      * definition.
      */
-    public ReadRegisterNode(Register register, boolean directUse, boolean incoming) {
+    public static ReadRegisterNode create(Register register, boolean directUse, boolean incoming) {
+        return USE_GENERATED_NODES ? new ReadRegisterNodeGen(register, directUse, incoming) : new ReadRegisterNode(register, directUse, incoming);
+    }
+
+    protected ReadRegisterNode(Register register, boolean directUse, boolean incoming) {
         super(StampFactory.forNodeIntrinsic());
         assert register != null;
         this.register = register;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,14 +25,20 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
+@NodeInfo
 public class ReverseBytesNode extends UnaryNode implements LIRLowerable {
 
-    public ReverseBytesNode(ValueNode value) {
+    public static ReverseBytesNode create(ValueNode value) {
+        return USE_GENERATED_NODES ? new ReverseBytesNodeGen(value) : new ReverseBytesNode(value);
+    }
+
+    protected ReverseBytesNode(ValueNode value) {
         super(StampFactory.forKind(value.getKind()), value);
         assert getKind() == Kind.Int || getKind() == Kind.Long;
     }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,7 +25,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -33,7 +33,7 @@
  * Changes the value of a specific register.
  */
 @NodeInfo(nameTemplate = "WriteRegister %{p#register}")
-public final class WriteRegisterNode extends FixedWithNextNode implements LIRLowerable {
+public class WriteRegisterNode extends FixedWithNextNode implements LIRLowerable {
 
     /**
      * The fixed register to access.
@@ -43,9 +43,13 @@
     /**
      * The new value assigned to the register.
      */
-    @Input private ValueNode value;
+    @Input ValueNode value;
 
-    public WriteRegisterNode(Register register, ValueNode value) {
+    public static WriteRegisterNode create(Register register, ValueNode value) {
+        return USE_GENERATED_NODES ? new WriteRegisterNodeGen(register, value) : new WriteRegisterNode(register, value);
+    }
+
+    protected WriteRegisterNode(Register register, ValueNode value) {
         super(StampFactory.forVoid());
         this.register = register;
         this.value = value;
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Mon Aug 25 21:15:59 2014 -0700
@@ -59,6 +59,7 @@
 import com.oracle.truffle.api.CompilerDirectives.SlowPath;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.Node;
 
 /**
  * Implementation of the Truffle runtime when running on top of Graal.
@@ -117,9 +118,16 @@
         return new OptimizedCallTarget(rootNode, this, TruffleMinInvokeThreshold.getValue(), TruffleCompilationThreshold.getValue(), compilationPolicy, new HotSpotSpeculationLog());
     }
 
+    public LoopNode createLoopNode(RepeatingNode repeating) {
+        if (!(repeating instanceof Node)) {
+            throw new IllegalArgumentException("Repeating node must be of type Node.");
+        }
+        return new OptimizedLoopNode(repeating);
+    }
+
     public DirectCallNode createDirectCallNode(CallTarget target) {
         if (target instanceof OptimizedCallTarget) {
-            return OptimizedDirectCallNode.create((OptimizedCallTarget) target);
+            return new OptimizedDirectCallNode((OptimizedCallTarget) target);
         } else {
             throw new IllegalStateException(String.format("Unexpected call target class %s!", target.getClass()));
         }
@@ -231,7 +239,7 @@
         MetaAccessProvider metaAccess = providers.getMetaAccess();
         SuitesProvider suitesProvider = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites();
         Suites suites = suitesProvider.createSuites();
-        suites.getHighTier().findPhase(InliningPhase.class).remove();
+        removeInliningPhase(suites);
         StructuredGraph graph = new StructuredGraph(javaMethod);
         new GraphBuilderPhase.Instance(metaAccess, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
         PhaseSuite<HighTierContext> graphBuilderSuite = suitesProvider.getDefaultGraphBuilderSuite();
@@ -247,6 +255,13 @@
         return runtimeProvider.getHostBackend().getProviders();
     }
 
+    private static void removeInliningPhase(Suites suites) {
+        ListIterator<BasePhase<? super HighTierContext>> inliningPhase = suites.getHighTier().findPhase(InliningPhase.class);
+        if (inliningPhase != null) {
+            inliningPhase.remove();
+        }
+    }
+
     @SlowPath
     @Override
     public <T> T iterateFrames(FrameInstanceVisitor<T> visitor) {
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -158,7 +158,7 @@
 
         try (Scope s = Debug.scope("Truffle", new DebugDumpScope("Comparison: " + methodName))) {
             Assumptions assumptions = new Assumptions(false);
-            StructuredGraph graph = parse(methodName);
+            StructuredGraph graph = parseEager(methodName);
             PhaseContext context = new PhaseContext(getProviders(), assumptions);
             CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
             canonicalizer.apply(graph, context);
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/BlockTestNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/BlockTestNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 
+@NodeInfo
 public class BlockTestNode extends AbstractTestNode {
 
     @Children private final AbstractTestNode[] statements;
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/ConstantWithAssumptionTestNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/ConstantWithAssumptionTestNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 
+@NodeInfo
 public class ConstantWithAssumptionTestNode extends AbstractTestNode {
 
     private final int value;
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/RootTestNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/RootTestNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 
+@NodeInfo
 public class RootTestNode extends RootNode {
 
     private final String name;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleSplittingStrategyNew.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleSplittingStrategyNew.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,7 +26,7 @@
 
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeUtil.*;
+import com.oracle.truffle.api.nodes.NodeUtil.NodeCountFilter;
 
 public class DefaultTruffleSplittingStrategyNew implements TruffleSplittingStrategy {
     private static int splitChangeCount;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java	Mon Aug 25 21:15:59 2014 -0700
@@ -81,7 +81,9 @@
     }
 
     private Object getObjectUnsafe(FrameSlot slot) {
-        return CompilerDirectives.unsafeGetObject(getLocals(), (long) slot.getIndex() * Unsafe.ARRAY_OBJECT_INDEX_SCALE + Unsafe.ARRAY_OBJECT_BASE_OFFSET, true, slot);
+        int slotIndex = slot.getIndex();
+        return CompilerDirectives.unsafeGetObject(getLocals(), (long) slotIndex * Unsafe.ARRAY_OBJECT_INDEX_SCALE + Unsafe.ARRAY_OBJECT_BASE_OFFSET,
+                        this.getTags()[slotIndex] == FrameSlotKind.Object.ordinal(), slot);
     }
 
     @Override
@@ -101,7 +103,9 @@
     }
 
     private byte getByteUnsafe(FrameSlot slot) {
-        return CompilerDirectives.unsafeGetByte(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot);
+        int slotIndex = slot.getIndex();
+        return CompilerDirectives.unsafeGetByte(getPrimitiveLocals(), (long) slotIndex * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET,
+                        this.getTags()[slotIndex] == FrameSlotKind.Byte.ordinal(), slot);
     }
 
     @Override
@@ -121,7 +125,9 @@
     }
 
     private boolean getBooleanUnsafe(FrameSlot slot) {
-        return CompilerDirectives.unsafeGetBoolean(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot);
+        int slotIndex = slot.getIndex();
+        return CompilerDirectives.unsafeGetBoolean(getPrimitiveLocals(), (long) slotIndex * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET,
+                        this.getTags()[slotIndex] == FrameSlotKind.Boolean.ordinal(), slot);
     }
 
     @Override
@@ -141,7 +147,9 @@
     }
 
     private float getFloatUnsafe(FrameSlot slot) {
-        return CompilerDirectives.unsafeGetFloat(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot);
+        int slotIndex = slot.getIndex();
+        return CompilerDirectives.unsafeGetFloat(getPrimitiveLocals(), (long) slotIndex * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET,
+                        this.getTags()[slotIndex] == FrameSlotKind.Float.ordinal(), slot);
     }
 
     @Override
@@ -161,7 +169,9 @@
     }
 
     private long getLongUnsafe(FrameSlot slot) {
-        return CompilerDirectives.unsafeGetLong(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot);
+        int slotIndex = slot.getIndex();
+        return CompilerDirectives.unsafeGetLong(getPrimitiveLocals(), (long) slotIndex * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET,
+                        this.getTags()[slotIndex] == FrameSlotKind.Long.ordinal(), slot);
     }
 
     @Override
@@ -181,7 +191,9 @@
     }
 
     private int getIntUnsafe(FrameSlot slot) {
-        return CompilerDirectives.unsafeGetInt(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot);
+        int slotIndex = slot.getIndex();
+        return CompilerDirectives.unsafeGetInt(getPrimitiveLocals(), (long) slotIndex * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET,
+                        this.getTags()[slotIndex] == FrameSlotKind.Int.ordinal(), slot);
     }
 
     @Override
@@ -201,7 +213,9 @@
     }
 
     private double getDoubleUnsafe(FrameSlot slot) {
-        return CompilerDirectives.unsafeGetDouble(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot);
+        int slotIndex = slot.getIndex();
+        return CompilerDirectives.unsafeGetDouble(getPrimitiveLocals(), (long) slotIndex * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET,
+                        this.getTags()[slotIndex] == FrameSlotKind.Double.ordinal(), slot);
     }
 
     @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/MaterializedFrameNotify.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/MaterializedFrameNotify.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.truffle;
 
-import com.oracle.truffle.api.frame.FrameInstance.*;
+import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
 
 public interface MaterializedFrameNotify {
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,9 +22,14 @@
  */
 package com.oracle.graal.truffle;
 
+import static com.oracle.graal.truffle.TruffleCompilerOptions.*;
+
 import java.lang.ref.*;
+import java.util.*;
+import java.util.stream.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.debug.*;
 import com.oracle.truffle.api.impl.*;
 import com.oracle.truffle.api.nodes.*;
 
@@ -52,16 +57,28 @@
     @Override
     public synchronized void invalidate() {
         if (isValid) {
+            boolean invalidatedInstalledCode = false;
             Entry e = first;
             while (e != null) {
                 InstalledCode installedCode = e.installedCode.get();
                 if (installedCode != null && installedCode.getVersion() == e.version) {
                     installedCode.invalidate();
+
+                    invalidatedInstalledCode = true;
+                    if (TraceTruffleAssumptions.getValue()) {
+                        logInvalidatedInstalledCode(installedCode);
+                    }
                 }
                 e = e.next;
             }
             first = null;
             isValid = false;
+
+            if (TraceTruffleAssumptions.getValue()) {
+                if (invalidatedInstalledCode) {
+                    logStackTrace();
+                }
+            }
         }
     }
 
@@ -81,4 +98,16 @@
     public boolean isValid() {
         return isValid;
     }
+
+    private void logInvalidatedInstalledCode(InstalledCode installedCode) {
+        TTY.out().out().printf("assumption '%s' invalidated installed code '%s'\n", name, installedCode);
+    }
+
+    private static void logStackTrace() {
+        final int skip = 1;
+        final int limit = 20;
+        StackTraceElement[] stackTrace = new Throwable().getStackTrace();
+        String suffix = stackTrace.length > skip + limit ? "\n  ..." : "";
+        TTY.out().out().println(Arrays.stream(stackTrace).skip(skip).limit(limit).map(StackTraceElement::toString).collect(Collectors.joining("\n  ", "", suffix)));
+    }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Mon Aug 25 21:15:59 2014 -0700
@@ -217,7 +217,7 @@
             logOptimizedInvalidated(this, oldNode, newNode, reason);
         }
         cancelInstalledTask(oldNode, newNode, reason);
-        invalidateInlining();
+        // invalidateInlining();
     }
 
     public void invalidateInlining() {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java	Mon Aug 25 21:15:59 2014 -0700
@@ -194,6 +194,7 @@
                     if (kind == NodeCost.POLYMORPHIC || kind == NodeCost.MEGAMORPHIC) {
                         Map<String, Object> props = new LinkedHashMap<>();
                         props.put("simpleName", node.getClass().getSimpleName());
+                        props.put("subtree", "\n" + NodeUtil.printCompactTreeToString(node));
                         String msg = kind == NodeCost.MEGAMORPHIC ? "megamorphic" : "polymorphic";
                         log(0, msg, node.toString(), props);
                     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedDirectCallNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedDirectCallNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -31,6 +31,7 @@
 /**
  * A call node with a constant {@link CallTarget} that can be optimized by Graal.
  */
+@NodeInfo
 public final class OptimizedDirectCallNode extends DirectCallNode implements MaterializedFrameNotify {
 
     private int callCount;
@@ -42,7 +43,7 @@
 
     private final TruffleSplittingStrategy splittingStrategy;
 
-    private OptimizedDirectCallNode(OptimizedCallTarget target) {
+    public OptimizedDirectCallNode(OptimizedCallTarget target) {
         super(target);
         if (TruffleCompilerOptions.TruffleSplittingNew.getValue()) {
             this.splittingStrategy = new DefaultTruffleSplittingStrategyNew(this);
@@ -66,7 +67,7 @@
 
     private void afterInterpreterCall(Object result) {
         splittingStrategy.afterCall(result);
-        propagateInliningInvalidations();
+        // propagateInliningInvalidations();
     }
 
     public static Object callProxy(MaterializedFrameNotify notify, CallTarget callTarget, VirtualFrame frame, Object[] arguments, boolean inlined, boolean direct) {
@@ -149,7 +150,7 @@
             getCurrentCallTarget().incrementKnownCallSites();
         }
         splittingStrategy.beforeCall(arguments);
-        propagateInliningInvalidations();
+        // propagateInliningInvalidations();
     }
 
     /** Used by the splitting strategy to install new targets. */
@@ -176,6 +177,7 @@
         }
     }
 
+    @SuppressWarnings("unused")
     private void propagateInliningInvalidations() {
         if (isInlined() && !getCurrentCallTarget().inliningPerformed) {
             replace(this, "Propagate invalid inlining from " + getCurrentCallTarget().toString());
@@ -197,8 +199,4 @@
         splittingStrategy.forceSplitting();
         return true;
     }
-
-    public static OptimizedDirectCallNode create(OptimizedCallTarget target) {
-        return new OptimizedDirectCallNode(target);
-    }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedIndirectCallNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedIndirectCallNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -31,6 +31,7 @@
 /**
  * A call node with a constant {@link CallTarget} that can be optimized by Graal.
  */
+@NodeInfo
 public final class OptimizedIndirectCallNode extends IndirectCallNode implements MaterializedFrameNotify {
 
     @CompilationFinal private FrameAccess outsideFrameAccess = FrameAccess.NONE;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedLoopNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2014, 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;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Temporary node for legacy loop count reporting support as it was most likely done in other
+ * implementations.
+ */
+public final class OptimizedLoopNode extends LoopNode {
+
+    @CompilationFinal private int loopCount;
+
+    public OptimizedLoopNode(RepeatingNode body) {
+        super(body);
+    }
+
+    @Override
+    public void executeLoop(VirtualFrame frame) {
+        try {
+            do {
+            } while (executeBody(frame));
+        } finally {
+            loopDone();
+        }
+    }
+
+    private final boolean executeBody(VirtualFrame frame) {
+        boolean result = executeRepeatNode(frame);
+        if (CompilerDirectives.inInterpreter()) {
+            if (result) {
+                loopCount++;
+            }
+        }
+        return result;
+    }
+
+    private void loopDone() {
+        if (CompilerDirectives.inInterpreter()) {
+            getRootNode().reportLoopCount(loopCount);
+            loopCount = 0;
+        }
+    }
+}
\ No newline at end of file
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Mon Aug 25 21:15:59 2014 -0700
@@ -38,8 +38,8 @@
 import com.oracle.graal.graph.Node;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.loop.*;
+import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
@@ -138,7 +138,11 @@
             }
 
             // EA frame and clean up.
-            new PartialEscapePhase(true, canonicalizer).apply(graph, tierContext);
+            try (Scope pe = Debug.scope("TrufflePartialEscape", graph)) {
+                new PartialEscapePhase(true, canonicalizer).apply(graph, tierContext);
+            } catch (Throwable t) {
+                Debug.handle(t);
+            }
             new VerifyNoIntrinsicsLeftPhase().apply(graph, false);
             for (MaterializeFrameNode materializeNode : graph.getNodes(MaterializeFrameNode.class).snapshot()) {
                 materializeNode.replaceAtUsages(materializeNode.getFrame());
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java	Mon Aug 25 21:15:59 2014 -0700
@@ -37,8 +37,8 @@
 import com.oracle.graal.graph.Node;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
@@ -276,7 +276,7 @@
             boolean removeAllocation = runtimeExceptionClass.isAssignableFrom(declaringClass) || errorClass.isAssignableFrom(declaringClass);
             boolean isControlFlowException = controlFlowExceptionClass.isAssignableFrom(exceptionType);
             if (removeAllocation && !isControlFlowException) {
-                DeoptimizeNode deoptNode = methodCallTargetNode.graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode));
+                DeoptimizeNode deoptNode = methodCallTargetNode.graph().add(DeoptimizeNode.create(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode));
                 FixedNode invokeNode = methodCallTargetNode.invoke().asNode();
                 invokeNode.replaceAtPredecessor(deoptNode);
                 GraphUtil.killCFG(invokeNode);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Mon Aug 25 21:15:59 2014 -0700
@@ -69,7 +69,7 @@
     @Option(help = "Experimental: Enable the new version of truffle splitting.")
     public static final OptionValue<Boolean> TruffleSplittingNew = new OptionValue<>(false);
     @Option(help = "Experimental. New splitting only: Whether or not splitting should be based instance comparisons of non TypedObjects")
-    public static final OptionValue<Boolean> TruffleSplittingClassInstanceStamps = new OptionValue<>(true);
+    public static final OptionValue<Boolean> TruffleSplittingClassInstanceStamps = new OptionValue<>(false);
     @Option(help = "Experimental. New splitting only: Whether or not splitting should be based instance comparisons of TypedObjects")
     public static final OptionValue<Boolean> TruffleSplittingTypeInstanceStamps = new OptionValue<>(true);
     @Option(help = "Experimental. New splitting only: The number of calls until splitting is performed. ")
@@ -121,6 +121,8 @@
     public static final OptionValue<Boolean> TraceTruffleSplitting = new OptionValue<>(false);
     @Option(help = "Print stack trace on transfer to interpreter")
     public static final OptionValue<Boolean> TraceTruffleTransferToInterpreter = new StableOptionValue<>(false);
+    @Option(help = "Print stack trace on assumption invalidation")
+    public static final OptionValue<Boolean> TraceTruffleAssumptions = new StableOptionValue<>(false);
     @Option(help = "")
     public static final OptionValue<Boolean> TruffleCallTargetProfiling = new StableOptionValue<>(false);
     // @formatter:on
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java	Mon Aug 25 21:15:59 2014 -0700
@@ -54,6 +54,7 @@
         registerSubstitutions(ExactMath.class, ExactMathSubstitutions.class);
         registerSubstitutions(OptimizedAssumption.class, OptimizedAssumptionSubstitutions.class);
         registerSubstitutions(OptimizedCallTarget.class, OptimizedCallTargetSubstitutions.class);
+        registerSubstitutions(FrameWithoutBoxing.class, FrameWithoutBoxingSubstitutions.class);
     }
 
     @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,15 +27,21 @@
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.truffle.*;
 
+@NodeInfo
 public class AssumptionNode extends MacroNode implements com.oracle.graal.graph.IterableNodeType, Simplifiable {
 
-    public AssumptionNode(Invoke invoke) {
+    public static AssumptionNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new AssumptionNodeGen(invoke) : new AssumptionNode(invoke);
+    }
+
+    protected AssumptionNode(Invoke invoke) {
         super(invoke);
         assert super.arguments.size() == 1;
     }
@@ -78,7 +84,7 @@
                     graph.replaceFixedWithFloating(this, ConstantNode.forBoolean(false, graph()));
                 } else {
                     tool.deleteBranch(this.next());
-                    this.replaceAndDelete(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.None)));
+                    this.replaceAndDelete(graph.add(DeoptimizeNode.create(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.None)));
                 }
             }
         }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,13 +25,19 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.nodes.*;
 
+@NodeInfo
 public class BailoutNode extends MacroNode implements Canonicalizable {
 
-    public BailoutNode(Invoke invoke) {
+    public static BailoutNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new BailoutNodeGen(invoke) : new BailoutNode(invoke);
+    }
+
+    protected BailoutNode(Invoke invoke) {
         super(invoke);
         assert arguments.size() == 1;
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/LoadIndexedFinalNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/LoadIndexedFinalNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
@@ -34,7 +35,8 @@
 /**
  * @see LoadIndexedNode
  */
-public final class LoadIndexedFinalNode extends AccessIndexedNode implements Canonicalizable {
+@NodeInfo
+public class LoadIndexedFinalNode extends AccessIndexedNode implements Canonicalizable {
 
     /**
      * Creates a new {@link LoadIndexedFinalNode}.
@@ -43,7 +45,11 @@
      * @param index the instruction producing the index
      * @param elementKind the element type
      */
-    public LoadIndexedFinalNode(ValueNode array, ValueNode index, Kind elementKind) {
+    public static LoadIndexedFinalNode create(ValueNode array, ValueNode index, Kind elementKind) {
+        return USE_GENERATED_NODES ? new LoadIndexedFinalNodeGen(array, index, elementKind) : new LoadIndexedFinalNode(array, index, elementKind);
+    }
+
+    protected LoadIndexedFinalNode(ValueNode array, ValueNode index, Kind elementKind) {
         super(createStamp(array, elementKind), array, index, elementKind);
     }
 
@@ -74,7 +80,7 @@
 
     @Override
     public void lower(LoweringTool tool) {
-        LoadIndexedNode loadIndexedNode = graph().add(new LoadIndexedNode(array(), index(), elementKind()));
+        LoadIndexedNode loadIndexedNode = graph().add(LoadIndexedNode.create(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	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -35,9 +36,14 @@
  * Node representing an exact integer addition that will throw an {@link ArithmeticException} in
  * case the addition would overflow the 32 bit range.
  */
+@NodeInfo
 public class IntegerAddExactNode extends IntegerAddNode implements IntegerExactArithmeticNode {
 
-    public IntegerAddExactNode(ValueNode x, ValueNode y) {
+    public static IntegerAddExactNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new IntegerAddExactNodeGen(x, y) : new IntegerAddExactNode(x, y);
+    }
+
+    protected IntegerAddExactNode(ValueNode x, ValueNode y) {
         super(x, y);
         assert x.stamp().isCompatible(y.stamp()) && x.stamp() instanceof IntegerStamp;
     }
@@ -51,7 +57,7 @@
     @Override
     public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
         if (forX.isConstant() && !forY.isConstant()) {
-            return new IntegerAddExactNode(forY, forX);
+            return IntegerAddExactNode.create(forY, forX);
         }
         if (forX.isConstant()) {
             return canonicalXconstant(forX, forY);
@@ -83,7 +89,7 @@
 
     @Override
     public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) {
-        return graph().add(new IntegerAddExactSplitNode(stamp(), getX(), getY(), next, deopt));
+        return graph().add(IntegerAddExactSplitNode.create(stamp(), getX(), getY(), next, deopt));
     }
 
     @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,12 +24,18 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public class IntegerAddExactSplitNode extends IntegerExactArithmeticSplitNode {
 
-    public IntegerAddExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
+    public static IntegerAddExactSplitNode create(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
+        return USE_GENERATED_NODES ? new IntegerAddExactSplitNodeGen(stamp, x, y, next, overflowSuccessor) : new IntegerAddExactSplitNode(stamp, x, y, next, overflowSuccessor);
+    }
+
+    protected IntegerAddExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
         super(stamp, x, y, next, overflowSuccessor);
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,16 +24,18 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public abstract class IntegerExactArithmeticSplitNode extends ControlSplitNode implements LIRLowerable {
 
-    @Successor private BeginNode overflowSuccessor;
-    @Successor private BeginNode next;
-    @Input private ValueNode x;
-    @Input private ValueNode y;
+    @Successor BeginNode overflowSuccessor;
+    @Successor BeginNode next;
+    @Input ValueNode x;
+    @Input ValueNode y;
 
     public IntegerExactArithmeticSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
         super(stamp);
@@ -78,8 +80,8 @@
             FixedWithNextNode previous = tool.lastFixedNode();
             FixedNode next = previous.next();
             previous.setNext(null);
-            DeoptimizeNode deopt = floatingNode.graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.ArithmeticException));
-            BeginNode normalBegin = floatingNode.graph().add(new BeginNode());
+            DeoptimizeNode deopt = floatingNode.graph().add(DeoptimizeNode.create(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.ArithmeticException));
+            BeginNode normalBegin = floatingNode.graph().add(BeginNode.create());
             normalBegin.setNext(next);
             IntegerExactArithmeticSplitNode split = node.createSplit(normalBegin, BeginNode.begin(deopt));
             previous.setNext(split);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -34,9 +35,14 @@
  * Node representing an exact integer multiplication that will throw an {@link ArithmeticException}
  * in case the addition would overflow the 32 bit range.
  */
+@NodeInfo
 public class IntegerMulExactNode extends IntegerMulNode implements IntegerExactArithmeticNode {
 
-    public IntegerMulExactNode(ValueNode x, ValueNode y) {
+    public static IntegerMulExactNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new IntegerMulExactNodeGen(x, y) : new IntegerMulExactNode(x, y);
+    }
+
+    protected IntegerMulExactNode(ValueNode x, ValueNode y) {
         super(x, y);
         assert x.stamp().isCompatible(y.stamp()) && x.stamp() instanceof IntegerStamp;
     }
@@ -44,7 +50,7 @@
     @Override
     public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
         if (forX.isConstant() && !forY.isConstant()) {
-            return new IntegerMulExactNode(forY, forX);
+            return IntegerMulExactNode.create(forY, forX);
         }
         if (forX.isConstant()) {
             return canonicalXconstant(forX, forY);
@@ -79,7 +85,7 @@
 
     @Override
     public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) {
-        return graph().add(new IntegerMulExactSplitNode(stamp(), getX(), getY(), next, deopt));
+        return graph().add(IntegerMulExactSplitNode.create(stamp(), getX(), getY(), next, deopt));
     }
 
     @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,12 +24,18 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public class IntegerMulExactSplitNode extends IntegerExactArithmeticSplitNode {
 
-    public IntegerMulExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
+    public static IntegerMulExactSplitNode create(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
+        return USE_GENERATED_NODES ? new IntegerMulExactSplitNodeGen(stamp, x, y, next, overflowSuccessor) : new IntegerMulExactSplitNode(stamp, x, y, next, overflowSuccessor);
+    }
+
+    protected IntegerMulExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
         super(stamp, x, y, next, overflowSuccessor);
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulHighNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulHighNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,9 +27,9 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -38,11 +38,19 @@
 @NodeInfo(shortName = "*H")
 public class IntegerMulHighNode extends IntegerArithmeticNode {
 
-    public IntegerMulHighNode(ValueNode x, ValueNode y) {
+    public static IntegerMulHighNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new IntegerMulHighNodeGen(x, y) : new IntegerMulHighNode(x, y);
+    }
+
+    protected IntegerMulHighNode(ValueNode x, ValueNode y) {
         this(x.stamp().unrestricted(), x, y);
     }
 
-    public IntegerMulHighNode(Stamp stamp, ValueNode x, ValueNode y) {
+    public static IntegerMulHighNode create(Stamp stamp, ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new IntegerMulHighNodeGen(stamp, x, y) : new IntegerMulHighNode(stamp, x, y);
+    }
+
+    protected IntegerMulHighNode(Stamp stamp, ValueNode x, ValueNode y) {
         super(stamp, x, y);
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -36,9 +37,14 @@
  * Node representing an exact integer substraction that will throw an {@link ArithmeticException} in
  * case the addition would overflow the 32 bit range.
  */
+@NodeInfo
 public class IntegerSubExactNode extends IntegerSubNode implements IntegerExactArithmeticNode {
 
-    public IntegerSubExactNode(ValueNode x, ValueNode y) {
+    public static IntegerSubExactNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new IntegerSubExactNodeGen(x, y) : new IntegerSubExactNode(x, y);
+    }
+
+    protected IntegerSubExactNode(ValueNode x, ValueNode y) {
         super(x, y);
         assert x.stamp().isCompatible(y.stamp()) && x.stamp() instanceof IntegerStamp;
     }
@@ -84,7 +90,7 @@
 
     @Override
     public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) {
-        return graph().add(new IntegerSubExactSplitNode(stamp(), getX(), getY(), next, deopt));
+        return graph().add(IntegerSubExactSplitNode.create(stamp(), getX(), getY(), next, deopt));
     }
 
     @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,12 +24,18 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public class IntegerSubExactSplitNode extends IntegerExactArithmeticSplitNode {
 
-    public IntegerSubExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
+    public static IntegerSubExactSplitNode create(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
+        return USE_GENERATED_NODES ? new IntegerSubExactSplitNodeGen(stamp, x, y, next, overflowSuccessor) : new IntegerSubExactSplitNode(stamp, x, y, next, overflowSuccessor);
+    }
+
+    protected IntegerSubExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) {
         super(stamp, x, y, next, overflowSuccessor);
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/UnsignedMulHighNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/UnsignedMulHighNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,9 +27,9 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -38,11 +38,19 @@
 @NodeInfo(shortName = "|*H|")
 public class UnsignedMulHighNode extends IntegerArithmeticNode {
 
-    public UnsignedMulHighNode(ValueNode x, ValueNode y) {
+    public static UnsignedMulHighNode create(ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new UnsignedMulHighNodeGen(x, y) : new UnsignedMulHighNode(x, y);
+    }
+
+    protected UnsignedMulHighNode(ValueNode x, ValueNode y) {
         this(x.stamp().unrestricted(), x, y);
     }
 
-    public UnsignedMulHighNode(Stamp stamp, ValueNode x, ValueNode y) {
+    public static UnsignedMulHighNode create(Stamp stamp, ValueNode x, ValueNode y) {
+        return USE_GENERATED_NODES ? new UnsignedMulHighNodeGen(stamp, x, y) : new UnsignedMulHighNode(stamp, x, y);
+    }
+
+    protected UnsignedMulHighNode(Stamp stamp, ValueNode x, ValueNode y) {
         super(stamp, x, y);
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/CompilationConstantNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/CompilationConstantNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,11 +24,17 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 
+@NodeInfo
 public class CompilationConstantNode extends NeverPartOfCompilationNode implements Canonicalizable {
 
-    public CompilationConstantNode(Invoke invoke) {
+    public static CompilationConstantNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new CompilationConstantNodeGen(invoke) : new CompilationConstantNode(invoke);
+    }
+
+    protected CompilationConstantNode(Invoke invoke) {
         super(invoke, "The value could not be reduced to a compile time constant.");
         assert arguments.size() == 1;
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,13 +22,19 @@
  */
 package com.oracle.graal.truffle.nodes.asserts;
 
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.nodes.*;
 
+@NodeInfo
 public class NeverInlineMacroNode extends MacroStateSplitNode implements com.oracle.graal.graph.IterableNodeType {
 
-    public NeverInlineMacroNode(Invoke invoke) {
+    public static NeverInlineMacroNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new NeverInlineMacroNodeGen(invoke) : new NeverInlineMacroNode(invoke);
+    }
+
+    protected NeverInlineMacroNode(Invoke invoke) {
         super(invoke);
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,18 +23,28 @@
 package com.oracle.graal.truffle.nodes.asserts;
 
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.nodes.*;
 
+@NodeInfo
 public class NeverPartOfCompilationNode extends MacroStateSplitNode implements IterableNodeType {
 
     private final String message;
 
-    public NeverPartOfCompilationNode(Invoke invoke) {
+    public static NeverPartOfCompilationNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new NeverPartOfCompilationNodeGen(invoke) : new NeverPartOfCompilationNode(invoke);
+    }
+
+    protected NeverPartOfCompilationNode(Invoke invoke) {
         this(invoke, "This code path should never be part of a compilation.");
     }
 
-    public NeverPartOfCompilationNode(Invoke invoke, String message) {
+    public static NeverPartOfCompilationNode create(Invoke invoke, String message) {
+        return USE_GENERATED_NODES ? new NeverPartOfCompilationNodeGen(invoke, message) : new NeverPartOfCompilationNode(invoke, message);
+    }
+
+    protected NeverPartOfCompilationNode(Invoke invoke, String message) {
         super(invoke);
         this.message = message;
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/ForceMaterializeNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/ForceMaterializeNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,14 +23,20 @@
 package com.oracle.graal.truffle.nodes.frame;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
+@NodeInfo
 public class ForceMaterializeNode extends FixedWithNextNode implements LIRLowerable {
 
-    @Input private ValueNode object;
+    @Input ValueNode object;
 
-    public ForceMaterializeNode(ValueNode object) {
+    public static ForceMaterializeNode create(ValueNode object) {
+        return USE_GENERATED_NODES ? new ForceMaterializeNodeGen(object) : new ForceMaterializeNode(object);
+    }
+
+    protected ForceMaterializeNode(ValueNode object) {
         super(StampFactory.forVoid());
         this.object = object;
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/MaterializeFrameNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/MaterializeFrameNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,6 +23,7 @@
 package com.oracle.graal.truffle.nodes.frame;
 
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.truffle.*;
 
@@ -32,9 +33,13 @@
 @NodeInfo(nameTemplate = "MaterializeFrame{p#frame/s}")
 public class MaterializeFrameNode extends FixedWithNextNode implements IterableNodeType {
 
-    @Input private ValueNode frame;
+    @Input ValueNode frame;
 
-    public MaterializeFrameNode(ValueNode frame) {
+    public static MaterializeFrameNode create(ValueNode frame) {
+        return USE_GENERATED_NODES ? new MaterializeFrameNodeGen(frame) : new MaterializeFrameNode(frame);
+    }
+
+    protected MaterializeFrameNode(ValueNode frame) {
         super(frame.stamp());
         this.frame = frame;
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -31,6 +31,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
@@ -44,18 +45,27 @@
  * Intrinsic node representing the call for creating a frame in the {@link OptimizedCallTarget}
  * class.
  */
+@NodeInfo
 public class NewFrameNode extends FixedWithNextNode implements IterableNodeType, VirtualizableAllocation, Canonicalizable {
 
-    @Input private ValueNode descriptor;
-    @Input private ValueNode arguments;
+    @Input ValueNode descriptor;
+    @Input ValueNode arguments;
 
-    public NewFrameNode(Stamp stamp, ValueNode descriptor, ValueNode arguments) {
+    public static NewFrameNode create(Stamp stamp, ValueNode descriptor, ValueNode arguments) {
+        return USE_GENERATED_NODES ? new NewFrameNodeGen(stamp, descriptor, arguments) : new NewFrameNode(stamp, descriptor, arguments);
+    }
+
+    protected NewFrameNode(Stamp stamp, ValueNode descriptor, ValueNode arguments) {
         super(stamp);
         this.descriptor = descriptor;
         this.arguments = arguments;
     }
 
-    public NewFrameNode(ResolvedJavaType frameType, ValueNode descriptor, ValueNode arguments) {
+    public static NewFrameNode create(ResolvedJavaType frameType, ValueNode descriptor, ValueNode arguments) {
+        return USE_GENERATED_NODES ? new NewFrameNodeGen(frameType, descriptor, arguments) : new NewFrameNode(frameType, descriptor, arguments);
+    }
+
+    protected NewFrameNode(ResolvedJavaType frameType, ValueNode descriptor, ValueNode arguments) {
         this(StampFactory.exactNonNull(frameType), descriptor, arguments);
     }
 
@@ -93,11 +103,16 @@
         throw new RuntimeException("Frame field not found: " + fieldName);
     }
 
+    @NodeInfo
     public static class VirtualOnlyInstanceNode extends VirtualInstanceNode {
 
         private boolean allowMaterialization;
 
-        public VirtualOnlyInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields) {
+        public static VirtualOnlyInstanceNode create(ResolvedJavaType type, ResolvedJavaField[] fields) {
+            return USE_GENERATED_NODES ? new NewFrameNode_VirtualOnlyInstanceNodeGen(type, fields) : new VirtualOnlyInstanceNode(type, fields);
+        }
+
+        VirtualOnlyInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields) {
             super(type, fields, false);
         }
 
@@ -115,10 +130,10 @@
     }
 
     public static ValueNode getMaterializedRepresentationHelper(VirtualObjectNode virtualNode, FixedNode fixed) {
-        if (fixed instanceof MaterializeFrameNode || fixed instanceof AbstractEndNode) {
+        if (fixed instanceof MaterializeFrameNode || fixed instanceof AbstractEndNode || fixed instanceof ForceMaterializeNode) {
             // We need to conservatively assume that a materialization of a virtual frame can also
             // happen at a merge point.
-            return new AllocatedObjectNode(virtualNode);
+            return AllocatedObjectNode.create(virtualNode);
         }
         String escapeReason;
         if (fixed instanceof StoreFieldNode) {
@@ -151,10 +166,10 @@
         ResolvedJavaField primitiveLocalsField = findField(frameFields, "primitiveLocals");
         ResolvedJavaField tagsField = findField(frameFields, "tags");
 
-        VirtualObjectNode virtualFrame = new VirtualInstanceNode(frameType, frameFields, false);
-        VirtualObjectNode virtualFrameObjectArray = new VirtualArrayNode((ResolvedJavaType) localsField.getType().getComponentType(), frameSize);
-        VirtualObjectNode virtualFramePrimitiveArray = new VirtualArrayNode((ResolvedJavaType) primitiveLocalsField.getType().getComponentType(), frameSize);
-        VirtualObjectNode virtualFrameTagArray = new VirtualArrayNode((ResolvedJavaType) tagsField.getType().getComponentType(), frameSize);
+        VirtualObjectNode virtualFrame = VirtualOnlyInstanceNode.create(frameType, frameFields);
+        VirtualObjectNode virtualFrameObjectArray = VirtualArrayNode.create((ResolvedJavaType) localsField.getType().getComponentType(), frameSize);
+        VirtualObjectNode virtualFramePrimitiveArray = VirtualArrayNode.create((ResolvedJavaType) primitiveLocalsField.getType().getComponentType(), frameSize);
+        VirtualObjectNode virtualFrameTagArray = VirtualArrayNode.create((ResolvedJavaType) tagsField.getType().getComponentType(), frameSize);
 
         ValueNode[] objectArrayEntryState = new ValueNode[frameSize];
         ValueNode[] primitiveArrayEntryState = new ValueNode[frameSize];
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,6 +27,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
@@ -39,14 +40,20 @@
  *
  * Substitution for method {@link CompilerDirectives#unsafeGetFinalObject} and friends.
  */
+@NodeInfo
 public class CustomizedUnsafeLoadFinalNode extends FixedWithNextNode implements Canonicalizable, Virtualizable, Lowerable {
-    @Input private ValueNode object;
-    @Input private ValueNode offset;
-    @Input private ValueNode condition;
-    @Input private ValueNode location;
+    @Input ValueNode object;
+    @Input ValueNode offset;
+    @Input ValueNode condition;
+    @Input ValueNode location;
     private final Kind accessKind;
 
-    public CustomizedUnsafeLoadFinalNode(ValueNode object, ValueNode offset, ValueNode condition, ValueNode location, Kind accessKind) {
+    public static CustomizedUnsafeLoadFinalNode create(ValueNode object, ValueNode offset, ValueNode condition, ValueNode location, Kind accessKind) {
+        return USE_GENERATED_NODES ? new CustomizedUnsafeLoadFinalNodeGen(object, offset, condition, location, accessKind) : new CustomizedUnsafeLoadFinalNode(object, offset, condition, location,
+                        accessKind);
+    }
+
+    protected CustomizedUnsafeLoadFinalNode(ValueNode object, ValueNode offset, ValueNode condition, ValueNode location, Kind accessKind) {
         super(StampFactory.forKind(accessKind.getStackKind()));
         this.object = object;
         this.offset = offset;
@@ -94,7 +101,7 @@
         } else {
             locationIdentity = ObjectLocationIdentity.create(location.asConstant());
         }
-        UnsafeLoadNode result = graph().add(new UnsafeLoadNode(object, offset, accessKind, locationIdentity, compare));
+        UnsafeLoadNode result = graph().add(UnsafeLoadNode.create(object, offset, accessKind, locationIdentity, compare));
         graph().replaceFixedWithFixed(this, result);
         result.lower(tool);
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
@@ -36,6 +37,7 @@
 /**
  * Macro node for method {@link CompilerDirectives#unsafeCast(Object, Class, boolean)}.
  */
+@NodeInfo
 public class CustomizedUnsafeLoadMacroNode extends NeverPartOfCompilationNode implements Canonicalizable {
 
     private static final int ARGUMENT_COUNT = 4;
@@ -44,7 +46,11 @@
     private static final int CONDITION_ARGUMENT_INDEX = 2;
     private static final int LOCATION_ARGUMENT_INDEX = 3;
 
-    public CustomizedUnsafeLoadMacroNode(Invoke invoke) {
+    public static CustomizedUnsafeLoadMacroNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new CustomizedUnsafeLoadMacroNodeGen(invoke) : new CustomizedUnsafeLoadMacroNode(invoke);
+    }
+
+    protected CustomizedUnsafeLoadMacroNode(Invoke invoke) {
         super(invoke, "The location argument could not be resolved to a constant.");
         assert arguments.size() == ARGUMENT_COUNT;
     }
@@ -64,7 +70,7 @@
             }
             CompareNode compare = CompareNode.createCompareNode(Condition.EQ, conditionArgument, ConstantNode.forBoolean(true));
             Kind returnKind = this.getTargetMethod().getSignature().getReturnKind();
-            return new UnsafeLoadNode(objectArgument, offsetArgument, returnKind, locationIdentity, compare);
+            return UnsafeLoadNode.create(objectArgument, offsetArgument, returnKind, locationIdentity, compare);
         }
         return this;
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.truffle.nodes.*;
@@ -34,6 +35,7 @@
 /**
  * Macro node for method {@link CompilerDirectives#unsafeCast(Object, Class, boolean)}.
  */
+@NodeInfo
 public class CustomizedUnsafeStoreMacroNode extends NeverPartOfCompilationNode implements Canonicalizable, StateSplit {
     private static final int ARGUMENT_COUNT = 4;
     private static final int OBJECT_ARGUMENT_INDEX = 0;
@@ -41,7 +43,11 @@
     private static final int VALUE_ARGUMENT_INDEX = 2;
     private static final int LOCATION_ARGUMENT_INDEX = 3;
 
-    public CustomizedUnsafeStoreMacroNode(Invoke invoke) {
+    public static CustomizedUnsafeStoreMacroNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new CustomizedUnsafeStoreMacroNodeGen(invoke) : new CustomizedUnsafeStoreMacroNode(invoke);
+    }
+
+    protected CustomizedUnsafeStoreMacroNode(Invoke invoke) {
         super(invoke, "The location argument could not be resolved to a constant.");
         assert arguments.size() == ARGUMENT_COUNT;
     }
@@ -60,7 +66,7 @@
                 locationIdentity = ObjectLocationIdentity.create(locationArgument.asConstant());
             }
 
-            return new UnsafeStoreNode(objectArgument, offsetArgument, valueArgument, this.getTargetMethod().getSignature().getParameterKind(VALUE_ARGUMENT_INDEX), locationIdentity, stateAfter());
+            return UnsafeStoreNode.create(objectArgument, offsetArgument, valueArgument, this.getTargetMethod().getSignature().getParameterKind(VALUE_ARGUMENT_INDEX), locationIdentity, stateAfter());
         }
         return this;
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.util.*;
@@ -35,6 +36,7 @@
 /**
  * Macro node for method {@link CompilerDirectives#unsafeCast(Object, Class, boolean, boolean)}.
  */
+@NodeInfo
 public class UnsafeTypeCastMacroNode extends NeverPartOfCompilationNode implements Simplifiable {
 
     private static final int OBJECT_ARGUMENT_INDEX = 0;
@@ -43,7 +45,11 @@
     private static final int NONNULL_ARGUMENT_INDEX = 3;
     private static final int ARGUMENT_COUNT = 4;
 
-    public UnsafeTypeCastMacroNode(Invoke invoke) {
+    public static UnsafeTypeCastMacroNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new UnsafeTypeCastMacroNodeGen(invoke) : new UnsafeTypeCastMacroNode(invoke);
+    }
+
+    protected UnsafeTypeCastMacroNode(Invoke invoke) {
         super(invoke, "The class of the unsafe cast could not be reduced to a compile time constant.");
         assert arguments.size() == ARGUMENT_COUNT;
     }
@@ -63,8 +69,8 @@
             } else {
                 Stamp stamp = StampFactory.declared(lookupJavaType, nonNullArgument.asConstant().asInt() != 0);
                 ConditionAnchorNode valueAnchorNode = graph().add(
-                                new ConditionAnchorNode(CompareNode.createCompareNode(graph(), Condition.EQ, conditionArgument, ConstantNode.forBoolean(true, graph()))));
-                PiNode piCast = graph().unique(new PiNode(objectArgument, stamp, valueAnchorNode));
+                                ConditionAnchorNode.create(CompareNode.createCompareNode(graph(), Condition.EQ, conditionArgument, ConstantNode.forBoolean(true, graph()))));
+                PiNode piCast = graph().unique(PiNode.create(objectArgument, stamp, valueAnchorNode));
                 replaceAtUsages(piCast);
                 graph().replaceFixedWithFixed(this, valueAnchorNode);
             }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,8 +23,8 @@
 package com.oracle.graal.truffle.phases;
 
 import com.oracle.graal.debug.*;
+import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014, 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.substitutions;
+
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.truffle.*;
+import com.oracle.graal.truffle.nodes.frame.*;
+import com.oracle.truffle.api.frame.*;
+
+@ClassSubstitution(FrameWithoutBoxing.class)
+public class FrameWithoutBoxingSubstitutions {
+
+    @MethodSubstitution(isStatic = false)
+    public static MaterializedFrame materialize(FrameWithoutBoxing frame) {
+        return MaterializeFrameNode.materialize(frame);
+    }
+}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializedObjectState.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializedObjectState.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,28 +23,34 @@
 package com.oracle.graal.virtual.nodes;
 
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.virtual.*;
 
 /**
  * This class encapsulated the materialized state of an escape analyzed object.
  */
-public final class MaterializedObjectState extends EscapeObjectState implements Node.ValueNumberable {
+@NodeInfo
+public class MaterializedObjectState extends EscapeObjectState implements Node.ValueNumberable {
 
-    @Input private ValueNode materializedValue;
+    @Input ValueNode materializedValue;
 
     public ValueNode materializedValue() {
         return materializedValue;
     }
 
-    public MaterializedObjectState(VirtualObjectNode object, ValueNode materializedValue) {
+    public static MaterializedObjectState create(VirtualObjectNode object, ValueNode materializedValue) {
+        return USE_GENERATED_NODES ? new MaterializedObjectStateGen(object, materializedValue) : new MaterializedObjectState(object, materializedValue);
+    }
+
+    protected MaterializedObjectState(VirtualObjectNode object, ValueNode materializedValue) {
         super(object);
         this.materializedValue = materializedValue;
     }
 
     @Override
     public MaterializedObjectState duplicateWithVirtualState() {
-        return graph().addWithoutUnique(new MaterializedObjectState(object(), materializedValue));
+        return graph().addWithoutUnique(MaterializedObjectState.create(object(), materializedValue));
     }
 
     @Override
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/VirtualObjectState.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/VirtualObjectState.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,27 +25,37 @@
 import java.util.*;
 
 import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.virtual.*;
 
 /**
  * This class encapsulated the virtual state of an escape analyzed object.
  */
-public final class VirtualObjectState extends EscapeObjectState implements Node.ValueNumberable {
+@NodeInfo
+public class VirtualObjectState extends EscapeObjectState implements Node.ValueNumberable {
 
-    @Input private final NodeInputList<ValueNode> values;
+    @Input NodeInputList<ValueNode> values;
 
     public NodeInputList<ValueNode> values() {
         return values;
     }
 
-    public VirtualObjectState(VirtualObjectNode object, ValueNode[] values) {
+    public static VirtualObjectState create(VirtualObjectNode object, ValueNode[] values) {
+        return USE_GENERATED_NODES ? new VirtualObjectStateGen(object, values) : new VirtualObjectState(object, values);
+    }
+
+    protected VirtualObjectState(VirtualObjectNode object, ValueNode[] values) {
         super(object);
         assert object.entryCount() == values.length;
         this.values = new NodeInputList<>(this, values);
     }
 
-    public VirtualObjectState(VirtualObjectNode object, List<ValueNode> values) {
+    public static VirtualObjectState create(VirtualObjectNode object, List<ValueNode> values) {
+        return USE_GENERATED_NODES ? new VirtualObjectStateGen(object, values) : new VirtualObjectState(object, values);
+    }
+
+    protected VirtualObjectState(VirtualObjectNode object, List<ValueNode> values) {
         super(object);
         assert object.entryCount() == values.size();
         this.values = new NodeInputList<>(this, values);
@@ -53,7 +63,7 @@
 
     @Override
     public VirtualObjectState duplicateWithVirtualState() {
-        return graph().addWithoutUnique(new VirtualObjectState(object(), values));
+        return graph().addWithoutUnique(VirtualObjectState.create(object(), values));
     }
 
     @Override
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -28,8 +28,8 @@
 
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
+import com.oracle.graal.graph.Graph.NodeEventScope;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java	Mon Aug 25 21:15:59 2014 -0700
@@ -125,7 +125,7 @@
                 if (initialState.getReadCache().get(entry.getKey()) != entry.getValue()) {
                     ValueNode value = exitState.getReadCache(entry.getKey().object, entry.getKey().identity, this);
                     if (!(value instanceof ProxyNode) || ((ProxyNode) value).proxyPoint() != exitNode) {
-                        ProxyNode proxy = new ValueProxyNode(value, exitNode);
+                        ProxyNode proxy = ValueProxyNode.create(value, exitNode);
                         effects.addFloatingNode(proxy, "readCacheProxy");
                         entry.setValue(proxy);
                     }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java	Mon Aug 25 21:15:59 2014 -0700
@@ -90,7 +90,7 @@
                 if (fixed.predecessor() instanceof CommitAllocationNode) {
                     commit = (CommitAllocationNode) fixed.predecessor();
                 } else {
-                    commit = graph.add(new CommitAllocationNode());
+                    commit = graph.add(CommitAllocationNode.create());
                     graph.addBeforeFixed(fixed, commit);
                 }
                 for (AllocatedObjectNode obj : objects) {
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Mon Aug 25 21:15:59 2014 -0700
@@ -188,9 +188,9 @@
                             }
                         }
                     }
-                    v = new VirtualObjectState(obj.virtual, fieldState);
+                    v = VirtualObjectState.create(obj.virtual, fieldState);
                 } else {
-                    v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue());
+                    v = MaterializedObjectState.create(obj.virtual, obj.getMaterializedValue());
                 }
                 effects.addVirtualMapping(frameState, v);
             }
@@ -237,7 +237,7 @@
                         ValueNode value = obj.getEntry(i);
                         if (!(value instanceof VirtualObjectNode || value.isConstant())) {
                             if (exitNode.loopBegin().isPhiAtMerge(value) || initialObj == null || !initialObj.isVirtual() || initialObj.getEntry(i) != value) {
-                                ProxyNode proxy = new ValueProxyNode(value, exitNode);
+                                ProxyNode proxy = ValueProxyNode.create(value, exitNode);
                                 obj.setEntry(i, proxy);
                                 effects.addFloatingNode(proxy, "virtualProxy");
                             }
@@ -247,7 +247,7 @@
                     if (initialObj == null || initialObj.isVirtual()) {
                         ProxyNode proxy = proxies.get(obj.virtual);
                         if (proxy == null) {
-                            proxy = new ValueProxyNode(obj.getMaterializedValue(), exitNode);
+                            proxy = ValueProxyNode.create(obj.getMaterializedValue(), exitNode);
                             effects.addFloatingNode(proxy, "proxy");
                         } else {
                             effects.replaceFirstInput(proxy, proxy.value(), obj.getMaterializedValue());
@@ -282,7 +282,7 @@
         protected <T> PhiNode getCachedPhi(T virtual, Stamp stamp) {
             ValuePhiNode result = materializedPhis.get(virtual);
             if (result == null) {
-                result = new ValuePhiNode(stamp, merge);
+                result = ValuePhiNode.create(stamp, merge);
                 materializedPhis.put(virtual, result);
             }
             return result;
@@ -456,11 +456,11 @@
                     for (int i = 1; i < objStates.length; i++) {
                         ValueNode[] fields = objStates[i].getEntries();
                         if (phis[valueIndex] == null && values[valueIndex] != fields[valueIndex]) {
-                            phis[valueIndex] = new ValuePhiNode(values[valueIndex].stamp().unrestricted(), merge);
+                            phis[valueIndex] = ValuePhiNode.create(values[valueIndex].stamp().unrestricted(), merge);
                         }
                     }
                     if (phis[valueIndex] != null && !phis[valueIndex].stamp().isCompatible(values[valueIndex].stamp())) {
-                        phis[valueIndex] = new ValuePhiNode(values[valueIndex].stamp().unrestricted(), merge);
+                        phis[valueIndex] = ValuePhiNode.create(values[valueIndex].stamp().unrestricted(), merge);
                     }
                     if (twoSlotKinds != null && twoSlotKinds[valueIndex] != null) {
                         // skip an entry after a long/double value that occupies two int slots
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java	Mon Aug 25 21:15:59 2014 -0700
@@ -84,6 +84,32 @@
         }
     }
 
+    /**
+     * CacheEntry describing an Unsafe memory reference. The memory location and the location
+     * identity are separate so both must be considered when looking for optimizable memory
+     * accesses.
+     *
+     */
+    static class UnsafeLoadCacheEntry extends CacheEntry<ValueNode> {
+
+        private LocationIdentity locationIdentity;
+
+        public UnsafeLoadCacheEntry(ValueNode object, ValueNode location, LocationIdentity locationIdentity) {
+            super(object, location);
+            this.locationIdentity = locationIdentity;
+        }
+
+        @Override
+        public CacheEntry<ValueNode> duplicateWithObject(ValueNode newObject) {
+            return new UnsafeLoadCacheEntry(newObject, identity, locationIdentity);
+        }
+
+        @Override
+        public boolean conflicts(LocationIdentity other) {
+            return locationIdentity == other;
+        }
+    }
+
     static class ReadCacheEntry extends CacheEntry<LocationNode> {
 
         public ReadCacheEntry(ValueNode object, LocationNode identity) {
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Mon Aug 25 21:15:59 2014 -0700
@@ -37,6 +37,7 @@
 import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.CacheEntry;
 import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.LoadCacheEntry;
 import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.ReadCacheEntry;
+import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.UnsafeLoadCacheEntry;
 
 public class ReadEliminationClosure extends EffectsClosure<ReadEliminationBlockState> {
 
@@ -89,7 +90,7 @@
                     ValueNode cachedValue = state.getCacheEntry(identifier);
                     if (cachedValue != null) {
                         if (read.getGuard() != null && !(read.getGuard() instanceof FixedNode)) {
-                            effects.addFixedNodeBefore(new ValueAnchorNode((ValueNode) read.getGuard()), read);
+                            effects.addFixedNodeBefore(ValueAnchorNode.create((ValueNode) read.getGuard()), read);
                         }
                         effects.replaceAtUsages(read, cachedValue);
                         addScalarAlias(read, cachedValue);
@@ -121,7 +122,7 @@
                 UnsafeLoadNode load = (UnsafeLoadNode) node;
                 if (load.offset().isConstant() && load.getLocationIdentity() != LocationIdentity.ANY_LOCATION) {
                     ValueNode object = GraphUtil.unproxify(load.object());
-                    LoadCacheEntry identifier = new LoadCacheEntry(object, load.getLocationIdentity());
+                    UnsafeLoadCacheEntry identifier = new UnsafeLoadCacheEntry(object, load.offset(), load.getLocationIdentity());
                     ValueNode cachedValue = state.getCacheEntry(identifier);
                     if (cachedValue != null) {
                         effects.replaceAtUsages(load, cachedValue);
@@ -136,7 +137,7 @@
                 UnsafeStoreNode write = (UnsafeStoreNode) node;
                 if (write.offset().isConstant() && write.getLocationIdentity() != LocationIdentity.ANY_LOCATION) {
                     ValueNode object = GraphUtil.unproxify(write.object());
-                    LoadCacheEntry identifier = new LoadCacheEntry(object, write.getLocationIdentity());
+                    UnsafeLoadCacheEntry identifier = new UnsafeLoadCacheEntry(object, write.offset(), write.getLocationIdentity());
                     ValueNode cachedValue = state.getCacheEntry(identifier);
 
                     ValueNode value = getScalarAlias(write.value());
@@ -174,7 +175,7 @@
         if (exitNode.graph().hasValueProxies()) {
             for (Map.Entry<CacheEntry<?>, ValueNode> entry : exitState.getReadCache().entrySet()) {
                 if (initialState.getReadCache().get(entry.getKey()) != entry.getValue()) {
-                    ProxyNode proxy = new ValueProxyNode(exitState.getCacheEntry(entry.getKey()), exitNode);
+                    ProxyNode proxy = ValueProxyNode.create(exitState.getCacheEntry(entry.getKey()), exitNode);
                     effects.addFloatingNode(proxy, "readCacheProxy");
                     entry.setValue(proxy);
                 }
@@ -203,7 +204,7 @@
         protected <T> PhiNode getCachedPhi(T virtual, Stamp stamp) {
             ValuePhiNode result = materializedPhis.get(virtual);
             if (result == null) {
-                result = new ValuePhiNode(stamp, merge);
+                result = ValuePhiNode.create(stamp, merge);
                 materializedPhis.put(virtual, result);
             }
             return result;
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -31,6 +31,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -42,27 +43,38 @@
  * nodes. Both scale and disp must eventually canonicalize to {@link ConstantNode constants} so that
  * this node can be canonicalized to a {@link IndexedLocationNode} or {@link ConstantLocationNode}.
  */
-public final class SnippetLocationNode extends LocationNode implements Canonicalizable {
+@NodeInfo
+public class SnippetLocationNode extends LocationNode implements Canonicalizable {
 
     private final SnippetReflectionProvider snippetReflection;
 
-    @Input private ValueNode valueKind;
-    @Input(InputType.Association) private ValueNode locationIdentity;
-    @Input private ValueNode displacement;
-    @Input private ValueNode index;
-    @Input private ValueNode indexScaling;
+    @Input ValueNode valueKind;
+    @Input(InputType.Association) ValueNode locationIdentity;
+    @Input ValueNode displacement;
+    @Input ValueNode index;
+    @Input ValueNode indexScaling;
 
-    public static SnippetLocationNode create(SnippetReflectionProvider snippetReflection, ValueNode identity, ValueNode kind, ValueNode displacement, ValueNode index, ValueNode indexScaling,
-                    Graph graph) {
-        return graph.unique(new SnippetLocationNode(snippetReflection, identity, kind, displacement, index, indexScaling));
+    public static SnippetLocationNode create(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode identity, ValueNode kind, ValueNode displacement, ValueNode index,
+                    ValueNode indexScaling, Graph graph) {
+        return graph.unique(SnippetLocationNode.create(snippetReflection, identity, kind, displacement, index, indexScaling));
     }
 
-    private SnippetLocationNode(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode kind, ValueNode displacement) {
+    public static SnippetLocationNode create(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode kind, ValueNode displacement) {
+        return USE_GENERATED_NODES ? new SnippetLocationNodeGen(snippetReflection, locationIdentity, kind, displacement) : new SnippetLocationNode(snippetReflection, locationIdentity, kind,
+                        displacement);
+    }
+
+    SnippetLocationNode(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode kind, ValueNode displacement) {
         this(snippetReflection, locationIdentity, kind, displacement, null, null);
     }
 
-    private SnippetLocationNode(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode kind, ValueNode displacement, ValueNode index,
+    public static SnippetLocationNode create(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode kind, ValueNode displacement, ValueNode index,
                     ValueNode indexScaling) {
+        return USE_GENERATED_NODES ? new SnippetLocationNodeGen(snippetReflection, locationIdentity, kind, displacement, index, indexScaling) : new SnippetLocationNode(snippetReflection,
+                        locationIdentity, kind, displacement, index, indexScaling);
+    }
+
+    SnippetLocationNode(SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode kind, ValueNode displacement, ValueNode index, ValueNode indexScaling) {
         super(StampFactory.object());
         this.snippetReflection = snippetReflection;
         this.valueKind = kind;
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.phases.*;
@@ -34,21 +35,26 @@
  * Cast between Word and Object that is introduced by the {@link WordTypeRewriterPhase}. It has an
  * impact on the pointer maps for the GC, so it must not be scheduled or optimized away.
  */
-public final class WordCastNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable {
+@NodeInfo
+public class WordCastNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable {
 
-    @Input private ValueNode input;
+    @Input ValueNode input;
 
     public static WordCastNode wordToObject(ValueNode input, Kind wordKind) {
         assert input.getKind() == wordKind;
-        return new WordCastNode(StampFactory.object(), input);
+        return WordCastNode.create(StampFactory.object(), input);
     }
 
     public static WordCastNode objectToWord(ValueNode input, Kind wordKind) {
         assert input.getKind() == Kind.Object;
-        return new WordCastNode(StampFactory.forKind(wordKind), input);
+        return WordCastNode.create(StampFactory.forKind(wordKind), input);
     }
 
-    private WordCastNode(Stamp stamp, ValueNode input) {
+    public static WordCastNode create(Stamp stamp, ValueNode input) {
+        return USE_GENERATED_NODES ? new WordCastNodeGen(stamp, input) : new WordCastNode(stamp, input);
+    }
+
+    WordCastNode(Stamp stamp, ValueNode input) {
         super(stamp);
         this.input = input;
     }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -157,9 +157,9 @@
              * depends on elementKind. Therefore, just create a new node and replace the old one.
              */
             if (node instanceof LoadIndexedNode) {
-                graph.replaceFixedWithFixed(node, graph.add(new LoadIndexedNode(node.array(), node.index(), wordKind)));
+                graph.replaceFixedWithFixed(node, graph.add(LoadIndexedNode.create(node.array(), node.index(), wordKind)));
             } else if (node instanceof StoreIndexedNode) {
-                graph.replaceFixedWithFixed(node, graph.add(new StoreIndexedNode(node.array(), node.index(), wordKind, ((StoreIndexedNode) node).value())));
+                graph.replaceFixedWithFixed(node, graph.add(StoreIndexedNode.create(node.array(), node.index(), wordKind, ((StoreIndexedNode) node).value())));
             } else {
                 throw GraalInternalError.shouldNotReachHere();
             }
@@ -213,7 +213,7 @@
 
             case NOT:
                 assert arguments.size() == 1;
-                replace(invoke, graph.unique(new XorNode(arguments.get(0), ConstantNode.forIntegerKind(wordKind, -1, graph))));
+                replace(invoke, graph.unique(XorNode.create(arguments.get(0), ConstantNode.forIntegerKind(wordKind, -1, graph))));
                 break;
 
             case READ_POINTER:
@@ -282,7 +282,7 @@
 
             case FROM_ARRAY:
                 assert arguments.size() == 2;
-                replace(invoke, graph.unique(new ComputeAddressNode(arguments.get(0), arguments.get(1), StampFactory.forKind(wordKind))));
+                replace(invoke, graph.unique(ComputeAddressNode.create(arguments.get(0), arguments.get(1), StampFactory.forKind(wordKind))));
                 break;
 
             case TO_OBJECT:
@@ -316,14 +316,14 @@
 
         if (toKind == Kind.Int) {
             assert value.getKind() == Kind.Long;
-            return graph.unique(new NarrowNode(value, 32));
+            return graph.unique(NarrowNode.create(value, 32));
         } else {
             assert toKind == Kind.Long;
             assert value.getKind().getStackKind() == Kind.Int;
             if (unsigned) {
-                return graph.unique(new ZeroExtendNode(value, 64));
+                return graph.unique(ZeroExtendNode.create(value, 64));
             } else {
-                return graph.unique(new SignExtendNode(value, 64));
+                return graph.unique(SignExtendNode.create(value, 64));
             }
         }
     }
@@ -335,8 +335,8 @@
      */
     private static ValueNode createBinaryNodeInstance(Class<? extends ValueNode> nodeClass, ValueNode left, ValueNode right) {
         try {
-            Constructor<? extends ValueNode> constructor = nodeClass.getConstructor(ValueNode.class, ValueNode.class);
-            return constructor.newInstance(left, right);
+            Method factory = nodeClass.getDeclaredMethod("create", ValueNode.class, ValueNode.class);
+            return (ValueNode) factory.invoke(null, left, right);
         } catch (Throwable ex) {
             throw new GraalInternalError(ex).addContext(nodeClass.getName());
         }
@@ -353,11 +353,11 @@
 
         CompareNode comparison;
         if (condition == Condition.EQ || condition == Condition.NE) {
-            comparison = new IntegerEqualsNode(a, b);
+            comparison = IntegerEqualsNode.create(a, b);
         } else if (condition.isUnsigned()) {
-            comparison = new IntegerBelowNode(a, b);
+            comparison = IntegerBelowNode.create(a, b);
         } else {
-            comparison = new IntegerLessThanNode(a, b);
+            comparison = IntegerLessThanNode.create(a, b);
         }
 
         ConstantNode trueValue = ConstantNode.forInt(1, graph);
@@ -368,7 +368,7 @@
             trueValue = falseValue;
             falseValue = temp;
         }
-        ConditionalNode materialize = graph.unique(new ConditionalNode(graph.unique(comparison), trueValue, falseValue));
+        ConditionalNode materialize = graph.unique(ConditionalNode.create(graph.unique(comparison), trueValue, falseValue));
         return materialize;
     }
 
@@ -393,7 +393,7 @@
     }
 
     protected ValueNode readOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location, BarrierType barrierType, boolean compressible) {
-        JavaReadNode read = graph.add(new JavaReadNode(base, location, barrierType, compressible));
+        JavaReadNode read = graph.add(JavaReadNode.create(base, location, barrierType, compressible));
         graph.addBeforeFixed(invoke.asNode(), read);
         /*
          * The read must not float outside its block otherwise it may float above an explicit zero
@@ -408,7 +408,7 @@
         final BarrierType barrier = (op == Opcode.WRITE_BARRIERED ? BarrierType.PRECISE : BarrierType.NONE);
         final boolean compressible = (op == Opcode.WRITE_OBJECT || op == Opcode.WRITE_BARRIERED);
         final boolean initialize = (op == Opcode.INITIALIZE);
-        JavaWriteNode write = graph.add(new JavaWriteNode(base, value, location, barrier, compressible, initialize));
+        JavaWriteNode write = graph.add(JavaWriteNode.create(base, value, location, barrier, compressible, initialize));
         write.setStateAfter(invoke.stateAfter());
         graph.addBeforeFixed(invoke.asNode(), write);
         return write;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.nfi.test/test/com/oracle/nfi/test/NativeFunctionInterfaceTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,397 @@
+/*
+ * 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.nfi.test;
+
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
+import static java.io.File.*;
+import static java.lang.System.*;
+import static org.junit.Assert.*;
+import static org.junit.Assume.*;
+
+import java.io.*;
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.nfi.*;
+import com.oracle.nfi.api.*;
+
+@Ignore
+public class NativeFunctionInterfaceTest {
+
+    public final NativeFunctionInterface nfi;
+
+    public NativeFunctionInterfaceTest() {
+        nfi = NativeFunctionInterfaceRuntime.getNativeFunctionInterface();
+    }
+
+    private List<Long> allocations = new ArrayList<>();
+
+    protected long malloc(int length) {
+        long buf = unsafe.allocateMemory(length);
+        allocations.add(buf);
+        return buf;
+    }
+
+    @After
+    public void cleanup() {
+        for (long buf : allocations) {
+            unsafe.freeMemory(buf);
+        }
+    }
+
+    private static void assertCStringEquals(long cString, String s) {
+        for (int i = 0; i < s.length(); i++) {
+            assertEquals(unsafe.getByte(cString + i) & 0xFF, (byte) s.charAt(i));
+        }
+        assertEquals(unsafe.getByte(cString + s.length()) & 0xFF, (byte) '\0');
+    }
+
+    @Test
+    public void test1() {
+        assumeTrue(nfi.isDefaultLibrarySearchSupported());
+        NativeFunctionHandle malloc = nfi.getFunctionHandle("malloc", long.class, int.class);
+        NativeFunctionHandle snprintf = nfi.getFunctionHandle("snprintf", int.class, long.class, int.class, long.class);
+        NativeFunctionHandle free = nfi.getFunctionHandle("free", void.class, long.class);
+
+        String string = "GRAAL";
+        int bufferLength = string.length() + 1;
+        long cString = (long) malloc.call(bufferLength);
+        writeCString(string, cString);
+
+        long cStringCopy = malloc(bufferLength);
+        int result = (int) snprintf.call(cStringCopy, bufferLength, cString);
+        Assert.assertEquals(string.length(), result);
+        assertCStringEquals(cString, string);
+        assertCStringEquals(cStringCopy, string);
+
+        free.call(cString);
+    }
+
+    @Test
+    public void test2() {
+        assumeTrue(nfi.isDefaultLibrarySearchSupported());
+        String formatString = "AB %f%f";
+        long formatCString = writeCString("AB %f%f", malloc(formatString.length() + 1));
+
+        String referenceString = "AB 1.0000001.000000";
+        int bufferLength = referenceString.length() + 1;
+        long buffer = malloc(bufferLength);
+
+        NativeFunctionHandle snprintf = nfi.getFunctionHandle("snprintf", int.class, long.class, int.class, long.class, double.class, double.class);
+        int result = (int) snprintf.call(buffer, bufferLength, formatCString, 1.0D, 1.0D);
+
+        assertCStringEquals(buffer, referenceString);
+        Assert.assertEquals(referenceString.length(), result);
+    }
+
+    @Test
+    public void test3() {
+        assumeTrue(nfi.isDefaultLibrarySearchSupported());
+        String format = "%i%i%i%i%i%i%i%i%i%i%i%i";
+        long formatCString = writeCString(format, malloc(format.length() + 1));
+        String referenceString = "01234567891011";
+
+        int bufferLength = referenceString.length() + 1;
+        long buffer = malloc(bufferLength);
+
+        NativeFunctionHandle snprintf = nfi.getFunctionHandle("snprintf", int.class, long.class, int.class, long.class, int.class, int.class, int.class, int.class, int.class, int.class, int.class,
+                        int.class, int.class, int.class, int.class, int.class);
+
+        int result = (int) snprintf.call(buffer, bufferLength, formatCString, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
+        assertCStringEquals(buffer, referenceString);
+        Assert.assertEquals(referenceString.length(), result);
+    }
+
+    @Test
+    public void test4() {
+        assumeTrue(nfi.isDefaultLibrarySearchSupported());
+        long str = malloc(49);
+        int[] val = new int[12];
+        for (int i = 0; i < 12; i++) {
+            unsafe.putByte(str + 2 * i, (byte) '%');
+            unsafe.putByte(str + 2 * i + 1, (byte) 'i');
+            val[i] = i;
+        }
+        double[] dval = new double[12];
+        for (int i = 12; i < 24; i++) {
+            unsafe.putByte(str + 2 * i, (byte) '%');
+            unsafe.putByte(str + 2 * i + 1, (byte) 'f');
+            dval[i - 12] = i + 0.5;
+        }
+        unsafe.putByte(str + 48, (byte) '\0');
+
+        String referenceString = "0123456789101112.50000013.50000014.50000015.50000016.50000017.50000018.50000019.50000020.500000" + "21.50000022.50000023.500000";
+        int bufferLength = referenceString.length() + 1;
+
+        long buffer = malloc(bufferLength);
+
+        NativeFunctionHandle snprintf = nfi.getFunctionHandle("snprintf", int.class, long.class, int.class, long.class, int.class, int.class, int.class, int.class, int.class, int.class, int.class,
+                        int.class, int.class, int.class, int.class, int.class, double.class, double.class, double.class, double.class, double.class, double.class, double.class, double.class,
+                        double.class, double.class, double.class, double.class);
+
+        int result = (int) snprintf.call(buffer, bufferLength, str, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9], val[10], val[11], dval[0], dval[1], dval[2],
+                        dval[3], dval[4], dval[5], dval[6], dval[7], dval[8], dval[9], dval[10], dval[11]);
+        assertCStringEquals(buffer, referenceString);
+        Assert.assertEquals(referenceString.length(), result);
+    }
+
+    @Test
+    public void test5() {
+        assumeTrue(nfi.isDefaultLibrarySearchSupported());
+        long str = malloc(73);
+        int[] val = new int[12];
+        for (int i = 0; i < 12; i++) {
+            unsafe.putByte(str + 2 * i, (byte) '%');
+            unsafe.putByte(str + 2 * i + 1, (byte) 'i');
+            val[i] = i;
+        }
+        double[] dval = new double[12];
+        for (int i = 12; i < 24; i++) {
+            unsafe.putByte(str + 2 * i, (byte) '%');
+            unsafe.putByte(str + 2 * i + 1, (byte) 'f');
+            dval[i - 12] = i + 0.5;
+        }
+        char[] cval = new char[12];
+        for (int i = 24; i < 36; i++) {
+            unsafe.putByte(str + 2 * i, (byte) '%');
+            unsafe.putByte(str + 2 * i + 1, (byte) 'c');
+            cval[i - 24] = (char) ('a' + (i - 24));
+        }
+        unsafe.putByte(str + 72, (byte) '\0');
+
+        String referenceString = "0123456789101112.50000013.50000014.50000015.50000016.50000017.50000018.50000019.50000020.50000021.50000022.50000023.500000abcdefghijkl";
+        int bufferLength = referenceString.length() + 1;
+
+        long buffer = malloc(bufferLength);
+
+        NativeFunctionHandle snprintf = nfi.getFunctionHandle("snprintf", int.class, long.class, int.class, long.class, int.class, int.class, int.class, int.class, int.class, int.class, int.class,
+                        int.class, int.class, int.class, int.class, int.class, double.class, double.class, double.class, double.class, double.class, double.class, double.class, double.class,
+                        double.class, double.class, double.class, double.class, char.class, char.class, char.class, char.class, char.class, char.class, char.class, char.class, char.class, char.class,
+                        char.class, char.class);
+
+        int result = (int) snprintf.call(buffer, bufferLength, str, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9], val[10], val[11], dval[0], dval[1], dval[2],
+                        dval[3], dval[4], dval[5], dval[6], dval[7], dval[8], dval[9], dval[10], dval[11], cval[0], cval[1], cval[2], cval[3], cval[4], cval[5], cval[6], cval[7], cval[8], cval[9],
+                        cval[10], cval[11]);
+        assertCStringEquals(buffer, referenceString);
+        Assert.assertEquals(referenceString.length(), result);
+    }
+
+    @Test
+    public void test6() {
+        assumeTrue(nfi.isDefaultLibrarySearchSupported());
+        NativeFunctionHandle handle = nfi.getFunctionHandle("pow", double.class, double.class, double.class);
+        double result = (double) handle.call(3D, 5.5D);
+        assertEquals(Math.pow(3D, 5.5D), result, 0);
+    }
+
+    @Test
+    public void test7() {
+        assumeTrue(nfi.isDefaultLibrarySearchSupported());
+        double result = 0;
+        NativeFunctionHandle handle = nfi.getFunctionHandle("pow", double.class, double.class, double.class);
+        for (int i = 0; i < 10; i++) {
+            result = (double) handle.call(3D, 5.5D);
+        }
+        assertEquals(Math.pow(3D, 5.5D), result, 0);
+    }
+
+    @Test
+    public void test8() {
+        assumeTrue(nfi.isDefaultLibrarySearchSupported());
+        String formatString = "AB %f%f";
+        long formatCString = writeCString("AB %f%f", malloc(formatString.length() + 1));
+
+        String expected = "AB 1.0000001.000000";
+        int bufferLength = expected.length() + 1;
+        byte[] buffer = new byte[bufferLength];
+
+        NativeFunctionHandle snprintf = nfi.getFunctionHandle("snprintf", int.class, byte[].class, int.class, long.class, double.class, double.class);
+        int result = (int) snprintf.call(buffer, bufferLength, formatCString, 1.0D, 1.0D);
+
+        // trim trailing '\0'
+        String actual = new String(buffer, 0, expected.length());
+
+        assertEquals(expected, actual);
+        Assert.assertEquals(expected.length(), result);
+    }
+
+    private static double[] someDoubles = {2454.346D, 98789.22D, Double.MAX_VALUE, Double.MIN_NORMAL, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY};
+
+    @Test
+    public void test9() {
+        assumeTrue(nfi.isDefaultLibrarySearchSupported());
+        double[] src = someDoubles.clone();
+        double[] dst = new double[src.length];
+
+        NativeFunctionHandle memcpy = nfi.getFunctionHandle("memcpy", void.class, double[].class, double[].class, int.class);
+        memcpy.call(dst, src, src.length * (Double.SIZE / Byte.SIZE));
+
+        assertArrayEquals(src, dst, 0.0D);
+    }
+
+    private static String getVMName() {
+        String vmName = System.getProperty("java.vm.name").toLowerCase();
+        String vm = null;
+        if (vmName.contains("server")) {
+            vm = "server";
+        } else if (vmName.contains("graal")) {
+            vm = "graal";
+        } else if (vmName.contains("client")) {
+            vm = "client";
+        }
+
+        Assume.assumeTrue(vm != null);
+        return vm;
+    }
+
+    private static String getVMLibPath() {
+        String vm = getVMName();
+
+        String path = String.format("%s%c%s%c%s", getProperty("sun.boot.library.path"), separatorChar, vm, separatorChar, mapLibraryName("jvm"));
+        // Only continue if the library file exists
+        Assume.assumeTrue(new File(path).exists());
+        return path;
+    }
+
+    @Test
+    public void test10() {
+        NativeLibraryHandle vmLib = nfi.getLibraryHandle(getVMLibPath());
+        NativeFunctionHandle currentTimeMillis = nfi.getFunctionHandle(vmLib, "JVM_CurrentTimeMillis", long.class);
+        long time1 = (long) currentTimeMillis.call();
+        long time2 = System.currentTimeMillis();
+        long delta = time2 - time1;
+
+        // The 2 calls to get the current time should not differ by more than
+        // 100 milliseconds at the very most
+        assertTrue(String.valueOf(delta), delta >= 0);
+        assertTrue(String.valueOf(delta), delta < 100);
+    }
+
+    private static String getJavaLibPath() {
+        String path = String.format("%s%c%s", getProperty("sun.boot.library.path"), separatorChar, mapLibraryName("java"));
+        Assume.assumeTrue(new File(path).exists());
+        return path;
+    }
+
+    private static void testD2L(NativeFunctionHandle d2l) {
+        for (double d : someDoubles) {
+            long expected = Double.doubleToRawLongBits(d);
+            long actual = (long) d2l.call(0L, 0L, d);
+            assertEquals(Double.toString(d), expected, actual);
+        }
+    }
+
+    @Test
+    public void test11() {
+        NativeLibraryHandle javaLib = nfi.getLibraryHandle(getJavaLibPath());
+        NativeFunctionHandle d2l = nfi.getFunctionHandle(javaLib, "Java_java_lang_Double_doubleToRawLongBits", long.class, long.class, long.class, double.class);
+        testD2L(d2l);
+    }
+
+    @Test
+    public void test12() {
+        NativeLibraryHandle[] libs = {nfi.getLibraryHandle(getVMLibPath()), nfi.getLibraryHandle(getJavaLibPath())};
+        NativeFunctionHandle d2l = nfi.getFunctionHandle(libs, "Java_java_lang_Double_doubleToRawLongBits", long.class, long.class, long.class, double.class);
+        testD2L(d2l);
+
+        NativeLibraryHandle[] libsReveresed = {libs[1], libs[0]};
+        d2l = nfi.getFunctionHandle(libsReveresed, "Java_java_lang_Double_doubleToRawLongBits", long.class, long.class, long.class, double.class);
+        testD2L(d2l);
+    }
+
+    @Test
+    public void test13() {
+        NativeLibraryHandle[] libs = {nfi.getLibraryHandle(getVMLibPath()), nfi.getLibraryHandle(getJavaLibPath())};
+        NativeFunctionPointer functionPointer = nfi.getFunctionPointer(libs, "Java_java_lang_Double_doubleToRawLongBits");
+        NativeFunctionHandle d2l = nfi.getFunctionHandle(functionPointer, long.class, long.class, long.class, double.class);
+        testD2L(d2l);
+
+        NativeLibraryHandle[] libsReveresed = {libs[1], libs[0]};
+        functionPointer = nfi.getFunctionPointer(libsReveresed, "Java_java_lang_Double_doubleToRawLongBits");
+        d2l = nfi.getFunctionHandle(functionPointer, long.class, long.class, long.class, double.class);
+        testD2L(d2l);
+    }
+
+    @Test
+    public void test14() {
+        if (!nfi.isDefaultLibrarySearchSupported()) {
+            try {
+                nfi.getFunctionHandle("snprintf", int.class);
+                fail();
+            } catch (UnsatisfiedLinkError e) {
+            }
+        }
+    }
+
+    @Test
+    public void test15() {
+        assumeTrue(nfi.isDefaultLibrarySearchSupported());
+        try {
+            nfi.getFunctionHandle("an invalid function name", int.class);
+            fail();
+        } catch (UnsatisfiedLinkError e) {
+        }
+    }
+
+    @Test
+    public void test16() {
+        NativeLibraryHandle javaLib = nfi.getLibraryHandle(getJavaLibPath());
+        try {
+
+            nfi.getFunctionHandle(javaLib, "an invalid function name", int.class);
+            fail();
+        } catch (UnsatisfiedLinkError e) {
+        }
+    }
+
+    @Test
+    public void test17() {
+        NativeLibraryHandle[] libs = {nfi.getLibraryHandle(getVMLibPath()), nfi.getLibraryHandle(getJavaLibPath())};
+        try {
+            nfi.getFunctionPointer(libs, "an invalid function name");
+            fail();
+        } catch (UnsatisfiedLinkError e) {
+        }
+    }
+
+    @Test
+    public void test18() {
+        NativeLibraryHandle[] libs = {nfi.getLibraryHandle(getVMLibPath()), nfi.getLibraryHandle(getJavaLibPath())};
+        try {
+            nfi.getFunctionHandle(libs, "an invalid function name", int.class);
+            fail();
+        } catch (UnsatisfiedLinkError e) {
+        }
+    }
+
+    @Test
+    public void test19() {
+        try {
+            nfi.getLibraryHandle("an invalid library name");
+            fail();
+        } catch (UnsatisfiedLinkError e) {
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.nfi/src/com/oracle/nfi/NativeFunctionInterfaceRuntime.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,59 @@
+/*
+ * 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.nfi;
+
+import com.oracle.nfi.api.*;
+
+/**
+ * Class for obtaining the {@link NativeFunctionInterface} (if any) provided by the VM.
+ */
+public final class NativeFunctionInterfaceRuntime {
+    private static final NativeFunctionInterface INSTANCE;
+
+    /**
+     * Creates a new {@link NativeFunctionInterface}.
+     *
+     * @throws UnsatisfiedLinkError if not running on a VM that provides a
+     *             {@link NativeFunctionInterface}
+     */
+    private static native NativeFunctionInterface createInterface();
+
+    /**
+     * Gets the {@link NativeFunctionInterface} (if any) provided by the VM.
+     *
+     * @return null if the VM does not provide a {@link NativeFunctionInterface}
+     */
+    public static NativeFunctionInterface getNativeFunctionInterface() {
+        return INSTANCE;
+    }
+
+    static {
+        NativeFunctionInterface instance;
+        try {
+            instance = createInterface();
+        } catch (UnsatisfiedLinkError e) {
+            instance = null;
+        }
+        INSTANCE = instance;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.nfi/src/com/oracle/nfi/api/NativeFunctionHandle.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,43 @@
+/*
+ * 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.nfi.api;
+
+/**
+ * A handle that can be used to {@linkplain #call(Object[]) call} a native function.
+ */
+public interface NativeFunctionHandle {
+
+    /**
+     * Calls the native function.
+     * <p>
+     * The caller is responsible for ensuring {@code args} comply with the platform ABI (e.g. <a
+     * href="http://www.uclibc.org/docs/psABI-x86_64.pdf"> Unix AMD64 ABI</a>). If the library
+     * function has struct parameters, the fields of the struct must be passed as individual
+     * arguments.
+     *
+     * @param args the arguments that will be passed to the native function
+     * @return boxed return value of the function call
+     */
+    Object call(Object... args);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.nfi/src/com/oracle/nfi/api/NativeFunctionInterface.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,122 @@
+/*
+ * 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.nfi.api;
+
+/**
+ * Interface to get a {@linkplain NativeFunctionHandle handle} or {@linkplain NativeFunctionPointer
+ * pointer} to a native function or a {@linkplain NativeLibraryHandle handle} to an open native
+ * library.
+ */
+public interface NativeFunctionInterface {
+
+    /**
+     * Resolves and returns a handle to an open native library. This method will open the library
+     * only if it is not already open.
+     *
+     * @param libPath the absolute path to the library
+     * @return the resolved library handle
+     * @throws UnsatisfiedLinkError if the library could not be found or opened
+     */
+    NativeLibraryHandle getLibraryHandle(String libPath);
+
+    /**
+     * Determines if the underlying platform/runtime supports the notion of a default library search
+     * path. For example, on *nix systems, this is typically defined by the {@code LD_LIBRARY_PATH}
+     * environment variable.
+     */
+    boolean isDefaultLibrarySearchSupported();
+
+    /**
+     * Resolves the function pointer {@code NativeFunctionPointer} of a native function.
+     *
+     * @param libraries the ordered list of libraries to search for the function
+     * @param name the name of the function to be resolved
+     * @return a pointer to the native function
+     * @throws UnsatisfiedLinkError if the function could not be resolved
+     */
+    NativeFunctionPointer getFunctionPointer(NativeLibraryHandle[] libraries, String name);
+
+    /**
+     * Resolves a function name to a {@linkplain NativeFunctionHandle handle} that can be called
+     * with a given signature. The signature contains the types of the arguments that will be passed
+     * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}.
+     *
+     * @param library the handle to a resolved library
+     * @param name the name of the function to be resolved
+     * @param returnType the type of the return value
+     * @param argumentTypes the types of the arguments
+     * @return the function handle of the native function
+     * @throws UnsatisfiedLinkError if the function handle could not be resolved
+     */
+    NativeFunctionHandle getFunctionHandle(NativeLibraryHandle library, String name, Class<?> returnType, Class<?>... argumentTypes);
+
+    /**
+     * Resolves a function pointer to a {@linkplain NativeFunctionHandle handle} that can be called
+     * with a given signature. The signature contains the types of the arguments that will be passed
+     * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}.
+     *
+     * @param functionPointer a function pointer
+     * @param returnType the type of the return value
+     * @param argumentTypes the types of the arguments
+     * @return the function handle of the native function
+     * @throws UnsatisfiedLinkError the function handle could not be created
+     */
+    NativeFunctionHandle getFunctionHandle(NativeFunctionPointer functionPointer, Class<?> returnType, Class<?>... argumentTypes);
+
+    /**
+     * Resolves a function name to a {@linkplain NativeFunctionHandle handle} that can be called
+     * with a given signature. The signature contains the types of the arguments that will be passed
+     * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}.
+     *
+     * @param libraries the ordered list of libraries to search for the function
+     * @param name the name of the function to be resolved
+     * @param returnType the type of the return value
+     * @param argumentTypes the types of the arguments
+     * @return the function handle of the native function
+     * @throws UnsatisfiedLinkError if the function handle could not be created
+     */
+    NativeFunctionHandle getFunctionHandle(NativeLibraryHandle[] libraries, String name, Class<?> returnType, Class<?>... argumentTypes);
+
+    /**
+     * Resolves a function name to a {@linkplain NativeFunctionHandle handle} that can be called
+     * with a given signature. The signature contains the types of the arguments that will be passed
+     * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}.
+     *
+     * @param name the name of the function to be resolved
+     * @param returnType the type of the return value
+     * @param argumentTypes the types of the arguments
+     * @return the function handle of the native function
+     * @throws UnsatisfiedLinkError if default library searching is not
+     *             {@linkplain #isDefaultLibrarySearchSupported() supported} or if the function
+     *             could not be resolved
+     */
+    NativeFunctionHandle getFunctionHandle(String name, Class<?> returnType, Class<?>... argumentTypes);
+
+    /**
+     * Creates a {@link NativeFunctionPointer} from a raw value.
+     *
+     * @param rawValue raw function pointer
+     * @return {@code NativeFunctionPointer} for {@code rawValue}
+     */
+    NativeFunctionPointer getNativeFunctionPointerFromRawValue(long rawValue);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.nfi/src/com/oracle/nfi/api/NativeFunctionPointer.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,48 @@
+/*
+ * 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.nfi.api;
+
+/**
+ * An opaque representation of a native function pointer.
+ * <p>
+ * Use {@code NativeFunctionInterface#getFunctionHandle(NativeFunctionPointer, Class, Class...)} to
+ * get a handle enabling the native function to be {@linkplain NativeFunctionHandle#call(Object...)
+ * called}.
+ */
+public interface NativeFunctionPointer {
+
+    /**
+     * Returns the name of the function.
+     *
+     * @return name of the function
+     */
+    String getName();
+
+    /**
+     * Returns the raw function pointer value.
+     * 
+     * @return raw function pointer value
+     */
+    long getRawValue();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.nfi/src/com/oracle/nfi/api/NativeLibraryHandle.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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.nfi.api;
+
+/**
+ * An opaque representation of a native library handle. A handle is obtained via
+ * {@link NativeFunctionInterface#getLibraryHandle(String)}. A handle is used to resolve a string to
+ * a {@linkplain NativeFunctionInterface#getFunctionHandle(String, Class, Class...) handle} or
+ * {@linkplain NativeFunctionInterface#getFunctionPointer(NativeLibraryHandle[], String) pointer}.
+ */
+public interface NativeLibraryHandle {
+    /**
+     * Gets a name for this library. This may be the path for the file from which the library was
+     * loaded.
+     */
+    String getName();
+}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AssumptionsTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AssumptionsTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -48,15 +48,16 @@
     @NodeAssumptions("assumption")
     abstract static class SingleAssumptionNode extends ValueNode {
 
-        @Specialization(order = 0, assumptions = "assumption")
-        int doInt() {
+        @Specialization(assumptions = "assumption")
+        int do2() {
             return 42;
         }
 
-        @Specialization
-        Object doObject() {
+        @Fallback
+        Object doFallBack() {
             return "42";
         }
+
     }
 
     @Test
@@ -67,9 +68,9 @@
 
         Assert.assertEquals(42, TestHelper.executeWith(root));
         assumption2.invalidate();
-        Assert.assertEquals("42", TestHelper.executeWith(root));
+        Assert.assertEquals("41", TestHelper.executeWith(root));
         assumption1.invalidate();
-        Assert.assertEquals("43", TestHelper.executeWith(root));
+        Assert.assertEquals("42", TestHelper.executeWith(root));
     }
 
     @NodeAssumptions({"assumption1", "assumption2"})
@@ -82,12 +83,12 @@
 
         @Specialization(assumptions = "assumption1")
         Object doObject() {
-            return "42";
+            return "41";
         }
 
-        @Generic
-        Object doGeneric() {
-            return "43";
+        @Fallback
+        Object doFallBack() {
+            return "42";
         }
     }
 
@@ -107,10 +108,11 @@
     @NodeAssumptions({"additionalAssumption"})
     abstract static class DerivedAssumptionNode extends SingleAssumptionNode {
 
-        @Specialization(order = 1, assumptions = "additionalAssumption")
+        @Specialization(assumptions = "additionalAssumption")
         int doIntDerived() {
             return 43;
         }
+
     }
 
     @Test
@@ -129,7 +131,7 @@
     @NodeAssumptions({"additionalAssumption", "assumption"})
     abstract static class DerivedAssumptionRedeclaredNode extends SingleAssumptionNode {
 
-        @Specialization(order = 1, assumptions = "additionalAssumption")
+        @Specialization(assumptions = "additionalAssumption")
         int doIntDerived() {
             return 43;
         }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BinaryNodeTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BinaryNodeTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -60,7 +60,7 @@
             return left + right;
         }
 
-        @Generic
+        @Fallback
         Object add(Object left, Object right) {
             return convertDouble(left) + convertDouble(right);
         }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -28,6 +28,9 @@
 import com.oracle.truffle.api.dsl.test.CodeFormatTestFactory.LineWrappingTestFactory;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
 
+/**
+ * Tests the generated code compiles without warnings for unusual large guard names.
+ */
 public class CodeFormatTest {
 
     @Test
--- /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/ContainsTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,643 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.internal.*;
+import com.oracle.truffle.api.dsl.test.ContainsTestFactory.Contains1Factory;
+import com.oracle.truffle.api.dsl.test.ContainsTestFactory.Contains2Factory;
+import com.oracle.truffle.api.dsl.test.ContainsTestFactory.Contains3Factory;
+import com.oracle.truffle.api.dsl.test.ContainsTestFactory.Contains4Factory;
+import com.oracle.truffle.api.dsl.test.ContainsTestFactory.PolymorphicToMonomorphic0Factory;
+import com.oracle.truffle.api.dsl.test.TestHelper.ExecutionListener;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+import com.oracle.truffle.api.nodes.*;
+
+@SuppressWarnings("unused")
+public class ContainsTest {
+
+    /*
+     * Tests a simple monomorphic inclusion.
+     */
+    @Test
+    public void testContains1() {
+        assertRuns(Contains1Factory.getInstance(), //
+                        array(1, "a", 2, "b"), //
+                        array(2, "aa", 3, "ba"),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                if (value instanceof String) {
+                                    // assert that the final specialization is always Object
+                                    Assert.assertEquals(Object.class, ((DSLNode) node.getNode()).getMetadata0().getSpecializedTypes()[0]);
+                                }
+                            }
+                        });
+    }
+
+    @NodeChild("a")
+    abstract static class Contains1 extends ValueNode {
+
+        @Specialization
+        int f1(int a) {
+            return a + 1;
+        }
+
+        @Specialization(contains = "f1")
+        Object f2(Object a) {
+            if (a instanceof Integer) {
+                return ((Integer) a) + 1;
+            }
+            return a + "a";
+        }
+    }
+
+    /*
+     * Tests an inclusion in within a polymorphic chain.
+     */
+    @Test
+    public void testContains2() {
+        assertRuns(Contains2Factory.getInstance(), //
+                        array(true, 1, 0, false), //
+                        array(false, -1, 1, true) //
+        );
+    }
+
+    @NodeChild("a")
+    abstract static class Contains2 extends ValueNode {
+
+        static boolean isZero(int a) {
+            return a == 0;
+        }
+
+        @Specialization(guards = "isZero")
+        int f1(int a) {
+            return a + 1;
+        }
+
+        @Specialization(contains = "f1")
+        int f2(int a) {
+            if (a == 0) {
+                return a + 1;
+            }
+            return -a;
+        }
+
+        @Specialization
+        boolean f3(boolean a) {
+            return !a;
+        }
+    }
+
+    /*
+     * Tests transitive monomorphic inclusion.
+     */
+    @Test
+    public void testContains3() {
+        assertRuns(Contains3Factory.getInstance(), //
+                        array(2, 1, 2, -3, -4), //
+                        array(-2, 2, -2, -3, -4),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                // assert that we are always monomorphic
+                                Assert.assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost());
+                            }
+                        });
+    }
+
+    @NodeChild("a")
+    abstract static class Contains3 extends ValueNode {
+
+        static boolean isGreaterZero(int a) {
+            return a > 0;
+        }
+
+        @Implies("isGreaterZero")
+        static boolean isOne(int a) {
+            return a == 1;
+        }
+
+        @Specialization(guards = {"isOne"})
+        int f1(int a) {
+            return a + 1;
+        }
+
+        @Specialization(contains = "f1", guards = {"isGreaterZero"})
+        int f2(int a) {
+            if (a == 1) {
+                return 2;
+            }
+            return -a;
+        }
+
+        @Specialization(contains = "f2")
+        int f3(int a) {
+            if (a > 0) {
+                return a == 1 ? 2 : -a;
+            } else {
+                return a;
+            }
+        }
+
+    }
+
+    /*
+     * Tests that if it can be derived that two specializations actually a as powerful as the latter
+     * we can combine them. Therefore operation should always become monomorphic in the end.
+     */
+    @Test
+    public void testContains4() {
+        assertRuns(Contains4Factory.getInstance(), //
+                        array(-1, 0, 1, 2), //
+                        array(1, 0, 1, 2),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                Assert.assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost());
+                            }
+                        });
+    }
+
+    @NodeChild("a")
+    abstract static class Contains4 extends ValueNode {
+
+        static boolean isGreaterEqualZero(int a) {
+            return a >= 0;
+        }
+
+        @Implies("isGreaterEqualZero")
+        static boolean isOne(int a) {
+            return a == 1;
+        }
+
+        @Specialization(guards = {"isOne"})
+        int f0(int a) {
+            return 1;
+        }
+
+        @Specialization(contains = "f0", guards = {"isGreaterEqualZero"})
+        int f1(int a) {
+            return a;
+        }
+
+        @Specialization(contains = {"f1"})
+        int f2(int a) {
+            return Math.abs(a);
+        }
+
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsError1 extends ValueNode {
+        @ExpectError("The contained specialization 'f1' must be declared before the containing specialization.")
+        @Specialization(contains = "f1")
+        int f0(int a) {
+            return a;
+        }
+
+        @Specialization
+        Object f1(String a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsError2 extends ValueNode {
+
+        @ExpectError("The referenced specialization 'does not exist' could not be found.")
+        @Specialization(contains = "does not exist")
+        int f0(int a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsError3 extends ValueNode {
+
+        @Specialization
+        int f0(int a) {
+            return a;
+        }
+
+        @ExpectError("Duplicate contains declaration 'f0'.")
+        @Specialization(contains = {"f0", "f0"})
+        Object f1(double a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsError4 extends ValueNode {
+
+        @ExpectError("Circular contained specialization 'f1(double)' found.")
+        @Specialization(contains = {"f1"})
+        Object f1(double a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsError5 extends ValueNode {
+
+        @ExpectError({"Circular contained specialization 'f0(int)' found.", "Circular contained specialization 'f1(double)' found.",
+                        "The contained specialization 'f1' must be declared before the containing specialization."})
+        @Specialization(contains = "f1")
+        int f0(int a) {
+            return a;
+        }
+
+        @ExpectError("Circular contained specialization 'f1(double)' found.")
+        @Specialization(contains = {"f0"})
+        Object f1(double a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsType1 extends ValueNode {
+        @Specialization
+        int f0(int a) {
+            return a;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by f0(int).")
+        @Specialization(contains = "f0")
+        Object f1(int a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsType2 extends ValueNode {
+        @Specialization
+        int f0(int a) {
+            return a;
+        }
+
+        @Specialization(contains = "f0")
+        Object f1(Object a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsType3 extends ValueNode {
+        @Specialization
+        int f0(int a) {
+            return a;
+        }
+
+        @Specialization(contains = "f0")
+        Object f1(double a) { // implicit type
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsType4 extends ValueNode {
+        @Specialization
+        double f0(double a) {
+            return a;
+        }
+
+        @ExpectError({"Specialization is not reachable. It is shadowed by f0(double).", "The contained specialization 'f0' is not fully compatible.%"})
+        @Specialization(contains = "f0")
+        int f1(int a) { // implicit type
+            return a;
+        }
+    }
+
+    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
+    abstract static class ContainsType5 extends ValueNode {
+        @Specialization
+        Object f0(Object a, int b) {
+            return a;
+        }
+
+        @ExpectError("The contained specialization 'f0' is not fully compatible.%")
+        @Specialization(contains = "f0")
+        Object f1(int a, Object b) {
+            return a;
+        }
+    }
+
+    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
+    abstract static class ContainsType6 extends ValueNode {
+        @Specialization
+        Object f0(double a, int b) {
+            return a;
+        }
+
+        @ExpectError("The contained specialization 'f0' is not fully compatible.%")
+        @Specialization(contains = "f0")
+        Object f1(int a, double b) { // implicit type
+            return a;
+        }
+    }
+
+    abstract static class ContainsGuard1 extends ValueNode {
+
+        boolean g1() {
+            return true;
+        }
+
+        @Specialization(guards = "g1")
+        Object f0() {
+            return null;
+        }
+
+        @Specialization(contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsGuard2 extends ValueNode {
+
+        boolean g1() {
+            return true;
+        }
+
+        @Specialization
+        Object f0() {
+            return null;
+        }
+
+        @ExpectError({"Specialization is not reachable. It is shadowed by f0().", "The contained specialization 'f0' is not fully compatible.%"})
+        @Specialization(guards = "g1", contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsGuard3 extends ValueNode {
+
+        boolean g1() {
+            return true;
+        }
+
+        @Specialization(guards = "g1")
+        Object f0() {
+            return null;
+        }
+
+        @ExpectError({"The contained specialization 'f0' is not fully compatible.%"})
+        @Specialization(guards = "!g1", contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsGuard4 extends ValueNode {
+
+        boolean g1() {
+            return true;
+        }
+
+        boolean g2() {
+            return true;
+        }
+
+        @Specialization(guards = "g1")
+        Object f0() {
+            return null;
+        }
+
+        @ExpectError({"The contained specialization 'f0' is not fully compatible.%"})
+        @Specialization(guards = "g2", contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsGuard5 extends ValueNode {
+
+        @Implies("g2")
+        boolean g1() {
+            return true;
+        }
+
+        boolean g2() {
+            return true;
+        }
+
+        @Specialization(guards = "g1")
+        Object f0() {
+            return null;
+        }
+
+        @Specialization(guards = "g2", contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsGuard6 extends ValueNode {
+
+        @Implies("!g2")
+        boolean g1() {
+            return true;
+        }
+
+        boolean g2() {
+            return true;
+        }
+
+        @Specialization(guards = "g1")
+        Object f0() {
+            return null;
+        }
+
+        @Specialization(guards = "!g2", contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsGuard7 extends ValueNode {
+
+        boolean g1() {
+            return true;
+        }
+
+        boolean g2() {
+            return true;
+        }
+
+        @Specialization(guards = {"g1", "g2"})
+        Object f0() {
+            return null;
+        }
+
+        @Specialization(guards = "g2", contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    @NodeAssumptions("a1")
+    abstract static class ContainsAssumption1 extends ValueNode {
+
+        @Specialization(assumptions = "a1")
+        Object f0() {
+            return null;
+        }
+
+        @Specialization(contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    @NodeAssumptions("a1")
+    abstract static class ContainsAssumption2 extends ValueNode {
+
+        @Specialization
+        Object f0() {
+            return null;
+        }
+
+        @ExpectError({"Specialization is not reachable. It is shadowed by f0().", "The contained specialization 'f0' is not fully compatible.%"})
+        @Specialization(contains = "f0", assumptions = "a1")
+        Object f1() {
+            return null;
+        }
+    }
+
+    @NodeAssumptions({"a1", "a2"})
+    abstract static class ContainsAssumption3 extends ValueNode {
+
+        @Specialization(assumptions = "a1")
+        Object f0() {
+            return null;
+        }
+
+        @ExpectError({"The contained specialization 'f0' is not fully compatible.%"})
+        @Specialization(contains = "f0", assumptions = "a2")
+        Object f1() {
+            return null;
+        }
+    }
+
+    @NodeAssumptions({"a1", "a2"})
+    abstract static class ContainsAssumption4 extends ValueNode {
+
+        @Specialization(assumptions = {"a1", "a2"})
+        Object f0() {
+            return null;
+        }
+
+        @Specialization(contains = "f0", assumptions = "a1")
+        Object f1() {
+            return null;
+        }
+    }
+
+    @NodeAssumptions({"a1", "a2"})
+    abstract static class ContainsAssumption5 extends ValueNode {
+
+        @Specialization(assumptions = {"a2", "a1"})
+        Object f0() {
+            return null;
+        }
+
+        @Specialization(contains = "f0", assumptions = "a1")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsThrowable1 extends ValueNode {
+
+        @Specialization(rewriteOn = RuntimeException.class)
+        Object f0() throws RuntimeException {
+            throw new RuntimeException();
+        }
+
+        @Specialization(contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsThrowable2 extends ValueNode {
+
+        @Specialization(rewriteOn = RuntimeException.class)
+        Object f0() throws RuntimeException {
+            throw new RuntimeException();
+        }
+
+        @Specialization(contains = "f0", rewriteOn = RuntimeException.class)
+        Object f1() throws RuntimeException {
+            throw new RuntimeException();
+        }
+
+        @Specialization(contains = "f1")
+        Object f2() {
+            return null;
+        }
+    }
+
+    @Test
+    public void testPolymorphicToMonomorphic0() {
+        TestRootNode<PolymorphicToMonomorphic0> root = createRoot(PolymorphicToMonomorphic0Factory.getInstance());
+        assertThat((int) executeWith(root, 1), is(1));
+        assertThat((int) executeWith(root, 2), is(2));
+        assertThat((int) executeWith(root, 3), is(3));
+        assertThat(root.getNode().getCost(), is(NodeCost.MONOMORPHIC));
+    }
+
+    @NodeChild("a")
+    static class PolymorphicToMonomorphic0 extends ValueNode {
+
+        boolean isOne(int a) {
+            return a == 1;
+        }
+
+        boolean isTwo(int a) {
+            return a == 2;
+        }
+
+        @Specialization(guards = "isOne")
+        int do1(int a) {
+            return a;
+        }
+
+        @Specialization(guards = "isTwo")
+        int do2(int a) {
+            return a;
+        }
+
+        @Specialization(contains = {"do1", "do2"})
+        int do3(int a) {
+            return a;
+        }
+
+    }
+
+}
--- /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/FallbackTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.FallbackTestFactory.Fallback1Factory;
+import com.oracle.truffle.api.dsl.test.FallbackTestFactory.Fallback2Factory;
+import com.oracle.truffle.api.dsl.test.FallbackTestFactory.Fallback3Factory;
+import com.oracle.truffle.api.dsl.test.FallbackTestFactory.Fallback4Factory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.*;
+import com.oracle.truffle.api.nodes.*;
+
+public class FallbackTest {
+
+    private static final Object UNKNOWN_OBJECT = new Object() {
+    };
+
+    @Test
+    public void testFallback1() {
+        assertRuns(Fallback1Factory.getInstance(), //
+                        array(42, UNKNOWN_OBJECT), //
+                        array("(int)", "(fallback)"));
+    }
+
+    /**
+     * test with fallback handler defined
+     */
+    @SuppressWarnings("unused")
+    @NodeChild("a")
+    abstract static class Fallback1 extends ValueNode {
+
+        @Specialization
+        String f1(int a) {
+            return "(int)";
+        }
+
+        @Fallback
+        String f2(Object a) {
+            return "(fallback)";
+        }
+    }
+
+    @Test
+    public void testFallback2() {
+        assertRuns(Fallback2Factory.getInstance(), //
+                        array(42, UNKNOWN_OBJECT), //
+                        array("(int)", UnsupportedSpecializationException.class));
+    }
+
+    /**
+     * test without fallback handler defined
+     */
+    @SuppressWarnings("unused")
+    @NodeChild("a")
+    abstract static class Fallback2 extends ValueNode {
+
+        @Specialization
+        String f1(int a) {
+            return "(int)";
+        }
+
+    }
+
+    @Test
+    public void testFallback3() {
+        assertRuns(Fallback3Factory.getInstance(), //
+                        array(42, 43, UNKNOWN_OBJECT, "somestring"), //
+                        array("(int)", "(int)", "(object)", "(object)"));
+    }
+
+    /**
+     * test without fallback handler and unreachable
+     */
+    @SuppressWarnings("unused")
+    @NodeChild("a")
+    abstract static class Fallback3 extends ValueNode {
+
+        @Specialization
+        String f1(int a) {
+            return "(int)";
+        }
+
+        @Specialization(guards = "notInt")
+        String f2(Object a) {
+            return "(object)";
+        }
+
+        boolean notInt(Object value) {
+            return !(value instanceof Integer);
+        }
+
+    }
+
+    /**
+     * Tests the contents of the {@link UnsupportedSpecializationException} contents in polymorphic
+     * nodes.
+     */
+    @Test
+    public void testFallback4() {
+        TestRootNode<Fallback4> node = createRoot(Fallback4Factory.getInstance());
+
+        Assert.assertEquals("(int)", executeWith(node, 1));
+        Assert.assertEquals("(boolean)", executeWith(node, true));
+        try {
+            executeWith(node, UNKNOWN_OBJECT);
+            Assert.fail();
+        } catch (UnsupportedSpecializationException e) {
+            Assert.assertEquals(node.getNode(), e.getNode());
+            Assert.assertArrayEquals(NodeUtil.findNodeChildren(node.getNode()).subList(0, 1).toArray(new Node[0]), e.getSuppliedNodes());
+            Assert.assertArrayEquals(new Object[]{UNKNOWN_OBJECT}, e.getSuppliedValues());
+        }
+    }
+
+    /**
+     * test without fallback handler and unreachable
+     */
+    @SuppressWarnings("unused")
+    @NodeChild("a")
+    abstract static class Fallback4 extends ValueNode {
+
+        @Specialization
+        String f1(int a) {
+            return "(int)";
+        }
+
+        @Specialization
+        String f2(boolean a) {
+            return "(boolean)";
+        }
+    }
+
+    /**
+     * Tests the contents of the {@link UnsupportedSpecializationException} contents in monomorphic
+     * nodes.
+     */
+    @Test
+    public void testFallback5() {
+        TestRootNode<Fallback4> node = createRoot(Fallback4Factory.getInstance());
+
+        Assert.assertEquals("(int)", executeWith(node, 1));
+        try {
+            executeWith(node, UNKNOWN_OBJECT);
+            Assert.fail();
+        } catch (UnsupportedSpecializationException e) {
+            Assert.assertEquals(node.getNode(), e.getNode());
+            Assert.assertArrayEquals(NodeUtil.findNodeChildren(node.getNode()).subList(0, 1).toArray(new Node[0]), e.getSuppliedNodes());
+            Assert.assertArrayEquals(new Object[]{UNKNOWN_OBJECT}, e.getSuppliedValues());
+        }
+    }
+
+    // test without fallback handler and unreachable
+    @SuppressWarnings("unused")
+    @NodeChild("a")
+    abstract static class Fallback5 extends ValueNode {
+
+        @Specialization
+        String f1(int a) {
+            return "(int)";
+        }
+    }
+
+}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/GuardsTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,315 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GlobalFlagGuardFactory;
-import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GuardWithBaseClassFactory;
-import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GuardWithBaseInterfaceFactory;
-import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GuardWithBoxedPrimitiveFactory;
-import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GuardWithObjectFactory;
-import com.oracle.truffle.api.dsl.test.GuardsTestFactory.InvocationGuardFactory;
-import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestAbstractGuard1Factory;
-import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestGuardResolve1Factory;
-import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestGuardResolve2Factory;
-import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestGuardResolve3Factory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.Abstract;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.BExtendsAbstract;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.CExtendsAbstract;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-@SuppressWarnings("unused")
-public class GuardsTest {
-
-    private static final Object NULL = new Object();
-
-    @Test
-    public void testGuardInvocations() {
-        TestRootNode<InvocationGuard> root = createRoot(InvocationGuardFactory.getInstance());
-
-        assertEquals(Integer.MAX_VALUE, executeWith(root, Integer.MAX_VALUE - 1, 1));
-        assertEquals(1, InvocationGuard.specializedInvocations);
-        assertEquals(0, InvocationGuard.genericInvocations);
-
-        assertEquals(42, executeWith(root, Integer.MAX_VALUE, 1));
-        assertEquals(1, InvocationGuard.specializedInvocations);
-        assertEquals(1, InvocationGuard.genericInvocations);
-    }
-
-    @NodeChildren({@NodeChild("value0"), @NodeChild("value1")})
-    public abstract static class InvocationGuard extends ValueNode {
-
-        static int specializedInvocations = 0;
-        static int genericInvocations = 0;
-
-        boolean guard(int value0, int value1) {
-            return value0 != Integer.MAX_VALUE;
-        }
-
-        @Specialization(guards = "guard")
-        int doSpecialized(int value0, int value1) {
-            specializedInvocations++;
-            return value0 + value1;
-        }
-
-        @Generic
-        int doGeneric(Object value0, Object value1) {
-            genericInvocations++;
-            return 42; // the generic answer to all questions
-        }
-    }
-
-    @Test
-    public void testGuardGlobal() {
-        TestRootNode<GlobalFlagGuard> root = createRoot(GlobalFlagGuardFactory.getInstance());
-
-        assertEquals(42, executeWith(root, NULL));
-
-        GlobalFlagGuard.globalFlag = true;
-        assertEquals(41, executeWith(root, NULL));
-
-        GlobalFlagGuard.globalFlag = false;
-        assertEquals(42, executeWith(root, NULL));
-    }
-
-    @NodeChild("expression")
-    public abstract static class GlobalFlagGuard extends ValueNode {
-
-        static boolean globalFlag = false;
-
-        static boolean globalFlagGuard() {
-            return globalFlag;
-        }
-
-        @Specialization(guards = "globalFlagGuard")
-        int doSpecialized(Object value0) {
-            return 41;
-        }
-
-        @Generic
-        int doGeneric(Object value0) {
-            return 42; // the generic answer to all questions
-        }
-    }
-
-    @Test
-    public void testGuardWithBaseClass() {
-        TestRootNode<?> root = createRoot(GuardWithBaseClassFactory.getInstance());
-
-        assertEquals(42, executeWith(root, new BExtendsAbstract()));
-    }
-
-    @NodeChild("expression")
-    public abstract static class GuardWithBaseClass extends ValueNode {
-
-        boolean baseGuard(Abstract base) {
-            return true;
-        }
-
-        @Specialization(guards = "baseGuard")
-        int doSpecialized(BExtendsAbstract value0) {
-            return 42;
-        }
-    }
-
-    @Test
-    public void testGuardWithBaseInterface() {
-        TestRootNode<?> root = createRoot(GuardWithBaseInterfaceFactory.getInstance());
-
-        assertEquals(42, executeWith(root, "anything"));
-    }
-
-    @NodeChild("expression")
-    public abstract static class GuardWithBaseInterface extends ValueNode {
-
-        boolean baseGuard(CharSequence base) {
-            return true;
-        }
-
-        @Specialization(guards = "baseGuard")
-        int doSpecialized(String value0) {
-            return 42;
-        }
-    }
-
-    @Test
-    public void testGuardWithPrimitive() {
-        TestRootNode<?> root = createRoot(GuardWithBoxedPrimitiveFactory.getInstance());
-
-        assertEquals(42, executeWith(root, 42));
-    }
-
-    @NodeChild("expression")
-    public abstract static class GuardWithBoxedPrimitive extends ValueNode {
-
-        boolean baseGuard(Integer primitive) {
-            return true;
-        }
-
-        @Specialization(guards = "baseGuard")
-        int doSpecialized(int value0) {
-            return value0;
-        }
-    }
-
-    @Test
-    public void testGuardWithObject() {
-        TestRootNode<?> root = createRoot(GuardWithObjectFactory.getInstance());
-
-        assertEquals(42, executeWith(root, 42));
-    }
-
-    @NodeChild("expression")
-    public abstract static class GuardWithObject extends ValueNode {
-
-        boolean baseGuard(Object primitive) {
-            return true;
-        }
-
-        @Specialization(guards = "baseGuard")
-        int doSpecialized(int value0) {
-            return value0;
-        }
-    }
-
-    @Test
-    public void testGuardResolve1() {
-        TestRootNode<?> root = createRoot(TestGuardResolve1Factory.getInstance());
-
-        assertEquals(42, executeWith(root, 42));
-    }
-
-    @NodeChild("expression")
-    public abstract static class TestGuardResolve1 extends ValueNode {
-
-        boolean guard(Object primitive) {
-            return false;
-        }
-
-        boolean guard(int primitive) {
-            return true;
-        }
-
-        @Specialization(guards = "guard")
-        int doSpecialized(int value0) {
-            return value0;
-        }
-    }
-
-    @Test
-    public void testGuardResolve2() {
-        TestRootNode<?> root = createRoot(TestGuardResolve2Factory.getInstance());
-        assertEquals(42, executeWith(root, new BExtendsAbstract()));
-    }
-
-    @NodeChild("expression")
-    public abstract static class TestGuardResolve2 extends ValueNode {
-
-        boolean guard(Object primitive) {
-            return false;
-        }
-
-        boolean guard(Abstract primitive) {
-            return true;
-        }
-
-        @Specialization(guards = "guard")
-        int doSpecialized(BExtendsAbstract value0) {
-            return 42;
-        }
-    }
-
-    @Test
-    public void testGuardResolve3() {
-        TestRootNode<?> root = createRoot(TestGuardResolve3Factory.getInstance());
-
-        assertEquals(42, executeWith(root, new BExtendsAbstract()));
-    }
-
-    @NodeChild("expression")
-    public abstract static class TestGuardResolve3 extends ValueNode {
-
-        boolean guard(Object primitive) {
-            return false;
-        }
-
-        boolean guard(Abstract primitive) {
-            return false;
-        }
-
-        boolean guard(BExtendsAbstract primitive) {
-            return true;
-        }
-
-        @Specialization(guards = "guard")
-        int doSpecialized(BExtendsAbstract value0) {
-            return 42;
-        }
-    }
-
-    @NodeChild("expression")
-    public abstract static class TestGuardResolve4 extends ValueNode {
-
-        boolean guard(Abstract primitive) {
-            return false;
-        }
-
-        @Specialization(guards = "guard")
-        int doSpecialized(BExtendsAbstract value0) {
-            return 42;
-        }
-    }
-
-    @Test
-    public void testAbstractGuard1() {
-        TestRootNode<?> root = createRoot(TestAbstractGuard1Factory.getInstance());
-
-        assertEquals(BExtendsAbstract.INSTANCE, executeWith(root, BExtendsAbstract.INSTANCE));
-        assertEquals(CExtendsAbstract.INSTANCE, executeWith(root, CExtendsAbstract.INSTANCE));
-    }
-
-    @NodeChild("expression")
-    public abstract static class TestAbstractGuard1 extends ValueNode {
-
-        boolean guard(Abstract value0) {
-            return true;
-        }
-
-        @Specialization(order = 1, guards = "guard")
-        BExtendsAbstract doSpecialized1(BExtendsAbstract value0) {
-            return value0;
-        }
-
-        @Specialization(order = 2, guards = "guard")
-        CExtendsAbstract doSpecialized2(CExtendsAbstract value0) {
-            return value0;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -34,7 +34,7 @@
 
 public class ImplicitCastTest {
 
-    @TypeSystem({int.class, boolean.class, String.class})
+    @TypeSystem({int.class, String.class, boolean.class})
     static class ImplicitCast0Types {
 
         @ImplicitCast
@@ -55,12 +55,12 @@
 
         public abstract Object executeEvaluated(VirtualFrame frame, Object value2);
 
-        @Specialization(order = 1)
+        @Specialization
         public String op1(String value) {
             return value;
         }
 
-        @Specialization(order = 2)
+        @Specialization
         public boolean op1(boolean value) {
             return value;
         }
@@ -81,22 +81,21 @@
 
     @TypeSystemReference(ImplicitCast0Types.class)
     @NodeChild(value = "operand", type = ImplicitCast1Node.class)
-    // TODO temporary workaround
     abstract static class ImplicitCast1Node extends ValueNode {
 
         public abstract Object executeEvaluated(VirtualFrame frame, Object operand);
 
-        @Specialization(order = 0)
+        @Specialization
         public String op0(String value) {
             return value;
         }
 
-        @Specialization(order = 1, rewriteOn = RuntimeException.class)
+        @Specialization(rewriteOn = RuntimeException.class)
         public boolean op1(@SuppressWarnings("unused") boolean value) throws RuntimeException {
             throw new RuntimeException();
         }
 
-        @Specialization(order = 2)
+        @Specialization(contains = "op1")
         public boolean op2(boolean value) {
             return value;
         }
@@ -120,18 +119,18 @@
     // TODO temporary workaround
     abstract static class ImplicitCast2Node extends ValueNode {
 
-        @Specialization(order = 0)
+        @Specialization
         public String op0(String v0, String v1) {
             return v0 + v1;
         }
 
         @SuppressWarnings("unused")
-        @Specialization(order = 1, rewriteOn = RuntimeException.class)
+        @Specialization(rewriteOn = RuntimeException.class)
         public boolean op1(boolean v0, boolean v1) throws RuntimeException {
             throw new RuntimeException();
         }
 
-        @Specialization(order = 2)
+        @Specialization(contains = "op1")
         public boolean op2(boolean v0, boolean v1) {
             return v0 && v1;
         }
@@ -156,4 +155,15 @@
         Assert.assertEquals(true, root.getNode().executeEvaluated(null, true, true));
     }
 
+    @TypeSystem({String.class, boolean.class})
+    static class ImplicitCastError1 {
+
+        @ImplicitCast
+        @ExpectError("Target type and source type of an @ImplicitCast must not be the same type.")
+        String castInvalid(@SuppressWarnings("unused") String value) {
+            throw new AssertionError();
+        }
+
+    }
+
 }
--- /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/ImportGuardsTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,168 @@
+/*
+ * 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 static com.oracle.truffle.api.dsl.test.TestHelper.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.ImportGuardsTestFactory.ImportGuards6Factory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class ImportGuardsTest {
+
+    @ImportGuards(Imports0.class)
+    @NodeChild("a")
+    static class ImportGuards0 extends ValueNode {
+
+        @Specialization(guards = "staticGuard")
+        int f0(int a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    @ImportGuards(Imports0.class)
+    static class ImportGuards1 extends ValueNode {
+
+        @ExpectError("No compatible guard with method name 'nonStaticGuard' found.")
+        @Specialization(guards = "nonStaticGuard")
+        int f1(int a) {
+            return a;
+        }
+
+        @ExpectError("No compatible guard with method name 'protectedGuard' found.")
+        @Specialization(guards = "protectedGuard")
+        int f2(int a) {
+            return a;
+        }
+
+        @ExpectError("No compatible guard with method name 'packageGuard' found.")
+        @Specialization(guards = "packageGuard")
+        int f3(int a) {
+            return a;
+        }
+
+        @ExpectError("No compatible guard with method name 'privateGuard' found.")
+        @Specialization(guards = "privateGuard")
+        int f4(int a) {
+            return a;
+        }
+    }
+
+    public static class Imports0 {
+        public static boolean staticGuard(int a) {
+            return a == 0;
+        }
+
+        public boolean nonStaticGuard(int a) {
+            return a == 0;
+        }
+
+        protected static boolean protectedGuard(int a) {
+            return a == 0;
+        }
+
+        static boolean packageGuard(int a) {
+            return a == 0;
+        }
+
+        @SuppressWarnings("unused")
+        private static boolean privateGuard(int a) {
+            return a == 0;
+        }
+
+    }
+
+    @ExpectError("The specified import guard class 'com.oracle.truffle.api.dsl.test.ImportGuardsTest.Imports1' must be public.")
+    @NodeChild("a")
+    @ImportGuards(Imports1.class)
+    static class ImportGuards2 extends ValueNode {
+
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    static class Imports1 {
+
+    }
+
+    @ExpectError("The specified import guard class 'com.oracle.truffle.api.dsl.test.ImportGuardsTest.Imports2' must be public.")
+    @NodeChild("a")
+    @ImportGuards(Imports2.class)
+    static class ImportGuards3 extends ValueNode {
+
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    @ExpectError("The specified import guard class 'boolean' is not a declared type.")
+    @NodeChild("a")
+    @ImportGuards(boolean.class)
+    static class ImportGuards4 extends ValueNode {
+
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    private static class Imports2 {
+
+    }
+
+    @ExpectError("At least import guard classes must be specified.")
+    @NodeChild("a")
+    @ImportGuards({})
+    static class ImportGuards5 extends ValueNode {
+
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    @Test
+    public void testImportGuards6() {
+        // should use the guar declared in the node instead of the imported one.
+        assertRuns(ImportGuards6Factory.getInstance(), //
+                        array(1, 1), //
+                        array(1, 1));
+    }
+
+    @ImportGuards(Imports0.class)
+    @NodeChild("a")
+    static class ImportGuards6 extends ValueNode {
+
+        static boolean staticGuard(int a) {
+            return a == 1;
+        }
+
+        @Specialization(guards = "staticGuard")
+        int f0(int a) {
+            return a;
+        }
+    }
+
+}
--- /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/InsertBeforeTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class InsertBeforeTest {
+
+    @NodeChild("a")
+    static class InsertBefore1Base extends ValueNode {
+
+        boolean g1(int a) {
+            return a == 1;
+        }
+
+        boolean g2(int a) {
+            return a == 2;
+        }
+
+        @Specialization(guards = "g1")
+        int f1(int a) {
+            return a;
+        }
+
+        @Specialization(guards = "g2")
+        int f3(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    static class InsertBefore1T1 extends InsertBefore1Base {
+
+        @Specialization
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    static class InsertBefore1T2 extends InsertBefore1Base {
+
+        boolean g0(int a) {
+            return a == 0;
+        }
+
+        @Specialization(guards = "g0", insertBefore = "f1")
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    static class InsertBefore1T3 extends InsertBefore1Base {
+
+        boolean g0(int a) {
+            return a == 0;
+        }
+
+        @Specialization(guards = "g0", insertBefore = "f3")
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    @ExpectError({"Method f3(int) at annotation @Specialization is erroneous: Specialization is not reachable. It is shadowed by f0(int).",
+                    "Method f1(int) at annotation @Specialization is erroneous: Specialization is not reachable. It is shadowed by f0(int)."})
+    static class InsertBefore1T4 extends InsertBefore1Base {
+
+        boolean g0(int a) {
+            return a == 0;
+        }
+
+        @Specialization(insertBefore = "f1")
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    @ExpectError({"Method f3(int) at annotation @Specialization is erroneous: Specialization is not reachable. It is shadowed by f0(int)."})
+    static class InsertBefore1T5 extends InsertBefore1Base {
+
+        boolean g0(int a) {
+            return a == 0;
+        }
+
+        @Specialization(insertBefore = "f3")
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    static class InsertBefore1T6_1 extends InsertBefore1Base {
+
+        boolean g0(int a) {
+            return a == 0;
+        }
+
+        @Specialization(insertBefore = "f1", guards = "g0")
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    static class InsertBefore1T6_2 extends InsertBefore1T6_1 {
+
+        boolean g(int a) {
+            return a == 0;
+        }
+
+        @Specialization(insertBefore = "f0", guards = "g")
+        int f(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    static class InsertBefore1Error1 extends InsertBefore1Base {
+
+        @ExpectError("Specializations can only be inserted before specializations in superclasses.")
+        @Specialization(insertBefore = "f0")
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    static class InsertBefore1Error2 extends InsertBefore1Base {
+
+        @ExpectError("The referenced specialization 'asdf' could not be found.")
+        @Specialization(insertBefore = "asdf")
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+}
--- /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/MethodGuardsTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.BinaryNodeTest.*;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GlobalFlagGuardFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardWithBaseClassFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardWithBoxedPrimitiveFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardWithObjectFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.InvocationGuardFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.TestAbstractGuard1Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.TestGuardResolve1Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.TestGuardResolve2Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.TestGuardResolve3Factory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.*;
+
+@SuppressWarnings("unused")
+public class MethodGuardsTest {
+
+    private static final Object NULL = new Object();
+
+    @Test
+    public void testGuardInvocations() {
+        TestRootNode<InvocationGuard> root = createRoot(InvocationGuardFactory.getInstance());
+
+        assertEquals(Integer.MAX_VALUE, executeWith(root, Integer.MAX_VALUE - 1, 1));
+        assertEquals(1, InvocationGuard.specializedInvocations);
+        assertEquals(0, InvocationGuard.genericInvocations);
+
+        assertEquals(42, executeWith(root, Integer.MAX_VALUE, 1));
+        assertEquals(1, InvocationGuard.specializedInvocations);
+        assertEquals(1, InvocationGuard.genericInvocations);
+    }
+
+    @NodeChildren({@NodeChild("value0"), @NodeChild("value1")})
+    public abstract static class InvocationGuard extends ValueNode {
+
+        static int specializedInvocations = 0;
+        static int genericInvocations = 0;
+
+        boolean guard(int value0, int value1) {
+            return value0 != Integer.MAX_VALUE;
+        }
+
+        @Specialization(guards = "guard")
+        int doSpecialized(int value0, int value1) {
+            specializedInvocations++;
+            return value0 + value1;
+        }
+
+        @Fallback
+        int doGeneric(Object value0, Object value1) {
+            genericInvocations++;
+            return 42; // the generic answer to all questions
+        }
+    }
+
+    @Test
+    public void testGuardGlobal() {
+        TestRootNode<GlobalFlagGuard> root = createRoot(GlobalFlagGuardFactory.getInstance());
+
+        assertEquals(42, executeWith(root, NULL));
+
+        GlobalFlagGuard.globalFlag = true;
+        assertEquals(41, executeWith(root, NULL));
+
+        GlobalFlagGuard.globalFlag = false;
+        assertEquals(42, executeWith(root, NULL));
+    }
+
+    @NodeChild("expression")
+    public abstract static class GlobalFlagGuard extends ValueNode {
+
+        static boolean globalFlag = false;
+
+        static boolean globalFlagGuard() {
+            return globalFlag;
+        }
+
+        @Specialization(guards = "globalFlagGuard")
+        int doSpecialized(Object value0) {
+            return 41;
+        }
+
+        @Fallback
+        int doGeneric(Object value0) {
+            return 42; // the generic answer to all questions
+        }
+    }
+
+    @Test
+    public void testGuardWithBaseClass() {
+        TestRootNode<?> root = createRoot(GuardWithBaseClassFactory.getInstance());
+
+        assertEquals(42, executeWith(root, new BExtendsAbstract()));
+    }
+
+    @NodeChild("expression")
+    public abstract static class GuardWithBaseClass extends ValueNode {
+
+        boolean baseGuard(Abstract base) {
+            return true;
+        }
+
+        @Specialization(guards = "baseGuard")
+        int doSpecialized(BExtendsAbstract value0) {
+            return 42;
+        }
+    }
+
+    @NodeChild("expression")
+    public abstract static class GuardWithBaseInterface extends ValueNode {
+
+        boolean baseGuard(CharSequence base) {
+            return true;
+        }
+
+        @Specialization(guards = "baseGuard")
+        @ExpectError("No guard with name 'baseGuard' matched the required signature.%")
+        int doSpecialized(String value0) {
+            return 42;
+        }
+    }
+
+    @Test
+    public void testGuardWithPrimitive() {
+        TestRootNode<?> root = createRoot(GuardWithBoxedPrimitiveFactory.getInstance());
+
+        assertEquals(42, executeWith(root, 42));
+    }
+
+    @NodeChild("expression")
+    public abstract static class GuardWithBoxedPrimitive extends ValueNode {
+
+        boolean baseGuard(Integer primitive) {
+            return true;
+        }
+
+        @Specialization(guards = "baseGuard")
+        int doSpecialized(int value0) {
+            return value0;
+        }
+    }
+
+    @Test
+    public void testGuardWithObject() {
+        TestRootNode<?> root = createRoot(GuardWithObjectFactory.getInstance());
+
+        assertEquals(42, executeWith(root, 42));
+    }
+
+    @NodeChild("expression")
+    public abstract static class GuardWithObject extends ValueNode {
+
+        boolean baseGuard(Object primitive) {
+            return true;
+        }
+
+        @Specialization(guards = "baseGuard")
+        int doSpecialized(int value0) {
+            return value0;
+        }
+    }
+
+    @Test
+    public void testGuardResolve1() {
+        TestRootNode<?> root = createRoot(TestGuardResolve1Factory.getInstance());
+
+        assertEquals(42, executeWith(root, 42));
+    }
+
+    @NodeChild("expression")
+    public abstract static class TestGuardResolve1 extends ValueNode {
+
+        boolean guard(Object primitive) {
+            return false;
+        }
+
+        boolean guard(int primitive) {
+            return true;
+        }
+
+        @Specialization(guards = "guard")
+        int doSpecialized(int value0) {
+            return value0;
+        }
+    }
+
+    @Test
+    public void testGuardResolve2() {
+        TestRootNode<?> root = createRoot(TestGuardResolve2Factory.getInstance());
+        assertEquals(42, executeWith(root, new BExtendsAbstract()));
+    }
+
+    @NodeChild("expression")
+    public abstract static class TestGuardResolve2 extends ValueNode {
+
+        boolean guard(Object primitive) {
+            return false;
+        }
+
+        boolean guard(Abstract primitive) {
+            return true;
+        }
+
+        @Specialization(guards = "guard")
+        int doSpecialized(BExtendsAbstract value0) {
+            return 42;
+        }
+    }
+
+    @Test
+    public void testGuardResolve3() {
+        TestRootNode<?> root = createRoot(TestGuardResolve3Factory.getInstance());
+
+        assertEquals(42, executeWith(root, new BExtendsAbstract()));
+    }
+
+    @NodeChild("expression")
+    public abstract static class TestGuardResolve3 extends ValueNode {
+
+        boolean guard(Object primitive) {
+            return false;
+        }
+
+        boolean guard(Abstract primitive) {
+            return false;
+        }
+
+        boolean guard(BExtendsAbstract primitive) {
+            return true;
+        }
+
+        @Specialization(guards = "guard")
+        int doSpecialized(BExtendsAbstract value0) {
+            return 42;
+        }
+    }
+
+    @NodeChild("expression")
+    public abstract static class TestGuardResolve4 extends ValueNode {
+
+        boolean guard(Abstract primitive) {
+            return false;
+        }
+
+        @Specialization(guards = "guard")
+        int doSpecialized(BExtendsAbstract value0) {
+            return 42;
+        }
+    }
+
+    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
+    abstract static class TestGuardResolve5 extends ValueNode {
+
+        @Specialization(guards = "guard")
+        int add(Interface left, Interface right) {
+            return 42;
+        }
+
+        boolean guard(Interface left, Object right) {
+            return true;
+        }
+    }
+
+    @Test
+    public void testAbstractGuard1() {
+        TestRootNode<?> root = createRoot(TestAbstractGuard1Factory.getInstance());
+
+        assertEquals(BExtendsAbstract.INSTANCE, executeWith(root, BExtendsAbstract.INSTANCE));
+        assertEquals(CExtendsAbstract.INSTANCE, executeWith(root, CExtendsAbstract.INSTANCE));
+    }
+
+    @NodeChild("expression")
+    public abstract static class TestAbstractGuard1 extends ValueNode {
+
+        boolean guard(Abstract value0) {
+            return true;
+        }
+
+        @Specialization(guards = "guard")
+        BExtendsAbstract do1(BExtendsAbstract value0) {
+            return value0;
+        }
+
+        @Specialization(guards = "guard")
+        CExtendsAbstract do2(CExtendsAbstract value0) {
+            return value0;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,265 @@
+/*
+ * 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 static com.oracle.truffle.api.dsl.test.TestHelper.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArguments0Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArguments1Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsDouble0Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsDouble1Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsDouble2Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsDouble3Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsSingle2Factory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class MethodGuardsWithArgumentsTest {
+
+    @Test
+    public void testMArguments0() {
+        TestRootNode<MArguments0> root = createRoot(MArguments0Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root));
+    }
+
+    abstract static class MArguments0 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @Specialization(guards = "guard()")
+        int do1() {
+            return 42;
+        }
+    }
+
+    @Test
+    public void testMArguments1() {
+        TestRootNode<MArguments1> root = createRoot(MArguments1Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root));
+    }
+
+    abstract static class MArguments1 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @Specialization(guards = "guard ()")
+        int do1() {
+            return 42;
+        }
+    }
+
+    @Test
+    public void testMArgumentsSingle0() {
+        TestRootNode<MArguments1> root = createRoot(MArguments1Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root, 42));
+    }
+
+    @NodeChild("a")
+    abstract static class MArgumentsSingle0 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @Specialization(guards = "guard()")
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    @Test
+    public void testMArgumentsSingle1() {
+        TestRootNode<MArguments1> root = createRoot(MArguments1Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root, 42));
+    }
+
+    @NodeChild("a")
+    abstract static class MArgumentsSingle1 extends ValueNode {
+
+        static boolean guard(int a) {
+            return a == 42;
+        }
+
+        @Specialization(guards = "guard(a)")
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    @Test
+    public void testMArgumentsSingle2() {
+        TestRootNode<MArgumentsSingle2> root = createRoot(MArgumentsSingle2Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root, 42));
+    }
+
+    @NodeChild("a")
+    abstract static class MArgumentsSingle2 extends ValueNode {
+
+        static boolean guard(int a1, int a2) {
+            return a1 == 42 && a2 == 42;
+        }
+
+        @Specialization(guards = "guard(a,a)")
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    @Test
+    public void testMArgumentsDouble0() {
+        TestRootNode<MArgumentsDouble0> root = createRoot(MArgumentsDouble0Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root, 42, 0));
+    }
+
+    @NodeChild("a")
+    abstract static class MArgumentsDouble0 extends ValueNode {
+
+        static boolean guard(int a1, Object a2) {
+            return a1 == 42 && a2.equals(new Integer(42));
+        }
+
+        @Specialization(guards = "guard(a,a)")
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    @Test
+    public void testMArgumentsDouble1() {
+        TestRootNode<MArgumentsDouble1> root = createRoot(MArgumentsDouble1Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root, 42, 41));
+    }
+
+    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
+    abstract static class MArgumentsDouble1 extends ValueNode {
+
+        static boolean guard(int a1, double a2) {
+            return a1 == 42 && a2 == 41;
+        }
+
+        @Specialization(guards = "guard(a,b)")
+        int do1(int a, @SuppressWarnings("unused") double b) {
+            return a;
+        }
+    }
+
+    @Test
+    public void testMArgumentsDouble2() {
+        TestRootNode<MArgumentsDouble2> root = createRoot(MArgumentsDouble2Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root, 42, 41.0));
+    }
+
+    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
+    abstract static class MArgumentsDouble2 extends ValueNode {
+
+        static boolean guard(double a1, int a2) {
+            return a1 == 41 && a2 == 42;
+        }
+
+        @Specialization(guards = "guard(b,a)")
+        int do1(int a, @SuppressWarnings("unused") double b) {
+            return a;
+        }
+    }
+
+    @Test
+    public void testMArgumentsDouble3() {
+        TestRootNode<MArgumentsDouble3> root = createRoot(MArgumentsDouble3Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root, 42, 41.0));
+    }
+
+    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
+    abstract static class MArgumentsDouble3 extends ValueNode {
+
+        static boolean guard(Object a1, double a2) {
+            return new Double(41.0).equals(a1) && a2 == 41;
+        }
+
+        @Specialization(guards = "guard(b,b)")
+        int do1(int a, @SuppressWarnings("unused") double b) {
+            return a;
+        }
+    }
+
+    abstract static class MArgumentsError0 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @ExpectError("No compatible guard with method name 'guard(' found.%")
+        @Specialization(guards = "guard(")
+        int do1() {
+            return 42;
+        }
+    }
+
+    abstract static class MArgumentsError1 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @ExpectError("No compatible guard with method name 'guard)' found.%")
+        @Specialization(guards = "guard)")
+        int do1() {
+            return 42;
+        }
+
+    }
+
+    abstract static class MArgumentsError2 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @ExpectError("Guard parameter 'a' for guard 'guard' could not be mapped to a declared child node.")
+        @Specialization(guards = "guard(a)")
+        int do1() {
+            return 42;
+        }
+    }
+
+    @NodeChild("b")
+    abstract static class MArgumentsError3 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @ExpectError("Guard parameter 'a' for guard 'guard' could not be mapped to a declared child node.")
+        @Specialization(guards = "guard(a)")
+        int do1(int b) {
+            return b;
+        }
+    }
+
+}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -45,12 +45,12 @@
             return true;
         }
 
-        @Specialization(order = 1, guards = "!guard")
+        @Specialization(guards = "!guard")
         int do1() {
             throw new AssertionError();
         }
 
-        @Specialization(order = 2)
+        @Specialization
         int do2() {
             return 42; // the generic answer to all questions
         }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -117,12 +117,12 @@
 
         public abstract String getField();
 
-        @Specialization(order = 1, rewriteOn = RuntimeException.class)
+        @Specialization(rewriteOn = RuntimeException.class)
         String alwaysRewrite() {
             throw new RuntimeException();
         }
 
-        @Specialization(order = 2)
+        @Specialization(contains = "alwaysRewrite")
         String returnField() {
             return getField();
         }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -25,11 +25,15 @@
 import static com.oracle.truffle.api.dsl.test.TestHelper.*;
 import static org.junit.Assert.*;
 
+import java.util.*;
+
 import org.junit.*;
 
 import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.BinaryNodeTest.BinaryNode;
-import com.oracle.truffle.api.dsl.test.PolymorphicTestFactory.Node1Factory;
+import com.oracle.truffle.api.dsl.test.PolymorphicTestFactory.Polymorphic1Factory;
+import com.oracle.truffle.api.dsl.test.PolymorphicTestFactory.Polymorphic2Factory;
+import com.oracle.truffle.api.dsl.test.PolymorphicTestFactory.Polymorphic3Factory;
+import com.oracle.truffle.api.dsl.test.TestHelper.ExecutionListener;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
 import com.oracle.truffle.api.nodes.*;
@@ -47,103 +51,155 @@
         }
     }
 
+    public static void assertNoDuplicates(Node node, Node... ignored) {
+        assertNoDuplicatesRec(new HashSet<>(Arrays.asList(ignored)), new HashSet<Class<?>>(), node);
+    }
+
+    private static void assertNoDuplicatesRec(Set<Node> ignored, Set<Class<?>> seenClasses, Node current) {
+        if (!ignored.contains(current)) {
+            if (seenClasses.contains(current.getClass())) {
+                Assert.fail(String.format("Multiple occurences of the same class %s. %nTree: %s", current.getClass().getSimpleName(), NodeUtil.printCompactTreeToString(current.getRootNode())));
+            } else {
+                seenClasses.add(current.getClass());
+            }
+        }
+
+        for (Node child : current.getChildren()) {
+            if (child != null) {
+                assertNoDuplicatesRec(ignored, seenClasses, child);
+            }
+        }
+    }
+
     @Test
-    public void testJustSpecialize() {
-        TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
-        assertEquals("(int,int)", executeWith(node, 42, 42));
-        assertEquals("(boolean,boolean)", executeWith(node, false, false));
-        assertEquals("(int,boolean)", executeWith(node, 42, false));
-        assertEquals("(boolean,int)", executeWith(node, false, 42));
-        assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost());
-        assertParent(node.getNode(), node.getNode().getLeft());
-        assertParent(node.getNode(), node.getNode().getRight());
+    public void testPolymorphic1() {
+        assertRuns(Polymorphic1Factory.getInstance(), //
+                        array(42, 43, true, false, "a", "b"), //
+                        array(42, 43, true, false, "a", "b"),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                Polymorphic1 polymorphic = ((Polymorphic1) node.getNode());
+                                assertParent(node.getNode(), polymorphic.getA());
+                                assertNoDuplicates(polymorphic, polymorphic.getA());
+                                if (index == 0) {
+                                    assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost());
+                                }
+                            }
+                        });
+    }
+
+    @NodeChild("a")
+    abstract static class Polymorphic1 extends ValueNode {
+
+        public abstract ValueNode getA();
+
+        @Specialization
+        int add(int a) {
+            return a;
+        }
+
+        @Specialization
+        boolean add(boolean a) {
+            return a;
+        }
+
+        @Specialization
+        String add(String a) {
+            return a;
+        }
+
+        @Fallback
+        String add(Object left) {
+            throw new AssertionError(left.toString());
+        }
+
     }
 
     @Test
     public void testPolymorphic2() {
-        TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
-        assertEquals("(int,boolean)", executeWith(node, 42, false));
-        assertEquals("(int,int)", executeWith(node, 42, 42));
-        assertEquals(NodeCost.POLYMORPHIC, node.getNode().getCost());
-        assertParent(node.getNode(), node.getNode().getLeft());
-        assertParent(node.getNode(), node.getNode().getRight());
+        assertRuns(Polymorphic2Factory.getInstance(), //
+                        array(0, 1, 1, "1", "2", 2, 3), //
+                        array(0, 1, 1, "1", "2", 2, 3),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                Polymorphic2 polymorphic = ((Polymorphic2) node.getNode());
+                                assertParent(node.getNode(), polymorphic.getA());
+                                assertNoDuplicates(polymorphic, polymorphic.getA());
+                                if (index == 0) {
+                                    assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost());
+                                }
+                            }
+                        });
+    }
+
+    @NodeChild("a")
+    abstract static class Polymorphic2 extends ValueNode {
+
+        public abstract ValueNode getA();
+
+        @Specialization
+        String s2(String a) {
+            return a;
+        }
+
+        @Specialization(rewriteOn = RuntimeException.class)
+        int s0(int a) {
+            if (a == 1) {
+                throw new RuntimeException();
+            }
+            return a;
+        }
+
+        @Specialization
+        int s1(int a) {
+            return a;
+        }
+
     }
 
     @Test
     public void testPolymorphic3() {
-        TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
-        assertEquals("(int,boolean)", executeWith(node, 42, false));
-        assertEquals("(boolean,boolean)", executeWith(node, true, false));
-        assertEquals("(int,int)", executeWith(node, 42, 42));
-        assertEquals(NodeCost.POLYMORPHIC, node.getNode().getCost());
-        assertParent(node.getNode(), node.getNode().getLeft());
-        assertParent(node.getNode(), node.getNode().getRight());
-    }
-
-    @Test
-    public void testGenericLimitReached() {
-        TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
-        assertEquals("(boolean,int)", executeWith(node, false, 42));
-        assertEquals("(int,boolean)", executeWith(node, 42, false));
-        assertEquals("(boolean,boolean)", executeWith(node, true, false));
-        assertEquals("(int,int)", executeWith(node, 42, 42));
-        assertEquals(NodeCost.MEGAMORPHIC, node.getNode().getCost());
-        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, "1", "1"));
-        assertEquals(NodeCost.MEGAMORPHIC, node.getNode().getCost());
-        assertParent(node.getNode(), node.getNode().getLeft());
-        assertParent(node.getNode(), node.getNode().getRight());
+        assertRuns(Polymorphic3Factory.getInstance(), //
+                        array("0", "1", 1, 1, 2, 2, 3, 3), //
+                        array("0", "1", 1, 1, 2, 2, 3, 3),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                Polymorphic3 polymorphic = ((Polymorphic3) node.getNode());
+                                assertParent(node.getNode(), polymorphic.getA());
+                                assertNoDuplicates(polymorphic, polymorphic.getA());
+                            }
+                        });
     }
 
-    @Test
-    public void testGenericPolymorphic1() {
-        TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
-        assertEquals("(boolean,int)", executeWith(node, false, 42));
-        assertEquals("(boolean,boolean)", executeWith(node, false, false));
-        assertEquals("(generic,generic)", executeWith(node, "", ""));
-        assertEquals(NodeCost.MEGAMORPHIC, node.getNode().getCost());
-        /* Assertions for bug GRAAL-425 */
-        assertParent(node.getNode(), node.getNode().getLeft());
-        assertParent(node.getNode(), node.getNode().getRight());
-    }
+    @NodeChild("a")
+    abstract static class Polymorphic3 extends ValueNode {
 
-    @SuppressWarnings("unused")
-    @PolymorphicLimit(3)
-    abstract static class Node1 extends BinaryNode {
-
-        public abstract ValueNode getLeft();
+        public abstract ValueNode getA();
 
-        public abstract ValueNode getRight();
-
-        @Specialization(order = 1)
-        String add(int left, int right) {
-            return "(int,int)";
+        @Specialization
+        String s2(String a) {
+            return a;
         }
 
-        @Specialization(order = 2)
-        String add(boolean left, boolean right) {
-            return "(boolean,boolean)";
+        @Specialization(rewriteOn = RuntimeException.class)
+        int s0(int a) {
+            if (a == 1) {
+                throw new RuntimeException();
+            }
+            return a;
         }
 
-        @Specialization(order = 3)
-        String add(int left, boolean right) {
-            return "(int,boolean)";
+        @Specialization(rewriteOn = RuntimeException.class)
+        int s1(int a) {
+            if (a == 1) {
+                throw new RuntimeException();
+            }
+            return a;
         }
 
-        @Specialization(order = 4)
-        String add(boolean left, int right) {
-            return "(boolean,int)";
-        }
-
-        @Generic
-        String add(Object left, Object right) {
-            return "(generic,generic)";
+        @Specialization
+        int s2(int a) {
+            return a;
         }
 
     }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java	Mon Aug 25 21:15:59 2014 -0700
@@ -29,7 +29,7 @@
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.dsl.test.BinaryNodeTest.BinaryNode;
-import com.oracle.truffle.api.dsl.test.PolymorphicTest2Factory.Node1Factory;
+import com.oracle.truffle.api.dsl.test.PolymorphicTest2Factory.Polymorphic1Factory;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
 import com.oracle.truffle.api.nodes.*;
 
@@ -38,7 +38,7 @@
     @Test
     public void testMultipleTypes() {
         /* Tests the unexpected polymorphic case. */
-        TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
+        TestRootNode<Polymorphic1> node = TestHelper.createRoot(Polymorphic1Factory.getInstance());
         assertEquals(21, executeWith(node, false, false));
         assertEquals(42, executeWith(node, 21, 21));
         assertEquals("(boolean,int)", executeWith(node, false, 42));
@@ -46,8 +46,7 @@
     }
 
     @SuppressWarnings("unused")
-    @PolymorphicLimit(3)
-    abstract static class Node1 extends BinaryNode {
+    abstract static class Polymorphic1 extends BinaryNode {
 
         @Specialization(order = 1)
         int add(int left, int right) {
--- /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/ReachabilityTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import java.math.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.*;
+
+public class ReachabilityTest {
+
+    static class Reachability1 extends ValueNode {
+        @Specialization
+        int do2() {
+            return 2;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
+        @Specialization
+        int do1() {
+            return 2;
+        }
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType1 extends ValueNode {
+        @Specialization
+        int do2(int a) {
+            return a;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2(int).")
+        @Specialization
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType2 extends ValueNode {
+        @Specialization
+        BExtendsAbstract do2(BExtendsAbstract a) {
+            return a;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2(BExtendsAbstract).")
+        @Specialization
+        BExtendsAbstract do1(BExtendsAbstract a) {
+            return a;
+        }
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType3 extends ValueNode {
+        @Specialization
+        Abstract do2(Abstract a) {
+            return a;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2(Abstract).")
+        @Specialization
+        BExtendsAbstract do1(BExtendsAbstract a) {
+            return a;
+        }
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType4 extends ValueNode {
+
+        @Specialization
+        BExtendsAbstract do2(BExtendsAbstract a) {
+            return a;
+        }
+
+        @Specialization
+        Abstract do1(Abstract a) {
+            return a;
+        }
+
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType5 extends ValueNode {
+
+        @Specialization
+        double do2(double a) {
+            return a;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2(double).")
+        @Specialization
+        int do1(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType6 extends ValueNode {
+
+        @Specialization
+        BigInteger do2(BigInteger a) {
+            return a;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2(BigInteger).")
+        @Specialization
+        int do1(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType7 extends ValueNode {
+
+        @Specialization
+        int do2(int a) {
+            return a;
+        }
+
+        @Specialization
+        BigInteger do1(BigInteger a) {
+            return a;
+        }
+
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType8 extends ValueNode {
+
+        @Specialization
+        int do2(int a) {
+            return a;
+        }
+
+        @Specialization
+        Object do1(Object a) {
+            return a;
+        }
+
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType9 extends ValueNode {
+
+        @Specialization
+        Object do2(Object a) {
+            return a;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2(Object).")
+        @Specialization
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    static class ReachabilityGuard1 extends ValueNode {
+
+        boolean foo() {
+            return false;
+        }
+
+        @Specialization(guards = "foo")
+        int do2() {
+            return 1;
+        }
+
+        @Specialization
+        int do1() {
+            return 2;
+        }
+
+    }
+
+    static class ReachabilityGuard2 extends ValueNode {
+
+        boolean foo() {
+            return false;
+        }
+
+        @Specialization
+        int do2() {
+            return 2;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
+        @Specialization(guards = "foo")
+        int do1() {
+            return 1;
+        }
+
+    }
+
+    static class ReachabilityGuard3 extends ValueNode {
+
+        boolean foo() {
+            return false;
+        }
+
+        @Specialization(guards = "foo")
+        int do2() {
+            return 1;
+        }
+
+        @Specialization
+        int do1() {
+            return 2;
+        }
+
+    }
+
+    static class ReachabilityGuard4 extends ValueNode {
+
+        boolean foo() {
+            return false;
+        }
+
+        @Specialization(guards = "foo")
+        int do2() {
+            return 1;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
+        @Specialization(guards = "foo")
+        int do1() {
+            return 2;
+        }
+
+    }
+
+    @NodeAssumptions({"a1"})
+    static class ReachabilityAssumption1 extends ValueNode {
+
+        @Specialization(assumptions = "a1")
+        int do2() {
+            return 1;
+        }
+
+        @Specialization
+        int do1() {
+            return 2;
+        }
+
+    }
+
+    @NodeAssumptions({"a1"})
+    static class ReachabilityAssumption2 extends ValueNode {
+
+        @Specialization(assumptions = "a1")
+        int do2() {
+            return 1;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
+        @Specialization(assumptions = "a1")
+        int do1() {
+            return 2;
+        }
+
+    }
+
+    @NodeAssumptions({"a1", "a2"})
+    static class ReachabilityAssumption3 extends ValueNode {
+
+        @Specialization(assumptions = {"a1", "a2"})
+        int do2() {
+            return 1;
+        }
+
+        @Specialization(assumptions = "a1")
+        int do1() {
+            return 2;
+        }
+
+    }
+
+    @NodeAssumptions({"a1", "a2"})
+    static class ReachabilityAssumption4 extends ValueNode {
+
+        @Specialization(assumptions = "a1")
+        int do2() {
+            return 1;
+        }
+
+        @Specialization(assumptions = "a2")
+        int do1() {
+            return 2;
+        }
+
+    }
+
+    @NodeAssumptions({"a1", "a2"})
+    static class ReachabilityAssumption5 extends ValueNode {
+
+        @Specialization
+        int do2() {
+            return 1;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
+        @Specialization(assumptions = "a2")
+        int do1() {
+            return 2;
+        }
+
+    }
+
+    @NodeAssumptions({"a1", "a2"})
+    static class ReachabilityAssumption6 extends ValueNode {
+
+        @Specialization(assumptions = {"a1"})
+        int do2() {
+            return 1;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
+        @Specialization(assumptions = {"a1", "a2"})
+        int do1() {
+            return 2;
+        }
+
+    }
+
+    static class ReachabilityThrowable1 extends ValueNode {
+
+        @Specialization(rewriteOn = RuntimeException.class)
+        int do2() throws RuntimeException {
+            return 1;
+        }
+
+        @Specialization
+        int do1() {
+            return 2;
+        }
+
+    }
+
+    static class ReachabilityThrowable2 extends ValueNode {
+
+        @Specialization
+        int do2() {
+            return 1;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
+        @Specialization(rewriteOn = RuntimeException.class)
+        int do1() throws RuntimeException {
+            return 2;
+        }
+
+    }
+
+}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -106,6 +106,26 @@
 
     }
 
+    @NodeChildren({@NodeChild("child0"), @NodeChild("child1")})
+    @SuppressWarnings("unused")
+    abstract static class GuardChildNode extends ValueNode {
+
+        @ShortCircuit("child1")
+        boolean needsChild1(Object a) {
+            return a.equals(new Integer(42));
+        }
+
+        static boolean guard(int a, boolean hasB, int b) {
+            return false;
+        }
+
+        @Specialization(guards = "guard")
+        int doIt(int a, boolean hasB, int b) {
+            return a + b;
+        }
+
+    }
+
     @Test
     public void testVarArgs1() {
         ArgumentNode arg0 = new ArgumentNode(0);
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SlowPathTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.CompilerDirectives.SlowPath;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.SlowPathTestFactory.SlowPathOnGeneric0Factory;
-import com.oracle.truffle.api.dsl.test.SlowPathTestFactory.SlowPathOnGeneric1Factory;
-import com.oracle.truffle.api.dsl.test.SlowPathTestFactory.SlowPathOnGeneric2Factory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/** Tests the generated placement of {@link SlowPath} in generated methods. */
-public class SlowPathTest {
-
-    @Test
-    public void testSlowPathOnGeneric0() throws NoSuchMethodException, SecurityException {
-        Node node = SlowPathOnGeneric0Factory.create(null);
-        Assert.assertNull(node.getClass().getSuperclass().getDeclaredMethod("executeGeneric0", VirtualFrame.class, Object.class).getAnnotation(SlowPath.class));
-    }
-
-    @NodeChild
-    abstract static class SlowPathOnGeneric0 extends ValueNode {
-
-        @Specialization
-        @SuppressWarnings("unused")
-        Object doObject0(VirtualFrame frame, int value0) {
-            throw new AssertionError();
-        }
-
-    }
-
-    @Test
-    public void testSlowPathOnGeneric1() throws NoSuchMethodException, SecurityException {
-        Node node = SlowPathOnGeneric1Factory.create(null);
-        Assert.assertNotNull(node.getClass().getSuperclass().getDeclaredMethod("executeGeneric0", Object.class).getAnnotation(SlowPath.class));
-    }
-
-    @NodeChild
-    abstract static class SlowPathOnGeneric1 extends ValueNode {
-
-        @Specialization
-        @SuppressWarnings("unused")
-        Object doObject0(int value0) {
-            throw new AssertionError();
-        }
-
-    }
-
-    @Test
-    public void testSlowPathOnGeneric2() throws NoSuchMethodException, SecurityException {
-        Node node = SlowPathOnGeneric2Factory.create(null);
-        Assert.assertNull(node.getClass().getSuperclass().getDeclaredMethod("executeGeneric0", VirtualFrame.class, Object.class).getAnnotation(SlowPath.class));
-    }
-
-    @NodeChild
-    abstract static class SlowPathOnGeneric2 extends ValueNode {
-
-        @Specialization(order = 0)
-        @SuppressWarnings("unused")
-        Object doObject0(int value0) {
-            throw new AssertionError();
-        }
-
-        @Specialization(order = 1)
-        @SuppressWarnings("unused")
-        Object doObject1(VirtualFrame frame, String value0) {
-            throw new AssertionError();
-        }
-
-    }
-
-}
--- /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/SourceSectionTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2014, 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 static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.experimental.theories.*;
+import org.junit.runner.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.SourceSectionTestFactory.SourceSection0Factory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+
+@RunWith(Theories.class)
+public class SourceSectionTest {
+
+    @DataPoints public static final int[] data = new int[]{1, 2, 3, 4};
+
+    @Theory
+    public void testSourceSections(int value0, int value1, int value2) {
+        TestRootNode<SourceSection0> root = createRoot(SourceSection0Factory.getInstance());
+        SourceSection section = new NullSourceSection("a", "b");
+        root.getNode().assignSourceSection(section);
+        expectSourceSection(root.getNode(), section);
+        assertThat((int) executeWith(root, value0), is(value0));
+        expectSourceSection(root.getNode(), section);
+        assertThat((int) executeWith(root, value1), is(value1));
+        expectSourceSection(root.getNode(), section);
+        assertThat((int) executeWith(root, value2), is(value2));
+        expectSourceSection(root.getNode(), section);
+    }
+
+    private void expectSourceSection(Node root, SourceSection section) {
+        assertThat(root.getSourceSection(), is(sameInstance(section)));
+        for (Node child : root.getChildren()) {
+            if (child instanceof ArgumentNode) {
+                continue;
+            }
+            if (child != null) {
+                expectSourceSection(child, section);
+            }
+        }
+    }
+
+    @NodeChild("a")
+    static class SourceSection0 extends ValueNode {
+
+        boolean isOne(int a) {
+            return a == 1;
+        }
+
+        boolean isTwo(int a) {
+            return a == 2;
+        }
+
+        boolean isThree(int a) {
+            return a == 3;
+        }
+
+        @Specialization(guards = "isOne")
+        int do1(int a) {
+            return a;
+        }
+
+        @Specialization(guards = "isTwo")
+        int do2(int a) {
+            return a;
+        }
+
+        @Specialization(guards = "isThree")
+        int do3(int a) {
+            return a;
+        }
+
+        @Fallback
+        Object do4(Object a) {
+            return a; // the generic answer to all questions
+        }
+    }
+}
--- /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/SpecializationFallthroughTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest0Factory;
+import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest1Factory;
+import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest2Factory;
+import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest3Factory;
+import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest4Factory;
+import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest5Factory;
+import com.oracle.truffle.api.dsl.test.TestHelper.ExecutionListener;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class SpecializationFallthroughTest {
+
+    @Test
+    public void testFallthrough0() {
+        assertRuns(FallthroughTest0Factory.getInstance(), //
+                        array(0, 0, 1, 2), //
+                        array(0, 0, 1, 2),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                if (!last) {
+                                    return;
+                                }
+                                if (FallthroughTest0.fallthroughCount > 1) {
+                                    Assert.fail("The fallthrough case must never be triggered twice. Therfore count must be <= 1, but is not.");
+                                }
+                            }
+                        });
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughTest0 extends ValueNode {
+
+        static int fallthroughCount = 0;
+
+        public FallthroughTest0() {
+            fallthroughCount = 0;
+        }
+
+        @Specialization(rewriteOn = ArithmeticException.class)
+        int do1(int a) throws ArithmeticException {
+            if (a == 0) {
+                fallthroughCount++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        @Fallback
+        Object doFallback(Object a) {
+            return a;
+        }
+    }
+
+    /*
+     * Tests that the fall through is never triggered twice for monomorphic cases.
+     */
+    @Test
+    public void testFallthrough1() {
+        assertRuns(FallthroughTest1Factory.getInstance(), //
+                        array(0, 0, 0, 1, 2), //
+                        array(0, 0, 0, 1, 2),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                if (!last) {
+                                    return;
+                                }
+                                if (FallthroughTest1.fallthroughCount > 1) {
+                                    Assert.fail("The fallthrough case must never be triggered twice. Therfore count must be <= 1, but is not.");
+                                }
+                            }
+                        });
+    }
+
+    /* TODO assert falltrough do1 before do2 */
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughTest1 extends ValueNode {
+
+        static int fallthroughCount;
+
+        public FallthroughTest1() {
+            fallthroughCount = 0;
+        }
+
+        @Specialization(rewriteOn = ArithmeticException.class)
+        int do1(int a) throws ArithmeticException {
+            if (a == 0) {
+                fallthroughCount++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        @Specialization
+        int do2(int a) {
+            return a;
+        }
+
+    }
+
+    /*
+     * Tests that the fall through is never triggered twice with two falltrhoughs in one operation.
+     */
+    @Test
+    public void testFallthrough2() {
+        assertRuns(FallthroughTest2Factory.getInstance(), //
+                        array(0, 0, 1, 1, 2, 2), //
+                        array(0, 0, 1, 1, 2, 2),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                if (!last) {
+                                    return;
+                                }
+                                if (FallthroughTest2.fallthrough1 > 1) {
+                                    Assert.fail();
+                                }
+                                if (FallthroughTest2.fallthrough2 > 1) {
+                                    Assert.fail();
+                                }
+                                FallthroughTest2.fallthrough1 = 0;
+                                FallthroughTest2.fallthrough2 = 0;
+                            }
+                        });
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughTest2 extends ValueNode {
+
+        static int fallthrough1;
+        static int fallthrough2;
+
+        @Specialization(order = 1, rewriteOn = ArithmeticException.class)
+        int do1(int a) throws ArithmeticException {
+            if (a == 0) {
+                fallthrough1++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        @Specialization(order = 2, rewriteOn = ArithmeticException.class)
+        int do2(int a) throws ArithmeticException {
+            if (a == 1) {
+                fallthrough2++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        @Specialization
+        int do3(int a) {
+            return a;
+        }
+    }
+
+    /*
+     * Tests that the fall through is never triggered twice. In this case mixed fallthrough with
+     * normal specializations.
+     */
+    @Test
+    public void testFallthrough3() {
+        assertRuns(FallthroughTest3Factory.getInstance(), //
+                        array(0, 0, 1, 1, 2, 2), //
+                        array(0, 0, 1, 1, 2, 2),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                if (!last) {
+                                    return;
+                                }
+                                if (FallthroughTest3.fallthrough1 > 1) {
+                                    Assert.fail(String.valueOf(FallthroughTest3.fallthrough1));
+                                }
+                                FallthroughTest3.fallthrough1 = 0;
+                            }
+                        });
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughTest3 extends ValueNode {
+
+        static int fallthrough1;
+
+        boolean guard0(int a) {
+            return a == 1;
+        }
+
+        @Specialization(guards = "guard0")
+        int do2(int a) {
+            return a;
+        }
+
+        @Specialization(rewriteOn = ArithmeticException.class)
+        int do1(int a) throws ArithmeticException {
+            if (a == 0) {
+                fallthrough1++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        @Specialization
+        int do3(int a) {
+            return a;
+        }
+
+    }
+
+    @Test
+    public void testFallthrough4() {
+        assertRuns(FallthroughTest4Factory.getInstance(), //
+                        array(0, 0, 1, 1, 2, 2), //
+                        array(0, 0, 1, 1, 2, 2),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                if (!last) {
+                                    return;
+                                }
+                                if (FallthroughTest4.fallthrough1 > 1) {
+                                    Assert.fail(String.valueOf(FallthroughTest4.fallthrough1));
+                                }
+                                if (FallthroughTest4.fallthrough2 > 1) {
+                                    Assert.fail(String.valueOf(FallthroughTest4.fallthrough1));
+                                }
+                                FallthroughTest4.fallthrough1 = 0;
+                                FallthroughTest4.fallthrough2 = 0;
+                            }
+                        });
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughTest4 extends ValueNode {
+
+        static int fallthrough1;
+        static int fallthrough2;
+
+        @Specialization(order = 1, rewriteOn = ArithmeticException.class)
+        int do1(int a) throws ArithmeticException {
+            if (a == 0) {
+                fallthrough1++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        @Specialization(order = 2, rewriteOn = ArithmeticException.class)
+        int do2(int a) throws ArithmeticException {
+            if (a == 1) {
+                fallthrough2++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        @Specialization
+        int do3(int a) {
+            return a;
+        }
+
+    }
+
+    @Test
+    public void testFallthrough5() {
+        assertRuns(FallthroughTest5Factory.getInstance(), //
+                        array(0, 0, 1, 1, 2, 2), //
+                        array(0, 0, 1, 1, 2, 2),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                if (!last) {
+                                    return;
+                                }
+                                if (FallthroughTest5.fallthrough1 > 1) {
+                                    Assert.fail(String.valueOf(FallthroughTest5.fallthrough1));
+                                }
+                                FallthroughTest5.fallthrough1 = 0;
+                            }
+                        });
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughTest5 extends ValueNode {
+
+        static int fallthrough1;
+
+        @Specialization(guards = "isDo1", rewriteOn = ArithmeticException.class)
+        int do1(int a) throws ArithmeticException {
+            if (a == 0) {
+                fallthrough1++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        protected static boolean isDo1(int a) {
+            return a == 0 || a == 1;
+        }
+
+        @Specialization(guards = "isDo1")
+        int do2(int a) {
+            return a;
+        }
+
+        @Specialization
+        int do3(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughTest6 extends ValueNode {
+
+        static int fallthrough1;
+        static int fallthrough2;
+        static int fallthrough3;
+        static int fallthrough4;
+
+        @Specialization(order = 1, rewriteOn = ArithmeticException.class)
+        int do4(int a) throws ArithmeticException {
+            return a;
+        }
+
+        @Specialization(order = 2, rewriteOn = ArithmeticException.class)
+        int do2(int a) throws ArithmeticException {
+            return a;
+        }
+
+        @Specialization(order = 3, rewriteOn = ArithmeticException.class)
+        int do3(int a) throws ArithmeticException {
+            return a;
+        }
+
+        @Specialization(order = 4, rewriteOn = ArithmeticException.class)
+        int do1(int a) throws ArithmeticException {
+            return a;
+        }
+
+        @Specialization
+        double do5(double a) {
+            return a;
+        }
+
+    }
+
+}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -48,7 +48,7 @@
         MockAssumption a2 = new MockAssumption(false);
         MockAssumption a3 = new MockAssumption(true);
 
-        TestRootNode<TestGrouping> root = TestHelper.createGenericRoot(TestGroupingFactory.getInstance(), a1, a2, a3);
+        TestRootNode<TestGrouping> root = TestHelper.createRoot(TestGroupingFactory.getInstance(), a1, a2, a3);
 
         SimpleTypes.intCast = 0;
         SimpleTypes.intCheck = 0;
@@ -59,29 +59,29 @@
         TestGrouping.true3 = 0;
 
         Assert.assertEquals(42, TestHelper.executeWith(root, 21, 21));
-        Assert.assertEquals(1, TestGrouping.true1);
-        Assert.assertEquals(1, TestGrouping.false1);
-        Assert.assertEquals(1, TestGrouping.true2);
-        Assert.assertEquals(1, TestGrouping.false2);
-        Assert.assertEquals(1, TestGrouping.true3);
-        Assert.assertEquals(2, SimpleTypes.intCheck);
-        Assert.assertEquals(2, SimpleTypes.intCast);
-        Assert.assertEquals(1, a1.checked);
-        Assert.assertEquals(1, a2.checked);
-        Assert.assertEquals(1, a3.checked);
+        Assert.assertEquals(4, TestGrouping.true1);
+        Assert.assertEquals(0, TestGrouping.false1);
+        Assert.assertEquals(4, TestGrouping.true2);
+        Assert.assertEquals(5, TestGrouping.false2);
+        Assert.assertEquals(5, TestGrouping.true3);
+        Assert.assertEquals(8, SimpleTypes.intCheck);
+        Assert.assertEquals(8, SimpleTypes.intCast);
+        Assert.assertEquals(4, a1.checked);
+        Assert.assertEquals(0, a2.checked);
+        Assert.assertEquals(4, a3.checked);
 
         Assert.assertEquals(42, TestHelper.executeWith(root, 21, 21));
-        Assert.assertEquals(2, TestGrouping.true1);
-        Assert.assertEquals(2, TestGrouping.false1);
-        Assert.assertEquals(2, TestGrouping.true2);
-        Assert.assertEquals(2, TestGrouping.false2);
-        Assert.assertEquals(2, TestGrouping.true3);
+        Assert.assertEquals(5, TestGrouping.true1);
+        Assert.assertEquals(0, TestGrouping.false1);
+        Assert.assertEquals(5, TestGrouping.true2);
+        Assert.assertEquals(6, TestGrouping.false2);
+        Assert.assertEquals(6, TestGrouping.true3);
 
-        Assert.assertEquals(2, a1.checked);
-        Assert.assertEquals(2, a2.checked);
-        Assert.assertEquals(2, a3.checked);
-        Assert.assertEquals(4, SimpleTypes.intCheck);
-        Assert.assertEquals(4, SimpleTypes.intCast);
+        Assert.assertEquals(5, a1.checked);
+        Assert.assertEquals(0, a2.checked);
+        Assert.assertEquals(5, a3.checked);
+        Assert.assertEquals(8, SimpleTypes.intCheck);
+        Assert.assertEquals(8, SimpleTypes.intCast);
 
     }
 
@@ -121,39 +121,39 @@
             return true;
         }
 
-        @Specialization(order = 1)
+        @Specialization
         public int fail(int value1, String value2) {
             throw new AssertionError();
         }
 
-        @Specialization(order = 2, guards = {"true1", "false1"})
-        public int fail1(int value1, int value2) {
-            throw new AssertionError();
-        }
-
-        @Specialization(order = 3, guards = {"true1", "true2"}, assumptions = {"a1", "a2"})
-        public int fail2(int value1, int value2) {
-            throw new AssertionError();
-        }
-
-        @Specialization(order = 4, guards = {"true1", "true2"}, assumptions = {"a1", "a3"}, rewriteOn = RuntimeException.class)
+        @Specialization(guards = {"true1", "true2", "!false2", "true3"}, assumptions = {"a1", "a3"}, rewriteOn = RuntimeException.class)
         public int throwRewrite(int value1, int value2) {
             throw new RuntimeException();
         }
 
-        @Specialization(order = 5, guards = {"true1", "true2", "false2"}, assumptions = {"a1", "a3"})
+        @Specialization(guards = {"true1", "true2", "!false2", "true3"}, contains = "throwRewrite", assumptions = {"a1", "a3"})
+        public int success(int value1, int value2) {
+            return value1 + value2;
+        }
+
+        @Specialization(guards = {"true1", "true2", "!false2", "!true3"}, assumptions = {"a1", "a3"})
+        public int fail5(int value1, int value2) {
+            throw new AssertionError();
+        }
+
+        @Specialization(guards = {"true1", "true2", "false2"}, assumptions = {"a1", "a3"})
         public int fail4(int value1, int value2) {
             throw new AssertionError();
         }
 
-        @Specialization(order = 6, guards = {"true1", "true2", "!false2", "!true3"}, assumptions = {"a1", "a3"})
-        public int fail5(int value1, int value2) {
+        @Specialization(guards = {"true1", "true2"}, assumptions = {"a1", "a3"})
+        public int fail2break(int value1, int value2) {
             throw new AssertionError();
         }
 
-        @Specialization(order = 7, guards = {"true1", "true2", "!false2", "true3"}, assumptions = {"a1", "a3"})
-        public int success(int value1, int value2) {
-            return value1 + value2;
+        @Specialization(guards = {"true1", "false1"})
+        public int fail1(int value1, int value2) {
+            throw new AssertionError();
         }
 
     }
@@ -168,18 +168,18 @@
     @NodeChild(value = "genericChild", type = GenericInt.class)
     public abstract static class TestElseConnectionBug1 extends ValueNode {
 
-        @Specialization(order = 1, rewriteOn = {SlowPathException.class}, guards = "isInitialized")
-        public int doInteger(int value) throws SlowPathException {
+        @Specialization(rewriteOn = {SlowPathException.class}, guards = "isInitialized")
+        public int do1(int value) throws SlowPathException {
             throw new SlowPathException();
         }
 
-        @Specialization(order = 3, guards = "isInitialized")
-        public int doObject(int value) {
+        @Specialization(contains = "do1", guards = "isInitialized")
+        public int do2(int value) {
             return value == 42 ? value : 0;
         }
 
-        @Specialization(order = 4, guards = "!isInitialized")
-        public Object doUninitialized(int value) {
+        @Specialization(guards = "!isInitialized")
+        public Object do3(int value) {
             throw new AssertionError();
         }
 
@@ -204,25 +204,25 @@
 
     @Test
     public void testElseConnectionBug2() {
-        TestHelper.assertRuns(TestElseConnectionBug2Factory.getInstance(), 42, 42);
+        TestHelper.assertRuns(TestElseConnectionBug2Factory.getInstance(), new Object[]{42}, new Object[]{42});
     }
 
     @SuppressWarnings("unused")
     @NodeChild
     public abstract static class TestElseConnectionBug2 extends ValueNode {
 
-        @Specialization(order = 2, guards = "guard0")
-        public int doGuard0(int value) {
+        @Specialization(guards = "guard0")
+        public int do1(int value) {
             throw new AssertionError();
         }
 
-        @Specialization(order = 3, guards = "guard1")
-        public int doGuard1(int value) {
+        @Specialization(guards = "guard1")
+        public int do2(int value) {
             throw new AssertionError();
         }
 
-        @Specialization(order = 4, guards = "!guard0")
-        public int doUninitialized(int value) {
+        @Specialization(guards = "!guard0")
+        public int do3(int value) {
             return value;
         }
 
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java	Mon Aug 25 21:15:59 2014 -0700
@@ -98,7 +98,7 @@
         return createCallTarget(node).call(values);
     }
 
-    static Object array(Object... val) {
+    static Object[] array(Object... val) {
         return val;
     }
 
@@ -138,29 +138,71 @@
         return output;
     }
 
+    static void assertRuns(NodeFactory<? extends ValueNode> factory, Object[] testValues, Object[] result) {
+        assertRuns(factory, testValues, result, null);
+    }
+
     /* Methods tests all test values in combinational order. */
-    static void assertRuns(NodeFactory<? extends ValueNode> factory, Object result, Object... testValues) {
+    static void assertRuns(NodeFactory<? extends ValueNode> factory, Object[] testValues, Object[] result, ExecutionListener listener) {
         // test each run by its own.
         for (int i = 0; i < testValues.length; i++) {
-            assertValue(createRoot(factory), result, testValues);
+            assertValue(createRoot(factory), 0, testValues[i], result[i], listener, true);
         }
 
         // test all combinations of the test values
-        List<List<Object>> permuts = permutations(Arrays.asList(testValues));
+        List<Object> testValuesList = Arrays.asList(testValues);
+        List<List<Object>> permuts = permutations(testValuesList);
         for (List<Object> list : permuts) {
             TestRootNode<?> root = createRoot(factory);
+            int index = 0;
             for (Object object : list) {
-                assertValue(root, result, object);
+                assertValue(root, index, object, result[testValuesList.indexOf(object)], listener, index == list.size() - 1);
+                index++;
             }
         }
     }
 
-    static void assertValue(TestRootNode<? extends ValueNode> root, Object result, Object testValues) {
-        if (testValues instanceof Object[]) {
-            assertEquals(result, executeWith(root, (Object[]) testValues));
+    static void assertValue(TestRootNode<? extends ValueNode> root, int index, Object value, Object result, ExecutionListener listener, boolean last) {
+        Object actualResult = null;
+        if (result instanceof Class && Throwable.class.isAssignableFrom((Class<?>) result)) {
+            try {
+                if (value instanceof Object[]) {
+                    actualResult = executeWith(root, (Object[]) value);
+                } else {
+                    actualResult = executeWith(root, value);
+                }
+                fail(String.format("Exception %s  expected but not occured.", result.getClass()));
+            } catch (Throwable e) {
+                actualResult = e;
+                if (!e.getClass().isAssignableFrom(((Class<?>) result))) {
+                    e.printStackTrace();
+                    fail(String.format("Incompatible exception class thrown. Expected %s but was %s.", result.toString(), e.getClass()));
+                }
+            }
+        } else if (value instanceof Object[]) {
+            actualResult = executeWith(root, (Object[]) value);
+            assertEquals(result, actualResult);
         } else {
-            assertEquals(result, executeWith(root, testValues));
+            actualResult = executeWith(root, value);
+            assertEquals(result, actualResult);
+        }
+        if (listener != null) {
+            listener.afterExecution(root, index, value, result, actualResult, last);
         }
     }
 
+    public static final class LogListener implements ExecutionListener {
+
+        public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+            System.out.printf("Run %3d Node:%-20s Parameters: %10s Expected: %10s Result %10s%n", index, node.getNode().getClass().getSimpleName(), value, expectedResult, actualResult);
+        }
+
+    }
+
+    interface ExecutionListener {
+
+        void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last);
+
+    }
+
 }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,6 +22,8 @@
  */
 package com.oracle.truffle.api.dsl.test;
 
+import java.math.*;
+
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
@@ -29,7 +31,8 @@
 
 public class TypeSystemTest {
 
-    @TypeSystem({int.class, boolean.class, String.class, CallTarget.class, BExtendsAbstract.class, CExtendsAbstract.class, Abstract.class, Object[].class})
+    @TypeSystem({int.class, double.class, boolean.class, BigInteger.class, String.class, CallTarget.class, BExtendsAbstract.class, CExtendsAbstract.class, Abstract.class, Interface.class,
+                    Object[].class})
     static class SimpleTypes {
 
         static int intCheck;
@@ -47,10 +50,20 @@
             return (int) value;
         }
 
+        @ImplicitCast
+        public double castDouble(int value) {
+            return value;
+        }
+
+        @ImplicitCast
+        public BigInteger castBigInteger(int value) {
+            return BigInteger.valueOf(value);
+        }
+
     }
 
     @TypeSystemReference(SimpleTypes.class)
-    public abstract static class ValueNode extends Node {
+    public static class ValueNode extends Node {
 
         public ValueNode() {
             super(null);
@@ -72,6 +85,10 @@
             return SimpleTypesGen.SIMPLETYPES.expectObjectArray(execute(frame));
         }
 
+        public BigInteger executeBigInteger(VirtualFrame frame) throws UnexpectedResultException {
+            return SimpleTypesGen.SIMPLETYPES.expectBigInteger(execute(frame));
+        }
+
         public BExtendsAbstract executeBExtendsAbstract(VirtualFrame frame) throws UnexpectedResultException {
             return SimpleTypesGen.SIMPLETYPES.expectBExtendsAbstract(execute(frame));
         }
@@ -80,7 +97,21 @@
             return SimpleTypesGen.SIMPLETYPES.expectCExtendsAbstract(execute(frame));
         }
 
-        public abstract Object execute(VirtualFrame frame);
+        public Abstract executeAbstract(VirtualFrame frame) throws UnexpectedResultException {
+            return SimpleTypesGen.SIMPLETYPES.expectAbstract(execute(frame));
+        }
+
+        public double executeDouble(VirtualFrame frame) throws UnexpectedResultException {
+            return SimpleTypesGen.SIMPLETYPES.expectDouble(execute(frame));
+        }
+
+        public Interface executeInterface(VirtualFrame frame) throws UnexpectedResultException {
+            return SimpleTypesGen.SIMPLETYPES.expectInterface(execute(frame));
+        }
+
+        public Object execute(@SuppressWarnings("unused") VirtualFrame frame) {
+            throw new UnsupportedOperationException();
+        }
 
         @Override
         public ValueNode copy() {
@@ -158,4 +189,6 @@
         static final CExtendsAbstract INSTANCE = new CExtendsAbstract();
     }
 
+    interface Interface {
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Fallback.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+/**
+ *
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface Fallback {
+
+}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Generic.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.lang.annotation.*;
-
-/**
- *
- */
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.METHOD})
-public @interface Generic {
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Implies.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+/*
+ * Experimental API.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface Implies {
+
+    String[] value();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ImportGuards.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+/**
+ * Imports all public static methods usable as guards for {@link Specialization} annotations to the
+ * current class. Using this annotation common guards can be shared across nodes. Imported guards
+ * are derived from super classes. Guards declared in the node type hierarchy are always preferred
+ * to imported guards. Imported guards for a more concrete type are preferred to guards imported in
+ * the base class.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface ImportGuards {
+
+    Class<?>[] value();
+
+}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/PolymorphicLimit.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.TYPE})
-public @interface PolymorphicLimit {
-
-    /** Specifies the maximum polymorphic cache depth until it falls back to the generic case. */
-    int value();
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java	Mon Aug 25 21:15:59 2014 -0700
@@ -30,12 +30,36 @@
 @Target({ElementType.METHOD})
 public @interface Specialization {
 
-    int DEFAULT_ORDER = -1;
+    /**
+     * @deprecated do not use anymore. Will get removed in the next release.
+     */
+    @Deprecated int DEFAULT_ORDER = -1;
 
+    /**
+     * The order has no effect anymore. The declaration order specialization methods is used
+     * instead.
+     *
+     * @deprecated use declaration order instead. Will get removed in the next release.
+     */
+    @Deprecated
     int order() default DEFAULT_ORDER;
 
+    /**
+     * Inserts this and all specializations that are declared after this specialization before a
+     * specialization in the superclass. By default all specializations of the subclass are appended
+     * to the specializations of the superclass.
+     */
+    String insertBefore() default "";
+
     Class<? extends Throwable>[] rewriteOn() default {};
 
+    /**
+     * The contains attribute declares all specializations that are contained by this
+     * specialization. A containing specialization must be strictly generic as the contained
+     * specialization.
+     */
+    String[] contains() default {};
+
     String[] guards() default {};
 
     /**
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeCheck.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeCheck.java	Mon Aug 25 21:15:59 2014 -0700
@@ -57,17 +57,17 @@
  *
  * {@literal @}TypeSystem(types = {int.class, BigInteger.class, String.class}, nodeBaseClass = TypedNode.class)
  * public abstract class Types {
- *
+ * 
  *     {@literal @}TypeCheck
  *     public boolean isBigInteger(Object value) {
  *         return value instanceof Integer || value instanceof BigInteger;
  *     }
- *
+ * 
  *     {@literal @}TypeCheck
  *     public boolean isBigInteger(int value) {
  *         return true;
  *     }
- *
+ * 
  * }
  * </pre>
  *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLMetadata.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.internal;
+
+/**
+ * This is NOT public API. Do not use directly. This code may change without notice.
+ */
+public final class DSLMetadata {
+
+    public static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[]{};
+    public static final DSLMetadata NONE = new DSLMetadata(null, EMPTY_CLASS_ARRAY, EMPTY_CLASS_ARRAY, EMPTY_CLASS_ARRAY, 0, 0);
+
+    private final Class<?> specializationClass;
+    private final Class<?>[] includes;
+    private final Class<?>[] excludedBy;
+    private final Class<?>[] specializedTypes;
+
+    private final int costs;
+    private final int order;
+
+    public DSLMetadata(Class<?> specializationClass, Class<?>[] includes, Class<?>[] excludes, Class<?>[] specializedTypes, int costs, int order) {
+        this.specializationClass = specializationClass;
+        this.includes = includes;
+        this.excludedBy = excludes;
+        this.specializedTypes = specializedTypes;
+        this.costs = costs;
+        this.order = order;
+    }
+
+    public Class<?> getSpecializationClass() {
+        return specializationClass;
+    }
+
+    public Class<?>[] getSpecializedTypes() {
+        return specializedTypes;
+    }
+
+    Class<?>[] getIncludes() {
+        return includes;
+    }
+
+    Class<?>[] getExcludedBy() {
+        return excludedBy;
+    }
+
+    int getCosts() {
+        return costs;
+    }
+
+    int getOrder() {
+        return order;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.internal;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * This is NOT public API. Do not use directly. This code may change without notice.
+ */
+public interface DSLNode {
+
+    DSLMetadata getMetadata0();
+
+    void adoptChildren0(Node other, Node next);
+
+    void updateTypes0(Class<?>[] types);
+
+    Node getNext0();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLShare.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.internal;
+
+import java.util.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+/** Contains utility classes shared across generated DSLNode implementations. */
+public class DSLShare {
+
+    public static boolean isExcluded(Node currentNode, DSLMetadata otherMetadata) {
+        assert otherMetadata.getExcludedBy().length > 0 : "At least one exclude must be defined for isIncluded.";
+        Node cur = findRoot(currentNode);
+        while (cur != null) {
+            Class<?> curClass = cur.getClass();
+            if (curClass == otherMetadata.getSpecializationClass()) {
+                return true;
+            } else if (containsClass(otherMetadata.getExcludedBy(), cur)) {
+                return true;
+            }
+            cur = getNext(cur);
+        }
+        return false;
+    }
+
+    private static boolean includes(Node oldNode, DSLNode newNode) {
+        return containsClass(newNode.getMetadata0().getIncludes(), oldNode);
+    }
+
+    public static <T extends Node & DSLNode> T rewrite(Node thisNode, T newNode, String message) {
+        assert newNode != null;
+        if (getNext(thisNode) != null || getPrevious(thisNode) != null) {
+            // already polymorphic -> append
+            return appendPolymorphic(findUninitialized(thisNode), newNode);
+        } else if (includes(thisNode, newNode)) {
+            // included -> remains monomorphic
+            newNode.adoptChildren0(thisNode, null);
+            return thisNode.replace(newNode, message);
+        } else {
+            // goto polymorphic
+            return null;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T extends Node> T findRoot(T node) {
+        Node prev = node;
+        Node cur;
+        do {
+            cur = prev;
+            prev = getPrevious(cur);
+        } while (prev != null);
+        return (T) cur;
+    }
+
+    private static Node findUninitialized(Node node) {
+        Node next = node;
+        Node cur;
+        do {
+            cur = next;
+            next = getNext(cur);
+        } while (next != null);
+        return cur;
+    }
+
+    public static <T extends Node & DSLNode> T rewriteUninitialized(Node uninitialized, T newNode) {
+        Node prev = getPrevious(uninitialized);
+        if (prev == null) {
+            newNode.adoptChildren0(uninitialized, null);
+            return uninitialized.replace(newNode, "Uninitialized monomorphic");
+        } else {
+            return appendPolymorphic(uninitialized, newNode);
+        }
+    }
+
+    public static <T extends Node & DSLNode> T rewriteToPolymorphic(Node oldNode, DSLNode uninitializedDSL, T polymorphic, DSLNode currentCopy, DSLNode newNodeDSL, String message) {
+        assert getNext(oldNode) == null;
+        assert getPrevious(oldNode) == null;
+        assert newNodeDSL != null;
+
+        Node uninitialized = (Node) uninitializedDSL;
+        Node newNode = (Node) newNodeDSL;
+        polymorphic.adoptChildren0(oldNode, (Node) currentCopy);
+
+        updateSourceSection(oldNode, uninitialized);
+        // new specialization
+        updateSourceSection(oldNode, newNode);
+        newNodeDSL.adoptChildren0(null, uninitialized);
+        currentCopy.adoptChildren0(null, newNode);
+
+        oldNode.replace(polymorphic, message);
+
+        assert polymorphic.getNext0() == currentCopy;
+        assert newNode != null ? currentCopy.getNext0() == newNode : currentCopy.getNext0() == uninitialized;
+        assert uninitializedDSL.getNext0() == null;
+        return polymorphic;
+    }
+
+    private static void updateSourceSection(Node oldNode, Node newNode) {
+        if (newNode.getSourceSection() == null) {
+            newNode.assignSourceSection(oldNode.getSourceSection());
+        }
+    }
+
+    private static Class<?>[] mergeTypes(DSLNode node, Class<?>[] types) {
+        Class<?>[] specializedTypes = node.getMetadata0().getSpecializedTypes();
+        if (specializedTypes.length == 0) {
+            return null;
+        } else if (types == null) {
+            return Arrays.copyOf(specializedTypes, specializedTypes.length);
+        } else {
+            for (int i = 0; i < specializedTypes.length; i++) {
+                if (specializedTypes[i] != types[i]) {
+                    types[i] = Object.class;
+                }
+            }
+            return types;
+        }
+    }
+
+    private static <T extends Node & DSLNode> T appendPolymorphic(Node uninitialized, T newNode) {
+        Class<?>[] includes = newNode.getMetadata0().getIncludes();
+        Node cur = getPrevious(uninitialized);
+        Node prev = uninitialized;
+        int depth = 0;
+        Class<?>[] types = null;
+        while (cur != null) {
+            if (containsClass(includes, cur)) {
+                cur.replace(prev, "Included in other specialization");
+                cur = prev;
+            } else {
+                depth++;
+                types = mergeTypes((DSLNode) cur, types);
+            }
+            prev = cur;
+            cur = getPrevious(cur);
+        }
+        assert prev.getCost() == NodeCost.POLYMORPHIC;
+
+        updateSourceSection(prev, newNode);
+        if (depth <= 1) {
+            newNode.adoptChildren0(prev, null);
+            return prev.replace(newNode, "Polymorphic to monomorphic.");
+        } else {
+            newNode.adoptChildren0(null, uninitialized);
+            ((DSLNode) prev).updateTypes0(mergeTypes(newNode, types));
+            return uninitialized.replace(newNode, "Appended polymorphic");
+        }
+    }
+
+    private static boolean containsClass(Class<?>[] classList, Node node) {
+        Class<?> nodeClass = node.getClass();
+        for (Class<?> toCheck : classList) {
+            if (nodeClass == toCheck) {
+                if (node.getCost() == NodeCost.UNINITIALIZED) {
+                    /*
+                     * In case a specialization is excluded by the fallback specialization the
+                     * uninitialized class is used as exclusion class. Because the fallback field in
+                     * the uninitialized specialization is not accessible we use the costs to check
+                     * if the fallback was reached or not. In case the fallback was reached in the
+                     * uninitialized version the cost is MONOMORPHIC, otherwise it is UNINITIALIZED.
+                     */
+                    continue;
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static Node getNext(Node node) {
+        return ((DSLNode) node).getNext0();
+    }
+
+    private static Node getPrevious(Node node) {
+        Node parent = node.getParent();
+        if (parent instanceof DSLNode && getNext(parent) == node) {
+            return parent;
+        } else {
+            return null;
+        }
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/NodeFactoryBase.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.internal;
+
+import java.util.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * This is NOT public API. Do not use directly. This code may change without notice.
+ */
+public abstract class NodeFactoryBase<T> implements NodeFactory<T> {
+
+    private final Class<T> nodeClass;
+    private final Class<?>[][] nodeSignatures;
+    private final Class<? extends Node>[] executionSignatures;
+
+    @SuppressWarnings("unchecked")
+    public NodeFactoryBase(Class<T> nodeClass, Class<?>[] executionSignatures, Class<?>[][] nodeSignatures) {
+        this.nodeClass = nodeClass;
+        this.nodeSignatures = nodeSignatures;
+        this.executionSignatures = (Class<? extends Node>[]) executionSignatures;
+    }
+
+    public abstract T createNode(Object... arguments);
+
+    public final Class<T> getNodeClass() {
+        return nodeClass;
+    }
+
+    public final List<List<Class<?>>> getNodeSignatures() {
+        List<List<Class<?>>> signatures = new ArrayList<>();
+        for (int i = 0; i < nodeSignatures.length; i++) {
+            signatures.add(Arrays.asList(nodeSignatures[i]));
+        }
+        return signatures;
+    }
+
+    public final List<Class<? extends Node>> getExecutionSignature() {
+        return Arrays.asList(executionSignatures);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/InstrumentationTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2014, 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.test;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * <h3>AST Instrumentation</h3>
+ *
+ * Instrumentation allows the insertion into Truffle ASTs language-specific instances of
+ * {@link Wrapper} that propagate {@link ExecutionEvents} through a {@link Probe} to any instances
+ * of {@link Instrument} that might be attached to the particular probe by tools.
+ * <ol>
+ * <li>Creates a simple add AST</li>
+ * <li>Verifies its structure</li>
+ * <li>"Probes" the add node by adding a {@link Wrapper} and associated {@link Probe}</li>
+ * <li>Attaches a simple {@link Instrument} to the node via its {@link Probe}</li>
+ * <li>Verifies the structure of the probed AST</li>
+ * <li>Verifies the execution of the probed AST</li>
+ * <li>Verifies the results observed by the instrument.</li>
+ * </ol>
+ * To do these tests, several required classes have been implemented in their most basic form, only
+ * implementing the methods necessary for the tests to pass, with stubs elsewhere.
+ */
+public class InstrumentationTest {
+
+    @Test
+    public void test() {
+        // Build a tree
+        TruffleRuntime runtime = Truffle.getRuntime();
+        TestChildNode leftChild = new TestChildNode();
+        TestChildNode rightChild = new TestChildNode();
+        TestSourceSection sourceSection = new TestSourceSection();
+        TestAddNode addNode = new TestAddNode(leftChild, rightChild, sourceSection);
+        TestRootNode rootNode = new TestRootNode(addNode);
+
+        // Have to create a call target before checking parent/child relationships
+        CallTarget target = runtime.createCallTarget(rootNode);
+
+        // Check tree structure
+        Assert.assertEquals(addNode, leftChild.getParent());
+        Assert.assertEquals(addNode, rightChild.getParent());
+        Iterator<Node> iterator = addNode.getChildren().iterator();
+        Assert.assertEquals(leftChild, iterator.next());
+        Assert.assertEquals(rightChild, iterator.next());
+        Assert.assertFalse(iterator.hasNext());
+        Assert.assertEquals(rootNode, addNode.getParent());
+        iterator = rootNode.getChildren().iterator();
+        Assert.assertEquals(addNode, iterator.next());
+        Assert.assertFalse(iterator.hasNext());
+        Object result = target.call();
+        Assert.assertEquals(42, result);
+
+        // Create another call target, this time with the "probed" add node
+        TestExecutionContext context = new TestExecutionContext();
+        TestWrapper wrapper = new TestWrapper(addNode, context);
+        rootNode = new TestRootNode(wrapper);
+        target = runtime.createCallTarget(rootNode);
+
+        // Check the new tree structure
+        Assert.assertEquals(addNode, leftChild.getParent());
+        Assert.assertEquals(addNode, rightChild.getParent());
+        iterator = addNode.getChildren().iterator();
+        Assert.assertEquals(leftChild, iterator.next());
+        Assert.assertEquals(rightChild, iterator.next());
+        Assert.assertFalse(iterator.hasNext());
+        Assert.assertEquals(wrapper, addNode.getParent());
+        iterator = wrapper.getChildren().iterator();
+        Assert.assertEquals(addNode, iterator.next());
+        Assert.assertFalse(iterator.hasNext());
+        Assert.assertEquals(rootNode, wrapper.getParent());
+        iterator = rootNode.getChildren().iterator();
+        Assert.assertEquals(wrapper, iterator.next());
+        Assert.assertFalse(iterator.hasNext());
+        result = target.call();
+        Assert.assertEquals(42, result);
+
+        // Create some instruments
+        final TestInstrument instrumentA = new TestInstrument();
+        final TestInstrument instrumentB = new TestInstrument();
+
+        wrapper.getProbe().addInstrument(instrumentA);
+
+        result = target.call();
+        Assert.assertEquals(instrumentA.numInstrumentEnter, 1);
+        Assert.assertEquals(instrumentA.numInstrumentLeave, 1);
+        Assert.assertEquals(instrumentB.numInstrumentEnter, 0);
+        Assert.assertEquals(instrumentB.numInstrumentLeave, 0);
+        Assert.assertEquals(42, result);
+
+        wrapper.getProbe().addInstrument(instrumentB);
+
+        result = target.call();
+        Assert.assertEquals(instrumentA.numInstrumentEnter, 2);
+        Assert.assertEquals(instrumentA.numInstrumentLeave, 2);
+        Assert.assertEquals(instrumentB.numInstrumentEnter, 1);
+        Assert.assertEquals(instrumentB.numInstrumentLeave, 1);
+        Assert.assertEquals(42, result);
+
+        wrapper.getProbe().removeInstrument(instrumentA);
+
+        result = target.call();
+        Assert.assertEquals(instrumentA.numInstrumentEnter, 2);
+        Assert.assertEquals(instrumentA.numInstrumentLeave, 2);
+        Assert.assertEquals(instrumentB.numInstrumentEnter, 2);
+        Assert.assertEquals(instrumentB.numInstrumentLeave, 2);
+        Assert.assertEquals(42, result);
+
+    }
+
+    private class TestRootNode extends RootNode {
+        @Child private RootNode child;
+
+        public TestRootNode(RootNode child) {
+            super(null);
+            this.child = child;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return child.execute(frame);
+        }
+    }
+
+    private class TestAddNode extends RootNode {
+
+        @Child private TestChildNode left;
+        @Child private TestChildNode right;
+
+        public TestAddNode(TestChildNode left, TestChildNode right, TestSourceSection sourceSection) {
+            super(sourceSection);
+            this.left = left;
+            this.right = right;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return left.execute() + right.execute();
+        }
+    }
+
+    private class TestChildNode extends Node {
+
+        public TestChildNode() {
+            super(null);
+        }
+
+        public int execute() {
+            return 21;
+        }
+    }
+
+    /**
+     * The wrapper node class is usually language-specific and inherits from the language-specific
+     * subclass of {@link Node}, not {@RootNode}.
+     */
+    private class TestWrapper extends RootNode implements Wrapper {
+        @Child private RootNode child;
+        private Probe probe;
+
+        public TestWrapper(RootNode child, ExecutionContext context) {
+            this.child = insert(child);
+            this.probe = context.createProbe(child.getSourceSection());
+        }
+
+        public boolean isTaggedAs(SyntaxTag tag) {
+            return false;
+        }
+
+        public Iterable<SyntaxTag> getSyntaxTags() {
+            return null;
+        }
+
+        public Node getChild() {
+            return child;
+        }
+
+        public Probe getProbe() {
+            return probe;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            probe.enter(child, frame);
+            Object result;
+
+            try {
+                result = child.execute(frame);
+                probe.leave(child, frame, result);
+            } catch (Exception e) {
+                probe.leaveExceptional(child, frame, e);
+                throw (e);
+            }
+            return result;
+        }
+    }
+
+    /**
+     * An "empty" description of the source code that might correspond to a particular AST node. The
+     * instrumentation framework tracks probes that have been inserted by their source location,
+     * using this as a key.
+     */
+    private class TestSourceSection implements SourceSection {
+
+        public Source getSource() {
+            return null;
+        }
+
+        public int getStartLine() {
+            return 0;
+        }
+
+        public LineLocation getLineLocation() {
+            return null;
+        }
+
+        public int getStartColumn() {
+            return 0;
+        }
+
+        public int getCharIndex() {
+            return 0;
+        }
+
+        public int getCharLength() {
+            return 0;
+        }
+
+        public int getCharEndIndex() {
+            return 0;
+        }
+
+        public String getIdentifier() {
+            return null;
+        }
+
+        public String getCode() {
+            return null;
+        }
+
+        public String getShortDescription() {
+            return null;
+        }
+
+    }
+
+    private class TestExecutionContext extends ExecutionContext {
+
+        @Override
+        public String getLanguageShortName() {
+            return "test";
+        }
+
+        @Override
+        protected void setSourceCallback(SourceCallback sourceCallback) {
+        }
+
+    }
+
+    private class TestInstrument extends Instrument {
+
+        public int numInstrumentEnter = 0;
+        public int numInstrumentLeave = 0;
+
+        @Override
+        public void enter(Node astNode, VirtualFrame frame) {
+            numInstrumentEnter++;
+        }
+
+        @Override
+        public void leave(Node astNode, VirtualFrame frame, Object result) {
+            numInstrumentLeave++;
+        }
+    }
+
+}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/package-info.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/package-info.java	Mon Aug 25 21:15:59 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2014, 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
@@ -44,6 +44,7 @@
  * <li>How to use frames and frame slots to store values local to an activation? {@link com.oracle.truffle.api.test.FrameTest}</li>
  * <li>How to use type specialization and speculation for frame slots? {@link com.oracle.truffle.api.test.FrameSlotTypeSpecializationTest}</li>
  * <li>How to use type specialization and speculation for node return values? {@link com.oracle.truffle.api.test.ReturnTypeSpecializationTest}</li>
+ * <li>How to "instrument" an AST with nodes that can provide access to runtime state from external tools {@link com.oracle.truffle.api.test.InstrumentationTest}</li>
  * </ul>
  *
  *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/BinaryConditionProfileTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014, 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.test.utilities;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+import org.junit.experimental.theories.*;
+import org.junit.runner.*;
+
+import com.oracle.truffle.api.utilities.*;
+
+@RunWith(Theories.class)
+public class BinaryConditionProfileTest {
+
+    @DataPoints public static boolean[] data = new boolean[]{true, false};
+
+    private BinaryConditionProfile profile;
+
+    @Before
+    public void create() {
+        profile = (BinaryConditionProfile) ConditionProfile.createBinaryProfile();
+    }
+
+    @Test
+    public void testInitial() {
+        assertThat(profile.wasTrue(), is(false));
+        assertThat(profile.wasFalse(), is(false));
+    }
+
+    @Theory
+    public void testProfileOne(boolean value) {
+        boolean result = profile.profile(value);
+
+        assertThat(result, is(value));
+        assertThat(profile.wasTrue(), is(value));
+        assertThat(profile.wasFalse(), is(!value));
+    }
+
+    @Theory
+    public void testProfileTwo(boolean value0, boolean value1) {
+        boolean result0 = profile.profile(value0);
+        boolean result1 = profile.profile(value1);
+
+        assertThat(result0, is(value0));
+        assertThat(result1, is(value1));
+        assertThat(profile.wasTrue(), is(value0 || value1));
+        assertThat(profile.wasFalse(), is(!value0 || !value1));
+    }
+
+    @Theory
+    public void testProfileThree(boolean value0, boolean value1, boolean value2) {
+        boolean result0 = profile.profile(value0);
+        boolean result1 = profile.profile(value1);
+        boolean result2 = profile.profile(value2);
+
+        assertThat(result0, is(value0));
+        assertThat(result1, is(value1));
+        assertThat(result2, is(value2));
+        assertThat(profile.wasTrue(), is(value0 || value1 || value2));
+        assertThat(profile.wasFalse(), is(!value0 || !value1 || !value2));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/CountingConditionProfileTest.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014, 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.test.utilities;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+import org.junit.experimental.theories.*;
+import org.junit.runner.*;
+
+import com.oracle.truffle.api.utilities.*;
+
+@RunWith(Theories.class)
+public class CountingConditionProfileTest {
+
+    @DataPoints public static boolean[] data = new boolean[]{true, false};
+
+    private CountingConditionProfile profile;
+
+    @Before
+    public void create() {
+        profile = (CountingConditionProfile) ConditionProfile.createCountingProfile();
+    }
+
+    @Test
+    public void testInitial() {
+        assertThat(profile.getTrueCount(), is(0));
+        assertThat(profile.getFalseCount(), is(0));
+    }
+
+    @Theory
+    public void testProfileOne(boolean value) {
+        boolean result = profile.profile(value);
+
+        assertThat(result, is(value));
+        assertThat(profile.getTrueCount(), is(value ? 1 : 0));
+        assertThat(profile.getFalseCount(), is(!value ? 1 : 0));
+    }
+
+    @Theory
+    public void testProfileTwo(boolean value0, boolean value1) {
+        boolean result0 = profile.profile(value0);
+        boolean result1 = profile.profile(value1);
+
+        assertThat(result0, is(value0));
+        assertThat(result1, is(value1));
+        assertThat(profile.getTrueCount(), is((value0 ? 1 : 0) + (value1 ? 1 : 0)));
+        assertThat(profile.getFalseCount(), is((!value0 ? 1 : 0) + (!value1 ? 1 : 0)));
+    }
+
+    @Theory
+    public void testProfileThree(boolean value0, boolean value1, boolean value2) {
+        boolean result0 = profile.profile(value0);
+        boolean result1 = profile.profile(value1);
+        boolean result2 = profile.profile(value2);
+
+        assertThat(result0, is(value0));
+        assertThat(result1, is(value1));
+        assertThat(result2, is(value2));
+        assertThat(profile.getTrueCount(), is((value0 ? 1 : 0) + (value1 ? 1 : 0) + (value2 ? 1 : 0)));
+        assertThat(profile.getFalseCount(), is((!value0 ? 1 : 0) + (!value1 ? 1 : 0) + (!value2 ? 1 : 0)));
+    }
+
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Assumption.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Assumption.java	Mon Aug 25 21:15:59 2014 -0700
@@ -34,6 +34,9 @@
  * method. The Truffle compiler has special knowledge of this class in order to produce efficient
  * machine code for checking an assumption in case the assumption object is a compile time constant.
  * Therefore, assumptions should be stored in final fields in Truffle nodes.
+ *
+ * All instances of classes implementing {@code Assumption} must be held in {@code final} fields for
+ * compiler optimizations to take effect.
  */
 public interface Assumption {
 
@@ -42,14 +45,14 @@
      * longer the case. This method is preferred over the {@link #isValid()} method when writing
      * guest language interpreter code. The catch block should perform a node rewrite (see
      * {@link Node#replace(Node)}) with a node that no longer relies on the assumption.
-     * 
+     *
      * @throws InvalidAssumptionException If the assumption is no longer valid.
      */
     void check() throws InvalidAssumptionException;
 
     /**
      * Checks whether the assumption is still valid.
-     * 
+     *
      * @return a boolean value indicating the validity of the assumption
      */
     boolean isValid();
@@ -61,7 +64,7 @@
 
     /**
      * A name for the assumption that is used for debug output.
-     * 
+     *
      * @return the name of the assumption
      */
     String getName();
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java	Mon Aug 25 21:15:59 2014 -0700
@@ -30,7 +30,7 @@
 public interface CallTarget {
 
     /**
-     * Calls this target as a root method..
+     * Calls this target as a root method.
      *
      * @param arguments passed arguments as an object array
      * @return the return result of the call
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java	Mon Aug 25 21:15:59 2014 -0700
@@ -45,6 +45,9 @@
     protected ExecutionContext() {
     }
 
+    /**
+     * Sets up the {@link SourceCallback} for this execution context.
+     */
     public void initialize() {
         setSourceCallback(new SourceCallback() {
 
@@ -99,23 +102,13 @@
     }
 
     /**
-     * Return the (possibly newly created) {@link Probe} uniquely associated with a particular
-     * source code location. A newly created probe carries no tags.
+     * Return a newly created, untagged, {@link Probe} associated with a particular source section,
+     * with no requirement that the association be unique.
      *
-     * @return a probe uniquely associated with an extent of guest language source code.
+     * @return a probe associated with an extent of guest language source code.
      */
-    public final Probe getProbe(SourceSection sourceSection) {
-        return probeManager.getProbe(sourceSection);
-    }
-
-    /**
-     * Has a {@link Probe} been created that is uniquely associated with a particular source code
-     * location.
-     *
-     * @return a probe uniquely associated with an extent of guest language source code.
-     */
-    public final boolean hasProbe(SourceSection sourceSection) {
-        return probeManager.hasProbe(sourceSection);
+    public final Probe createProbe(SourceSection source) {
+        return probeManager.createProbe(source);
     }
 
     /**
@@ -127,14 +120,6 @@
     }
 
     /**
-     * Returns all existing probes with first character on a specified line; empty collection if no
-     * probes found.
-     */
-    public final Collection<Probe> findProbesByLine(LineLocation lineLocation) {
-        return probeManager.findProbesByLine(lineLocation);
-    }
-
-    /**
      * Sets a trap that will make a callback at any AST location where a existing probe holds a
      * specified tag; only one trap may be set at a time.
      *
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,6 +24,8 @@
  */
 package com.oracle.truffle.api;
 
+import java.security.*;
+
 import com.oracle.truffle.api.impl.*;
 
 /**
@@ -31,7 +33,7 @@
  */
 public class Truffle {
 
-    private static final TruffleRuntime RUNTIME;
+    private static final TruffleRuntime RUNTIME = initRuntime();
 
     /**
      * Creates a new {@link TruffleRuntime} instance if the runtime has a specialized
@@ -46,13 +48,15 @@
         return RUNTIME;
     }
 
-    static {
-        TruffleRuntime runtime;
+    private static TruffleRuntime initRuntime() {
         try {
-            runtime = createRuntime();
+            return AccessController.doPrivileged(new PrivilegedAction<TruffleRuntime>() {
+                public TruffleRuntime run() {
+                    return createRuntime();
+                }
+            });
         } catch (UnsatisfiedLinkError e) {
-            runtime = new DefaultTruffleRuntime();
+            return new DefaultTruffleRuntime();
         }
-        RUNTIME = runtime;
     }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,6 +24,8 @@
  */
 package com.oracle.truffle.api;
 
+import java.security.*;
+
 import com.oracle.truffle.api.nodes.*;
 
 /**
@@ -36,7 +38,7 @@
      * <p>
      * Can be set with {@code -Dtruffle.TraceRewrites=true}.
      */
-    public static boolean TraceRewrites = Boolean.getBoolean("truffle.TraceRewrites");
+    public static boolean TraceRewrites;
 
     /**
      * Enables the generation of detailed rewrite reasons. Enabling this may introduce some overhead
@@ -44,7 +46,7 @@
      * <p>
      * Can be set with {@code -Dtruffle.DetailedRewriteReasons=true}.
      */
-    public static final boolean DetailedRewriteReasons = Boolean.getBoolean("truffle.DetailedRewriteReasons");
+    public static final boolean DetailedRewriteReasons;
 
     /**
      * Filters rewrites that do not contain the given string in the qualified name of the source or
@@ -52,7 +54,7 @@
      * <p>
      * Can be set with {@code -Dtruffle.TraceRewritesFilterClass=name}.
      */
-    public static String TraceRewritesFilterClass = System.getProperty("truffle.TraceRewritesFilterClass");
+    public static String TraceRewritesFilterClass;
 
     /**
      * Filters rewrites which does not contain the {@link NodeCost} in its source {@link NodeInfo}.
@@ -61,7 +63,7 @@
      * Can be set with
      * {@code -Dtruffle.TraceRewritesFilterFromCost=NONE|MONOMORPHIC|POLYMORPHIC|MEGAMORPHIC}.
      */
-    public static NodeCost TraceRewritesFilterFromCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterFromCost"));
+    public static NodeCost TraceRewritesFilterFromCost;
 
     /**
      * Filters rewrites which does not contain the {@link NodeCost} in its target {@link NodeInfo}.
@@ -70,14 +72,14 @@
      * Can be set with
      * {@code -Dtruffle.TraceRewritesFilterToKind=UNINITIALIZED|SPECIALIZED|POLYMORPHIC|GENERIC}.
      */
-    public static NodeCost TraceRewritesFilterToCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterToCost"));
+    public static NodeCost TraceRewritesFilterToCost;
 
     /**
      * Enables the dumping of Node creations and AST rewrites in JSON format.
      * <p>
      * Can be set with {@code -Dtruffle.TraceASTJSON=true}.
      */
-    public static final boolean TraceASTJSON = Boolean.getBoolean("truffle.TraceASTJSON");
+    public static final boolean TraceASTJSON;
 
     private static NodeCost parseNodeInfoKind(String kind) {
         if (kind == null) {
@@ -87,4 +89,21 @@
         return NodeCost.valueOf(kind);
     }
 
+    static {
+        final boolean[] values = {false, false};
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            public Void run() {
+                TraceRewrites = Boolean.getBoolean("truffle.TraceRewrites");
+                TraceRewritesFilterClass = System.getProperty("truffle.TraceRewritesFilterClass");
+                TraceRewritesFilterFromCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterFromCost"));
+                TraceRewritesFilterToCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterToCost"));
+                values[0] = Boolean.getBoolean("truffle.DetailedRewriteReasons");
+                values[1] = Boolean.getBoolean("truffle.TraceASTJSON");
+                return null;
+            }
+        });
+
+        DetailedRewriteReasons = values[0];
+        TraceASTJSON = values[1];
+    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java	Mon Aug 25 21:15:59 2014 -0700
@@ -59,6 +59,11 @@
     DirectCallNode createDirectCallNode(CallTarget target);
 
     /**
+     * Experimental API. May change without notice.
+     */
+    LoopNode createLoopNode(RepeatingNode body);
+
+    /**
      * Creates a new runtime specific version of {@link IndirectCallNode}.
      *
      * @return the new call node
@@ -135,4 +140,5 @@
      * Internal API method. Do not use.
      */
     void notifyTransferToInterpreter();
+
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java	Mon Aug 25 21:15:59 2014 -0700
@@ -53,13 +53,17 @@
     }
 
     public FrameSlot addFrameSlot(Object identifier) {
-        return addFrameSlot(identifier, FrameSlotKind.Illegal);
+        return addFrameSlot(identifier, null, FrameSlotKind.Illegal);
     }
 
     public FrameSlot addFrameSlot(Object identifier, FrameSlotKind kind) {
+        return addFrameSlot(identifier, null, kind);
+    }
+
+    public FrameSlot addFrameSlot(Object identifier, Object info, FrameSlotKind kind) {
         CompilerAsserts.neverPartOfCompilation("interpreter-only.  includes hashmap operations.");
         assert !identifierToSlotMap.containsKey(identifier);
-        FrameSlot slot = new FrameSlot(this, identifier, slots.size(), kind);
+        FrameSlot slot = new FrameSlot(this, identifier, info, slots.size(), kind);
         slots.add(slot);
         identifierToSlotMap.put(identifier, slot);
         updateVersion();
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java	Mon Aug 25 21:15:59 2014 -0700
@@ -34,12 +34,14 @@
 
     private final FrameDescriptor descriptor;
     private final Object identifier;
+    private final Object info;
     private final int index;
     @CompilationFinal private FrameSlotKind kind;
 
-    public FrameSlot(FrameDescriptor descriptor, Object identifier, int index, FrameSlotKind kind) {
+    public FrameSlot(FrameDescriptor descriptor, Object identifier, Object info, int index, FrameSlotKind kind) {
         this.descriptor = descriptor;
         this.identifier = identifier;
+        this.info = info;
         this.index = index;
         this.kind = kind;
     }
@@ -48,6 +50,10 @@
         return identifier;
     }
 
+    public Object getInfo() {
+        return info;
+    }
+
     public int getIndex() {
         return index;
     }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultIndirectCallNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultIndirectCallNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -32,10 +32,32 @@
  * This is runtime specific API. Do not use in a guest language.
  */
 final class DefaultIndirectCallNode extends IndirectCallNode {
+    @Override
+    public Object call(final VirtualFrame frame, final CallTarget target, Object[] arguments) {
+        DefaultTruffleRuntime truffleRuntime = (DefaultTruffleRuntime) Truffle.getRuntime();
+        final CallTarget currentCallTarget = truffleRuntime.getCurrentFrame().getCallTarget();
+        FrameInstance frameInstance = new FrameInstance() {
+            public Frame getFrame(FrameAccess access, boolean slowPath) {
+                return frame;
+            }
 
-    @Override
-    public Object call(VirtualFrame frame, CallTarget target, Object[] arguments) {
-        return target.call(arguments);
+            public boolean isVirtualFrame() {
+                return false;
+            }
+
+            public Node getCallNode() {
+                return DefaultIndirectCallNode.this;
+            }
+
+            public CallTarget getCallTarget() {
+                return currentCallTarget;
+            }
+        };
+        truffleRuntime.pushFrame(frameInstance);
+        try {
+            return target.call(arguments);
+        } finally {
+            truffleRuntime.popFrame();
+        }
     }
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultLoopNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, 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.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+public final class DefaultLoopNode extends LoopNode {
+
+    public DefaultLoopNode(RepeatingNode repeatNode) {
+        super(repeatNode);
+    }
+
+    @Override
+    public void executeLoop(VirtualFrame frame) {
+        do {
+        } while (executeRepeatNode(frame));
+    }
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java	Mon Aug 25 21:15:59 2014 -0700
@@ -138,4 +138,11 @@
 
     public void notifyTransferToInterpreter() {
     }
+
+    public LoopNode createLoopNode(RepeatingNode repeating) {
+        if (!(repeating instanceof Node)) {
+            throw new IllegalArgumentException("Repeating node must be of type Node.");
+        }
+        return new DefaultLoopNode(repeating);
+    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTNodeProber.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTNodeProber.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,11 +27,10 @@
 import com.oracle.truffle.api.nodes.*;
 
 /**
- * Implementation of a policy for <em>instrumenting</em> inserting a {@link Probe} at a Truffle AST
- * node.
+ * Methods for inserting a {@link Probe} at a Truffle AST node.
  * <p>
- * Note that this interface is guest language agnostic, but current extensions are
- * language-specific. This will be revisited.
+ * This interface is guest language agnostic, but current extensions are language-specific. This
+ * will be revisited.
  * <p>
  * <strong>Disclaimer:</strong> experimental interface under development. Really!
  */
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTPrinter.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTPrinter.java	Mon Aug 25 21:15:59 2014 -0700
@@ -29,7 +29,8 @@
 import com.oracle.truffle.api.nodes.*;
 
 /**
- * Language-agnostic access to AST-based debugging support.
+ * Access to AST-based debugging support, which is could be language implementation specific in the
+ * details chosen to be presented.
  * <p>
  * <strong>WARNING:</strong> this interface is under development and will change substantially.
  */
@@ -37,7 +38,7 @@
 
     /**
      * Prints a textual AST display, one line per node, with nesting.
-     * 
+     *
      * @param p
      * @param node the root node of the display.
      * @param maxDepth the maximum number of levels to print below the root
@@ -47,7 +48,7 @@
 
     /**
      * Creates a textual AST display, one line per node, with nesting.
-     * 
+     *
      * @param node the root node of the display.
      * @param maxDepth the maximum number of levels to print below the root
      * @param markNode a node to mark with a textual arrow prefix, if present.
@@ -56,7 +57,7 @@
 
     /**
      * Creates a textual AST display, one line per node, with nesting.
-     * 
+     *
      * @param node the root node of the display.
      * @param maxDepth the maximum number of levels to print below the root
      */
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ExecutionEvents.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ExecutionEvents.java	Mon Aug 25 21:15:59 2014 -0700
@@ -28,8 +28,9 @@
 import com.oracle.truffle.api.nodes.*;
 
 /**
- * Normal events during program execution at Truffle AST nodes that are reported via a {@link Probe}
- * associated with the node, and made available to the probe's attached {@link Instrument}s.
+ * Normal events at each Truffle AST {@link Node} that occur during guest language execution, and
+ * which the {@link Probe} associated with that node, if any, reports to every {@link Instrument}
+ * attached to the {@link Probe}.
  * <p>
  * <strong>Disclaimer:</strong> experimental interface under development.
  */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumentable.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, 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.instrument;
+
+import com.oracle.truffle.api.*;
+
+public interface Instrumentable {
+
+    /**
+     * Optionally applies <em>instrumentation</em> at a Truffle AST node, depending on guest
+     * language characteristics and use-case policy. Ideally, the parent node of the guest language
+     * implements this interface.
+     * <ul>
+     * <li>if no instrumentation is to be applied, returns the AST node unmodified;</li>
+     * <li>if an AST node is to be instrumented, then creates a new Wrapper that <em>decorates</em>
+     * the AST node. Additionally, this creates a probe on the wrapper that is to be used for
+     * attaching instruments. This {@link Probe} is notified of all {@link ExecutionEvents} at the
+     * wrapped AST node.</li>
+     * </ul>
+     *
+     * @param context The {@link ExecutionContext} of the guest language used to create probes on
+     *            the wrapper.
+     * @return The probe that was created.
+     */
+    public Probe probe(ExecutionContext context);
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java	Mon Aug 25 21:15:59 2014 -0700
@@ -45,9 +45,6 @@
  * attached instruments seldom changes. The assumption is invalidated when instruments are added or
  * removed, but some instruments may change their internal state in such a way that the assumption
  * should also be invalidated.
- * <p>
- * <strong>Disclaimer:</strong> experimental interface under development. In particular, the
- * <em>notify</em> methods must be migrated to another interface.
  *
  * @see Instrument
  * @see Wrapper
@@ -55,24 +52,34 @@
 public interface Probe extends ExecutionEvents, SyntaxTagged {
 
     /**
-     * The source location with which this probe is (presumably uniquely) associated.
+     * Get the {@link SourceSection} in some Truffle AST associated with this probe.
+     *
+     * @return The source associated with this probe.
      */
     SourceSection getSourceLocation();
 
     /**
-     * Mark this probe as being associated with an AST node in some category useful for debugging
-     * and other tools.
+     * Mark this probe as belonging to some tool-related category that can be used to guide tool
+     * behavior at an associated AST node. For example, a debugger might add the tag
+     * {@link StandardSyntaxTag#STATEMENT} as a way of configuring where execution should stop when
+     * stepping.
      */
     void tagAs(SyntaxTag tag);
 
     /**
-     * Adds an instrument to this probe.
+     * Adds an {@link Instrument} to this probe's collection. No check is made to see if the same
+     * instrument has already been added.
+     *
+     * @param newInstrument The instrument to add to this probe.
      */
     void addInstrument(Instrument newInstrument);
 
     /**
-     * Removes an instrument from this probe.
+     * Removes the given instrument from the probe's collection.
+     *
+     * @param oldInstrument The instrument to remove from this probe.
+     * @throws RuntimeException if no matching instrument has been attached.
      */
-    void removeInstrument(Instrument oldInstrument);
+    void removeInstrument(Instrument oldInstrument) throws RuntimeException;
 
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeListener.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeListener.java	Mon Aug 25 21:15:59 2014 -0700
@@ -39,7 +39,7 @@
      * Notifies that a newly created (untagged) {@link Probe} has been inserted into a Truffle AST.
      * There will be no notification when an existing {@link Probe} is shared by an AST copy.
      */
-    void newProbeInserted(SourceSection location, Probe probe);
+    void newProbeInserted(SourceSection source, Probe probe);
 
     /**
      * Notifies that a (fully constructed) {@link Probe} has been tagged. A subsequent marking with
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SyntaxTagged.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SyntaxTagged.java	Mon Aug 25 21:15:59 2014 -0700
@@ -36,12 +36,13 @@
 public interface SyntaxTagged {
 
     /**
-     * Is this node tagged as belonging to a particular category of language constructs?
+     * Is this node tagged as belonging to a particular human-sensible category of language
+     * constructs?
      */
     boolean isTaggedAs(SyntaxTag tag);
 
     /**
-     * In which categories has this node been tagged (<em>empty set</em> if none).
+     * In which user-sensible categories has this node been tagged (<em>empty set</em> if none).
      */
     Iterable<SyntaxTag> getSyntaxTags();
 
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -34,9 +34,9 @@
 import com.oracle.truffle.api.source.*;
 
 /**
- * Abstract implementation of Truffle {@link Node} to be used for AST probes and instruments.
- * <p>
- * Coordinates propagation of Truffle AST {@link ExecutionEvents}.
+ * Abstract implementation of Truffle {@link Node}s used as AST {@link Probe}s and
+ * {@link Instrument}s. A {@link Probe} manages its attached {@link Instrument}s by appending them
+ * to a chain through which {@link ExecutionEvents} are propagated.
  */
 public abstract class InstrumentationNode extends Node implements ExecutionEvents {
 
@@ -44,18 +44,12 @@
         void newTagAdded(ProbeImpl probe, SyntaxTag tag);
     }
 
-    /**
-     * Creates a new {@link Probe}, presumed to be unique to a particular {@linkplain SourceSection}
-     * extent of guest language source code.
-     *
-     * @return a new probe
-     */
-    static ProbeImpl createProbe(SourceSection sourceSection, ProbeCallback probeCallback) {
-        return new ProbeImpl(sourceSection, probeCallback);
+    static ProbeImpl createProbe(SourceSection source, ProbeCallback probeCallback) {
+        return new ProbeImpl(source, probeCallback);
     }
 
     /**
-     * Next in chain.
+     * Next instrumentation node in chain.
      */
     @Child protected InstrumentationNode next;
 
@@ -71,7 +65,7 @@
     }
 
     /**
-     * Add a probe to the end of this probe chain.
+     * Add an instrument to the end of this instrument chain.
      */
     private void internalAddInstrument(Instrument newInstrument) {
         if (next == null) {
@@ -81,6 +75,12 @@
         }
     }
 
+    /**
+     * Remove an instrument from this instrument chain. If no matching instrument is found, a
+     * {@link RuntimeException} is thrown.
+     *
+     * @param oldInstrument The {@link Instrument} to remove.
+     */
     private void internalRemoveInstrument(Instrument oldInstrument) {
         if (next == null) {
             throw new RuntimeException("Couldn't find probe to remove: " + oldInstrument);
@@ -109,6 +109,14 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution is just about to enter an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalEnter(Node, VirtualFrame)} to inform all instruments in the chain.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of entry
+     */
     protected void internalEnter(Node astNode, VirtualFrame frame) {
         enter(astNode, frame);
         if (next != null) {
@@ -116,6 +124,15 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalEnter(Node, VirtualFrame)} to inform all instruments in the chain. In this
+     * case, there is no return value.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     */
     protected void internalLeave(Node astNode, VirtualFrame frame) {
         leave(astNode, frame);
         if (next != null) {
@@ -123,6 +140,16 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalLeave(Node, VirtualFrame, boolean)} to inform all instruments in the chain.
+     * In this case, a boolean value was returned.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     * @param result The boolean result
+     */
     protected void internalLeave(Node astNode, VirtualFrame frame, boolean result) {
         leave(astNode, frame, result);
         if (next != null) {
@@ -130,6 +157,16 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalLeave(Node, VirtualFrame, byte)} to inform all instruments in the chain. In
+     * this case, a byte value was returned.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     * @param result The byte result
+     */
     protected void internalLeave(Node astNode, VirtualFrame frame, byte result) {
         leave(astNode, frame, result);
         if (next != null) {
@@ -137,6 +174,16 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalLeave(Node, VirtualFrame, short)} to inform all instruments in the chain. In
+     * this case, a short value was returned.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     * @param result The short result
+     */
     protected void internalLeave(Node astNode, VirtualFrame frame, short result) {
         leave(astNode, frame, result);
         if (next != null) {
@@ -144,6 +191,16 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalLeave(Node, VirtualFrame, int)} to inform all instruments in the chain. In
+     * this case, a int value was returned.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     * @param result The int result
+     */
     protected void internalLeave(Node astNode, VirtualFrame frame, int result) {
         leave(astNode, frame, result);
         if (next != null) {
@@ -151,6 +208,16 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalLeave(Node, VirtualFrame, long)} to inform all instruments in the chain. In
+     * this case, a long value was returned.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     * @param result The long result
+     */
     protected void internalLeave(Node astNode, VirtualFrame frame, long result) {
         leave(astNode, frame, result);
         if (next != null) {
@@ -158,6 +225,16 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalLeave(Node, VirtualFrame, char)} to inform all instruments in the chain. In
+     * this case, a char value was returned.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     * @param result The char result
+     */
     protected void internalLeave(Node astNode, VirtualFrame frame, char result) {
         leave(astNode, frame, result);
         if (next != null) {
@@ -165,6 +242,16 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalLeave(Node, VirtualFrame, float)} to inform all instruments in the chain. In
+     * this case, a float value was returned.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     * @param result The float result
+     */
     protected void internalLeave(Node astNode, VirtualFrame frame, float result) {
         leave(astNode, frame, result);
         if (next != null) {
@@ -172,6 +259,16 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalLeave(Node, VirtualFrame, double)} to inform all instruments in the chain. In
+     * this case, a double value was returned.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     * @param result The double result
+     */
     protected void internalLeave(Node astNode, VirtualFrame frame, double result) {
         leave(astNode, frame, result);
         if (next != null) {
@@ -179,6 +276,16 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalLeave(Node, VirtualFrame, Object)} to inform all instruments in the chain. In
+     * this case, an Object was returned.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     * @param result The Object result
+     */
     protected void internalLeave(Node astNode, VirtualFrame frame, Object result) {
         leave(astNode, frame, result);
         if (next != null) {
@@ -186,6 +293,16 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalLeaveExceptional(Node, VirtualFrame, Exception)} to inform all instruments in
+     * the chain. In this case, a exception (sometimes containing a value) was thrown.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     * @param e The exception
+     */
     protected void internalLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
         leaveExceptional(astNode, frame, null);
         if (next != null) {
@@ -195,41 +312,66 @@
 
     /**
      * Holder of a chain of {@linkplain InstrumentationNode instruments}: manages the
-     * {@link Assumption} that none of the instruments have changed since last checked.
+     * {@link Assumption} that no {@link Instrument}s have been added or removed and that none of
+     * the attached instruments have changed state in a way that would require deopt.
      * <p>
      * An instance is intended to be shared by every clone of the AST node with which it is
      * originally attached, so it holds no parent pointer.
      * <p>
-     * May be categorized by one or more {@linkplain SyntaxTag tags}, signifying information useful
-     * for instrumentation about its AST location(s).
+     * Each probe is associated with a {@link SourceSection}, not necessarily uniquely, although
+     * such a policy could be enforced for some uses.
+     * <p>
+     * Each {@link Probe} be categorized by one or more {@linkplain SyntaxTag tags}, signifying
+     * information useful for instrumentation about its AST location(s).
      */
     static final class ProbeImpl extends InstrumentationNode implements Probe {
 
         private final ProbeCallback probeCallback;
 
-        /**
-         * Source information about the AST node (and its clones) to which this probe is attached.
-         */
-        private final SourceSection probedSourceSection;
-
         // TODO (mlvdv) assumption model broken
         @CompilerDirectives.CompilationFinal private Assumption probeUnchanged;
 
         @CompilerDirectives.CompilationFinal private SyntaxTagTrap trap = null;
 
+        /**
+         * The collection of tags for this instrumentation node
+         */
         private final ArrayList<SyntaxTag> tags = new ArrayList<>();
 
-        private ProbeImpl(SourceSection sourceSection, ProbeCallback probeCallback) {
+        /**
+         * The region of source code associated with this probe. Note that this is distinct from
+         * {@link Node#getSourceSection()}, which is {@code null} for all instances of
+         * {@link InstrumentationNode} since they have no corresponding source of their own.
+         */
+        private final SourceSection source;
+
+        /**
+         * Constructor.
+         *
+         * @param source The {@link SourceSection} associated with this probe.
+         * @param probeCallback The {@link ProbeCallback} to inform when tags have been added to
+         *            this probe.
+         */
+        private ProbeImpl(SourceSection source, ProbeCallback probeCallback) {
             this.probeCallback = probeCallback;
-            this.probedSourceSection = sourceSection;
+            this.source = source;
             this.probeUnchanged = Truffle.getRuntime().createAssumption();
             this.next = null;
         }
 
+        /**
+         * Returns the {@link SourceSection} associated with this probe.
+         */
         public SourceSection getSourceLocation() {
-            return probedSourceSection;
+            return source;
         }
 
+        /**
+         * Tags this probe with the given {@link SyntaxTag}. If the tag already exists, the tag is
+         * not added.
+         *
+         * @param tag The tag to add to this probe.
+         */
         @SlowPath
         public void tagAs(SyntaxTag tag) {
             assert tag != null;
@@ -239,15 +381,32 @@
             }
         }
 
+        /**
+         * Checks if this probe has been tagged with the given tag.
+         *
+         * @param tag The {@link SyntaxTag} to check for.
+         * @return True if this probe has the given tag, false otherwise.
+         */
         public boolean isTaggedAs(SyntaxTag tag) {
             assert tag != null;
             return tags.contains(tag);
         }
 
+        /**
+         * Returns an iterable collection of all syntax tags on this probe.
+         *
+         * @return A collection of {@link SyntaxTag}s.
+         */
         public Iterable<SyntaxTag> getSyntaxTags() {
             return tags;
         }
 
+        /**
+         * Adds the given {@link Instrument} to this probe's chain of instruments. This method does
+         * not check to see if the same instrument has already been added.
+         *
+         * @param instrument The instrument to add to this probe.
+         */
         @SlowPath
         public void addInstrument(Instrument instrument) {
             probeUnchanged.invalidate();
@@ -255,6 +414,12 @@
             probeUnchanged = Truffle.getRuntime().createAssumption();
         }
 
+        /**
+         * Removes the given instrument from the chain of instruments. If no matching instrument is
+         * found, a {@link RuntimeException} is thrown.
+         *
+         * @param instrument The instrument to remove from this probe.
+         */
         @SlowPath
         public void removeInstrument(Instrument instrument) {
             probeUnchanged.invalidate();
@@ -262,6 +427,9 @@
             probeUnchanged = Truffle.getRuntime().createAssumption();
         }
 
+        /**
+         * Returns this probe.
+         */
         @Override
         protected Probe getProbe() {
             return this;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineLocationToProbeCollectionMap.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2014, 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.instrument.impl;
+
+import java.util.*;
+
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * A mapping from {@link LineLocation} (a line number in a specific piece of {@link Source} code) to
+ * a collection of {@link Probe}s whose associated {@link SourceSection} starts on that line.
+ */
+public class LineLocationToProbeCollectionMap implements ProbeListener {
+
+    /**
+     * Map: Source line ==> probes associated with source sections starting on the line.
+     */
+    private final Map<LineLocation, Collection<Probe>> lineToProbesMap = new HashMap<>();
+
+    public LineLocationToProbeCollectionMap() {
+    }
+
+    public void newProbeInserted(SourceSection source, Probe probe) {
+        if (source != null && !(source instanceof NullSourceSection))
+            this.addProbeToLine(source.getLineLocation(), probe);
+    }
+
+    public void probeTaggedAs(Probe probe, SyntaxTag tag) {
+        // This map ignores tags
+    }
+
+    /**
+     * Returns the {@link Probe}, if any, associated with source that starts on a specified line; if
+     * there are more than one, return the one with the first starting character location.
+     */
+    public Probe findLineProbe(LineLocation lineLocation) {
+        Probe probe = null;
+        final Collection<Probe> probes = getProbesAtLine(lineLocation);
+        for (Probe probeOnLine : probes) {
+            if (probe == null) {
+                probe = probeOnLine;
+            } else if (probeOnLine.getSourceLocation().getCharIndex() < probe.getSourceLocation().getCharIndex()) {
+                probe = probeOnLine;
+            }
+        }
+        return probe;
+    }
+
+    /**
+     * Records creation of a probe whose associated source starts on the given line.
+     * <p>
+     * If the line already exists in the internal {@link #lineToProbesMap}, this probe will be added
+     * to the existing collection. If no line already exists in the internal map, then a new key is
+     * added along with a new collection containing the probe.
+     * <p>
+     * This class requires that each added line/probe pair hasn't been previously added. However,
+     * attaching the same probe to a new line location is allowed.
+     *
+     * @param line The {@link LineLocation} to attach the probe to.
+     * @param probe The {@link Probe} to attach for that line location.
+     */
+    protected void addProbeToLine(LineLocation line, Probe probe) {
+
+        if (!lineToProbesMap.containsKey(line)) {
+            // Key does not exist, add new probe list
+            final ArrayList<Probe> newProbeList = new ArrayList<>(2);
+            newProbeList.add(probe);
+            lineToProbesMap.put(line, newProbeList);
+        } else {
+            // Probe list exists, add to existing
+            final Collection<Probe> existingProbeList = lineToProbesMap.get(line);
+            assert !existingProbeList.contains(probe);
+            existingProbeList.add(probe);
+        }
+    }
+
+    /**
+     * 
+     * Returns a collection of {@link Probe}s whose associated source begins at the given
+     * {@link LineLocation}. If there are no probes at that line, an empty list is returned.
+     *
+     * @param line The line to check.
+     * @return A collection of probes at the given line.
+     */
+    public Collection<Probe> getProbesAtLine(LineLocation line) {
+        Collection<Probe> probeList = lineToProbesMap.get(line);
+
+        if (probeList == null)
+            probeList = new ArrayList<>(1);
+
+        return probeList;
+    }
+
+    /**
+     * Convenience method to get probes according to a int line number. Returns a collection of
+     * {@link Probe}s at the given line number. If there are no probes at that line, a new empty
+     * list is returned.
+     *
+     * @param lineNumber The line number to check.
+     * @return A iterable collection of probes at the given line.
+     */
+    public Collection<Probe> getProbesAtLineNumber(int lineNumber) {
+        ArrayList<Probe> probes = new ArrayList<>();
+
+        for (LineLocation line : lineToProbesMap.keySet()) {
+            if (line.getLineNumber() == lineNumber)
+                probes.addAll(lineToProbesMap.get(line));
+        }
+
+        return probes;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineLocationToSourceSectionCollectionMap.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2014, 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.instrument.impl;
+
+import java.util.*;
+
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * A mapping from {@link LineLocation} (a line number in a specific piece of {@link Source} code) to
+ * a collection of {@link SourceSection}s that exist on that line. This class assumes that all nodes
+ * are instrumented as it uses the {@link ProbeListener} interface to determine the source sections
+ * that exist in the file.
+ */
+public class LineLocationToSourceSectionCollectionMap implements ProbeListener {
+
+    /**
+     * Map: Source line ==> source sections that exist on the line.
+     */
+    private final Map<LineLocation, Collection<SourceSection>> lineToSourceSectionsMap = new HashMap<>();
+
+    public LineLocationToSourceSectionCollectionMap() {
+
+    }
+
+    public void newProbeInserted(SourceSection sourceSection, Probe probe) {
+        if (sourceSection != null && !(sourceSection instanceof NullSourceSection)) {
+            this.addSourceSectionToLine(sourceSection.getLineLocation(), sourceSection);
+        }
+    }
+
+    public void probeTaggedAs(Probe probe, SyntaxTag tag) {
+        // This map ignores tags, but this subclasses can override this method to operate on tags.
+    }
+
+    /**
+     * Adds a source section to the given line.
+     * <p>
+     * If the line already exists in the internal {@link #lineToSourceSectionsMap}, this source
+     * section will be added to the existing collection. If no line already exists in the internal
+     * map, then a new key is added along with a new collection containing the source section.
+     * <p>
+     * This class does not check if a source section has already been added to a line.
+     *
+     * @param line The {@link LineLocation} to attach the source section to.
+     * @param sourceSection The {@link SourceSection} to attach for that line location.
+     */
+    protected void addSourceSectionToLine(LineLocation line, SourceSection sourceSection) {
+        if (!lineToSourceSectionsMap.containsKey(line)) {
+            // Key does not exist, add new source section list
+            final ArrayList<SourceSection> newSourceSectionList = new ArrayList<>(2);
+            newSourceSectionList.add(sourceSection);
+            lineToSourceSectionsMap.put(line, newSourceSectionList);
+        } else {
+            // Source section list exists, add to existing
+            final Collection<SourceSection> existingSourceSectionList = lineToSourceSectionsMap.get(line);
+            existingSourceSectionList.add(sourceSection);
+        }
+    }
+
+    /**
+     * Returns a collection of {@link SourceSection}s at the given {@link LineLocation}. If there
+     * are no source sections at that line, a new empty list of size 1 is returned.
+     *
+     * @param line The line to check.
+     * @return A iterable collection of source sections at the given line.
+     */
+    public Collection<SourceSection> getSourceSectionsAtLine(LineLocation line) {
+        Collection<SourceSection> sourceSectionList = lineToSourceSectionsMap.get(line);
+
+        if (sourceSectionList == null)
+            sourceSectionList = new ArrayList<>(1);
+
+        return sourceSectionList;
+    }
+
+    /**
+     * Convenience method to get source sections according to a int line number. Returns a
+     * collection of {@link SourceSection}s at the given line number. If there are no source
+     * sections at that line, a new empty list is returned.
+     *
+     * @param lineNumber The line number to check.
+     * @return A iterable collection of source sections at the given line.
+     */
+    public Collection<SourceSection> getSourceSectionsAtLineNumber(int lineNumber) {
+        ArrayList<SourceSection> sourceSections = new ArrayList<>();
+
+        for (LineLocation line : lineToSourceSectionsMap.keySet()) {
+            if (line.getLineNumber() == lineNumber)
+                sourceSections.addAll(lineToSourceSectionsMap.get(line));
+        }
+
+        return sourceSections;
+    }
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/ProbeManager.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/ProbeManager.java	Mon Aug 25 21:15:59 2014 -0700
@@ -36,20 +36,13 @@
  */
 public final class ProbeManager {
 
-    // TODO (mlvdv) use weak references.
-    /**
-     * Map: SourceSection ==> probe associated with that source section in an AST.
-     */
-    private final Map<SourceSection, ProbeImpl> srcToProbe = new HashMap<>();
-
-    // TODO (mlvdv) use weak references.
-    /**
-     * Map: Source line ==> probes associated with source sections starting on the line.
-     */
-    private final Map<LineLocation, Collection<Probe>> lineToProbes = new HashMap<>();
-
     private final List<ProbeListener> probeListeners = new ArrayList<>();
 
+    private final List<ProbeImpl> allProbes = new ArrayList<>();
+
+    /**
+     * Called when a {@link #tagTrap} is activated in a Probe.
+     */
     private final ProbeCallback probeCallback;
 
     /**
@@ -74,11 +67,17 @@
         };
     }
 
+    /**
+     * Adds a {@link ProbeListener} to receive events.
+     */
     public void addProbeListener(ProbeListener listener) {
         assert listener != null;
         probeListeners.add(listener);
     }
 
+    /**
+     * Removes a {@link ProbeListener}. Ignored if listener not found.
+     */
     public void removeProbeListener(ProbeListener removeListener) {
         final List<ProbeListener> listeners = new ArrayList<>(probeListeners);
         for (ProbeListener listener : listeners) {
@@ -88,45 +87,32 @@
         }
     }
 
-    public Probe getProbe(SourceSection sourceSection) {
-        assert sourceSection != null;
-
-        ProbeImpl probe = srcToProbe.get(sourceSection);
-
-        if (probe != null) {
-            return probe;
-        }
-        probe = InstrumentationNode.createProbe(sourceSection, probeCallback);
+    /**
+     * Creates a new {@link Probe} associated with a {@link SourceSection} of code corresponding to
+     * a Truffle AST node.
+     */
+    public Probe createProbe(SourceSection source) {
+        assert source != null;
 
-        // Register new probe by unique SourceSection
-        srcToProbe.put(sourceSection, probe);
-
-        // Register new probe by source line, there may be more than one
-        // Create line location for map key
-        final LineLocation lineLocation = sourceSection.getLineLocation();
-
-        Collection<Probe> probes = lineToProbes.get(lineLocation);
-        if (probes == null) {
-            probes = new ArrayList<>(2);
-            lineToProbes.put(lineLocation, probes);
-        }
-        probes.add(probe);
+        ProbeImpl probe = InstrumentationNode.createProbe(source, probeCallback);
+        allProbes.add(probe);
 
         for (ProbeListener listener : probeListeners) {
-            listener.newProbeInserted(sourceSection, probe);
+            listener.newProbeInserted(source, probe);
         }
 
         return probe;
     }
 
-    public boolean hasProbe(SourceSection sourceSection) {
-        assert sourceSection != null;
-        return srcToProbe.get(sourceSection) != null;
-    }
-
+    /**
+     * Returns the subset of all {@link Probe}s holding a particular {@link SyntaxTag}, or the whole
+     * collection if the specified tag is {@code null}.
+     *
+     * @return A collection of probes containing the given tag.
+     */
     public Collection<Probe> findProbesTaggedAs(SyntaxTag tag) {
         final List<Probe> probes = new ArrayList<>();
-        for (Probe probe : srcToProbe.values()) {
+        for (Probe probe : allProbes) {
             if (tag == null || probe.isTaggedAs(tag)) {
                 probes.add(probe);
             }
@@ -134,15 +120,16 @@
         return probes;
     }
 
-    public Collection<Probe> findProbesByLine(LineLocation lineLocation) {
-        final Collection<Probe> probes = lineToProbes.get(lineLocation);
-        if (probes == null) {
-            return Collections.emptyList();
-        }
-        return new ArrayList<>(probes);
-    }
-
-    public void setTagTrap(SyntaxTagTrap tagTrap) {
+    /**
+     * Sets the current "tag trap", which will cause a callback to be triggered whenever execution
+     * reaches a Probe (existing or subsequently created) with the specified tag. There can only be
+     * one tag trap set at a time.
+     * <p>
+     *
+     * @param tagTrap The {@link SyntaxTagTrap} to set.
+     * @throws IllegalStateException if a trap is currently set.
+     */
+    public void setTagTrap(SyntaxTagTrap tagTrap) throws IllegalStateException {
         assert tagTrap != null;
         if (this.tagTrap != null) {
             throw new IllegalStateException("trap already set");
@@ -150,18 +137,23 @@
         this.tagTrap = tagTrap;
 
         SyntaxTag tag = tagTrap.getTag();
-        for (ProbeImpl probe : srcToProbe.values()) {
+        for (ProbeImpl probe : allProbes) {
             if (probe.isTaggedAs(tag)) {
                 probe.setTrap(tagTrap);
             }
         }
     }
 
+    /**
+     * Clears the current {@link SyntaxTagTrap}.
+     *
+     * @throws IllegalStateException if no trap is currently set.
+     */
     public void clearTagTrap() {
         if (this.tagTrap == null) {
             throw new IllegalStateException("no trap set");
         }
-        for (ProbeImpl probe : srcToProbe.values()) {
+        for (ProbeImpl probe : allProbes) {
             if (probe.isTaggedAs(tagTrap.getTag())) {
                 probe.setTrap(null);
             }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/LoopNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2014, 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.nodes;
+
+import com.oracle.truffle.api.frame.*;
+
+/**
+ * Experimental API: may change significantly without notice.
+ */
+public abstract class LoopNode extends Node {
+
+    /*
+     * TODO Unfortunately we cannot yet use interface typed fields as child fields.
+     */
+    @Child protected Node repeatingNode;
+
+    public LoopNode(RepeatingNode repeatintNode) {
+        this.repeatingNode = (Node) repeatintNode;
+    }
+
+    public abstract void executeLoop(VirtualFrame frame);
+
+    protected final boolean executeRepeatNode(VirtualFrame frame) {
+        return getRepeatNode().executeRepeating(frame);
+    }
+
+    public final RepeatingNode getRepeatNode() {
+        return (RepeatingNode) repeatingNode;
+    }
+
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Mon Aug 25 21:15:59 2014 -0700
@@ -299,12 +299,17 @@
     }
 
     private void reportReplace(Node oldNode, Node newNode, CharSequence reason) {
-        RootNode rootNode = getRootNode();
-        if (rootNode != null) {
-            CallTarget target = rootNode.getCallTarget();
-            if (target instanceof ReplaceObserver) {
-                ((ReplaceObserver) target).nodeReplaced(oldNode, newNode, reason);
+        Node node = this;
+        while (node != null) {
+            if (node instanceof ReplaceObserver) {
+                ((ReplaceObserver) node).nodeReplaced(oldNode, newNode, reason);
+            } else if (node instanceof RootNode) {
+                CallTarget target = ((RootNode) node).getCallTarget();
+                if (target instanceof ReplaceObserver) {
+                    ((ReplaceObserver) target).nodeReplaced(oldNode, newNode, reason);
+                }
             }
+            node = node.getParent();
         }
         if (TruffleOptions.TraceRewrites) {
             NodeUtil.traceRewrite(this, newNode, reason);
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Mon Aug 25 21:15:59 2014 -0700
@@ -27,6 +27,7 @@
 import java.io.*;
 import java.lang.annotation.*;
 import java.lang.reflect.*;
+import java.security.*;
 import java.util.*;
 
 import sun.misc.*;
@@ -160,9 +161,13 @@
         private static final ClassValue<NodeClass> nodeClasses = new ClassValue<NodeClass>() {
             @SuppressWarnings("unchecked")
             @Override
-            protected NodeClass computeValue(Class<?> clazz) {
+            protected NodeClass computeValue(final Class<?> clazz) {
                 assert Node.class.isAssignableFrom(clazz);
-                return new NodeClass((Class<? extends Node>) clazz, unsafeFieldOffsetProvider);
+                return AccessController.doPrivileged(new PrivilegedAction<NodeClass>() {
+                    public NodeClass run() {
+                        return new NodeClass((Class<? extends Node>) clazz, unsafeFieldOffsetProvider);
+                    }
+                });
             }
         };
 
@@ -840,9 +845,10 @@
         if (section != null) {
             final String srcText = section.getCode();
             final StringBuilder sb = new StringBuilder();
-            sb.append("source:  len=" + srcText.length());
+            sb.append("source:");
             sb.append(" (" + section.getCharIndex() + "," + (section.getCharEndIndex() - 1) + ")");
-            sb.append(" ___" + srcText + "___");
+            sb.append(" len=" + srcText.length());
+            sb.append(" text=\"" + srcText + "\"");
             return sb.toString();
         }
         return "";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RepeatingNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,36 @@
+/*
+ * 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.  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.nodes;
+
+import com.oracle.truffle.api.frame.*;
+
+/**
+ * Experimental API: may change significantly without notice.
+ */
+public interface RepeatingNode {
+
+    boolean executeRepeating(VirtualFrame frame);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BinaryConditionProfile.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014, 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.utilities;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.*;
+
+/**
+ * Utility class to speculate on conditions to be never true or to be never false. Condition
+ * profiles are intended to be used as part of if conditions.
+ *
+ * @see ConditionProfile#createBinaryProfile()
+ */
+public final class BinaryConditionProfile extends ConditionProfile {
+
+    @CompilationFinal private boolean wasTrue;
+    @CompilationFinal private boolean wasFalse;
+
+    BinaryConditionProfile() {
+        /* package protected constructor */
+    }
+
+    @Override
+    public boolean profile(boolean value) {
+        if (value) {
+            if (!wasTrue) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                wasTrue = true;
+            }
+        } else {
+            if (!wasFalse) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                wasFalse = true;
+            }
+        }
+        return value;
+    }
+
+    public boolean wasTrue() {
+        return wasTrue;
+    }
+
+    public boolean wasFalse() {
+        return wasFalse;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s(wasTrue=%s, wasFalse=%s)@%x", getClass().getSimpleName(), wasTrue, wasFalse, hashCode());
+    }
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BranchProfile.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BranchProfile.java	Mon Aug 25 21:15:59 2014 -0700
@@ -32,6 +32,9 @@
  * invoked first the optimized code is invalidated and the branch where {@link #enter()} is invoked
  * is enabled for compilation. Otherwise if the {@link #enter()} method was never invoked the branch
  * will not get compiled.
+ *
+ * All {@code BranchProfile} instances must be held in {@code final} fields for compiler
+ * optimizations to take effect.
  */
 public final class BranchProfile {
 
@@ -44,6 +47,10 @@
         }
     }
 
+    public boolean isVisited() {
+        return visited;
+    }
+
     @Override
     public String toString() {
         return String.format("%s(%s)@%x", getClass().getSimpleName(), visited ? "visited" : "not-visited", hashCode());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ConditionProfile.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014, 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.utilities;
+
+import com.oracle.truffle.api.*;
+
+/**
+ * Abstract utility class to speculate on conditions. Condition profiles are intended to be used as
+ * part of if conditions.
+ *
+ * Example usage:
+ *
+ * <pre>
+ * private final ConditionProfile zero = ConditionProfile.createBinaryProfile();
+ * 
+ * int value = ...;
+ * if (zero.profile(value == 0)) {
+ *   return 0;
+ * } else {
+ *   return value;
+ * }
+ *
+ * </pre>
+ *
+ * All instances of {@code ConditionProfile} (and subclasses) must be held in {@code final} fields
+ * for compiler optimizations to take effect.
+ *
+ * @see #createCountingProfile()
+ * @see #createBinaryProfile()
+ */
+public abstract class ConditionProfile {
+
+    public abstract boolean profile(boolean value);
+
+    /**
+     * Returns a {@link ConditionProfile} that speculates on conditions to be never
+     * <code>true</code> or to be never <code>false</code>. Additionally to a binary profile this
+     * method returns a condition profile that also counts the number of times the condition was
+     * true and false. This information is reported to the underlying optimization system using
+     * {@link CompilerDirectives#injectBranchProbability(double, boolean)}. Condition profiles are
+     * intended to be used as part of if conditions.
+     *
+     * @see ConditionProfile
+     * @see #createBinaryProfile()
+     */
+    public static ConditionProfile createCountingProfile() {
+        return new CountingConditionProfile();
+    }
+
+    /**
+     * Returns a {@link ConditionProfile} that speculates on conditions to be never true or to be
+     * never false. Condition profiles are intended to be used as part of if conditions.
+     *
+     * @see ConditionProfile
+     * @see ConditionProfile#createCountingProfile()
+     */
+    public static ConditionProfile createBinaryProfile() {
+        return new BinaryConditionProfile();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/CountingConditionProfile.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014, 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.utilities;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.*;
+
+/**
+ * Utility class to speculate on conditions to be never true or to be never false. Additionally to
+ * {@link BinaryConditionProfile} this implementation of {@link ConditionProfile} also counts the
+ * number of times the condition was true and false. This information is reported to the underlying
+ * optimization system using {@link CompilerDirectives#injectBranchProbability(double, boolean)}.
+ * Condition profiles are intended to be used as part of if conditions.
+ *
+ * @see ConditionProfile#createCountingProfile()
+ */
+public final class CountingConditionProfile extends ConditionProfile {
+
+    @CompilationFinal private int trueCount;
+    @CompilationFinal private int falseCount;
+
+    CountingConditionProfile() {
+        /* package protected constructor */
+    }
+
+    @Override
+    public boolean profile(boolean value) {
+        if (value) {
+            if (trueCount == 0) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+            }
+            if (CompilerDirectives.inInterpreter()) {
+                trueCount++;
+            }
+        } else {
+            if (falseCount == 0) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+            }
+            if (CompilerDirectives.inInterpreter()) {
+                falseCount++;
+            }
+        }
+        return CompilerDirectives.injectBranchProbability((double) trueCount / (double) (trueCount + falseCount), value);
+    }
+
+    public int getTrueCount() {
+        return trueCount;
+    }
+
+    public int getFalseCount() {
+        return falseCount;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s(trueCount=%s, falseCount=%s)@%x", getClass().getSimpleName(), trueCount, falseCount, hashCode());
+    }
+}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractParser.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-import javax.tools.Diagnostic.Kind;
-
-import com.oracle.truffle.dsl.processor.template.*;
-
-/**
- * THIS IS NOT PUBLIC API.
- */
-public abstract class AbstractParser<M extends Template> {
-
-    protected final ProcessorContext context;
-    protected final ProcessingEnvironment processingEnv;
-    protected RoundEnvironment roundEnv;
-
-    protected final Log log;
-
-    public AbstractParser(ProcessorContext c) {
-        this.context = c;
-        this.processingEnv = c.getEnvironment();
-        this.log = c.getLog();
-    }
-
-    public final M parse(RoundEnvironment env, Element element) {
-        this.roundEnv = env;
-        M model = null;
-        try {
-            AnnotationMirror mirror = null;
-            if (getAnnotationType() != null) {
-                mirror = Utils.findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), getAnnotationType());
-            }
-
-            if (!context.getTruffleTypes().verify(context, element, mirror)) {
-                return null;
-            }
-            model = parse(element, mirror);
-            if (model == null) {
-                return null;
-            }
-
-            model.emitMessages(context, (TypeElement) element, log);
-            return filterErrorElements(model);
-        } catch (CompileErrorException e) {
-            log.message(Kind.WARNING, element, null, null, "The truffle processor could not parse class due to error: %s", e.getMessage());
-            return null;
-        } finally {
-            this.roundEnv = null;
-        }
-    }
-
-    protected M filterErrorElements(M model) {
-        return model.hasErrors() ? null : model;
-    }
-
-    protected abstract M parse(Element element, AnnotationMirror mirror);
-
-    public abstract Class<? extends Annotation> getAnnotationType();
-
-    public boolean isDelegateToRootDeclaredType() {
-        return false;
-    }
-
-    public List<Class<? extends Annotation>> getAllAnnotationTypes() {
-        List<Class<? extends Annotation>> list = new ArrayList<>();
-        if (getAnnotationType() != null) {
-            list.add(getAnnotationType());
-        }
-        list.addAll(getTypeDelegatedAnnotationTypes());
-        return list;
-    }
-
-    public List<Class<? extends Annotation>> getTypeDelegatedAnnotationTypes() {
-        return Collections.emptyList();
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AnnotationProcessor.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AnnotationProcessor.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,18 +22,17 @@
  */
 package com.oracle.truffle.dsl.processor;
 
-import java.io.*;
 import java.util.*;
 
-import javax.annotation.processing.*;
 import javax.lang.model.element.*;
 import javax.lang.model.type.*;
-import javax.tools.*;
 
-import com.oracle.truffle.dsl.processor.ast.*;
-import com.oracle.truffle.dsl.processor.codewriter.*;
-import com.oracle.truffle.dsl.processor.compiler.*;
-import com.oracle.truffle.dsl.processor.template.*;
+import com.oracle.truffle.dsl.processor.generator.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.java.transform.*;
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.parser.*;
 
 /**
  * THIS IS NOT PUBLIC API.
@@ -41,13 +40,11 @@
 class AnnotationProcessor<M extends Template> {
 
     private final AbstractParser<M> parser;
-    private final CompilationUnitFactory<M> factory;
-    private final ProcessorContext context;
+    private final AbstractCompilationUnitFactory<M> factory;
 
     private final Set<String> processedElements = new HashSet<>();
 
-    public AnnotationProcessor(ProcessorContext context, AbstractParser<M> parser, CompilationUnitFactory<M> factory) {
-        this.context = context;
+    public AnnotationProcessor(AbstractParser<M> parser, AbstractCompilationUnitFactory<M> factory) {
         this.parser = parser;
         this.factory = factory;
     }
@@ -56,23 +53,19 @@
         return parser;
     }
 
-    public ProcessorContext getContext() {
-        return context;
-    }
-
     @SuppressWarnings({"unchecked"})
-    public void process(RoundEnvironment env, Element element, boolean callback) {
-
+    public void process(Element element, boolean callback) {
         // since it is not guaranteed to be called only once by the compiler
         // we check for already processed elements to avoid errors when writing files.
         if (!callback && element instanceof TypeElement) {
-            String qualifiedName = Utils.getQualifiedName((TypeElement) element);
+            String qualifiedName = ElementUtils.getQualifiedName((TypeElement) element);
             if (processedElements.contains(qualifiedName)) {
                 return;
             }
             processedElements.add(qualifiedName);
         }
 
+        ProcessorContext context = ProcessorContext.getInstance();
         TypeElement type = (TypeElement) element;
 
         M model = (M) context.getTemplate(type.asType(), false);
@@ -80,7 +73,7 @@
 
         if (firstRun || !callback) {
             context.registerTemplate(type, null);
-            model = parser.parse(env, element);
+            model = parser.parse(element);
             context.registerTemplate(type, model);
 
             if (model != null) {
@@ -91,7 +84,7 @@
                 DeclaredType overrideType = (DeclaredType) context.getType(Override.class);
                 DeclaredType unusedType = (DeclaredType) context.getType(SuppressWarnings.class);
                 unit.accept(new GenerateOverrideVisitor(overrideType), null);
-                unit.accept(new FixWarningsVisitor(context, unusedType, overrideType), null);
+                unit.accept(new FixWarningsVisitor(context.getEnvironment(), unusedType, overrideType), null);
 
                 if (!callback) {
                     unit.accept(new CodeWriter(context.getEnvironment(), element), null);
@@ -100,33 +93,4 @@
         }
     }
 
-    private static class CodeWriter extends AbstractCodeWriter {
-
-        private final Element originalElement;
-        private final ProcessingEnvironment env;
-
-        public CodeWriter(ProcessingEnvironment env, Element originalElement) {
-            this.env = env;
-            this.originalElement = originalElement;
-        }
-
-        @Override
-        protected Writer createWriter(CodeTypeElement clazz) throws IOException {
-            JavaFileObject jfo = env.getFiler().createSourceFile(clazz.getQualifiedName(), originalElement);
-            return new BufferedWriter(jfo.openWriter());
-        }
-
-        @Override
-        protected void writeHeader() {
-            if (env == null) {
-                return;
-            }
-            String comment = CompilerFactory.getCompiler(originalElement).getHeaderComment(env, originalElement);
-            if (comment != null) {
-                writeLn(comment);
-            }
-        }
-
-    }
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/CodeWriter.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor;
+
+import java.io.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.tools.*;
+
+import com.oracle.truffle.dsl.processor.java.compiler.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.java.transform.*;
+
+public final class CodeWriter extends AbstractCodeWriter {
+
+    private final Element originalElement;
+    private final ProcessingEnvironment env;
+
+    public CodeWriter(ProcessingEnvironment env, Element originalElement) {
+        this.env = env;
+        this.originalElement = originalElement;
+    }
+
+    @Override
+    protected Writer createWriter(CodeTypeElement clazz) throws IOException {
+        JavaFileObject jfo = env.getFiler().createSourceFile(clazz.getQualifiedName(), originalElement);
+        return new BufferedWriter(jfo.openWriter());
+    }
+
+    @Override
+    protected void writeHeader() {
+        if (env == null) {
+            return;
+        }
+        String comment = CompilerFactory.getCompiler(originalElement).getHeaderComment(env, originalElement);
+        if (comment != null) {
+            writeLn(comment);
+        }
+    }
+
+}
\ No newline at end of file
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Log.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Log.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,7 +26,7 @@
 import javax.lang.model.element.*;
 import javax.tools.Diagnostic.Kind;
 
-import com.oracle.truffle.dsl.processor.ast.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
 
 /**
  * THIS IS NOT PUBLIC API.
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,8 +22,6 @@
  */
 package com.oracle.truffle.dsl.processor;
 
-import static com.oracle.truffle.dsl.processor.Utils.*;
-
 import java.util.*;
 
 import javax.annotation.processing.*;
@@ -31,9 +29,9 @@
 import javax.lang.model.type.*;
 import javax.lang.model.util.*;
 
-import com.oracle.truffle.dsl.processor.ast.*;
-import com.oracle.truffle.dsl.processor.ast.CodeTypeMirror.ArrayCodeTypeMirror;
-import com.oracle.truffle.dsl.processor.template.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.model.*;
 
 /**
  * THIS IS NOT PUBLIC API.
@@ -43,13 +41,12 @@
     private final ProcessingEnvironment environment;
 
     private final Map<String, Template> models = new HashMap<>();
-    private final Map<String, Map<String, TypeMirror>> generatedClasses = new HashMap<>();
 
     private final ProcessCallback callback;
     private final Log log;
     private final TruffleTypes truffleTypes;
 
-    public ProcessorContext(ProcessingEnvironment env, ProcessCallback callback) {
+    ProcessorContext(ProcessingEnvironment env, ProcessCallback callback) {
         this.environment = env;
         this.callback = callback;
         this.log = new Log(environment);
@@ -69,116 +66,25 @@
     }
 
     public boolean containsTemplate(TypeElement element) {
-        return models.containsKey(Utils.getQualifiedName(element));
+        return models.containsKey(ElementUtils.getQualifiedName(element));
     }
 
     public void registerTemplate(TypeElement element, Template model) {
-        models.put(Utils.getQualifiedName(element), model);
-    }
-
-    public void registerType(TypeElement templateType, TypeMirror generatedTypeMirror) {
-        String templateQualifiedName = getQualifiedName(templateType);
-        Map<String, TypeMirror> simpleNameToType = generatedClasses.get(templateQualifiedName);
-        if (simpleNameToType == null) {
-            simpleNameToType = new HashMap<>();
-            generatedClasses.put(templateQualifiedName, simpleNameToType);
-        }
-        String generatedSimpleName = getSimpleName(generatedTypeMirror);
-        simpleNameToType.put(generatedSimpleName, generatedTypeMirror);
+        models.put(ElementUtils.getQualifiedName(element), model);
     }
 
     public Template getTemplate(TypeMirror templateTypeMirror, boolean invokeCallback) {
-        String qualifiedName = Utils.getQualifiedName(templateTypeMirror);
+        String qualifiedName = ElementUtils.getQualifiedName(templateTypeMirror);
         Template model = models.get(qualifiedName);
         if (model == null && invokeCallback) {
-            callback.callback(Utils.fromTypeMirror(templateTypeMirror));
+            callback.callback(ElementUtils.fromTypeMirror(templateTypeMirror));
             model = models.get(qualifiedName);
         }
         return model;
     }
 
-    public TypeMirror resolveNotYetCompiledType(TypeMirror mirror, Template templateHint) {
-        TypeMirror resolvedType = null;
-        if (mirror.getKind() == TypeKind.ARRAY) {
-            TypeMirror originalComponentType = ((ArrayType) mirror).getComponentType();
-            TypeMirror resolvedComponent = resolveNotYetCompiledType(originalComponentType, templateHint);
-            if (resolvedComponent != originalComponentType) {
-                return new ArrayCodeTypeMirror(resolvedComponent);
-            }
-        }
-
-        if (mirror.getKind() == TypeKind.ERROR) {
-            Element element = ((ErrorType) mirror).asElement();
-            ElementKind kind = element.getKind();
-            if (kind == ElementKind.CLASS || kind == ElementKind.PARAMETER || kind == ElementKind.ENUM) {
-                String simpleName = element.getSimpleName().toString();
-                resolvedType = findGeneratedClassBySimpleName(simpleName, templateHint);
-            }
-        } else {
-            resolvedType = mirror;
-        }
-
-        return resolvedType;
-    }
-
-    public TypeMirror findGeneratedClassBySimpleName(String simpleName, Template templateHint) {
-        if (templateHint == null) {
-            // search all
-            for (String qualifiedTemplateName : generatedClasses.keySet()) {
-                Map<String, TypeMirror> mirrors = generatedClasses.get(qualifiedTemplateName);
-                if (mirrors.get(simpleName) != null) {
-                    return mirrors.get(simpleName);
-                }
-            }
-            return null;
-        } else {
-            String templateQualifiedName = getQualifiedName(templateHint.getTemplateType());
-            Map<String, TypeMirror> simpleNameToType = generatedClasses.get(templateQualifiedName);
-            if (simpleNameToType == null) {
-                return null;
-            }
-            return simpleNameToType.get(simpleName);
-        }
-    }
-
-    public TypeMirror getType(String className) {
-        TypeElement element = environment.getElementUtils().getTypeElement(className);
-        if (element != null) {
-            return element.asType();
-        }
-        return null;
-    }
-
     public TypeMirror getType(Class<?> element) {
-        TypeMirror mirror;
-        if (element.isPrimitive()) {
-            if (element == boolean.class) {
-                mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.BOOLEAN);
-            } else if (element == byte.class) {
-                mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.BYTE);
-            } else if (element == short.class) {
-                mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.SHORT);
-            } else if (element == char.class) {
-                mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.CHAR);
-            } else if (element == int.class) {
-                mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.INT);
-            } else if (element == long.class) {
-                mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.LONG);
-            } else if (element == float.class) {
-                mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.FLOAT);
-            } else if (element == double.class) {
-                mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.DOUBLE);
-            } else if (element == void.class) {
-                mirror = environment.getTypeUtils().getNoType(TypeKind.VOID);
-            } else {
-                assert false;
-                return null;
-            }
-        } else {
-            TypeElement typeElement = environment.getElementUtils().getTypeElement(element.getCanonicalName());
-            mirror = typeElement.asType();
-        }
-        return mirror;
+        return ElementUtils.getType(environment, element);
     }
 
     public interface ProcessCallback {
@@ -191,6 +97,14 @@
         return getType(type.getQualifiedName().toString());
     }
 
+    private TypeMirror getType(String className) {
+        TypeElement element = environment.getElementUtils().getTypeElement(className);
+        if (element != null) {
+            return element.asType();
+        }
+        return null;
+    }
+
     public TypeMirror reloadType(TypeMirror type) {
         if (type instanceof CodeTypeMirror) {
             return type;
@@ -209,4 +123,14 @@
         }
         return type;
     }
+
+    private static final ThreadLocal<ProcessorContext> instance = new ThreadLocal<>();
+
+    public static void setThreadLocalInstance(ProcessorContext context) {
+        instance.set(context);
+    }
+
+    public static ProcessorContext getInstance() {
+        return instance.get();
+    }
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleProcessor.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleProcessor.java	Mon Aug 25 21:15:59 2014 -0700
@@ -31,8 +31,9 @@
 import javax.tools.Diagnostic.Kind;
 
 import com.oracle.truffle.dsl.processor.ProcessorContext.ProcessCallback;
-import com.oracle.truffle.dsl.processor.node.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
+import com.oracle.truffle.dsl.processor.generator.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.parser.*;
 
 /**
  * THIS IS NOT PUBLIC API.
@@ -42,11 +43,8 @@
 @SupportedSourceVersion(SourceVersion.RELEASE_7)
 public class TruffleProcessor extends AbstractProcessor implements ProcessCallback {
 
-    private ProcessorContext context;
     private List<AnnotationProcessor<?>> generators;
 
-    private RoundEnvironment round;
-
     @Override
     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
         if (!roundEnv.processingOver()) {
@@ -56,15 +54,15 @@
     }
 
     private void processImpl(RoundEnvironment env) {
-        this.round = env;
         // TODO run verifications that other annotations are not processed out of scope of the
         // operation or typelattice.
         try {
+            ProcessorContext.setThreadLocalInstance(new ProcessorContext(processingEnv, this));
             for (AnnotationProcessor<?> generator : getGenerators()) {
                 AbstractParser<?> parser = generator.getParser();
                 if (parser.getAnnotationType() != null) {
                     for (Element e : env.getElementsAnnotatedWith(parser.getAnnotationType())) {
-                        processElement(env, generator, e, false);
+                        processElement(generator, e, false);
                     }
                 }
 
@@ -72,23 +70,23 @@
                     for (Element e : env.getElementsAnnotatedWith(annotationType)) {
                         TypeElement processedType;
                         if (parser.isDelegateToRootDeclaredType()) {
-                            processedType = Utils.findRootEnclosingType(e);
+                            processedType = ElementUtils.findRootEnclosingType(e);
                         } else {
-                            processedType = Utils.findNearestEnclosingType(e);
+                            processedType = ElementUtils.findNearestEnclosingType(e);
                         }
-                        processElement(env, generator, processedType, false);
+                        processElement(generator, processedType, false);
                     }
                 }
 
             }
         } finally {
-            this.round = null;
+            ProcessorContext.setThreadLocalInstance(null);
         }
     }
 
-    private static void processElement(RoundEnvironment env, AnnotationProcessor<?> generator, Element e, boolean callback) {
+    private static void processElement(AnnotationProcessor<?> generator, Element e, boolean callback) {
         try {
-            generator.process(env, e, callback);
+            generator.process(e, callback);
         } catch (Throwable e1) {
             handleThrowable(generator, e1, e);
         }
@@ -96,7 +94,7 @@
 
     private static void handleThrowable(AnnotationProcessor<?> generator, Throwable t, Element e) {
         String message = "Uncaught error in " + generator.getClass().getSimpleName() + " while processing " + e;
-        generator.getContext().getEnvironment().getMessager().printMessage(Kind.ERROR, message + ": " + Utils.printException(t), e);
+        ProcessorContext.getInstance().getEnvironment().getMessager().printMessage(Kind.ERROR, message + ": " + ElementUtils.printException(t), e);
     }
 
     @Override
@@ -106,7 +104,7 @@
             if (annotationType != null) {
                 Annotation annotation = template.getAnnotation(annotationType);
                 if (annotation != null) {
-                    processElement(round, generator, template, true);
+                    processElement(generator, template, true);
                 }
             }
         }
@@ -127,19 +125,12 @@
     private List<AnnotationProcessor<?>> getGenerators() {
         if (generators == null && processingEnv != null) {
             generators = new ArrayList<>();
-            generators.add(new AnnotationProcessor<>(getContext(), new TypeSystemParser(getContext()), new TypeSystemCodeGenerator(getContext())));
-            generators.add(new AnnotationProcessor<>(getContext(), new NodeParser(getContext()), new NodeCodeGenerator(getContext())));
+            generators.add(new AnnotationProcessor<>(new TypeSystemParser(), new TypeSystemCodeGenerator()));
+            generators.add(new AnnotationProcessor<>(new NodeParser(), new NodeCodeGenerator()));
         }
         return generators;
     }
 
-    private ProcessorContext getContext() {
-        if (context == null) {
-            context = new ProcessorContext(processingEnv, this);
-        }
-        return context;
-    }
-
     @Override
     public synchronized void init(ProcessingEnvironment env) {
         this.processingEnv = env;
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java	Mon Aug 25 21:15:59 2014 -0700
@@ -32,6 +32,7 @@
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.SlowPath;
 import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.internal.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.nodes.Node.Child;
@@ -61,11 +62,18 @@
     private final DeclaredType sourceSection;
     private final DeclaredType truffleOptions;
     private final DeclaredType compilationFinal;
+    private final DeclaredType nodeUtil;
+    private final DeclaredType dslNode;
+    private final DeclaredType dslShare;
+    private final DeclaredType nodeFactory;
+    private final DeclaredType nodeFactoryBase;
+    private final DeclaredType dslMetadata;
+    private final DeclaredType implies;
     private final TypeElement expectError;
 
     private final List<String> errors = new ArrayList<>();
 
-    public TruffleTypes(ProcessorContext context) {
+    TruffleTypes(ProcessorContext context) {
         node = getRequired(context, Node.class);
         nodeArray = context.getEnvironment().getTypeUtils().getArrayType(node);
         unexpectedValueException = getRequired(context, UnexpectedResultException.class);
@@ -82,9 +90,40 @@
         sourceSection = getRequired(context, SourceSection.class);
         truffleOptions = getRequired(context, TruffleOptions.class);
         compilationFinal = getRequired(context, CompilationFinal.class);
+        nodeUtil = getRequired(context, NodeUtil.class);
+        dslNode = getRequired(context, DSLNode.class);
+        dslShare = getRequired(context, DSLShare.class);
+        nodeFactory = getRequired(context, NodeFactory.class);
+        nodeFactoryBase = getRequired(context, NodeFactoryBase.class);
+        dslMetadata = getRequired(context, DSLMetadata.class);
+        implies = getRequired(context, Implies.class);
         expectError = (TypeElement) getRequired(context, ExpectError.class).asElement();
     }
 
+    public DeclaredType getImplies() {
+        return implies;
+    }
+
+    public DeclaredType getDslMetadata() {
+        return dslMetadata;
+    }
+
+    public DeclaredType getNodeFactory() {
+        return nodeFactory;
+    }
+
+    public DeclaredType getNodeFactoryBase() {
+        return nodeFactoryBase;
+    }
+
+    public DeclaredType getDslNode() {
+        return dslNode;
+    }
+
+    public DeclaredType getDslShare() {
+        return dslShare;
+    }
+
     public DeclaredType getCompilationFinal() {
         return compilationFinal;
     }
@@ -172,4 +211,8 @@
     public DeclaredType getSourceSection() {
         return sourceSection;
     }
+
+    public DeclaredType getNodeUtil() {
+        return nodeUtil;
+    }
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,997 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor;
-
-import java.io.*;
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.dsl.processor.ast.*;
-import com.oracle.truffle.dsl.processor.ast.CodeTypeMirror.DeclaredCodeTypeMirror;
-import com.oracle.truffle.dsl.processor.compiler.*;
-
-/**
- * THIS IS NOT PUBLIC API.
- */
-public class Utils {
-
-    public static ExecutableElement findExecutableElement(DeclaredType type, String name) {
-        List<? extends ExecutableElement> elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements());
-        for (ExecutableElement executableElement : elements) {
-            if (executableElement.getSimpleName().toString().equals(name)) {
-                return executableElement;
-            }
-        }
-        return null;
-    }
-
-    public static boolean needsCastTo(ProcessorContext context, TypeMirror sourceType, TypeMirror targetType) {
-        if (typeEquals(sourceType, targetType)) {
-            return false;
-        } else if (isObject(targetType)) {
-            return false;
-        } else if (isVoid(targetType)) {
-            return false;
-        } else if (isAssignable(context, sourceType, targetType)) {
-            return false;
-        }
-        return true;
-    }
-
-    public static VariableElement findVariableElement(DeclaredType type, String name) {
-        List<? extends VariableElement> elements = ElementFilter.fieldsIn(type.asElement().getEnclosedElements());
-        for (VariableElement variableElement : elements) {
-            if (variableElement.getSimpleName().toString().equals(name)) {
-                return variableElement;
-            }
-        }
-        return null;
-    }
-
-    public static String getMethodBody(ProcessingEnvironment env, ExecutableElement method) {
-        if (method instanceof CodeExecutableElement) {
-            return ((CodeExecutableElement) method).getBody();
-        } else {
-            return CompilerFactory.getCompiler(method).getMethodBody(env, method);
-        }
-    }
-
-    public static TypeMirror boxType(ProcessorContext context, TypeMirror primitiveType) {
-        TypeMirror boxedType = primitiveType;
-        if (boxedType.getKind().isPrimitive()) {
-            boxedType = context.getEnvironment().getTypeUtils().boxedClass((PrimitiveType) boxedType).asType();
-        }
-        return boxedType;
-    }
-
-    public static List<TypeMirror> asTypeMirrors(List<? extends Element> elements) {
-        List<TypeMirror> types = new ArrayList<>(elements.size());
-        for (Element element : elements) {
-            types.add(element.asType());
-        }
-        return types;
-    }
-
-    public static DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs) {
-        return new DeclaredCodeTypeMirror(typeElem, Arrays.asList(typeArgs));
-    }
-
-    public static List<AnnotationMirror> collectAnnotations(ProcessorContext context, AnnotationMirror markerAnnotation, String elementName, Element element,
-                    Class<? extends Annotation> annotationClass) {
-        List<AnnotationMirror> result = new ArrayList<>();
-        if (markerAnnotation != null) {
-            result.addAll(Utils.getAnnotationValueList(AnnotationMirror.class, markerAnnotation, elementName));
-        }
-        AnnotationMirror explicit = Utils.findAnnotationMirror(context.getEnvironment(), element, annotationClass);
-        if (explicit != null) {
-            result.add(explicit);
-        }
-        return result;
-    }
-
-    public static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror[] types) {
-        if (types.length == 0) {
-            return context.getType(Object.class);
-        }
-        TypeMirror prev = types[0];
-        for (int i = 1; i < types.length; i++) {
-            prev = getCommonSuperType(context, prev, types[i]);
-        }
-        return prev;
-    }
-
-    public static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror type1, TypeMirror type2) {
-        if (typeEquals(type1, type2)) {
-            return type1;
-        }
-        TypeElement element1 = fromTypeMirror(type1);
-        TypeElement element2 = fromTypeMirror(type2);
-        if (element1 == null || element2 == null) {
-            return context.getType(Object.class);
-        }
-
-        List<TypeElement> element1Types = getDirectSuperTypes(element1);
-        element1Types.add(0, element1);
-        List<TypeElement> element2Types = getDirectSuperTypes(element2);
-        element2Types.add(0, element2);
-
-        for (TypeElement superType1 : element1Types) {
-            for (TypeElement superType2 : element2Types) {
-                if (typeEquals(superType1.asType(), superType2.asType())) {
-                    return superType2.asType();
-                }
-            }
-        }
-        return context.getType(Object.class);
-    }
-
-    public static String getReadableSignature(ExecutableElement method) {
-        // TODO toString does not guarantee a good signature
-        return method.toString();
-    }
-
-    public static boolean hasError(TypeMirror mirror) {
-        switch (mirror.getKind()) {
-            case BOOLEAN:
-            case BYTE:
-            case CHAR:
-            case DOUBLE:
-            case FLOAT:
-            case INT:
-            case SHORT:
-            case LONG:
-            case DECLARED:
-            case VOID:
-            case TYPEVAR:
-                return false;
-            case ARRAY:
-                return hasError(((ArrayType) mirror).getComponentType());
-            case ERROR:
-                return true;
-            default:
-                throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
-        }
-    }
-
-    public static boolean isAssignable(ProcessorContext context, TypeMirror from, TypeMirror to) {
-        if (!(from instanceof CodeTypeMirror) && !(to instanceof CodeTypeMirror)) {
-            return context.getEnvironment().getTypeUtils().isAssignable(context.reloadType(from), context.reloadType(to));
-        } else {
-            return isAssignableImpl(context, from, to);
-        }
-    }
-
-    private static boolean isAssignableImpl(ProcessorContext context, TypeMirror from, TypeMirror to) {
-        // JLS 5.1.1 identity conversion
-        if (Utils.typeEquals(from, to)) {
-            return true;
-        }
-
-        if (isObject(to)) {
-            return true;
-        }
-
-        // JLS 5.1.2 widening primitives
-        if (Utils.isPrimitive(from) && Utils.isPrimitive(to)) {
-            TypeKind fromKind = from.getKind();
-            TypeKind toKind = to.getKind();
-            switch (fromKind) {
-                case BYTE:
-                    switch (toKind) {
-                        case SHORT:
-                        case INT:
-                        case LONG:
-                        case FLOAT:
-                        case DOUBLE:
-                            return true;
-                    }
-                    break;
-                case SHORT:
-                    switch (toKind) {
-                        case INT:
-                        case LONG:
-                        case FLOAT:
-                        case DOUBLE:
-                            return true;
-                    }
-                    break;
-                case CHAR:
-                    switch (toKind) {
-                        case INT:
-                        case LONG:
-                        case FLOAT:
-                        case DOUBLE:
-                            return true;
-                    }
-                    break;
-                case INT:
-                    switch (toKind) {
-                        case LONG:
-                        case FLOAT:
-                        case DOUBLE:
-                            return true;
-                    }
-                    break;
-                case LONG:
-                    switch (toKind) {
-                        case FLOAT:
-                        case DOUBLE:
-                            return true;
-                    }
-                    break;
-                case FLOAT:
-                    switch (toKind) {
-                        case DOUBLE:
-                            return true;
-                    }
-                    break;
-
-            }
-            return false;
-        } else if (Utils.isPrimitive(from) || Utils.isPrimitive(to)) {
-            return false;
-        }
-
-        if (from instanceof ArrayType && to instanceof ArrayType) {
-            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) {
-            return false;
-        }
-        // JLS 5.1.6 narrowing reference conversion
-
-        List<TypeElement> superTypes = Utils.getSuperTypes(fromType);
-        for (TypeElement superType : superTypes) {
-            if (Utils.typeEquals(superType.asType(), to)) {
-                return true;
-            }
-        }
-
-        // TODO more spec
-        return false;
-    }
-
-    public static Set<Modifier> modifiers(Modifier... modifier) {
-        return new LinkedHashSet<>(Arrays.asList(modifier));
-    }
-
-    public static String getTypeId(TypeMirror mirror) {
-        switch (mirror.getKind()) {
-            case BOOLEAN:
-                return "Boolean";
-            case BYTE:
-                return "Byte";
-            case CHAR:
-                return "Char";
-            case DOUBLE:
-                return "Double";
-            case FLOAT:
-                return "Float";
-            case SHORT:
-                return "Short";
-            case INT:
-                return "Int";
-            case LONG:
-                return "Long";
-            case DECLARED:
-                return fixECJBinaryNameIssue(((DeclaredType) mirror).asElement().getSimpleName().toString());
-            case ARRAY:
-                return getTypeId(((ArrayType) mirror).getComponentType()) + "Array";
-            case VOID:
-                return "Void";
-            case WILDCARD:
-                StringBuilder b = new StringBuilder();
-                WildcardType type = (WildcardType) mirror;
-                if (type.getExtendsBound() != null) {
-                    b.append("Extends").append(getTypeId(type.getExtendsBound()));
-                } else if (type.getSuperBound() != null) {
-                    b.append("Super").append(getTypeId(type.getExtendsBound()));
-                }
-                return b.toString();
-            case TYPEVAR:
-                return "Any";
-            case ERROR:
-                throw new CompileErrorException("Type error " + mirror);
-            default:
-                throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
-        }
-    }
-
-    public static String getSimpleName(TypeElement element) {
-        return getSimpleName(element.asType());
-    }
-
-    public static String getSimpleName(TypeMirror mirror) {
-        switch (mirror.getKind()) {
-            case BOOLEAN:
-                return "boolean";
-            case BYTE:
-                return "byte";
-            case CHAR:
-                return "char";
-            case DOUBLE:
-                return "double";
-            case FLOAT:
-                return "float";
-            case SHORT:
-                return "short";
-            case INT:
-                return "int";
-            case LONG:
-                return "long";
-            case DECLARED:
-                return getDeclaredName((DeclaredType) mirror);
-            case ARRAY:
-                return getSimpleName(((ArrayType) mirror).getComponentType()) + "[]";
-            case VOID:
-                return "void";
-            case WILDCARD:
-                return getWildcardName((WildcardType) mirror);
-            case TYPEVAR:
-                return "?";
-            case ERROR:
-                throw new CompileErrorException("Type error " + mirror);
-            default:
-                throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
-        }
-    }
-
-    private static String getWildcardName(WildcardType type) {
-        StringBuilder b = new StringBuilder();
-        if (type.getExtendsBound() != null) {
-            b.append("? extends ").append(getSimpleName(type.getExtendsBound()));
-        } else if (type.getSuperBound() != null) {
-            b.append("? super ").append(getSimpleName(type.getExtendsBound()));
-        }
-        return b.toString();
-    }
-
-    private static String getDeclaredName(DeclaredType element) {
-        String simpleName = fixECJBinaryNameIssue(element.asElement().getSimpleName().toString());
-
-        if (element.getTypeArguments().size() == 0) {
-            return simpleName;
-        }
-
-        StringBuilder b = new StringBuilder(simpleName);
-        b.append("<");
-        if (element.getTypeArguments().size() > 0) {
-            for (int i = 0; i < element.getTypeArguments().size(); i++) {
-                b.append(getSimpleName(element.getTypeArguments().get(i)));
-                if (i < element.getTypeArguments().size() - 1) {
-                    b.append(", ");
-                }
-            }
-        }
-        b.append(">");
-        return b.toString();
-    }
-
-    public static String fixECJBinaryNameIssue(String name) {
-        if (name.contains("$")) {
-            int lastIndex = name.lastIndexOf('$');
-            return name.substring(lastIndex + 1, name.length());
-        }
-        return name;
-    }
-
-    public static String getQualifiedName(TypeElement element) {
-        String qualifiedName = element.getQualifiedName().toString();
-        if (qualifiedName.contains("$")) {
-            /*
-             * If a class gets loaded in its binary form by the ECJ compiler it fails to produce the
-             * proper canonical class name. It leaves the $ in the qualified name of the class. So
-             * one instance of a TypeElement may be loaded in binary and one in source form. The
-             * current type comparison in #typeEquals compares by the qualified name so the
-             * qualified name must match. This is basically a hack to fix the returned qualified
-             * name of eclipse.
-             */
-            qualifiedName = qualifiedName.replace('$', '.');
-        }
-        return qualifiedName;
-    }
-
-    public static String getQualifiedName(TypeMirror mirror) {
-        switch (mirror.getKind()) {
-            case BOOLEAN:
-                return "boolean";
-            case BYTE:
-                return "byte";
-            case CHAR:
-                return "char";
-            case DOUBLE:
-                return "double";
-            case SHORT:
-                return "short";
-            case FLOAT:
-                return "float";
-            case INT:
-                return "int";
-            case LONG:
-                return "long";
-            case DECLARED:
-                return getQualifiedName(fromTypeMirror(mirror));
-            case ARRAY:
-                return getQualifiedName(((ArrayType) mirror).getComponentType());
-            case VOID:
-                return "void";
-            case TYPEVAR:
-                return getSimpleName(mirror);
-            case ERROR:
-                throw new CompileErrorException("Type error " + mirror);
-            case EXECUTABLE:
-                return ((ExecutableType) mirror).toString();
-            case NONE:
-                return "$none";
-            default:
-                throw new RuntimeException("Unknown type specified " + mirror + " mirror: " + mirror);
-        }
-    }
-
-    public static boolean isVoid(TypeMirror mirror) {
-        return mirror.getKind() == TypeKind.VOID;
-    }
-
-    public static boolean isPrimitive(TypeMirror mirror) {
-        return mirror.getKind().isPrimitive();
-    }
-
-    public static boolean isPrimitiveOrVoid(TypeMirror mirror) {
-        return isPrimitive(mirror) || isVoid(mirror);
-    }
-
-    public static List<String> getQualifiedSuperTypeNames(TypeElement element) {
-        List<TypeElement> types = getSuperTypes(element);
-        List<String> qualifiedNames = new ArrayList<>();
-        for (TypeElement type : types) {
-            qualifiedNames.add(getQualifiedName(type));
-        }
-        return qualifiedNames;
-    }
-
-    public static List<TypeElement> getDeclaredTypes(TypeElement element) {
-        return ElementFilter.typesIn(element.getEnclosedElements());
-    }
-
-    public static VariableElement findDeclaredField(TypeMirror type, String singletonName) {
-        List<VariableElement> elements = ElementFilter.fieldsIn(fromTypeMirror(type).getEnclosedElements());
-        for (VariableElement var : elements) {
-            if (var.getSimpleName().toString().equals(singletonName)) {
-                return var;
-            }
-        }
-        return null;
-    }
-
-    public static TypeElement findRootEnclosingType(Element element) {
-        List<Element> elements = getElementHierarchy(element);
-
-        for (int i = elements.size() - 1; i >= 0; i--) {
-            if (elements.get(i).getKind().isClass()) {
-                return (TypeElement) elements.get(i);
-            }
-        }
-
-        return null;
-    }
-
-    public static List<Element> getElementHierarchy(Element e) {
-        List<Element> elements = new ArrayList<>();
-        elements.add(e);
-
-        Element enclosing = e.getEnclosingElement();
-        while (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE) {
-            elements.add(enclosing);
-            enclosing = enclosing.getEnclosingElement();
-        }
-        if (enclosing != null) {
-            elements.add(enclosing);
-        }
-        return elements;
-    }
-
-    public static TypeElement findNearestEnclosingType(Element element) {
-        List<Element> elements = getElementHierarchy(element);
-        for (Element e : elements) {
-            if (e.getKind().isClass()) {
-                return (TypeElement) e;
-            }
-        }
-        return null;
-    }
-
-    public static List<TypeElement> getDirectSuperTypes(TypeElement element) {
-        List<TypeElement> types = new ArrayList<>();
-        if (element.getSuperclass() != null) {
-            TypeElement superElement = fromTypeMirror(element.getSuperclass());
-            if (superElement != null) {
-                types.add(superElement);
-                types.addAll(getDirectSuperTypes(superElement));
-            }
-        }
-
-        return types;
-    }
-
-    public static List<TypeMirror> getAssignableTypes(ProcessorContext context, TypeMirror type) {
-        if (isPrimitive(type)) {
-            return Arrays.asList(type, boxType(context, type), context.getType(Object.class));
-        } else if (type.getKind() == TypeKind.ARRAY) {
-            return Arrays.asList(type, context.getType(Object.class));
-        } else if (type.getKind() == TypeKind.DECLARED) {
-            List<TypeElement> types = getSuperTypes(fromTypeMirror(type));
-            List<TypeMirror> mirrors = new ArrayList<>(types.size());
-            mirrors.add(type);
-            for (TypeElement typeElement : types) {
-                mirrors.add(typeElement.asType());
-            }
-            return mirrors;
-        } else {
-            return Collections.emptyList();
-        }
-    }
-
-    public static List<TypeElement> getSuperTypes(TypeElement element) {
-        List<TypeElement> types = new ArrayList<>();
-        List<TypeElement> superTypes = null;
-        List<TypeElement> superInterfaces = null;
-        if (element.getSuperclass() != null) {
-            TypeElement superElement = fromTypeMirror(element.getSuperclass());
-            if (superElement != null) {
-                types.add(superElement);
-                superTypes = getSuperTypes(superElement);
-            }
-        }
-        for (TypeMirror interfaceMirror : element.getInterfaces()) {
-            TypeElement interfaceElement = fromTypeMirror(interfaceMirror);
-            if (interfaceElement != null) {
-                types.add(interfaceElement);
-                superInterfaces = getSuperTypes(interfaceElement);
-            }
-        }
-
-        if (superTypes != null) {
-            types.addAll(superTypes);
-        }
-
-        if (superInterfaces != null) {
-            types.addAll(superInterfaces);
-        }
-
-        return types;
-    }
-
-    public static String getPackageName(TypeElement element) {
-        return findPackageElement(element).getQualifiedName().toString();
-    }
-
-    public static String getPackageName(TypeMirror mirror) {
-        switch (mirror.getKind()) {
-            case BOOLEAN:
-            case BYTE:
-            case CHAR:
-            case DOUBLE:
-            case FLOAT:
-            case SHORT:
-            case INT:
-            case LONG:
-            case VOID:
-            case TYPEVAR:
-                return null;
-            case DECLARED:
-                PackageElement pack = findPackageElement(fromTypeMirror(mirror));
-                if (pack == null) {
-                    throw new IllegalArgumentException("No package element found for declared type " + getSimpleName(mirror));
-                }
-                return pack.getQualifiedName().toString();
-            case ARRAY:
-                return getSimpleName(((ArrayType) mirror).getComponentType());
-            default:
-                throw new RuntimeException("Unknown type specified " + mirror.getKind());
-        }
-    }
-
-    public static String createConstantName(String simpleName) {
-        // TODO use camel case to produce underscores.
-        return simpleName.toString().toUpperCase();
-    }
-
-    public static TypeElement fromTypeMirror(TypeMirror mirror) {
-        switch (mirror.getKind()) {
-            case DECLARED:
-                return (TypeElement) ((DeclaredType) mirror).asElement();
-            case ARRAY:
-                return fromTypeMirror(((ArrayType) mirror).getComponentType());
-            default:
-                return null;
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    public static <T> List<T> getAnnotationValueList(Class<T> expectedListType, AnnotationMirror mirror, String name) {
-        List<? extends AnnotationValue> values = getAnnotationValue(List.class, mirror, name);
-        List<T> result = new ArrayList<>();
-
-        if (values != null) {
-            for (AnnotationValue value : values) {
-                T annotationValue = resolveAnnotationValue(expectedListType, value);
-                if (annotationValue != null) {
-                    result.add(annotationValue);
-                }
-            }
-        }
-        return result;
-    }
-
-    public static <T> T getAnnotationValue(Class<T> expectedType, AnnotationMirror mirror, String name) {
-        return resolveAnnotationValue(expectedType, getAnnotationValue(mirror, name));
-    }
-
-    @SuppressWarnings({"unchecked"})
-    private static <T> T resolveAnnotationValue(Class<T> expectedType, AnnotationValue value) {
-        if (value == null) {
-            return null;
-        }
-
-        Object unboxedValue = value.accept(new AnnotationValueVisitorImpl(), null);
-        if (unboxedValue != null) {
-            if (expectedType == TypeMirror.class && unboxedValue instanceof String) {
-                return null;
-            }
-            if (!expectedType.isAssignableFrom(unboxedValue.getClass())) {
-                throw new ClassCastException(unboxedValue.getClass().getName() + " not assignable from " + expectedType.getName());
-            }
-        }
-        return (T) unboxedValue;
-    }
-
-    public static AnnotationValue getAnnotationValue(AnnotationMirror mirror, String name) {
-        ExecutableElement valueMethod = null;
-        for (ExecutableElement method : ElementFilter.methodsIn(mirror.getAnnotationType().asElement().getEnclosedElements())) {
-            if (method.getSimpleName().toString().equals(name)) {
-                valueMethod = method;
-                break;
-            }
-        }
-
-        if (valueMethod == null) {
-            return null;
-        }
-
-        AnnotationValue value = mirror.getElementValues().get(valueMethod);
-        if (value == null) {
-            value = valueMethod.getDefaultValue();
-        }
-
-        return value;
-    }
-
-    private static class AnnotationValueVisitorImpl extends AbstractAnnotationValueVisitor7<Object, Void> {
-
-        @Override
-        public Object visitBoolean(boolean b, Void p) {
-            return Boolean.valueOf(b);
-        }
-
-        @Override
-        public Object visitByte(byte b, Void p) {
-            return Byte.valueOf(b);
-        }
-
-        @Override
-        public Object visitChar(char c, Void p) {
-            return c;
-        }
-
-        @Override
-        public Object visitDouble(double d, Void p) {
-            return d;
-        }
-
-        @Override
-        public Object visitFloat(float f, Void p) {
-            return f;
-        }
-
-        @Override
-        public Object visitInt(int i, Void p) {
-            return i;
-        }
-
-        @Override
-        public Object visitLong(long i, Void p) {
-            return i;
-        }
-
-        @Override
-        public Object visitShort(short s, Void p) {
-            return s;
-        }
-
-        @Override
-        public Object visitString(String s, Void p) {
-            return s;
-        }
-
-        @Override
-        public Object visitType(TypeMirror t, Void p) {
-            return t;
-        }
-
-        @Override
-        public Object visitEnumConstant(VariableElement c, Void p) {
-            return c;
-        }
-
-        @Override
-        public Object visitAnnotation(AnnotationMirror a, Void p) {
-            return a;
-        }
-
-        @Override
-        public Object visitArray(List<? extends AnnotationValue> vals, Void p) {
-            return vals;
-        }
-
-    }
-
-    public static boolean getAnnotationValueBoolean(AnnotationMirror mirror, String name) {
-        return (Boolean) getAnnotationValue(mirror, name).getValue();
-    }
-
-    public static String printException(Throwable e) {
-        StringWriter string = new StringWriter();
-        PrintWriter writer = new PrintWriter(string);
-        e.printStackTrace(writer);
-        writer.flush();
-        return e.getMessage() + "\r\n" + string.toString();
-    }
-
-    public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, Element element, Class<?> annotationClass) {
-        return findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), annotationClass);
-    }
-
-    public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, List<? extends AnnotationMirror> mirrors, Class<?> annotationClass) {
-        TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName());
-        return findAnnotationMirror(mirrors, expectedAnnotationType);
-    }
-
-    public static AnnotationMirror findAnnotationMirror(List<? extends AnnotationMirror> mirrors, TypeElement expectedAnnotationType) {
-        for (AnnotationMirror mirror : mirrors) {
-            DeclaredType annotationType = mirror.getAnnotationType();
-            TypeElement actualAnnotationType = (TypeElement) annotationType.asElement();
-            if (actualAnnotationType.equals(expectedAnnotationType)) {
-                return mirror;
-            }
-        }
-        return null;
-    }
-
-    private static PackageElement findPackageElement(Element type) {
-        List<Element> hierarchy = getElementHierarchy(type);
-        for (Element element : hierarchy) {
-            if (element.getKind() == ElementKind.PACKAGE) {
-                return (PackageElement) element;
-            }
-        }
-        return null;
-    }
-
-    public static String firstLetterUpperCase(String name) {
-        if (name == null || name.isEmpty()) {
-            return name;
-        }
-        return Character.toUpperCase(name.charAt(0)) + name.substring(1, name.length());
-    }
-
-    public static String firstLetterLowerCase(String name) {
-        if (name == null || name.isEmpty()) {
-            return name;
-        }
-        return Character.toLowerCase(name.charAt(0)) + name.substring(1, name.length());
-    }
-
-    private static ExecutableElement getDeclaredMethod(TypeElement element, String name, TypeMirror[] params) {
-        List<ExecutableElement> methods = ElementFilter.methodsIn(element.getEnclosedElements());
-        method: for (ExecutableElement method : methods) {
-            if (!method.getSimpleName().toString().equals(name)) {
-                continue;
-            }
-            if (method.getParameters().size() != params.length) {
-                continue;
-            }
-            for (int i = 0; i < params.length; i++) {
-                TypeMirror param1 = params[i];
-                TypeMirror param2 = method.getParameters().get(i).asType();
-                if (param1.getKind() != TypeKind.TYPEVAR && param2.getKind() != TypeKind.TYPEVAR) {
-                    if (!getQualifiedName(param1).equals(getQualifiedName(param2))) {
-                        continue method;
-                    }
-                }
-            }
-            return method;
-        }
-        return null;
-    }
-
-    private static boolean isDeclaredMethod(TypeElement element, String name, TypeMirror[] params) {
-        return getDeclaredMethod(element, name, params) != null;
-    }
-
-    public static boolean isDeclaredMethodInSuperType(TypeElement element, String name, TypeMirror[] params) {
-        List<TypeElement> superElements = getSuperTypes(element);
-
-        for (TypeElement typeElement : superElements) {
-            if (isDeclaredMethod(typeElement, name, params)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private static ExecutableElement getDeclaredMethodInSuperType(TypeElement element, String name, TypeMirror[] params) {
-        List<TypeElement> superElements = getSuperTypes(element);
-
-        for (TypeElement typeElement : superElements) {
-            ExecutableElement declared = getDeclaredMethod(typeElement, name, params);
-            if (declared != null) {
-                return declared;
-            }
-        }
-        return null;
-    }
-
-    public static ExecutableElement getDeclaredMethodRecursive(TypeElement element, String name, TypeMirror[] params) {
-        ExecutableElement declared = getDeclaredMethod(element, name, params);
-        if (declared != null) {
-            return declared;
-        }
-        return getDeclaredMethodInSuperType(element, name, params);
-    }
-
-    public static boolean typeEquals(TypeMirror type1, TypeMirror type2) {
-        if (type1 == null && type2 == null) {
-            return true;
-        } else if (type1 == null || type2 == null) {
-            return false;
-        } else if (type1 == type2) {
-            return true;
-        }
-        String qualified1 = getQualifiedName(type1);
-        String qualified2 = getQualifiedName(type2);
-
-        if (type1.getKind() == TypeKind.ARRAY || type2.getKind() == TypeKind.ARRAY) {
-            if (type1.getKind() == TypeKind.ARRAY && type2.getKind() == TypeKind.ARRAY) {
-                return typeEquals(((ArrayType) type1).getComponentType(), ((ArrayType) type2).getComponentType());
-            } else {
-                return false;
-            }
-        }
-        return qualified1.equals(qualified2);
-    }
-
-    public static int compareByTypeHierarchy(TypeMirror t1, TypeMirror t2) {
-        if (typeEquals(t1, t2)) {
-            return 0;
-        }
-        Set<String> t1SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t1)));
-        if (t1SuperSet.contains(getQualifiedName(t2))) {
-            return -1;
-        }
-
-        Set<String> t2SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t2)));
-        if (t2SuperSet.contains(getQualifiedName(t1))) {
-            return 1;
-        }
-        return 0;
-    }
-
-    public static boolean canThrowType(List<? extends TypeMirror> thrownTypes, TypeMirror exceptionType) {
-        if (Utils.containsType(thrownTypes, exceptionType)) {
-            return true;
-        }
-
-        if (isRuntimeException(exceptionType)) {
-            return true;
-        }
-
-        // search for any super types
-        TypeElement exceptionTypeElement = fromTypeMirror(exceptionType);
-        List<TypeElement> superTypes = getSuperTypes(exceptionTypeElement);
-        for (TypeElement typeElement : superTypes) {
-            if (Utils.containsType(thrownTypes, typeElement.asType())) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    public static Modifier getVisibility(Set<Modifier> modifier) {
-        for (Modifier mod : modifier) {
-            if (mod == Modifier.PUBLIC || mod == Modifier.PRIVATE || mod == Modifier.PROTECTED) {
-                return mod;
-            }
-        }
-        return null;
-    }
-
-    private static boolean isRuntimeException(TypeMirror type) {
-        Set<String> typeSuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(type)));
-        String typeName = getQualifiedName(type);
-        if (!typeSuperSet.contains(Throwable.class.getCanonicalName()) && !typeName.equals(Throwable.class.getCanonicalName())) {
-            throw new IllegalArgumentException("Given type does not extend Throwable.");
-        }
-        return typeSuperSet.contains(RuntimeException.class.getCanonicalName()) || typeName.equals(RuntimeException.class.getCanonicalName());
-    }
-
-    private static boolean containsType(Collection<? extends TypeMirror> collection, TypeMirror type) {
-        for (TypeMirror otherTypeMirror : collection) {
-            if (typeEquals(otherTypeMirror, type)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public static boolean isTopLevelClass(TypeMirror importType) {
-        TypeElement type = fromTypeMirror(importType);
-        if (type != null && type.getEnclosingElement() != null) {
-            return !type.getEnclosingElement().getKind().isClass();
-        }
-        return true;
-    }
-
-    public static boolean isObject(TypeMirror actualType) {
-        return actualType.getKind() == TypeKind.DECLARED && getQualifiedName(actualType).equals("java.lang.Object");
-    }
-
-    public static boolean isFieldAccessible(Element element, VariableElement variable) {
-        TypeElement type = Utils.findNearestEnclosingType(element);
-        TypeElement varType = Utils.findNearestEnclosingType(variable);
-
-        while (type != null) {
-            if (typeEquals(type.asType(), varType.asType())) {
-                return true;
-            }
-            if (type.getSuperclass() != null) {
-                type = Utils.fromTypeMirror(type.getSuperclass());
-            } else {
-                type = null;
-            }
-        }
-        return false;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/ExtensionContext.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.api;
-
-import javax.annotation.processing.*;
-
-import com.oracle.truffle.dsl.processor.api.element.*;
-
-public interface ExtensionContext {
-
-    ProcessingEnvironment getProcessingEnvironment();
-
-    RoundEnvironment getRoundEnvironment();
-
-    WritableElementFactory getElementFactory();
-
-    void addGeneratedElement(WritableElement element);
-
-    void removeGeneratedElement(WritableElement element);
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableAnnotationMirror.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.api.element;
-
-import javax.lang.model.element.*;
-
-public interface WritableAnnotationMirror extends AnnotationMirror {
-
-    void setElementValue(ExecutableElement valueName, AnnotationValue value);
-
-    AnnotationValue getElementValue(ExecutableElement valueName);
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableElement.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.api.element;
-
-import javax.lang.model.element.*;
-
-public interface WritableElement extends Element {
-
-    void addAnnotationMirror(AnnotationMirror annotationMirror);
-
-    void removeAnnotationMirror(AnnotationMirror annotationMirror);
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableElementFactory.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.api.element;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-public interface WritableElementFactory {
-
-    WritableExecutableElement cloneExecutableElement(ExecutableElement method);
-
-    WritableVariableElement cloneVariableElement(VariableElement parameter);
-
-    WritableAnnotationMirror cloneAnnotationMirror(AnnotationMirror mirror);
-
-    WritableVariableElement createParameter(TypeMirror type, String simpleName);
-
-    WritableExecutableElement createExecutableElement(TypeMirror returnType, String methodName);
-
-    WritableAnnotationMirror createAnnotationMirror(DeclaredType annotationClass);
-
-    Name createName(String name);
-
-    AnnotationValue createAnnotationValue(Object value);
-
-    TypeMirror createTypeMirror(Class<?> javaClass);
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableExecutableElement.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.api.element;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-public interface WritableExecutableElement extends ExecutableElement, WritableElement {
-
-    void setReturnType(TypeMirror type);
-
-    void setDefaultValue(AnnotationValue defaultValue);
-
-    void addParameter(VariableElement parameter);
-
-    void removeParameter(VariableElement parameter);
-
-    void addThrownType(TypeMirror thrownType);
-
-    void removeThrownType(TypeMirror thrownType);
-
-    void setSimpleName(Name name);
-
-    void setVarArgs(boolean varargs);
-
-    void setBody(String body);
-
-    String getBody();
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableVariableElement.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.api.element;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-public interface WritableVariableElement extends VariableElement, WritableElement {
-
-    void setSimpleName(Name name);
-
-    void setType(TypeMirror type);
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeAnnotationMirror.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.api.element.*;
-
-public class CodeAnnotationMirror implements WritableAnnotationMirror {
-
-    private final DeclaredType annotationType;
-    private final Map<ExecutableElement, AnnotationValue> values = new LinkedHashMap<>();
-
-    public CodeAnnotationMirror(DeclaredType annotationType) {
-        this.annotationType = annotationType;
-    }
-
-    @Override
-    public DeclaredType getAnnotationType() {
-        return annotationType;
-    }
-
-    @Override
-    public Map<? extends ExecutableElement, ? extends AnnotationValue> getElementValues() {
-        return values;
-    }
-
-    @Override
-    public AnnotationValue getElementValue(ExecutableElement method) {
-        return values.get(method);
-    }
-
-    @Override
-    public void setElementValue(ExecutableElement method, AnnotationValue value) {
-        values.put(method, value);
-    }
-
-    public ExecutableElement findExecutableElement(String name) {
-        return Utils.findExecutableElement(annotationType, name);
-    }
-
-    public static CodeAnnotationMirror clone(AnnotationMirror mirror) {
-        CodeAnnotationMirror copy = new CodeAnnotationMirror(mirror.getAnnotationType());
-        for (ExecutableElement key : mirror.getElementValues().keySet()) {
-            copy.setElementValue(key, mirror.getElementValues().get(key));
-        }
-        return copy;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeAnnotationValue.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-public class CodeAnnotationValue implements AnnotationValue {
-
-    private final Object value;
-
-    public CodeAnnotationValue(Object value) {
-        Objects.requireNonNull(value);
-        if ((value instanceof AnnotationMirror) || (value instanceof List<?>) || (value instanceof Boolean) || (value instanceof Byte) || (value instanceof Character) || (value instanceof Double) ||
-                        (value instanceof VariableElement) || (value instanceof Float) || (value instanceof Integer) || (value instanceof Long) || (value instanceof Short) ||
-                        (value instanceof String) || (value instanceof TypeMirror)) {
-            this.value = value;
-        } else {
-            throw new IllegalArgumentException("Invalid annotation value type " + value.getClass().getName());
-        }
-    }
-
-    @Override
-    public Object getValue() {
-        return value;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
-        if (value instanceof AnnotationMirror) {
-            return v.visitAnnotation((AnnotationMirror) value, p);
-        } else if (value instanceof List<?>) {
-            return v.visitArray((List<? extends AnnotationValue>) value, p);
-        } else if (value instanceof Boolean) {
-            return v.visitBoolean((boolean) value, p);
-        } else if (value instanceof Byte) {
-            return v.visitByte((byte) value, p);
-        } else if (value instanceof Character) {
-            return v.visitChar((char) value, p);
-        } else if (value instanceof Double) {
-            return v.visitDouble((double) value, p);
-        } else if (value instanceof VariableElement) {
-            return v.visitEnumConstant((VariableElement) value, p);
-        } else if (value instanceof Float) {
-            return v.visitFloat((float) value, p);
-        } else if (value instanceof Integer) {
-            return v.visitInt((int) value, p);
-        } else if (value instanceof Long) {
-            return v.visitLong((long) value, p);
-        } else if (value instanceof Short) {
-            return v.visitShort((short) value, p);
-        } else if (value instanceof String) {
-            return v.visitString((String) value, p);
-        } else if (value instanceof TypeMirror) {
-            return v.visitType((TypeMirror) value, p);
-        } else {
-            return v.visitUnknown(this, p);
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeCompilationUnit.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-public class CodeCompilationUnit extends CodeElement<TypeElement> {
-
-    public CodeCompilationUnit() {
-        super(Collections.<Modifier> emptySet());
-    }
-
-    @Override
-    public TypeMirror asType() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public ElementKind getKind() {
-        return ElementKind.OTHER;
-    }
-
-    @Override
-    public Name getSimpleName() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
-        for (Element type : getEnclosedElements()) {
-            if (type.getKind().isClass()) {
-                type.accept(v, p);
-            } else {
-                throw new ClassCastException(type.getClass().getName());
-            }
-        }
-        return null;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeElement.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,367 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import java.io.*;
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.api.element.*;
-import com.oracle.truffle.dsl.processor.codewriter.*;
-
-public abstract class CodeElement<E extends Element> implements WritableElement, GeneratedElement {
-
-    private final Set<Modifier> modifiers;
-    private List<AnnotationMirror> annotations;
-    private List<E> enclosedElements;
-
-    private Element enclosingElement;
-
-    private Element generatorElement;
-    private AnnotationMirror generatorAnnotationMirror;
-
-    public CodeElement() {
-        this.modifiers = new LinkedHashSet<>();
-    }
-
-    @Override
-    public void setGeneratorAnnotationMirror(AnnotationMirror mirror) {
-        this.generatorAnnotationMirror = mirror;
-    }
-
-    @Override
-    public void setGeneratorElement(Element element) {
-        this.generatorElement = element;
-    }
-
-    @Override
-    public AnnotationMirror getGeneratorAnnotationMirror() {
-        return generatorAnnotationMirror;
-    }
-
-    @Override
-    public Element getGeneratorElement() {
-        return generatorElement;
-    }
-
-    public CodeElement(Set<Modifier> modifiers) {
-        this.modifiers = new LinkedHashSet<>(modifiers);
-    }
-
-    public E add(E element) {
-        if (element == null) {
-            throw new NullPointerException();
-        }
-        getEnclosedElements().add(element);
-        return element;
-    }
-
-    public E addOptional(E element) {
-        if (element != null) {
-            add(element);
-        }
-        return element;
-    }
-
-    public void remove(E element) {
-        getEnclosedElements().remove(element);
-    }
-
-    @Override
-    public Set<Modifier> getModifiers() {
-        return modifiers;
-    }
-
-    @Override
-    public List<E> getEnclosedElements() {
-        if (enclosedElements == null) {
-            enclosedElements = parentableList(this, new ArrayList<E>());
-        }
-        return enclosedElements;
-    }
-
-    @Override
-    public List<AnnotationMirror> getAnnotationMirrors() {
-        if (annotations == null) {
-            annotations = parentableList(this, new ArrayList<AnnotationMirror>());
-        }
-        return annotations;
-    }
-
-    /**
-     * Support JDK8 langtools.
-     *
-     * @param annotationType
-     */
-    public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Support for some JDK8 builds. (remove after jdk8 is released)
-     *
-     * @param annotationType
-     */
-    public <A extends Annotation> A[] getAnnotations(Class<A> annotationType) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Support for some JDK8 builds. (remove after jdk8 is released)
-     *
-     * @param annotationType
-     */
-    public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void addAnnotationMirror(AnnotationMirror annotationMirror) {
-        getAnnotationMirrors().add(annotationMirror);
-    }
-
-    public void removeAnnotationMirror(AnnotationMirror annotationMirror) {
-        getAnnotationMirrors().remove(annotationMirror);
-    }
-
-    void setEnclosingElement(Element parent) {
-        this.enclosingElement = parent;
-    }
-
-    public Element getEnclosingElement() {
-        return enclosingElement;
-    }
-
-    public CodeTypeElement getEnclosingClass() {
-        Element p = enclosingElement;
-        while (p != null && p.getKind() != ElementKind.CLASS && p.getKind() != ElementKind.ENUM) {
-            p = p.getEnclosingElement();
-        }
-        return (CodeTypeElement) p;
-    }
-
-    <T> List<T> parentableList(Element parent, List<T> list) {
-        return new ParentableList<>(parent, list);
-    }
-
-    @Override
-    public String toString() {
-        StringBuilderCodeWriter codeWriter = new StringBuilderCodeWriter();
-        accept(codeWriter, null);
-        return codeWriter.getString();
-    }
-
-    private static class StringBuilderCodeWriter extends AbstractCodeWriter {
-
-        public StringBuilderCodeWriter() {
-            this.writer = new CharArrayWriter();
-        }
-
-        @Override
-        protected Writer createWriter(CodeTypeElement clazz) throws IOException {
-            return writer;
-        }
-
-        public String getString() {
-            return new String(((CharArrayWriter) writer).toCharArray()).trim();
-        }
-
-    }
-
-    private static class ParentableList<T> implements List<T> {
-
-        private final Element parent;
-        private final List<T> delegate;
-
-        public ParentableList(Element parent, List<T> delegate) {
-            this.parent = parent;
-            this.delegate = delegate;
-        }
-
-        private void addImpl(T element) {
-            if (element != null) {
-                if (element instanceof CodeElement<?>) {
-                    ((CodeElement<?>) element).setEnclosingElement(parent);
-                }
-            }
-        }
-
-        private static void removeImpl(Object element) {
-            if (element instanceof CodeElement<?>) {
-                ((CodeElement<?>) element).setEnclosingElement(null);
-            }
-        }
-
-        @Override
-        public int size() {
-            return delegate.size();
-        }
-
-        @Override
-        public boolean isEmpty() {
-            return delegate.isEmpty();
-        }
-
-        @Override
-        public boolean contains(Object o) {
-            return delegate.contains(o);
-        }
-
-        @Override
-        public Iterator<T> iterator() {
-            return delegate.iterator();
-        }
-
-        @Override
-        public Object[] toArray() {
-            return delegate.toArray();
-        }
-
-        @Override
-        public <E> E[] toArray(E[] a) {
-            return delegate.toArray(a);
-        }
-
-        @Override
-        public boolean add(T e) {
-            addImpl(e);
-            return delegate.add(e);
-        }
-
-        @Override
-        public boolean remove(Object o) {
-            boolean removed = delegate.remove(o);
-            if (removed) {
-                removeImpl(o);
-            }
-            return removed;
-        }
-
-        @Override
-        public boolean containsAll(Collection<?> c) {
-            return delegate.containsAll(c);
-        }
-
-        @Override
-        public boolean addAll(Collection<? extends T> c) {
-            if (c != null) {
-                for (T t : c) {
-                    addImpl(t);
-                }
-            }
-            return delegate.addAll(c);
-        }
-
-        @Override
-        public boolean addAll(int index, Collection<? extends T> c) {
-            if (c != null) {
-                for (T t : c) {
-                    addImpl(t);
-                }
-            }
-            return delegate.addAll(index, c);
-        }
-
-        @Override
-        public boolean removeAll(Collection<?> c) {
-            if (c != null) {
-                for (Object t : c) {
-                    removeImpl(t);
-                }
-            }
-            return delegate.removeAll(c);
-        }
-
-        @Override
-        public String toString() {
-            return delegate.toString();
-        }
-
-        @Override
-        public boolean retainAll(Collection<?> c) {
-            throw new UnsupportedOperationException("Not supported by parentable list");
-        }
-
-        @Override
-        public void clear() {
-            for (Object e : this) {
-                removeImpl(e);
-            }
-            delegate.clear();
-        }
-
-        @Override
-        public T get(int index) {
-            return delegate.get(index);
-        }
-
-        @Override
-        public T set(int index, T element) {
-            removeImpl(delegate.get(index));
-            addImpl(element);
-            return delegate.set(index, element);
-        }
-
-        @Override
-        public void add(int index, T element) {
-            addImpl(element);
-            delegate.add(index, element);
-        }
-
-        @Override
-        public T remove(int index) {
-            T element = delegate.remove(index);
-            removeImpl(element);
-            return element;
-        }
-
-        @Override
-        public int indexOf(Object o) {
-            return delegate.indexOf(o);
-        }
-
-        @Override
-        public int lastIndexOf(Object o) {
-            return delegate.lastIndexOf(o);
-        }
-
-        @Override
-        public ListIterator<T> listIterator() {
-            return delegate.listIterator();
-        }
-
-        @Override
-        public ListIterator<T> listIterator(int index) {
-            return delegate.listIterator(index);
-        }
-
-        @Override
-        public List<T> subList(int fromIndex, int toIndex) {
-            return new ParentableList<>(parent, delegate.subList(fromIndex, toIndex));
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeElementScanner.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import javax.lang.model.element.*;
-import javax.lang.model.util.*;
-
-public abstract class CodeElementScanner<R, P> extends ElementScanner7<R, P> {
-
-    @Override
-    public final R visitExecutable(ExecutableElement e, P p) {
-        return visitExecutable(cast(e, CodeExecutableElement.class), p);
-    }
-
-    public R visitExecutable(CodeExecutableElement e, P p) {
-        R ret = super.visitExecutable(e, p);
-        if (e.getBodyTree() != null) {
-            visitTree(e.getBodyTree(), p);
-        }
-        return ret;
-    }
-
-    @Override
-    public R visitPackage(PackageElement e, P p) {
-        return super.visitPackage(e, p);
-    }
-
-    @Override
-    public final R visitType(TypeElement e, P p) {
-        return visitType(cast(e, CodeTypeElement.class), p);
-    }
-
-    public R visitType(CodeTypeElement e, P p) {
-        return super.visitType(e, p);
-    }
-
-    @Override
-    public R visitTypeParameter(TypeParameterElement e, P p) {
-        return super.visitTypeParameter(e, p);
-    }
-
-    private static <E> E cast(Element element, Class<E> clazz) {
-        return clazz.cast(element);
-    }
-
-    public void visitTree(CodeTree e, P p) {
-        for (CodeTree tree : e.getEnclosedElements()) {
-            tree.acceptCodeElementScanner(this, p);
-        }
-    }
-
-    @SuppressWarnings("unused")
-    public void visitImport(CodeImport e, P p) {
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeExecutableElement.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,236 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.api.element.*;
-
-public class CodeExecutableElement extends CodeElement<Element> implements WritableExecutableElement {
-
-    private final List<TypeMirror> throwables = new ArrayList<>();
-    private final List<VariableElement> parameters = parentableList(this, new ArrayList<VariableElement>());
-
-    private TypeMirror returnType;
-    private Name name;
-
-    private CodeTree bodyTree;
-    private String body;
-    private AnnotationValue defaultValue;
-    private boolean varArgs;
-
-    public CodeExecutableElement(TypeMirror returnType, String name) {
-        super(Utils.modifiers());
-        this.returnType = returnType;
-        this.name = CodeNames.of(name);
-    }
-
-    public CodeExecutableElement(Set<Modifier> modifiers, TypeMirror returnType, String name, CodeVariableElement... parameters) {
-        super(modifiers);
-        this.returnType = returnType;
-        this.name = CodeNames.of(name);
-        for (CodeVariableElement codeParameter : parameters) {
-            addParameter(codeParameter);
-        }
-    }
-
-    /* Support JDK8 langtools. */
-    public boolean isDefault() {
-        return false;
-    }
-
-    @Override
-    public List<TypeMirror> getThrownTypes() {
-        return throwables;
-    }
-
-    @Override
-    public TypeMirror asType() {
-        return returnType;
-    }
-
-    @Override
-    public ElementKind getKind() {
-        if (getReturnType() == null) {
-            return ElementKind.CONSTRUCTOR;
-        } else {
-            return ElementKind.METHOD;
-        }
-    }
-
-    @Override
-    public List<? extends TypeParameterElement> getTypeParameters() {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public void setVarArgs(boolean varargs) {
-        this.varArgs = varargs;
-    }
-
-    @Override
-    public boolean isVarArgs() {
-        return varArgs;
-    }
-
-    @Override
-    public void setDefaultValue(AnnotationValue defaultValue) {
-        this.defaultValue = defaultValue;
-    }
-
-    @Override
-    public AnnotationValue getDefaultValue() {
-        return defaultValue;
-    }
-
-    @Override
-    public Name getSimpleName() {
-        return name;
-    }
-
-    public CodeTreeBuilder getBuilder() {
-        CodeTree tree = this.bodyTree;
-        return createBuilder().tree(tree);
-    }
-
-    public CodeTreeBuilder createBuilder() {
-        CodeTreeBuilder builder = new CodeTreeBuilder(null);
-        this.bodyTree = builder.getTree();
-        this.bodyTree.setEnclosingElement(this);
-        this.body = null;
-        return builder;
-    }
-
-    public void setBodyTree(CodeTree body) {
-        this.bodyTree = body;
-    }
-
-    public CodeTree getBodyTree() {
-        return bodyTree;
-    }
-
-    public TypeMirror getReturnType() {
-        return returnType;
-    }
-
-    @Override
-    public List<VariableElement> getParameters() {
-        return parameters;
-    }
-
-    public TypeMirror[] getParameterTypes() {
-        TypeMirror[] types = new TypeMirror[getParameters().size()];
-        for (int i = 0; i < types.length; i++) {
-            types[i] = parameters.get(i).asType();
-        }
-        return types;
-    }
-
-    @Override
-    public void setReturnType(TypeMirror type) {
-        returnType = type;
-    }
-
-    @Override
-    public void addParameter(VariableElement parameter) {
-        parameters.add(parameter);
-    }
-
-    @Override
-    public void removeParameter(VariableElement parameter) {
-        parameters.remove(parameter);
-    }
-
-    public void removeParameter(String varName) {
-        VariableElement remove = null;
-        for (VariableElement var : getParameters()) {
-            if (var.getSimpleName().toString().equals(varName)) {
-                remove = var;
-                break;
-            }
-        }
-        if (remove != null) {
-            parameters.remove(remove);
-        }
-    }
-
-    @Override
-    public void addThrownType(TypeMirror thrownType) {
-        throwables.add(thrownType);
-    }
-
-    @Override
-    public void removeThrownType(TypeMirror thrownType) {
-        throwables.remove(thrownType);
-    }
-
-    @Override
-    public void setSimpleName(Name name) {
-        this.name = name;
-    }
-
-    @Override
-    public void setBody(String body) {
-        this.body = body;
-    }
-
-    @Override
-    public String getBody() {
-        return body;
-    }
-
-    @Override
-    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
-        return v.visitExecutable(this, p);
-    }
-
-    public static CodeExecutableElement clone(@SuppressWarnings("unused") ProcessingEnvironment env, ExecutableElement method) {
-        CodeExecutableElement copy = new CodeExecutableElement(method.getReturnType(), method.getSimpleName().toString());
-        for (TypeMirror thrownType : method.getThrownTypes()) {
-            copy.addThrownType(thrownType);
-        }
-        copy.setDefaultValue(method.getDefaultValue());
-
-        for (AnnotationMirror mirror : method.getAnnotationMirrors()) {
-            copy.addAnnotationMirror(mirror);
-        }
-        for (VariableElement var : method.getParameters()) {
-            copy.addParameter(CodeVariableElement.clone(var));
-        }
-        for (Element element : method.getEnclosedElements()) {
-            copy.add(element);
-        }
-        copy.getModifiers().addAll(method.getModifiers());
-        copy.setVarArgs(method.isVarArgs());
-        return copy;
-    }
-
-    public TypeMirror getReceiverType() {
-        throw new UnsupportedOperationException();
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeImport.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import javax.lang.model.type.*;
-
-public class CodeImport implements Comparable<CodeImport> {
-
-    private final TypeMirror importType;
-    private final String importString;
-    private final boolean staticImport;
-
-    public CodeImport(TypeMirror importedType, String importString, boolean staticImport) {
-        this.importType = importedType;
-        this.importString = importString;
-        this.staticImport = staticImport;
-    }
-
-    public TypeMirror getImportType() {
-        return importType;
-    }
-
-    public boolean isStaticImport() {
-        return staticImport;
-    }
-
-    public String getImportString() {
-        return importString;
-    }
-
-    @Override
-    public int compareTo(CodeImport o) {
-        if (staticImport && !o.staticImport) {
-            return 1;
-        } else if (!staticImport && o.staticImport) {
-            return -1;
-        } else {
-            return importString.compareTo(o.getImportString());
-        }
-    }
-
-    public <P> void accept(CodeElementScanner<?, P> s, P p) {
-        s.visitImport(this, p);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((importString == null) ? 0 : importString.hashCode());
-        result = prime * result + (staticImport ? 1231 : 1237);
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        CodeImport other = (CodeImport) obj;
-        if (importString == null) {
-            if (other.importString != null) {
-                return false;
-            }
-        } else if (!importString.equals(other.importString)) {
-            return false;
-        }
-        if (staticImport != other.staticImport) {
-            return false;
-        }
-        return true;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeNames.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-
-public abstract class CodeNames {
-
-    private static Map<String, Name> names = new HashMap<>();
-
-    public static Name of(String value) {
-        Name name = names.get(value);
-        if (name == null) {
-            name = new NameImpl(value);
-            names.put(value, name);
-        }
-        return name;
-    }
-
-    private static class NameImpl implements Name {
-
-        private final String name;
-
-        public NameImpl(String name) {
-            this.name = name;
-        }
-
-        @Override
-        public int length() {
-            return name.length();
-        }
-
-        @Override
-        public char charAt(int index) {
-            return name.charAt(index);
-        }
-
-        @Override
-        public CharSequence subSequence(int start, int end) {
-            return name.subSequence(start, end);
-        }
-
-        @Override
-        public boolean contentEquals(CharSequence cs) {
-            return name.contentEquals(cs);
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof Name) {
-                return ((Name) obj).contentEquals(name);
-            }
-            return super.equals(obj);
-        }
-
-        @Override
-        public int hashCode() {
-            return name.hashCode();
-        }
-
-        @Override
-        public String toString() {
-            return name;
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTree.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-public class CodeTree extends CodeElement<CodeTree> {
-
-    private final CodeTreeKind kind;
-
-    private final TypeMirror type;
-    private final String string;
-
-    public CodeTree(CodeTreeKind kind, TypeMirror type, String string) {
-        this.kind = kind;
-        this.type = type;
-        this.string = string;
-    }
-
-    public TypeMirror getType() {
-        return type;
-    }
-
-    public CodeTreeKind getCodeKind() {
-        return kind;
-    }
-
-    public String getString() {
-        return string;
-    }
-
-    public <P> void acceptCodeElementScanner(CodeElementScanner<?, P> s, P p) {
-        s.visitTree(this, p);
-    }
-
-    @Override
-    public TypeMirror asType() {
-        return type;
-    }
-
-    @Override
-    public ElementKind getKind() {
-        return ElementKind.OTHER;
-    }
-
-    @Override
-    public Name getSimpleName() {
-        return CodeNames.of(getString());
-    }
-
-    @Override
-    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
-        if (v instanceof CodeElementScanner<?, ?>) {
-            acceptCodeElementScanner((CodeElementScanner<?, P>) v, p);
-            return null;
-        } else {
-            throw new UnsupportedOperationException();
-        }
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeBuilder.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,884 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import static com.oracle.truffle.dsl.processor.ast.CodeTreeKind.*;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-
-public class CodeTreeBuilder {
-
-    private final CodeTreeBuilder parent;
-
-    private BuilderCodeTree currentElement;
-    private final BuilderCodeTree root;
-
-    private int treeCount;
-
-    public CodeTreeBuilder(CodeTreeBuilder parent) {
-        this.root = new BuilderCodeTree(GROUP, null, null);
-        this.currentElement = root;
-        this.parent = parent;
-    }
-
-    @Override
-    public String toString() {
-        return root.toString();
-    }
-
-    public int getTreeCount() {
-        return treeCount;
-    }
-
-    public boolean isEmpty() {
-        return treeCount == 0;
-    }
-
-    public CodeTreeBuilder statement(String statement) {
-        return startStatement().string(statement).end();
-    }
-
-    public CodeTreeBuilder statement(CodeTree statement) {
-        return startStatement().tree(statement).end();
-    }
-
-    public static CodeTreeBuilder createBuilder() {
-        return new CodeTreeBuilder(null);
-    }
-
-    public static CodeTree singleString(String s) {
-        return new CodeTreeBuilder(null).string(s).getTree();
-    }
-
-    public static CodeTree singleType(TypeMirror s) {
-        return new CodeTreeBuilder(null).type(s).getTree();
-    }
-
-    private CodeTreeBuilder push(CodeTreeKind kind) {
-        return push(new BuilderCodeTree(kind, null, null));
-    }
-
-    private CodeTreeBuilder push(String string) {
-        return push(new BuilderCodeTree(CodeTreeKind.STRING, null, string));
-    }
-
-    private CodeTreeBuilder push(TypeMirror type) {
-        return push(new BuilderCodeTree(CodeTreeKind.TYPE, type, null));
-    }
-
-    private CodeTreeBuilder push(CodeTreeKind kind, TypeMirror type, String string) {
-        return push(new BuilderCodeTree(kind, type, string));
-    }
-
-    private CodeTreeBuilder push(BuilderCodeTree tree) {
-        if (currentElement != null) {
-            if (!removeLastIfEnqueued(tree)) {
-                return this;
-            }
-            currentElement.add(tree);
-        }
-        switch (tree.getCodeKind()) {
-            case COMMA_GROUP:
-            case GROUP:
-            case INDENT:
-                currentElement = tree;
-                break;
-        }
-        treeCount++;
-        return this;
-    }
-
-    private boolean removeLastIfEnqueued(BuilderCodeTree tree) {
-        if (tree.getCodeKind() == REMOVE_LAST) {
-            return !clearLastRec(tree.removeLast, currentElement.getEnclosedElements());
-        }
-        List<CodeTree> childTree = tree.getEnclosedElements();
-        if (!childTree.isEmpty()) {
-            CodeTree last = childTree.get(0);
-            if (last instanceof BuilderCodeTree) {
-                if (!removeLastIfEnqueued((BuilderCodeTree) last)) {
-                    childTree.remove(0);
-                }
-            }
-        }
-        return true;
-    }
-
-    private void clearLast(CodeTreeKind kind) {
-        if (clearLastRec(kind, currentElement.getEnclosedElements())) {
-            treeCount--;
-        } else {
-            // delay clearing the last
-            BuilderCodeTree tree = new BuilderCodeTree(REMOVE_LAST, null, null);
-            tree.removeLast = kind;
-            push(tree);
-        }
-    }
-
-    public CodeTreeBuilder startStatement() {
-        startGroup();
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-                string(";").newLine();
-            }
-
-            @Override
-            public void afterEnd() {
-            }
-        });
-        return this;
-    }
-
-    public CodeTreeBuilder startGroup() {
-        return push(CodeTreeKind.GROUP);
-    }
-
-    public CodeTreeBuilder startCommaGroup() {
-        return push(CodeTreeKind.COMMA_GROUP);
-    }
-
-    public CodeTreeBuilder startCall(String 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().tree(receiver).string(".").string(callSite).startParanthesesCommaGroup().endAfter();
-        }
-    }
-
-    public CodeTreeBuilder startStaticCall(TypeMirror type, String methodName) {
-        return startGroup().push(CodeTreeKind.STATIC_METHOD_REFERENCE, type, methodName).startParanthesesCommaGroup().endAfter();
-    }
-
-    public CodeTreeBuilder startStaticCall(ExecutableElement method) {
-        return startStaticCall(Utils.findNearestEnclosingType(method).asType(), method.getSimpleName().toString());
-    }
-
-    public CodeTreeBuilder staticReference(TypeMirror type, String fieldName) {
-        return push(CodeTreeKind.STATIC_FIELD_REFERENCE, type, fieldName);
-    }
-
-    private CodeTreeBuilder endAndWhitespaceAfter() {
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-            }
-
-            @Override
-            public void afterEnd() {
-                string(" ");
-                end();
-            }
-        });
-        return this;
-    }
-
-    private CodeTreeBuilder endAfter() {
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-            }
-
-            @Override
-            public void afterEnd() {
-                end();
-            }
-        });
-        return this;
-    }
-
-    private CodeTreeBuilder startParanthesesCommaGroup() {
-        startGroup();
-        string("(").startCommaGroup();
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-            }
-
-            @Override
-            public void afterEnd() {
-                string(")");
-            }
-        });
-        endAfter();
-        return this;
-    }
-
-    private CodeTreeBuilder startCurlyBracesCommaGroup() {
-        startGroup();
-        string("{").startCommaGroup();
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-            }
-
-            @Override
-            public void afterEnd() {
-                string("}");
-            }
-        });
-        endAfter();
-        return this;
-    }
-
-    public CodeTreeBuilder startParantheses() {
-        startGroup();
-        string("(").startGroup();
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-            }
-
-            @Override
-            public void afterEnd() {
-                string(")");
-            }
-        });
-        endAfter();
-        return this;
-    }
-
-    public CodeTreeBuilder doubleQuote(String s) {
-        return startGroup().string("\"" + s + "\"").end();
-    }
-
-    public CodeTreeBuilder string(String chunk1) {
-        return push(chunk1);
-    }
-
-    public CodeTreeBuilder string(String chunk1, String chunk2) {
-        return push(GROUP).string(chunk1).string(chunk2).end();
-    }
-
-    public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3) {
-        return push(GROUP).string(chunk1).string(chunk2).string(chunk3).end();
-    }
-
-    public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4) {
-        return push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4).end();
-    }
-
-    public CodeTreeBuilder tree(CodeTree treeToAdd) {
-        if (treeToAdd instanceof BuilderCodeTree) {
-            return push((BuilderCodeTree) treeToAdd).end();
-        } else {
-            BuilderCodeTree tree = new BuilderCodeTree(GROUP, null, null);
-            tree.add(treeToAdd);
-            return push(tree).end();
-        }
-    }
-
-    public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4, String... chunks) {
-        push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4);
-        for (int i = 0; i < chunks.length; i++) {
-            string(chunks[i]);
-        }
-        return end();
-    }
-
-    public CodeTreeBuilder dot() {
-        return string(".");
-    }
-
-    public CodeTreeBuilder newLine() {
-        return push(NEW_LINE);
-    }
-
-    public CodeTreeBuilder startWhile() {
-        return startGroup().string("while ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter();
-    }
-
-    public CodeTreeBuilder startDoBlock() {
-        return startGroup().string("do ").startBlock();
-    }
-
-    public CodeTreeBuilder startDoWhile() {
-        clearLast(CodeTreeKind.NEW_LINE);
-        return startStatement().string(" while ").startParanthesesCommaGroup().endAfter().startGroup().endAfter();
-    }
-
-    public CodeTreeBuilder startIf() {
-        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();
-        } else {
-            startIf();
-        }
-        return true;
-    }
-
-    public CodeTreeBuilder startElseIf() {
-        clearLast(CodeTreeKind.NEW_LINE);
-        return startGroup().string(" else if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter();
-    }
-
-    public CodeTreeBuilder startElseBlock() {
-        clearLast(CodeTreeKind.NEW_LINE);
-        return startGroup().string(" else ").startBlock().endAfter();
-    }
-
-    private boolean clearLastRec(CodeTreeKind kind, List<CodeTree> children) {
-        for (int i = children.size() - 1; i >= 0; i--) {
-            CodeTree child = children.get(i);
-            if (child.getCodeKind() == kind) {
-                children.remove(children.get(i));
-                return true;
-            } else {
-                if (clearLastRec(kind, child.getEnclosedElements())) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    public CodeTreeBuilder startCase() {
-        startGroup().string("case ");
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-                string(" :").newLine();
-            }
-
-            @Override
-            public void afterEnd() {
-            }
-        });
-        return this;
-    }
-
-    public CodeTreeBuilder caseDefault() {
-        return startGroup().string("default :").newLine().end();
-    }
-
-    public CodeTreeBuilder startSwitch() {
-        return startGroup().string("switch ").startParanthesesCommaGroup().endAndWhitespaceAfter();
-    }
-
-    public CodeTreeBuilder startReturn() {
-        ExecutableElement method = findMethod();
-        if (method != null && Utils.isVoid(method.getReturnType())) {
-            startGroup();
-            registerCallBack(new EndCallback() {
-
-                @Override
-                public void beforeEnd() {
-                    string(";").newLine(); // complete statement to execute
-                }
-
-                @Override
-                public void afterEnd() {
-                    string("return").string(";").newLine(); // emit a return;
-                }
-            });
-            return this;
-        } else {
-            return startStatement().string("return ");
-        }
-    }
-
-    public CodeTreeBuilder startAssert() {
-        return startStatement().string("assert ");
-    }
-
-    public CodeTreeBuilder startNewArray(ArrayType arrayType, CodeTree size) {
-        startGroup().string("new ").type(arrayType.getComponentType()).string("[");
-        if (size != null) {
-            tree(size);
-        }
-        string("]");
-        if (size == null) {
-            string(" ");
-            startCurlyBracesCommaGroup().endAfter();
-        }
-        return this;
-    }
-
-    public CodeTreeBuilder startNew(TypeMirror uninializedNodeClass) {
-        return startGroup().string("new ").type(uninializedNodeClass).startParanthesesCommaGroup().endAfter();
-    }
-
-    public CodeTreeBuilder startNew(String typeName) {
-        return startGroup().string("new ").string(typeName).startParanthesesCommaGroup().endAfter();
-    }
-
-    public CodeTreeBuilder startIndention() {
-        return push(CodeTreeKind.INDENT);
-    }
-
-    public CodeTreeBuilder end(int times) {
-        for (int i = 0; i < times; i++) {
-            end();
-        }
-        return this;
-    }
-
-    public CodeTreeBuilder end() {
-        BuilderCodeTree tree = currentElement;
-        EndCallback callback = tree.getAtEndListener();
-        if (callback != null) {
-            callback.beforeEnd();
-            toParent();
-            callback.afterEnd();
-        } else {
-            toParent();
-        }
-        return this;
-    }
-
-    private void toParent() {
-        Element parentElement = currentElement.getEnclosingElement();
-        if (currentElement != root) {
-            this.currentElement = (BuilderCodeTree) parentElement;
-        } else {
-            this.currentElement = root;
-        }
-    }
-
-    public CodeTreeBuilder startBlock() {
-        startGroup();
-        string("{").newLine().startIndention();
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-            }
-
-            @Override
-            public void afterEnd() {
-                string("}").newLine();
-            }
-        });
-        endAfter();
-        return this;
-    }
-
-    private void registerCallBack(EndCallback callback) {
-        currentElement.registerAtEnd(callback);
-    }
-
-    public CodeTreeBuilder defaultDeclaration(TypeMirror type, String name) {
-        if (!Utils.isVoid(type)) {
-            startStatement();
-            type(type);
-            string(" ");
-            string(name);
-            string(" = ");
-            defaultValue(type);
-            end(); // statement
-        }
-        return this;
-    }
-
-    public CodeTreeBuilder declaration(TypeMirror type, String name, String init) {
-        return declaration(type, name, singleString(init));
-    }
-
-    public CodeTreeBuilder declaration(String type, String name, CodeTree init) {
-        startStatement();
-        string(type);
-        string(" ");
-        string(name);
-        if (init != null) {
-            string(" = ");
-            tree(init);
-        }
-        end(); // statement
-        return this;
-    }
-
-    public CodeTreeBuilder declaration(String type, String name, String init) {
-        return declaration(type, name, singleString(init));
-    }
-
-    public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTree init) {
-        if (Utils.isVoid(type)) {
-            startStatement();
-            tree(init);
-            end();
-        } else {
-            startStatement();
-            type(type);
-            string(" ");
-            string(name);
-            if (init != null) {
-                string(" = ");
-                tree(init);
-            }
-            end(); // statement
-        }
-        return this;
-    }
-
-    public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTreeBuilder init) {
-        if (init == this) {
-            throw new IllegalArgumentException("Recursive builder usage.");
-        }
-        return declaration(type, name, init.getTree());
-    }
-
-    public CodeTreeBuilder declaration(String type, String name, CodeTreeBuilder init) {
-        if (init == this) {
-            throw new IllegalArgumentException("Recursive builder usage.");
-        }
-        return declaration(type, name, init.getTree());
-    }
-
-    public CodeTreeBuilder declaration(TypeMirror type, String name) {
-        return declaration(type, name, (CodeTree) null);
-    }
-
-    public CodeTreeBuilder create() {
-        return new CodeTreeBuilder(this);
-    }
-
-    public CodeTreeBuilder type(TypeMirror type) {
-        return push(type);
-    }
-
-    public CodeTreeBuilder typeLiteral(TypeMirror type) {
-        return startGroup().type(type).string(".class").end();
-    }
-
-    private void assertRoot() {
-        if (currentElement != root) {
-            throw new IllegalStateException("CodeTreeBuilder was not ended properly.");
-        }
-    }
-
-    public CodeTreeBuilder startCaseBlock() {
-        return startIndention();
-    }
-
-    public CodeTreeBuilder startThrow() {
-        return startStatement().string("throw ");
-    }
-
-    public CodeTree getTree() {
-        assertRoot();
-        return root;
-    }
-
-    public CodeTree getRoot() {
-        return root;
-    }
-
-    public CodeTreeBuilder cast(String baseClassName) {
-        string("(").string(baseClassName).string(") ");
-        return this;
-    }
-
-    public CodeTreeBuilder cast(TypeMirror type, CodeTree content) {
-        if (Utils.isVoid(type)) {
-            tree(content);
-            return this;
-        } else if (type.getKind() == TypeKind.DECLARED && Utils.getQualifiedName(type).equals("java.lang.Object")) {
-            tree(content);
-            return this;
-        } else {
-            return startGroup().string("(").type(type).string(")").string(" ").tree(content).end();
-        }
-    }
-
-    public CodeTreeBuilder startSuperCall() {
-        return string("super").startParanthesesCommaGroup();
-    }
-
-    public CodeTreeBuilder returnFalse() {
-        return startReturn().string("false").end();
-    }
-
-    public CodeTreeBuilder returnStatement() {
-        return statement("return");
-    }
-
-    public ExecutableElement findMethod() {
-        Element element = currentElement;
-        while (element != null && (element.getKind() != ElementKind.METHOD && (element.getKind() != ElementKind.CONSTRUCTOR))) {
-            element = element.getEnclosingElement();
-        }
-        ExecutableElement found = element != null ? (ExecutableElement) element : null;
-        if (found == null && parent != null) {
-            found = parent.findMethod();
-        }
-        return found;
-    }
-
-    public CodeTreeBuilder returnTrue() {
-        return startReturn().string("true").end();
-    }
-
-    public CodeTreeBuilder instanceOf(CodeTree var, CodeTree type) {
-        tree(var).string(" instanceof ").tree(type);
-        return this;
-    }
-
-    public CodeTreeBuilder instanceOf(String var, String type) {
-        return instanceOf(singleString(var), singleString(type));
-    }
-
-    public CodeTreeBuilder instanceOf(String var, TypeMirror type) {
-        TypeElement element = Utils.fromTypeMirror(type);
-        if (element == null) {
-            throw new IllegalArgumentException("Cannot call instanceof for a non supported type: " + type.getKind());
-        }
-        return instanceOf(singleString(var), singleType(type));
-    }
-
-    public CodeTreeBuilder defaultValue(TypeMirror mirror) {
-        switch (mirror.getKind()) {
-            case VOID:
-                return string("");
-            case ARRAY:
-            case DECLARED:
-            case PACKAGE:
-            case NULL:
-                return string("null");
-            case BOOLEAN:
-                return string("false");
-            case BYTE:
-                return string("(byte) 0");
-            case CHAR:
-                return string("(char) 0");
-            case DOUBLE:
-                return string("0.0D");
-            case LONG:
-                return string("0L");
-            case INT:
-                return string("0");
-            case FLOAT:
-                return string("0.0F");
-            case SHORT:
-                return string("(short) 0");
-            default:
-                throw new AssertionError();
-        }
-    }
-
-    public CodeTreeBuilder assertFalse() {
-        return startAssert().string("false").end();
-    }
-
-    public CodeTreeBuilder breakStatement() {
-        return statement("break");
-    }
-
-    public CodeTreeBuilder isNull() {
-        return string(" == null");
-    }
-
-    public CodeTreeBuilder isNotNull() {
-        return string(" != null");
-    }
-
-    public CodeTreeBuilder is(CodeTree tree) {
-        return string(" == ").tree(tree);
-    }
-
-    public CodeTreeBuilder startTryBlock() {
-        return string("try ").startBlock();
-    }
-
-    public CodeTreeBuilder startCatchBlock(TypeMirror exceptionType, String localVarName) {
-        clearLast(CodeTreeKind.NEW_LINE);
-        string(" catch (").type(exceptionType).string(" ").string(localVarName).string(") ");
-        return startBlock();
-    }
-
-    public CodeTreeBuilder startFinallyBlock() {
-        clearLast(CodeTreeKind.NEW_LINE);
-        string(" finally ");
-        return startBlock();
-    }
-
-    public CodeTreeBuilder nullLiteral() {
-        return string("null");
-    }
-
-    private static class BuilderCodeTree extends CodeTree {
-
-        private EndCallback atEndListener;
-        private CodeTreeKind removeLast;
-
-        public BuilderCodeTree(CodeTreeKind kind, TypeMirror type, String string) {
-            super(kind, type, string);
-        }
-
-        public void registerAtEnd(EndCallback atEnd) {
-            if (this.atEndListener != null) {
-                this.atEndListener = new CompoundCallback(this.atEndListener, atEnd);
-            } else {
-                this.atEndListener = atEnd;
-            }
-        }
-
-        public EndCallback getAtEndListener() {
-            return atEndListener;
-        }
-
-        @Override
-        public String toString() {
-            final StringBuilder b = new StringBuilder();
-            acceptCodeElementScanner(new Printer(b), null);
-            return b.toString();
-        }
-
-        private static class CompoundCallback implements EndCallback {
-
-            private final EndCallback callback1;
-            private final EndCallback callback2;
-
-            public CompoundCallback(EndCallback callback1, EndCallback callback2) {
-                this.callback1 = callback1;
-                this.callback2 = callback2;
-            }
-
-            @Override
-            public void afterEnd() {
-                callback1.afterEnd();
-                callback2.afterEnd();
-            }
-
-            @Override
-            public void beforeEnd() {
-                callback1.beforeEnd();
-                callback1.beforeEnd();
-            }
-        }
-
-    }
-
-    private interface EndCallback {
-
-        void beforeEnd();
-
-        void afterEnd();
-    }
-
-    private static class Printer extends CodeElementScanner<Void, Void> {
-
-        private int indent;
-        private boolean newLine;
-        private final String ln = "\n";
-
-        private final StringBuilder b;
-
-        Printer(StringBuilder b) {
-            this.b = b;
-        }
-
-        @Override
-        public void visitTree(CodeTree e, Void p) {
-            switch (e.getCodeKind()) {
-                case COMMA_GROUP:
-                    List<CodeTree> children = e.getEnclosedElements();
-                    for (int i = 0; i < children.size(); i++) {
-                        children.get(i).acceptCodeElementScanner(this, p);
-                        if (i < e.getEnclosedElements().size() - 1) {
-                            b.append(", ");
-                        }
-                    }
-                    break;
-                case GROUP:
-                    super.visitTree(e, p);
-                    break;
-                case INDENT:
-                    indent();
-                    super.visitTree(e, p);
-                    dedent();
-                    break;
-                case NEW_LINE:
-                    writeLn();
-                    break;
-                case STRING:
-                    if (e.getString() != null) {
-                        write(e.getString());
-                    } else {
-                        write("null");
-                    }
-                    break;
-                case TYPE:
-                    write(Utils.getSimpleName(e.getType()));
-                    break;
-                default:
-                    assert false;
-                    return;
-            }
-        }
-
-        private void indent() {
-            indent++;
-        }
-
-        private void dedent() {
-            indent--;
-        }
-
-        private void writeLn() {
-            write(ln);
-            newLine = true;
-        }
-
-        private void write(String m) {
-            if (newLine && m != ln) {
-                writeIndent();
-                newLine = false;
-            }
-            b.append(m);
-        }
-
-        private void writeIndent() {
-            for (int i = 0; i < indent; i++) {
-                b.append("    ");
-            }
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeKind.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-public enum CodeTreeKind {
-    STATIC_FIELD_REFERENCE,
-    STATIC_METHOD_REFERENCE,
-    GROUP,
-    COMMA_GROUP,
-    REMOVE_LAST,
-    INDENT,
-    STRING,
-    NEW_LINE,
-    TYPE;
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTypeElement.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,212 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.dsl.processor.ast.CodeTypeMirror.DeclaredCodeTypeMirror;
-
-public class CodeTypeElement extends CodeElement<Element> implements TypeElement {
-
-    private final List<? extends CodeImport> imports = parentableList(this, new ArrayList<CodeImport>());
-
-    private final PackageElement packageElement;
-
-    private final Name simpleName;
-    private final Name packageName;
-    private Name qualifiedName;
-
-    private final List<TypeMirror> implementsInterfaces = new ArrayList<>();
-    private final ElementKind kind;
-    private TypeMirror superClass;
-
-    private final DeclaredCodeTypeMirror mirror = new DeclaredCodeTypeMirror(this);
-
-    public CodeTypeElement(Set<Modifier> modifiers, ElementKind kind, PackageElement packageElement, String simpleName) {
-        super(modifiers);
-        this.kind = kind;
-        this.packageElement = packageElement;
-        this.simpleName = CodeNames.of(simpleName);
-        if (this.packageElement != null) {
-            this.packageName = packageElement.getQualifiedName();
-        } else {
-            this.packageName = CodeNames.of("default");
-        }
-        this.qualifiedName = createQualifiedName();
-    }
-
-    @Override
-    public TypeMirror asType() {
-        return mirror;
-    }
-
-    @Override
-    public ElementKind getKind() {
-        return kind;
-    }
-
-    public boolean containsField(String name) {
-        for (VariableElement field : getFields()) {
-            if (field.getSimpleName().toString().equals(name)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public NestingKind getNestingKind() {
-        return isTopLevelClass() ? NestingKind.TOP_LEVEL : NestingKind.LOCAL;
-    }
-
-    @Override
-    public Element getEnclosingElement() {
-        if (isTopLevelClass()) {
-            return packageElement;
-        } else {
-            return super.getEnclosingElement();
-        }
-    }
-
-    @Override
-    public TypeMirror getSuperclass() {
-        return superClass;
-    }
-
-    @Override
-    public List<TypeMirror> getInterfaces() {
-        return implementsInterfaces;
-    }
-
-    @Override
-    public List<? extends TypeParameterElement> getTypeParameters() {
-        return Collections.emptyList();
-    }
-
-    public boolean isTopLevelClass() {
-        return super.getEnclosingElement() instanceof CodeCompilationUnit;
-    }
-
-    public CodeVariableElement getField(String name) {
-        for (VariableElement field : ElementFilter.fieldsIn(getEnclosedElements())) {
-            if (field.getSimpleName().toString().equals(name)) {
-                return (CodeVariableElement) field;
-            }
-        }
-        return null;
-    }
-
-    private Name createQualifiedName() {
-        TypeElement enclosingType = getEnclosingClass();
-        if (enclosingType == null) {
-            return CodeNames.of(packageName + "." + simpleName);
-        } else {
-            return CodeNames.of(enclosingType.getQualifiedName() + "." + simpleName);
-        }
-    }
-
-    @Override
-    void setEnclosingElement(Element element) {
-        super.setEnclosingElement(element);
-
-        // update qualified name on container change
-        this.qualifiedName = createQualifiedName();
-    }
-
-    public Name getPackageName() {
-        return packageName;
-    }
-
-    @Override
-    public Name getQualifiedName() {
-        return qualifiedName;
-    }
-
-    @Override
-    public Name getSimpleName() {
-        return simpleName;
-    }
-
-    public void setSuperClass(TypeMirror superType) {
-        this.superClass = superType;
-    }
-
-    public List<? extends CodeImport> getImports() {
-        return imports;
-    }
-
-    public List<TypeMirror> getImplements() {
-        return implementsInterfaces;
-    }
-
-    @Override
-    public int hashCode() {
-        return getQualifiedName().hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj == this) {
-            return true;
-        } else if (obj instanceof TypeElement) {
-            return getQualifiedName().equals(((TypeElement) obj).getQualifiedName());
-        }
-        return false;
-    }
-
-    public List<VariableElement> getFields() {
-        return ElementFilter.fieldsIn(getEnclosedElements());
-    }
-
-    public ExecutableElement getMethod(String name) {
-        for (Element element : getEnclosedElements()) {
-            if (element.getKind() == ElementKind.METHOD && element.getSimpleName().toString().equals(name)) {
-                return (ExecutableElement) element;
-            }
-        }
-        return null;
-    }
-
-    public List<ExecutableElement> getMethods() {
-        return ElementFilter.methodsIn(getEnclosedElements());
-    }
-
-    public List<TypeElement> getInnerClasses() {
-        return ElementFilter.typesIn(getEnclosedElements());
-    }
-
-    @Override
-    public String toString() {
-        return getQualifiedName().toString();
-    }
-
-    @Override
-    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
-        return v.visitType(this, p);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTypeMirror.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-public class CodeTypeMirror implements TypeMirror {
-
-    private final TypeKind kind;
-
-    public CodeTypeMirror(TypeKind kind) {
-        this.kind = kind;
-    }
-
-    @Override
-    public TypeKind getKind() {
-        return kind;
-    }
-
-    @Override
-    public <R, P> R accept(TypeVisitor<R, P> v, P p) {
-        throw new UnsupportedOperationException();
-    }
-
-    public static class ArrayCodeTypeMirror extends CodeTypeMirror implements ArrayType {
-
-        private final TypeMirror component;
-
-        public ArrayCodeTypeMirror(TypeMirror component) {
-            super(TypeKind.ARRAY);
-            this.component = component;
-        }
-
-        @Override
-        public TypeMirror getComponentType() {
-            return component;
-        }
-
-    }
-
-    public static class DeclaredCodeTypeMirror extends CodeTypeMirror implements DeclaredType {
-
-        private final TypeElement clazz;
-        private final List<? extends TypeMirror> typeArguments;
-
-        public DeclaredCodeTypeMirror(TypeElement clazz) {
-            this(clazz, Collections.<TypeMirror> emptyList());
-        }
-
-        public DeclaredCodeTypeMirror(TypeElement clazz, List<? extends TypeMirror> typeArguments) {
-            super(TypeKind.DECLARED);
-            this.clazz = clazz;
-            this.typeArguments = typeArguments;
-        }
-
-        @Override
-        public Element asElement() {
-            return clazz;
-        }
-
-        @Override
-        public TypeMirror getEnclosingType() {
-            return clazz.getEnclosingElement().asType();
-        }
-
-        @Override
-        public List<? extends TypeMirror> getTypeArguments() {
-            return typeArguments;
-        }
-
-        @Override
-        public String toString() {
-            return clazz.getQualifiedName().toString();
-        }
-
-    }
-
-    public List<? extends AnnotationMirror> getAnnotationMirrors() {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @param annotationType
-     */
-    public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @param annotationType
-     */
-    public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) {
-        throw new UnsupportedOperationException();
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeVariableElement.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.api.element.*;
-
-public final class CodeVariableElement extends CodeElement<Element> implements WritableVariableElement {
-
-    private Name name;
-    private TypeMirror type;
-    private Object constantValue;
-
-    private CodeTree init;
-
-    public CodeVariableElement(TypeMirror type, String name) {
-        super(Utils.modifiers());
-        this.type = type;
-        this.name = CodeNames.of(name);
-    }
-
-    public CodeVariableElement(Set<Modifier> modifiers, TypeMirror type, String name) {
-        super(modifiers);
-        this.type = type;
-        this.name = CodeNames.of(name);
-    }
-
-    public CodeVariableElement(Set<Modifier> modifiers, TypeMirror type, String name, String init) {
-        this(modifiers, type, name);
-        if (init != null) {
-            this.init = new CodeTree(CodeTreeKind.STRING, null, init);
-        }
-    }
-
-    public CodeTreeBuilder createInitBuilder() {
-        CodeTreeBuilder builder = new CodeTreeBuilder(null);
-        init = builder.getTree();
-        init.setEnclosingElement(this);
-        return builder;
-    }
-
-    public void setInit(CodeTree init) {
-        this.init = init;
-    }
-
-    public CodeTree getInit() {
-        return init;
-    }
-
-    public Name getSimpleName() {
-        return name;
-    }
-
-    public TypeMirror getType() {
-        return type;
-    }
-
-    @Override
-    public TypeMirror asType() {
-        return type;
-    }
-
-    @Override
-    public ElementKind getKind() {
-        if (getEnclosingElement() instanceof ExecutableElement) {
-            return ElementKind.PARAMETER;
-        } else if (getEnclosingElement() instanceof TypeElement) {
-            return ElementKind.FIELD;
-        } else {
-            return ElementKind.PARAMETER;
-        }
-    }
-
-    public void setConstantValue(Object constantValue) {
-        this.constantValue = constantValue;
-    }
-
-    @Override
-    public Object getConstantValue() {
-        return constantValue;
-    }
-
-    public String getName() {
-        return getSimpleName().toString();
-    }
-
-    @Override
-    public void setSimpleName(Name name) {
-        this.name = name;
-    }
-
-    public void setName(String name) {
-        this.name = CodeNames.of(name);
-    }
-
-    @Override
-    public void setType(TypeMirror type) {
-        this.type = type;
-    }
-
-    @Override
-    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
-        return v.visitVariable(this, p);
-    }
-
-    public static CodeVariableElement clone(VariableElement var) {
-        CodeVariableElement copy = new CodeVariableElement(var.getModifiers(), var.asType(), var.getSimpleName().toString());
-        copy.setConstantValue(var.getConstantValue());
-        for (AnnotationMirror mirror : var.getAnnotationMirrors()) {
-            copy.addAnnotationMirror(mirror);
-        }
-        for (Element element : var.getEnclosedElements()) {
-            copy.add(element);
-        }
-        return copy;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/GeneratedElement.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import javax.lang.model.element.*;
-
-public interface GeneratedElement {
-
-    AnnotationMirror getGeneratorAnnotationMirror();
-
-    void setGeneratorAnnotationMirror(AnnotationMirror mirror);
-
-    Element getGeneratorElement();
-
-    void setGeneratorElement(Element element);
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/AbstractCodeWriter.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,764 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.codewriter;
-
-import static com.oracle.truffle.dsl.processor.Utils.*;
-
-import java.io.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.ast.*;
-
-public abstract class AbstractCodeWriter extends CodeElementScanner<Void, Void> {
-
-    private static final int MAX_LINE_LENGTH = 200;
-    private static final int LINE_WRAP_INDENTS = 3;
-    private static final String IDENT_STRING = "    ";
-    private static final String LN = "\n"; /* unix style */
-
-    protected Writer writer;
-    private int indent;
-    private boolean newLine;
-    private int lineLength;
-    private boolean lineWrapping = false;
-
-    private OrganizedImports imports;
-
-    public void visitCompilationUnit(CodeCompilationUnit e) {
-        for (TypeElement clazz : e.getEnclosedElements()) {
-            clazz.accept(this, null);
-        }
-    }
-
-    protected abstract Writer createWriter(CodeTypeElement clazz) throws IOException;
-
-    @Override
-    public Void visitType(CodeTypeElement e, Void p) {
-        if (e.isTopLevelClass()) {
-            Writer w = null;
-            try {
-                imports = OrganizedImports.organize(e);
-                w = new TrimTrailingSpaceWriter(createWriter(e));
-                writer = w;
-                writeRootClass(e);
-            } catch (IOException ex) {
-                throw new RuntimeException(ex);
-            } finally {
-                if (w != null) {
-                    try {
-                        w.close();
-                    } catch (Throwable e1) {
-                        // see eclipse bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=361378
-                        // TODO temporary suppress errors on close.
-                    }
-                }
-                writer = null;
-            }
-        } else {
-            writeClassImpl(e);
-        }
-        return null;
-    }
-
-    private void writeRootClass(CodeTypeElement e) {
-        writeHeader();
-        write("package ").write(e.getPackageName()).write(";").writeLn();
-        writeEmptyLn();
-
-        Set<CodeImport> generateImports = imports.generateImports();
-        List<CodeImport> typeImports = new ArrayList<>();
-        List<CodeImport> staticImports = new ArrayList<>();
-
-        for (CodeImport codeImport : generateImports) {
-            if (codeImport.isStaticImport()) {
-                staticImports.add(codeImport);
-            } else {
-                typeImports.add(codeImport);
-            }
-        }
-        Collections.sort(typeImports);
-        Collections.sort(staticImports);
-
-        for (CodeImport imp : staticImports) {
-            imp.accept(this, null);
-            writeLn();
-        }
-        if (!staticImports.isEmpty()) {
-            writeEmptyLn();
-        }
-
-        for (CodeImport imp : typeImports) {
-            imp.accept(this, null);
-            writeLn();
-        }
-        if (!typeImports.isEmpty()) {
-            writeEmptyLn();
-        }
-
-        writeClassImpl(e);
-    }
-
-    private String useImport(Element enclosedType, TypeMirror type) {
-        if (imports != null) {
-            return imports.createTypeReference(enclosedType, type);
-        } else {
-            return Utils.getSimpleName(type);
-        }
-    }
-
-    private void writeClassImpl(CodeTypeElement e) {
-        for (AnnotationMirror annotation : e.getAnnotationMirrors()) {
-            visitAnnotation(e, annotation);
-            writeLn();
-        }
-
-        writeModifiers(e.getModifiers());
-        if (e.getKind() == ElementKind.ENUM) {
-            write("enum ");
-        } else {
-            write("class ");
-        }
-        write(e.getSimpleName());
-        if (e.getSuperclass() != null && !getQualifiedName(e.getSuperclass()).equals("java.lang.Object")) {
-            write(" extends ").write(useImport(e, e.getSuperclass()));
-        }
-        if (e.getImplements().size() > 0) {
-            write(" implements ");
-            for (int i = 0; i < e.getImplements().size(); i++) {
-                write(useImport(e, e.getImplements().get(i)));
-                if (i < e.getImplements().size() - 1) {
-                    write(", ");
-                }
-            }
-        }
-
-        write(" {").writeLn();
-        writeEmptyLn();
-        indent(1);
-
-        List<VariableElement> staticFields = getStaticFields(e);
-        List<VariableElement> instanceFields = getInstanceFields(e);
-
-        for (int i = 0; i < staticFields.size(); i++) {
-            VariableElement field = staticFields.get(i);
-            field.accept(this, null);
-            if (e.getKind() == ElementKind.ENUM && i < staticFields.size() - 1) {
-                write(",");
-                writeLn();
-            } else {
-                write(";");
-                writeLn();
-            }
-        }
-
-        if (staticFields.size() > 0) {
-            writeEmptyLn();
-        }
-
-        for (VariableElement field : instanceFields) {
-            field.accept(this, null);
-            write(";");
-            writeLn();
-        }
-        if (instanceFields.size() > 0) {
-            writeEmptyLn();
-        }
-
-        for (ExecutableElement method : ElementFilter.constructorsIn(e.getEnclosedElements())) {
-            method.accept(this, null);
-        }
-
-        for (ExecutableElement method : getInstanceMethods(e)) {
-            method.accept(this, null);
-        }
-
-        for (ExecutableElement method : getStaticMethods(e)) {
-            method.accept(this, null);
-        }
-
-        for (TypeElement clazz : e.getInnerClasses()) {
-            clazz.accept(this, null);
-        }
-
-        dedent(1);
-        write("}");
-        writeEmptyLn();
-    }
-
-    private static List<VariableElement> getStaticFields(CodeTypeElement clazz) {
-        List<VariableElement> staticFields = new ArrayList<>();
-        for (VariableElement field : clazz.getFields()) {
-            if (field.getModifiers().contains(Modifier.STATIC)) {
-                staticFields.add(field);
-            }
-        }
-        return staticFields;
-    }
-
-    private static List<VariableElement> getInstanceFields(CodeTypeElement clazz) {
-        List<VariableElement> instanceFields = new ArrayList<>();
-        for (VariableElement field : clazz.getFields()) {
-            if (!field.getModifiers().contains(Modifier.STATIC)) {
-                instanceFields.add(field);
-            }
-        }
-        return instanceFields;
-    }
-
-    private static List<ExecutableElement> getStaticMethods(CodeTypeElement clazz) {
-        List<ExecutableElement> staticMethods = new ArrayList<>();
-        for (ExecutableElement method : clazz.getMethods()) {
-            if (method.getModifiers().contains(Modifier.STATIC)) {
-                staticMethods.add(method);
-            }
-        }
-        return staticMethods;
-    }
-
-    private static List<ExecutableElement> getInstanceMethods(CodeTypeElement clazz) {
-        List<ExecutableElement> instanceMethods = new ArrayList<>();
-        for (ExecutableElement method : clazz.getMethods()) {
-            if (!method.getModifiers().contains(Modifier.STATIC)) {
-                instanceMethods.add(method);
-            }
-        }
-        return instanceMethods;
-    }
-
-    @Override
-    public Void visitVariable(VariableElement f, Void p) {
-        Element parent = f.getEnclosingElement();
-
-        for (AnnotationMirror annotation : f.getAnnotationMirrors()) {
-            visitAnnotation(f, annotation);
-            write(" ");
-        }
-
-        CodeTree init = null;
-        if (f instanceof CodeVariableElement) {
-            init = ((CodeVariableElement) f).getInit();
-        }
-
-        if (parent.getKind() == ElementKind.ENUM && f.getModifiers().contains(Modifier.STATIC)) {
-            write(f.getSimpleName());
-            if (init != null) {
-                write("(");
-                init.acceptCodeElementScanner(this, p);
-                write(")");
-            }
-        } else {
-            Element enclosing = f.getEnclosingElement();
-            writeModifiers(f.getModifiers());
-
-            boolean varArgs = false;
-            if (enclosing.getKind() == ElementKind.METHOD) {
-                ExecutableElement method = (ExecutableElement) enclosing;
-                if (method.isVarArgs() && method.getParameters().indexOf(f) == method.getParameters().size() - 1) {
-                    varArgs = true;
-                }
-            }
-
-            TypeMirror varType = f.asType();
-            if (varArgs) {
-                if (varType.getKind() == TypeKind.ARRAY) {
-                    varType = ((ArrayType) varType).getComponentType();
-                }
-                write(useImport(f, varType));
-                write("...");
-            } else {
-                write(useImport(f, varType));
-            }
-
-            write(" ");
-            write(f.getSimpleName());
-            if (init != null) {
-                write(" = ");
-                init.acceptCodeElementScanner(this, p);
-            }
-        }
-        return null;
-    }
-
-    public void visitAnnotation(Element enclosedElement, AnnotationMirror e) {
-        write("@").write(useImport(enclosedElement, e.getAnnotationType()));
-
-        if (!e.getElementValues().isEmpty()) {
-            write("(");
-            final ExecutableElement defaultElement = findExecutableElement(e.getAnnotationType(), "value");
-
-            Map<? extends ExecutableElement, ? extends AnnotationValue> values = e.getElementValues();
-            if (defaultElement != null && values.size() == 1 && values.get(defaultElement) != null) {
-                visitAnnotationValue(enclosedElement, values.get(defaultElement));
-            } else {
-                Set<? extends ExecutableElement> methodsSet = values.keySet();
-                List<ExecutableElement> methodsList = new ArrayList<>();
-                for (ExecutableElement method : methodsSet) {
-                    if (values.get(method) == null) {
-                        continue;
-                    }
-                    methodsList.add(method);
-                }
-
-                Collections.sort(methodsList, new Comparator<ExecutableElement>() {
-
-                    @Override
-                    public int compare(ExecutableElement o1, ExecutableElement o2) {
-                        return o1.getSimpleName().toString().compareTo(o2.getSimpleName().toString());
-                    }
-                });
-
-                for (int i = 0; i < methodsList.size(); i++) {
-                    ExecutableElement method = methodsList.get(i);
-                    AnnotationValue value = values.get(method);
-                    write(method.getSimpleName().toString());
-                    write(" = ");
-                    visitAnnotationValue(enclosedElement, value);
-
-                    if (i < methodsList.size() - 1) {
-                        write(", ");
-                    }
-                }
-            }
-
-            write(")");
-        }
-    }
-
-    public void visitAnnotationValue(Element enclosedElement, AnnotationValue e) {
-        e.accept(new AnnotationValueWriterVisitor(enclosedElement), null);
-    }
-
-    private class AnnotationValueWriterVisitor extends AbstractAnnotationValueVisitor7<Void, Void> {
-
-        private final Element enclosedElement;
-
-        public AnnotationValueWriterVisitor(Element enclosedElement) {
-            this.enclosedElement = enclosedElement;
-        }
-
-        @Override
-        public Void visitBoolean(boolean b, Void p) {
-            write(Boolean.toString(b));
-            return null;
-        }
-
-        @Override
-        public Void visitByte(byte b, Void p) {
-            write(Byte.toString(b));
-            return null;
-        }
-
-        @Override
-        public Void visitChar(char c, Void p) {
-            write(Character.toString(c));
-            return null;
-        }
-
-        @Override
-        public Void visitDouble(double d, Void p) {
-            write(Double.toString(d));
-            return null;
-        }
-
-        @Override
-        public Void visitFloat(float f, Void p) {
-            write(Float.toString(f));
-            return null;
-        }
-
-        @Override
-        public Void visitInt(int i, Void p) {
-            write(Integer.toString(i));
-            return null;
-        }
-
-        @Override
-        public Void visitLong(long i, Void p) {
-            write(Long.toString(i));
-            return null;
-        }
-
-        @Override
-        public Void visitShort(short s, Void p) {
-            write(Short.toString(s));
-            return null;
-        }
-
-        @Override
-        public Void visitString(String s, Void p) {
-            write("\"");
-            write(s);
-            write("\"");
-            return null;
-        }
-
-        @Override
-        public Void visitType(TypeMirror t, Void p) {
-            write(useImport(enclosedElement, t));
-            write(".class");
-            return null;
-        }
-
-        @Override
-        public Void visitEnumConstant(VariableElement c, Void p) {
-            write(useImport(enclosedElement, c.asType()));
-            write(".");
-            write(c.getSimpleName().toString());
-            return null;
-        }
-
-        @Override
-        public Void visitAnnotation(AnnotationMirror a, Void p) {
-            AbstractCodeWriter.this.visitAnnotation(enclosedElement, a);
-            return null;
-        }
-
-        @Override
-        public Void visitArray(List<? extends AnnotationValue> vals, Void p) {
-            write("{");
-            for (int i = 0; i < vals.size(); i++) {
-                AnnotationValue value = vals.get(i);
-                AbstractCodeWriter.this.visitAnnotationValue(enclosedElement, value);
-                if (i < vals.size() - 1) {
-                    write(", ");
-                }
-            }
-            write("}");
-            return null;
-        }
-    }
-
-    public ExecutableElement findExecutableElement(DeclaredType type, String name) {
-        List<? extends ExecutableElement> elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements());
-        for (ExecutableElement executableElement : elements) {
-            if (executableElement.getSimpleName().toString().equals(name)) {
-                return executableElement;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public void visitImport(CodeImport e, Void p) {
-        if (e.isStaticImport()) {
-            write("import static ").write(e.getImportString()).write(";");
-        } else {
-            write("import ").write(e.getImportString()).write(";");
-        }
-    }
-
-    @Override
-    public Void visitExecutable(CodeExecutableElement e, Void p) {
-        for (AnnotationMirror annotation : e.getAnnotationMirrors()) {
-            visitAnnotation(e, annotation);
-            writeLn();
-        }
-
-        writeModifiers(e.getModifiers());
-
-        if (e.getReturnType() != null) {
-            write(useImport(e, e.getReturnType()));
-            write(" ");
-        }
-        write(e.getSimpleName());
-        write("(");
-
-        for (int i = 0; i < e.getParameters().size(); i++) {
-            VariableElement param = e.getParameters().get(i);
-            param.accept(this, p);
-            if (i < e.getParameters().size() - 1) {
-                write(", ");
-            }
-        }
-        write(")");
-
-        List<TypeMirror> throwables = e.getThrownTypes();
-        if (throwables.size() > 0) {
-            write(" throws ");
-            for (int i = 0; i < throwables.size(); i++) {
-                write(useImport(e, throwables.get(i)));
-                if (i < throwables.size() - 1) {
-                    write(", ");
-                }
-            }
-        }
-
-        if (e.getModifiers().contains(Modifier.ABSTRACT)) {
-            writeLn(";");
-        } else if (e.getBodyTree() != null) {
-            writeLn(" {");
-            indent(1);
-            e.getBodyTree().acceptCodeElementScanner(this, p);
-            dedent(1);
-            writeLn("}");
-        } else if (e.getBody() != null) {
-            write(" {");
-            write(e.getBody());
-            writeLn("}");
-        } else {
-            writeLn("{ }");
-        }
-        writeEmptyLn();
-        return null;
-    }
-
-    @Override
-    public void visitTree(CodeTree e, Void p) {
-        CodeTreeKind kind = e.getCodeKind();
-
-        switch (kind) {
-            case COMMA_GROUP:
-                List<CodeTree> children = e.getEnclosedElements();
-                for (int i = 0; i < children.size(); i++) {
-                    children.get(i).acceptCodeElementScanner(this, p);
-                    if (i < e.getEnclosedElements().size() - 1) {
-                        write(", ");
-                    }
-                }
-                break;
-            case GROUP:
-                for (CodeTree tree : e.getEnclosedElements()) {
-                    tree.acceptCodeElementScanner(this, p);
-                }
-                break;
-            case INDENT:
-                indent(1);
-                for (CodeTree tree : e.getEnclosedElements()) {
-                    tree.acceptCodeElementScanner(this, p);
-                }
-                dedent(1);
-                break;
-            case NEW_LINE:
-                writeLn();
-                break;
-            case STRING:
-                if (e.getString() != null) {
-                    write(e.getString());
-                } else {
-                    write("null");
-                }
-                break;
-            case STATIC_FIELD_REFERENCE:
-                if (e.getString() != null) {
-                    write(imports.createStaticFieldReference(e, e.getType(), e.getString()));
-                } else {
-                    write("null");
-                }
-                break;
-            case STATIC_METHOD_REFERENCE:
-                if (e.getString() != null) {
-                    write(imports.createStaticMethodReference(e, e.getType(), e.getString()));
-                } else {
-                    write("null");
-                }
-                break;
-            case TYPE:
-                write(useImport(e, e.getType()));
-                break;
-            default:
-                assert false;
-                return;
-        }
-    }
-
-    protected void writeHeader() {
-        // default implementation does nothing
-    }
-
-    private void writeModifiers(Set<Modifier> modifiers) {
-        if (modifiers != null) {
-            for (Modifier modifier : modifiers) {
-                write(modifier.toString());
-                write(" ");
-            }
-        }
-    }
-
-    protected void indent(int count) {
-        indent += count;
-    }
-
-    protected void dedent(int count) {
-        indent -= count;
-    }
-
-    protected void writeLn() {
-        writeLn("");
-    }
-
-    protected void writeLn(String text) {
-        write(text);
-        write(LN);
-        lineLength = 0;
-        newLine = true;
-        if (lineWrapping) {
-            dedent(LINE_WRAP_INDENTS);
-            lineWrapping = false;
-        }
-        lineWrapping = false;
-    }
-
-    protected void writeEmptyLn() {
-        writeLn();
-    }
-
-    private AbstractCodeWriter write(Name name) {
-        return write(name.toString());
-    }
-
-    private AbstractCodeWriter write(String m) {
-        if (m.isEmpty()) {
-            return this;
-        }
-        try {
-            String s = m;
-            lineLength += s.length();
-            if (newLine && s != LN) {
-                writeIndent();
-                newLine = false;
-            }
-            if (lineLength > MAX_LINE_LENGTH) {
-                s = wrapLine(s);
-            }
-            writer.write(s);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-        return this;
-    }
-
-    private String wrapLine(String m) throws IOException {
-        assert !m.isEmpty();
-
-        char firstCharacter = m.charAt(0);
-        char lastCharacter = m.charAt(m.length() - 1);
-        if (firstCharacter == '\"' && lastCharacter == '\"') {
-            // string line wrapping
-            String string = m.substring(1, m.length() - 1);
-            if (string.isEmpty()) {
-                return m;
-            }
-
-            // restore original line length
-            lineLength = lineLength - m.length();
-            int size = 0;
-            for (int i = 0; i < string.length(); i += size) {
-                if (i != 0) {
-                    write("+ ");
-                }
-
-                int nextSize = MAX_LINE_LENGTH - lineLength - 2;
-                if (nextSize <= 0) {
-                    writeLn();
-                    nextSize = MAX_LINE_LENGTH - lineLength - 2;
-                }
-
-                int end = Math.min(i + nextSize, string.length());
-
-                // TODO(CH): fails in normal usage - output ok though
-                // assert lineLength + (end - i) + 2 < MAX_LINE_LENGTH;
-
-                write("\"" + string.substring(i, end) + "\"");
-                size = nextSize;
-            }
-
-            return "";
-        } else if (!Character.isAlphabetic(firstCharacter) && firstCharacter != '+') {
-            return m;
-        }
-
-        if (!lineWrapping) {
-            indent(LINE_WRAP_INDENTS);
-        }
-        lineWrapping = true;
-        lineLength = 0;
-        write(LN);
-        writeIndent();
-        return m;
-    }
-
-    private void writeIndent() throws IOException {
-        lineLength += indentSize();
-        for (int i = 0; i < indent; i++) {
-            writer.write(IDENT_STRING);
-        }
-    }
-
-    private int indentSize() {
-        return IDENT_STRING.length() * indent;
-    }
-
-    private static class TrimTrailingSpaceWriter extends Writer {
-
-        private final Writer delegate;
-        private final StringBuilder buffer = new StringBuilder();
-
-        public TrimTrailingSpaceWriter(Writer delegate) {
-            this.delegate = delegate;
-        }
-
-        @Override
-        public void close() throws IOException {
-            this.delegate.close();
-        }
-
-        @Override
-        public void flush() throws IOException {
-            this.delegate.flush();
-        }
-
-        @Override
-        public void write(char[] cbuf, int off, int len) throws IOException {
-            buffer.append(cbuf, off, len);
-            int newLinePoint = buffer.indexOf(LN);
-
-            if (newLinePoint != -1) {
-                String lhs = trimTrailing(buffer.substring(0, newLinePoint));
-                delegate.write(lhs);
-                delegate.write(LN);
-                buffer.delete(0, newLinePoint + 1);
-            }
-        }
-
-        private static String trimTrailing(String s) {
-            int cut = 0;
-            for (int i = s.length() - 1; i >= 0; i--) {
-                if (Character.isWhitespace(s.charAt(i))) {
-                    cut++;
-                } else {
-                    break;
-                }
-            }
-            if (cut > 0) {
-                return s.substring(0, s.length() - cut);
-            }
-            return s;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/FixWarningsVisitor.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.codewriter;
-
-import static com.oracle.truffle.dsl.processor.Utils.*;
-import static javax.lang.model.element.Modifier.*;
-
-import java.io.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.ast.*;
-
-public class FixWarningsVisitor extends CodeElementScanner<Void, Void> {
-
-    private final Set<String> symbolsUsed = new HashSet<>();
-
-    private final ProcessorContext context;
-    private final DeclaredType unusedAnnotation;
-    private final DeclaredType overrideType;
-
-    public FixWarningsVisitor(ProcessorContext context, DeclaredType unusedAnnotation, DeclaredType overrideType) {
-        this.context = context;
-        this.unusedAnnotation = unusedAnnotation;
-        this.overrideType = overrideType;
-    }
-
-    @Override
-    public Void visitType(CodeTypeElement e, Void p) {
-        List<TypeElement> superTypes = Utils.getSuperTypes(e);
-        for (TypeElement type : superTypes) {
-            String qualifiedName = Utils.getQualifiedName(type);
-            if (qualifiedName.equals(Serializable.class.getCanonicalName())) {
-                if (!e.containsField("serialVersionUID")) {
-                    e.add(new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), context.getType(long.class), "serialVersionUID", "1L"));
-                }
-                break;
-            }
-        }
-
-        return super.visitType(e, p);
-    }
-
-    @Override
-    public Void visitExecutable(CodeExecutableElement e, Void p) {
-        if (e.getParameters().isEmpty()) {
-            return null;
-        } else if (e.getModifiers().contains(Modifier.ABSTRACT)) {
-            return null;
-        } else if (containsOverride(e)) {
-            return null;
-        }
-
-        symbolsUsed.clear();
-        super.visitExecutable(e, p);
-        if (e.getBodyTree() == null && e.getBody() != null) {
-            computeSymbols(e.getBody());
-        }
-
-        for (VariableElement parameter : e.getParameters()) {
-            if (!symbolsUsed.contains(parameter.getSimpleName().toString())) {
-                e.getAnnotationMirrors().add(createUnusedAnnotationMirror());
-                break;
-            }
-        }
-        return null;
-    }
-
-    private boolean containsOverride(CodeExecutableElement e) {
-        for (AnnotationMirror mirror : e.getAnnotationMirrors()) {
-            if (Utils.typeEquals(overrideType, mirror.getAnnotationType())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private CodeAnnotationMirror createUnusedAnnotationMirror() {
-        CodeAnnotationMirror mirror = new CodeAnnotationMirror(unusedAnnotation);
-        mirror.setElementValue(mirror.findExecutableElement("value"), new CodeAnnotationValue("unused"));
-        return mirror;
-    }
-
-    @Override
-    public void visitTree(CodeTree e, Void p) {
-        if (e.getString() != null) {
-            computeSymbols(e.getString());
-        }
-        super.visitTree(e, p);
-    }
-
-    private void computeSymbols(String s) {
-        // TODO there should not be any need for a StringTokenizer if we have a real AST for
-        // method bodies. Also the current solution is not perfect. What if one token
-        // is spread across multiple CodeTree instances? But for now that works.
-        StringTokenizer tokenizer = new StringTokenizer(s, ".= :,()[];{}\"\"'' ", false);
-        while (tokenizer.hasMoreElements()) {
-            String token = tokenizer.nextToken().trim();
-            if (token.length() > 0) {
-                symbolsUsed.add(token);
-            }
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/GenerateOverrideVisitor.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.codewriter;
-
-import static com.oracle.truffle.dsl.processor.Utils.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.ast.*;
-
-public class GenerateOverrideVisitor extends CodeElementScanner<Void, Void> {
-
-    private final DeclaredType overrideType;
-
-    public GenerateOverrideVisitor(DeclaredType overrideType) {
-        this.overrideType = overrideType;
-    }
-
-    @Override
-    public Void visitExecutable(CodeExecutableElement e, Void p) {
-        if (!e.getModifiers().contains(Modifier.STATIC) && !e.getModifiers().contains(Modifier.PRIVATE)) {
-            String name = e.getSimpleName().toString();
-            TypeMirror[] params = e.getParameterTypes();
-
-            for (AnnotationMirror mirror : e.getAnnotationMirrors()) {
-                if (Utils.typeEquals(overrideType, mirror.getAnnotationType())) {
-                    // already declared (may happen if method copied from super class)
-                    return super.visitExecutable(e, p);
-                }
-            }
-
-            if (isDeclaredMethodInSuperType(e.getEnclosingClass(), name, params)) {
-                e.addAnnotationMirror(new CodeAnnotationMirror(overrideType));
-            }
-        }
-        return super.visitExecutable(e, p);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/OrganizedImports.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,491 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.codewriter;
-
-import static com.oracle.truffle.dsl.processor.Utils.*;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.ast.*;
-
-public final class OrganizedImports {
-
-    private final Set<TypeMirror> staticImportUsage = new HashSet<>();
-
-    private final Map<String, TypeMirror> simpleNamesUsed = new HashMap<>();
-
-    private final Set<String> declaredStaticMethods = new HashSet<>();
-    private final Set<String> declaredStaticFields = new HashSet<>();
-    private final Set<String> ambiguousStaticMethods = new HashSet<>();
-    private final Set<String> ambiguousStaticFields = new HashSet<>();
-
-    private final CodeTypeElement topLevelClass;
-
-    private OrganizedImports(CodeTypeElement topLevelClass) {
-        this.topLevelClass = topLevelClass;
-    }
-
-    public static OrganizedImports organize(CodeTypeElement topLevelClass) {
-        OrganizedImports organized = new OrganizedImports(topLevelClass);
-        organized.organizeImpl();
-        return organized;
-    }
-
-    private void organizeImpl() {
-        ImportTypeReferenceVisitor reference = new ImportTypeReferenceVisitor();
-        topLevelClass.accept(reference, null);
-
-        processStaticImports(topLevelClass);
-        List<TypeElement> types = Utils.getSuperTypes(topLevelClass);
-        for (TypeElement typeElement : types) {
-            processStaticImports(typeElement);
-        }
-
-        for (TypeMirror type : staticImportUsage) {
-            TypeElement element = fromTypeMirror(type);
-            if (element != null) {
-                // already processed by supertype
-                if (types.contains(element)) {
-                    continue;
-                }
-                processStaticImports(element);
-            }
-        }
-    }
-
-    public String createTypeReference(Element enclosedElement, TypeMirror type) {
-        switch (type.getKind()) {
-            case BOOLEAN:
-            case BYTE:
-            case CHAR:
-            case DOUBLE:
-            case FLOAT:
-            case SHORT:
-            case INT:
-            case LONG:
-            case VOID:
-                return Utils.getSimpleName(type);
-            case DECLARED:
-                return createDeclaredTypeName(enclosedElement, (DeclaredType) type);
-            case ARRAY:
-                return createTypeReference(enclosedElement, ((ArrayType) type).getComponentType()) + "[]";
-            case WILDCARD:
-                return createWildcardName(enclosedElement, (WildcardType) type);
-            case TYPEVAR:
-                return "?";
-            default:
-                throw new RuntimeException("Unknown type specified " + type.getKind() + " mirror: " + type);
-        }
-    }
-
-    public String createStaticFieldReference(Element enclosedElement, TypeMirror type, String fieldName) {
-        return createStaticReference(enclosedElement, type, fieldName, ambiguousStaticFields, declaredStaticFields);
-    }
-
-    public String createStaticMethodReference(Element enclosedElement, TypeMirror type, String methodName) {
-        return createStaticReference(enclosedElement, type, methodName, ambiguousStaticMethods, declaredStaticMethods);
-    }
-
-    private String createStaticReference(Element enclosedElement, TypeMirror type, String name, Set<String> ambiguousSymbols, Set<String> declaredSymbols) {
-        if (ambiguousSymbols.contains(name)) {
-            // ambiguous import
-            return createTypeReference(enclosedElement, type) + "." + name;
-        } else if (!declaredSymbols.contains(name)) {
-            // not imported at all
-            return createTypeReference(enclosedElement, type) + "." + name;
-        } else {
-            // import declared and not ambiguous
-            return name;
-        }
-    }
-
-    private String createWildcardName(Element enclosedElement, WildcardType type) {
-        StringBuilder b = new StringBuilder();
-        if (type.getExtendsBound() != null) {
-            b.append("? extends ").append(createTypeReference(enclosedElement, type.getExtendsBound()));
-        } else if (type.getSuperBound() != null) {
-            b.append("? super ").append(createTypeReference(enclosedElement, type.getExtendsBound()));
-        }
-        return b.toString();
-    }
-
-    private String createDeclaredTypeName(Element enclosedElement, DeclaredType type) {
-        String name = Utils.fixECJBinaryNameIssue(type.asElement().getSimpleName().toString());
-
-        if (needsImport(enclosedElement, type)) {
-            TypeMirror usedByType = simpleNamesUsed.get(name);
-            if (usedByType == null) {
-                simpleNamesUsed.put(name, type);
-                usedByType = type;
-            }
-
-            if (!typeEquals(type, usedByType)) {
-                name = getQualifiedName(type);
-            }
-        }
-
-        if (type.getTypeArguments().size() == 0) {
-            return name;
-        }
-
-        StringBuilder b = new StringBuilder(name);
-        b.append("<");
-        if (type.getTypeArguments().size() > 0) {
-            for (int i = 0; i < type.getTypeArguments().size(); i++) {
-                b.append(createTypeReference(enclosedElement, type.getTypeArguments().get(i)));
-                if (i < type.getTypeArguments().size() - 1) {
-                    b.append(", ");
-                }
-            }
-        }
-        b.append(">");
-        return b.toString();
-    }
-
-    public Set<CodeImport> generateImports() {
-        Set<CodeImport> imports = new HashSet<>();
-
-        imports.addAll(generateImports(simpleNamesUsed.values()));
-        imports.addAll(generateStaticImports(staticImportUsage));
-
-        return imports;
-    }
-
-    boolean processStaticImports(TypeElement element) {
-        Set<String> importedMethods = new HashSet<>();
-        List<ExecutableElement> methods = ElementFilter.methodsIn(element.getEnclosedElements());
-        for (ExecutableElement method : methods) {
-            if (method.getModifiers().contains(Modifier.STATIC)) {
-                importedMethods.add(method.getSimpleName().toString());
-            }
-        }
-
-        boolean allMethodsAmbiguous = processStaticImportElements(importedMethods, this.ambiguousStaticMethods, this.declaredStaticMethods);
-
-        Set<String> importedFields = new HashSet<>();
-        List<VariableElement> fields = ElementFilter.fieldsIn(element.getEnclosedElements());
-        for (VariableElement field : fields) {
-            if (field.getModifiers().contains(Modifier.STATIC)) {
-                importedFields.add(field.getSimpleName().toString());
-            }
-        }
-
-        boolean allFieldsAmbiguous = processStaticImportElements(importedFields, this.ambiguousStaticFields, this.declaredStaticFields);
-
-        return allMethodsAmbiguous && allFieldsAmbiguous;
-    }
-
-    private static boolean processStaticImportElements(Set<String> newElements, Set<String> ambiguousElements, Set<String> declaredElements) {
-        boolean allAmbiguous = false;
-        if (declaredElements.containsAll(newElements)) {
-            // all types already declared -> we can remove the import completely -> they will all
-            // get ambiguous
-            allAmbiguous = true;
-        }
-        Set<String> newAmbiguous = new HashSet<>();
-        Set<String> newDeclared = new HashSet<>();
-
-        for (String newElement : newElements) {
-            if (declaredElements.contains(newElement)) {
-                newAmbiguous.add(newElement);
-            } else if (ambiguousElements.contains(newElement)) {
-                // nothing to do
-            } else {
-                newDeclared.add(newElement);
-            }
-        }
-
-        ambiguousElements.addAll(newAmbiguous);
-        declaredElements.addAll(newDeclared);
-        return allAmbiguous;
-    }
-
-    private boolean needsImport(Element enclosedElement, TypeMirror importType) {
-        String importPackagName = getPackageName(importType);
-        if (importPackagName == null) {
-            return false;
-        } else if (importPackagName.equals("java.lang")) {
-            return false;
-        } else if (importPackagName.equals(getPackageName(topLevelClass)) && Utils.isTopLevelClass(importType)) {
-            return false; // same package name -> no import
-        }
-
-        List<Element> elements = Utils.getElementHierarchy(enclosedElement);
-
-        Set<String> autoImportedTypes = new HashSet<>();
-        for (Element element : elements) {
-            if (element.getKind().isClass()) {
-                collectSuperTypeImports((TypeElement) element, autoImportedTypes);
-                collectInnerTypeImports((TypeElement) element, autoImportedTypes);
-            }
-        }
-
-        String qualifiedName = getQualifiedName(importType);
-        if (autoImportedTypes.contains(qualifiedName)) {
-            return false;
-        }
-
-        return true;
-    }
-
-    private static Set<CodeImport> generateImports(Collection<TypeMirror> toGenerate) {
-        TreeSet<CodeImport> importObjects = new TreeSet<>();
-        for (TypeMirror importType : toGenerate) {
-            importObjects.add(new CodeImport(importType, getQualifiedName(importType), false));
-        }
-        return importObjects;
-    }
-
-    private static void collectInnerTypeImports(TypeElement e, Set<String> autoImportedTypes) {
-        autoImportedTypes.add(getQualifiedName(e));
-        for (TypeElement innerClass : ElementFilter.typesIn(e.getEnclosedElements())) {
-            collectInnerTypeImports(innerClass, autoImportedTypes);
-        }
-    }
-
-    private static void collectSuperTypeImports(TypeElement e, Set<String> autoImportedTypes) {
-        List<TypeElement> superTypes = getSuperTypes(e);
-        for (TypeElement superType : superTypes) {
-            List<TypeElement> declaredTypes = getDeclaredTypes(superType);
-            for (TypeElement declaredType : declaredTypes) {
-                autoImportedTypes.add(getQualifiedName(declaredType));
-            }
-        }
-    }
-
-    private Set<CodeImport> generateStaticImports(Set<TypeMirror> toGenerate) {
-        Set<String> autoImportedStaticTypes = new HashSet<>();
-
-        // if type is declared inside a super type of this class -> no import
-        autoImportedStaticTypes.add(getQualifiedName(topLevelClass));
-        autoImportedStaticTypes.addAll(getQualifiedSuperTypeNames(topLevelClass));
-
-        TreeSet<CodeImport> importObjects = new TreeSet<>();
-        for (TypeMirror importType : toGenerate) {
-            if (getPackageName(importType) == null) {
-                continue; // no package name -> no import
-            }
-
-            String qualifiedName = getQualifiedName(importType);
-            if (autoImportedStaticTypes.contains(qualifiedName)) {
-                continue;
-            }
-
-            importObjects.add(new CodeImport(importType, qualifiedName + ".*", true));
-        }
-
-        return importObjects;
-    }
-
-    private abstract static class TypeReferenceVisitor extends CodeElementScanner<Void, Void> {
-
-        @Override
-        public void visitTree(CodeTree e, Void p) {
-            if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) {
-                visitStaticFieldReference(e, e.getType(), e.getString());
-            } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) {
-                visitStaticMethodReference(e, e.getType(), e.getString());
-            } else if (e.getType() != null) {
-                visitTypeReference(e, e.getType());
-            }
-            super.visitTree(e, p);
-        }
-
-        @Override
-        public Void visitExecutable(CodeExecutableElement e, Void p) {
-            visitAnnotations(e, e.getAnnotationMirrors());
-            if (e.getReturnType() != null) {
-                visitTypeReference(e, e.getReturnType());
-            }
-            for (TypeMirror type : e.getThrownTypes()) {
-                visitTypeReference(e, type);
-            }
-            return super.visitExecutable(e, p);
-        }
-
-        @Override
-        public Void visitType(CodeTypeElement e, Void p) {
-            visitAnnotations(e, e.getAnnotationMirrors());
-
-            visitTypeReference(e, e.getSuperclass());
-            for (TypeMirror type : e.getImplements()) {
-                visitTypeReference(e, type);
-            }
-
-            return super.visitType(e, p);
-        }
-
-        private void visitAnnotations(Element enclosingElement, List<? extends AnnotationMirror> mirrors) {
-            for (AnnotationMirror mirror : mirrors) {
-                visitAnnotation(enclosingElement, mirror);
-            }
-        }
-
-        public void visitAnnotation(Element enclosingElement, AnnotationMirror e) {
-            visitTypeReference(enclosingElement, e.getAnnotationType());
-            if (!e.getElementValues().isEmpty()) {
-                Map<? extends ExecutableElement, ? extends AnnotationValue> values = e.getElementValues();
-                Set<? extends ExecutableElement> methodsSet = values.keySet();
-                List<ExecutableElement> methodsList = new ArrayList<>();
-                for (ExecutableElement method : methodsSet) {
-                    if (values.get(method) == null) {
-                        continue;
-                    }
-                    methodsList.add(method);
-                }
-
-                for (int i = 0; i < methodsList.size(); i++) {
-                    AnnotationValue value = values.get(methodsList.get(i));
-                    visitAnnotationValue(enclosingElement, value);
-                }
-            }
-        }
-
-        public void visitAnnotationValue(Element enclosingElement, AnnotationValue e) {
-            e.accept(new AnnotationValueReferenceVisitor(enclosingElement), null);
-        }
-
-        private class AnnotationValueReferenceVisitor extends AbstractAnnotationValueVisitor7<Void, Void> {
-
-            private final Element enclosingElement;
-
-            public AnnotationValueReferenceVisitor(Element enclosedElement) {
-                this.enclosingElement = enclosedElement;
-            }
-
-            @Override
-            public Void visitBoolean(boolean b, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitByte(byte b, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitChar(char c, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitDouble(double d, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitFloat(float f, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitInt(int i, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitLong(long i, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitShort(short s, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitString(String s, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitType(TypeMirror t, Void p) {
-                visitTypeReference(enclosingElement, t);
-                return null;
-            }
-
-            @Override
-            public Void visitEnumConstant(VariableElement c, Void p) {
-                visitTypeReference(enclosingElement, c.asType());
-                return null;
-            }
-
-            @Override
-            public Void visitAnnotation(AnnotationMirror a, Void p) {
-                TypeReferenceVisitor.this.visitAnnotation(enclosingElement, a);
-                return null;
-            }
-
-            @Override
-            public Void visitArray(List<? extends AnnotationValue> vals, Void p) {
-                for (int i = 0; i < vals.size(); i++) {
-                    TypeReferenceVisitor.this.visitAnnotationValue(enclosingElement, vals.get(i));
-                }
-                return null;
-            }
-        }
-
-        @Override
-        public Void visitVariable(VariableElement f, Void p) {
-            visitAnnotations(f, f.getAnnotationMirrors());
-            visitTypeReference(f, f.asType());
-            return super.visitVariable(f, p);
-        }
-
-        @Override
-        public void visitImport(CodeImport e, Void p) {
-        }
-
-        public abstract void visitTypeReference(Element enclosedType, TypeMirror type);
-
-        public abstract void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName);
-
-        public abstract void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName);
-
-    }
-
-    private class ImportTypeReferenceVisitor extends TypeReferenceVisitor {
-
-        @Override
-        public void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName) {
-            staticImportUsage.add(type);
-        }
-
-        @Override
-        public void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName) {
-            staticImportUsage.add(type);
-        }
-
-        @Override
-        public void visitTypeReference(Element enclosedType, TypeMirror type) {
-            createTypeReference(enclosedType, type);
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/AbstractCompiler.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.compiler;
-
-import java.lang.reflect.*;
-
-public abstract class AbstractCompiler implements Compiler {
-
-    protected static Object method(Object o, String methodName) throws Exception {
-        Method method = o.getClass().getMethod(methodName);
-        method.setAccessible(true);
-        return method.invoke(o);
-    }
-
-    protected static Object method(Object o, String methodName, Class<?>[] paramTypes, Object... values) throws Exception {
-        Method method = o.getClass().getMethod(methodName, paramTypes);
-        method.setAccessible(true);
-        return method.invoke(o, values);
-    }
-
-    protected static Object field(Object o, String fieldName) throws Exception {
-        if (o == null) {
-            return null;
-        }
-        Field field = o.getClass().getField(fieldName);
-        field.setAccessible(true);
-        return field.get(o);
-    }
-
-    protected static String parseHeader(String content) {
-        int index = content.indexOf("/*");
-        if (index == -1) {
-            return null;
-        }
-        if (!content.substring(0, index).trim().equals("")) {
-            // just whitespace before
-            return null;
-        }
-
-        int endIndex = content.indexOf("*/", index);
-        if (endIndex == -1) {
-            return null;
-        }
-        return content.substring(index, endIndex + 2);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/Compiler.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.compiler;
-
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-
-public interface Compiler {
-
-    String getMethodBody(ProcessingEnvironment env, ExecutableElement method);
-
-    String getHeaderComment(ProcessingEnvironment env, Element type);
-
-    List<? extends Element> getEnclosedElementsDeclarationOrder(TypeElement type);
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/CompilerFactory.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.compiler;
-
-import javax.lang.model.element.*;
-
-public class CompilerFactory {
-
-    private static Compiler javac;
-    private static Compiler jdt;
-
-    public static Compiler getCompiler(Element currentElement) {
-        if (JavaCCompiler.isValidElement(currentElement)) {
-            if (javac == null) {
-                javac = new JavaCCompiler();
-            }
-            return javac;
-        } else if (JDTCompiler.isValidElement(currentElement)) {
-            if (jdt == null) {
-                jdt = new JDTCompiler();
-            }
-            return jdt;
-        } else {
-            throw new UnsupportedOperationException("Unsupported compiler for element " + currentElement.getClass().getName() + ".");
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JDTCompiler.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.compiler;
-
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.*;
-
-public class JDTCompiler extends AbstractCompiler {
-
-    public static boolean isValidElement(Element currentElement) {
-        try {
-            Class<?> elementClass = Class.forName("org.eclipse.jdt.internal.compiler.apt.model.ElementImpl");
-            return elementClass.isAssignableFrom(currentElement.getClass());
-        } catch (ClassNotFoundException e) {
-            return false;
-        }
-    }
-
-    public List<? extends Element> getEnclosedElementsDeclarationOrder(TypeElement type) {
-        try {
-            Object binding = field(type, "_binding");
-
-            Class<?> sourceTypeBinding = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding");
-
-            final List<Object> declarationOrder;
-            if (sourceTypeBinding.isAssignableFrom(binding.getClass())) {
-                declarationOrder = findSourceOrder(binding);
-            } else {
-                return null;
-            }
-
-            List<Element> enclosedElements = new ArrayList<>(type.getEnclosedElements());
-            Collections.sort(enclosedElements, new Comparator<Element>() {
-
-                public int compare(Element o1, Element o2) {
-                    try {
-                        Object o1Binding = field(o1, "_binding");
-                        Object o2Binding = field(o2, "_binding");
-
-                        int i1 = declarationOrder.indexOf(o1Binding);
-                        int i2 = declarationOrder.indexOf(o2Binding);
-
-                        return i1 - i2;
-                    } catch (Exception e) {
-                        return 0;
-                    }
-                }
-
-            });
-            return enclosedElements;
-        } catch (Exception e) {
-            return null;
-        }
-    }
-
-    private static List<Object> findSourceOrder(Object binding) throws Exception {
-        Object referenceContext = field(field(binding, "scope"), "referenceContext");
-
-        TreeMap<Integer, Object> orderedBindings = new TreeMap<>();
-
-        collectSourceOrder(orderedBindings, referenceContext, "methods");
-        collectSourceOrder(orderedBindings, referenceContext, "fields");
-        collectSourceOrder(orderedBindings, referenceContext, "memberTypes");
-
-        return new ArrayList<>(orderedBindings.values());
-    }
-
-    private static void collectSourceOrder(TreeMap<Integer, Object> orderedBindings, Object referenceContext, String fieldName) throws Exception {
-        Object[] declarations = (Object[]) field(referenceContext, fieldName);
-        if (declarations != null) {
-            for (int i = 0; i < declarations.length; i++) {
-                Integer declarationSourceStart = (Integer) field(declarations[i], "declarationSourceStart");
-                orderedBindings.put(declarationSourceStart, field(declarations[i], "binding"));
-            }
-        }
-    }
-
-    @Override
-    public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) {
-        try {
-
-            char[] source = getSource(method);
-            if (source == null) {
-                return null;
-            }
-
-            /*
-             * AbstractMethodDeclaration decl =
-             * ((MethodBinding)(((ElementImpl)method)._binding)).sourceMethod(); int bodyStart =
-             * decl.bodyStart; int bodyEnd = decl.bodyEnd;
-             */
-            Object decl = method(field(method, "_binding"), "sourceMethod");
-            int bodyStart = (int) field(decl, "bodyStart");
-            int bodyEnd = (int) field(decl, "bodyEnd");
-
-            int length = bodyEnd - bodyStart;
-            char[] target = new char[length];
-            System.arraycopy(source, bodyStart, target, 0, length);
-
-            return new String(target);
-        } catch (Exception e) {
-            return Utils.printException(e);
-        }
-    }
-
-    private static char[] getSource(Element element) throws Exception {
-        /*
-         * Binding binding = ((ElementImpl)element)._binding; char[] source = null; if (binding
-         * instanceof MethodBinding) { source = ((MethodBinding)
-         * binding).sourceMethod().compilationResult.getCompilationUnit().getContents(); } else if
-         * (binding instanceof SourceTypeBinding) { source =
-         * ((SourceTypeBinding)binding).scope.referenceContext
-         * .compilationResult.compilationUnit.getContents(); } return source;
-         */
-
-        Object binding = field(element, "_binding");
-        Class<?> methodBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.MethodBinding");
-        Class<?> referenceBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding");
-
-        char[] source = null;
-        if (methodBindingClass.isAssignableFrom(binding.getClass())) {
-            Object sourceMethod = method(binding, "sourceMethod");
-            if (sourceMethod == null) {
-                return null;
-            }
-            source = (char[]) method(method(field(sourceMethod, "compilationResult"), "getCompilationUnit"), "getContents");
-        } else if (referenceBindingClass.isAssignableFrom(binding.getClass())) {
-            source = (char[]) method(field(field(field(field(binding, "scope"), "referenceContext"), "compilationResult"), "compilationUnit"), "getContents");
-        }
-        return source;
-    }
-
-    @Override
-    public String getHeaderComment(ProcessingEnvironment env, Element type) {
-        try {
-            char[] source = getSource(type);
-            if (source == null) {
-                return null;
-            }
-            return parseHeader(new String(source));
-        } catch (Exception e) {
-            return Utils.printException(e);
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JavaCCompiler.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.compiler;
-
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.*;
-
-public class JavaCCompiler extends AbstractCompiler {
-
-    public static boolean isValidElement(Element currentElement) {
-        try {
-            Class<?> elementClass = Class.forName("com.sun.tools.javac.code.Symbol");
-            return elementClass.isAssignableFrom(currentElement.getClass());
-        } catch (ClassNotFoundException e) {
-            return false;
-        }
-    }
-
-    public List<? extends Element> getEnclosedElementsDeclarationOrder(TypeElement type) {
-        return type.getEnclosedElements();
-    }
-
-    private static final Class<?>[] getTreeAndTopLevelSignature = new Class[]{Element.class, AnnotationMirror.class, AnnotationValue.class};
-    private static final Class<?>[] getCharContentSignature = new Class[]{boolean.class};
-
-    @Override
-    public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) {
-        try {
-            /*
-             * if (false) { Pair<JCTree, JCCompilationUnit> treeAndTopLevel = ((JavacElements)
-             * env.getElementUtils()).getTreeAndTopLevel(method, null, null); JCBlock block =
-             * ((JCMethodDecl) treeAndTopLevel.fst).getBody(); int startPos = block.pos; int endPos
-             * = block.endpos; String methodBody =
-             * treeAndTopLevel.snd.getSourceFile().getCharContent(true).subSequence(startPos + 1,
-             * endPos).toString(); return methodBody; }
-             */
-
-            Object treeAndTopLevel = getTreeAndTopLevel(env, method);
-            Object block = method(field(treeAndTopLevel, "fst"), "getBody");
-            int startPos = (int) field(block, "pos");
-            int endPos = (int) field(block, "endpos");
-            return getContent(treeAndTopLevel).subSequence(startPos + 1, endPos).toString();
-        } catch (Exception e) {
-            return Utils.printException(e);
-        }
-    }
-
-    private static CharSequence getContent(Object treeAndTopLevel) throws Exception {
-        /*
-         * CharSequence content = treeAndTopLevel.snd.getSourceFile().getCharContent(true);
-         */
-        return (CharSequence) method(method(field(treeAndTopLevel, "snd"), "getSourceFile"), "getCharContent", getCharContentSignature, true);
-    }
-
-    private static Object getTreeAndTopLevel(ProcessingEnvironment env, Element element) throws Exception {
-        /*
-         * Pair<JCTree, JCCompilationUnit> treeAndTopLevel = ((JavacElements)
-         * env.getElementUtils()).getTreeAndTopLevel(method, null, null);
-         */
-        return method(method(env, "getElementUtils"), "getTreeAndTopLevel", getTreeAndTopLevelSignature, element, null, null);
-    }
-
-    @Override
-    public String getHeaderComment(ProcessingEnvironment env, Element type) {
-        try {
-            String content = getContent(getTreeAndTopLevel(env, type)).toString();
-            return parseHeader(content);
-        } catch (Exception e) {
-            return Utils.printException(e);
-        }
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/AbstractClassElementFactory.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,133 @@
+/*
+ * 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.truffle.dsl.processor.generator;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+import static javax.lang.model.element.Modifier.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public abstract class AbstractClassElementFactory<M> extends AbstractCodeElementFactory<M> {
+
+    @Override
+    protected abstract CodeTypeElement create(M m);
+
+    @Override
+    public CodeTypeElement getElement() {
+        return (CodeTypeElement) super.getElement();
+    }
+
+    protected CodeExecutableElement createConstructorUsingFields(Set<Modifier> modifiers, CodeTypeElement clazz) {
+        CodeExecutableElement method = new CodeExecutableElement(modifiers, null, clazz.getSimpleName().toString());
+        CodeTreeBuilder builder = method.createBuilder();
+        TypeElement superClass = fromTypeMirror(clazz.getSuperclass());
+        ExecutableElement constructor = findConstructor(superClass);
+        if (constructor != null && constructor.getParameters().size() > 0) {
+            builder.startStatement();
+            builder.startSuperCall();
+            for (VariableElement parameter : constructor.getParameters()) {
+                method.addParameter(new CodeVariableElement(parameter.asType(), parameter.getSimpleName().toString()));
+                builder.string(parameter.getSimpleName().toString());
+            }
+            builder.end(); // super
+            builder.end(); // statement
+        }
+
+        for (VariableElement field : clazz.getFields()) {
+            if (field.getModifiers().contains(STATIC)) {
+                continue;
+            }
+            String fieldName = field.getSimpleName().toString();
+            method.addParameter(new CodeVariableElement(field.asType(), fieldName));
+            builder.startStatement();
+            builder.string("this.");
+            builder.string(fieldName);
+            builder.string(" = ");
+            if (isAssignable(field.asType(), getContext().getTruffleTypes().getNode())) {
+                builder.string("adoptChild(").string(fieldName).string(")");
+            } else {
+                builder.string(fieldName);
+            }
+            builder.end(); // statement
+        }
+
+        return method;
+    }
+
+    private static ExecutableElement findConstructor(TypeElement clazz) {
+        List<ExecutableElement> constructors = ElementFilter.constructorsIn(clazz.getEnclosedElements());
+        if (constructors.isEmpty()) {
+            return null;
+        } else {
+            return constructors.get(0);
+        }
+    }
+
+    protected CodeExecutableElement createSuperConstructor(TypeElement type, ExecutableElement element) {
+        if (element.getModifiers().contains(Modifier.PRIVATE)) {
+            return null;
+        }
+        CodeExecutableElement executable = CodeExecutableElement.clone(getContext().getEnvironment(), element);
+        executable.setReturnType(null);
+        executable.setSimpleName(CodeNames.of(type.getSimpleName().toString()));
+        CodeTreeBuilder b = executable.createBuilder();
+        b.startStatement();
+        b.startSuperCall();
+        for (VariableElement v : element.getParameters()) {
+            b.string(v.getSimpleName().toString());
+        }
+        b.end();
+        b.end();
+
+        return executable;
+    }
+
+    protected CodeTypeElement createClass(Template model, Set<Modifier> modifiers, String simpleName, TypeMirror superType, boolean enumType) {
+        TypeElement templateType = model.getTemplateType();
+
+        PackageElement pack = getContext().getEnvironment().getElementUtils().getPackageOf(templateType);
+        CodeTypeElement clazz = new CodeTypeElement(modifiers, enumType ? ElementKind.ENUM : ElementKind.CLASS, pack, simpleName);
+        TypeMirror resolvedSuperType = superType;
+        if (resolvedSuperType == null) {
+            resolvedSuperType = getContext().getType(Object.class);
+        }
+        clazz.setSuperClass(resolvedSuperType);
+
+        CodeAnnotationMirror generatedByAnnotation = new CodeAnnotationMirror((DeclaredType) getContext().getType(GeneratedBy.class));
+        generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("value"), new CodeAnnotationValue(templateType.asType()));
+        if (model.getTemplateMethodName() != null) {
+            generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("methodName"), new CodeAnnotationValue(model.getTemplateMethodName()));
+        }
+
+        clazz.addAnnotationMirror(generatedByAnnotation);
+        return clazz;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/AbstractCodeElementFactory.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.generator;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public abstract class AbstractCodeElementFactory<M> {
+
+    protected final ProcessorContext context;
+    private M model;
+
+    private CodeElement<? super Element> element;
+
+    public AbstractCodeElementFactory() {
+        this.context = ProcessorContext.getInstance();
+    }
+
+    protected abstract CodeElement<?> create(M m);
+
+    @SuppressWarnings("unused")
+    protected void createChildren(M m) {
+    }
+
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    public CodeElement<?> process(CodeElement parent, M m) {
+        model = m;
+        element = (CodeElement<? super Element>) create(model);
+        if (parent != null) {
+            parent.add(element);
+        }
+        if (element != null) {
+            createChildren(model);
+        }
+        return element;
+    }
+
+    @SuppressWarnings("rawtypes")
+    public CodeElement getElement() {
+        return element;
+    }
+
+    protected <MO, K extends Element> void add(AbstractCodeElementFactory<MO> factory, MO m) {
+        factory.process(this.element, m);
+    }
+
+    public ProcessorContext getContext() {
+        return context;
+    }
+
+    public M getModel() {
+        return model;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/AbstractCompilationUnitFactory.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,43 @@
+/*
+ * 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.truffle.dsl.processor.generator;
+
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public abstract class AbstractCompilationUnitFactory<M> extends AbstractCodeElementFactory<M> {
+
+    @Override
+    public final CodeCompilationUnit create(M m) {
+        return new CodeCompilationUnit();
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Override
+    public CodeCompilationUnit process(CodeElement parent, M m) {
+        return (CodeCompilationUnit) super.process(parent, m);
+    }
+
+    @Override
+    protected abstract void createChildren(M m);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,2952 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.generator;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+import static javax.lang.model.element.Modifier.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror;
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality;
+import com.oracle.truffle.dsl.processor.parser.*;
+import com.oracle.truffle.dsl.processor.parser.SpecializationGroup.TypeGuard;
+
+public class NodeCodeGenerator extends AbstractCompilationUnitFactory<NodeData> {
+
+    private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode";
+
+    private static final String EXECUTE_CHAINED = "executeChained0";
+    private static final String SPECIALIZE = "specialize0";
+    private static final String DSLSHARE_REWRITE = "rewrite";
+    private static final String DSLSHARE_FIND_ROOT = "findRoot";
+    private static final String DSLSHARE_REWRITE_TO_POLYMORHPIC = "rewriteToPolymorphic";
+    private static final String EXECUTE_UNINITIALIZED = "executeUninitialized0";
+    private static final String REWRITE = "rewrite0";
+    private static final String CREATE_INFO = "createInfo0";
+    private static final String CONTAINS_FALLBACK = "containsFallback";
+
+    private static final String FACTORY_METHOD_NAME = "create0";
+    private static final String EMPTY_CLASS_ARRAY = "EMPTY_CLASS_ARRAY";
+
+    private static final String METADATA_FIELD_NAME = "METADATA";
+
+    private TypeMirror getUnexpectedValueException() {
+        return getContext().getTruffleTypes().getUnexpectedValueException();
+    }
+
+    private static String factoryClassName(NodeData node) {
+        return node.getNodeId() + "Factory";
+    }
+
+    private static String nodeSpecializationClassName(SpecializationData specialization) {
+        String nodeid = resolveNodeId(specialization.getNode());
+        String name = ElementUtils.firstLetterUpperCase(nodeid);
+        name += ElementUtils.firstLetterUpperCase(specialization.getId());
+        name += "Node";
+        return name;
+    }
+
+    private static String nodePolymorphicClassName(NodeData node) {
+        return ElementUtils.firstLetterUpperCase(resolveNodeId(node)) + "PolymorphicNode";
+    }
+
+    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(Parameter targetParameter) {
+        return valueName(targetParameter) + "Evaluated";
+    }
+
+    private static String implicitTypeName(Parameter param) {
+        return param.getLocalName() + "ImplicitType";
+    }
+
+    private static String polymorphicTypeName(NodeExecutionData param) {
+        return param.getName() + "PolymorphicType";
+    }
+
+    private static String valueName(Parameter param) {
+        return param.getLocalName();
+    }
+
+    private static CodeTree createAccessChild(NodeExecutionData targetExecution, String thisReference) {
+        String reference = thisReference;
+        if (reference == null) {
+            reference = "this";
+        }
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        Element accessElement = targetExecution.getChild().getAccessElement();
+        if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) {
+            builder.string(reference).string(".").string(targetExecution.getChild().getName());
+        } else if (accessElement.getKind() == ElementKind.FIELD) {
+            builder.string(reference).string(".").string(accessElement.getSimpleName().toString());
+        } else {
+            throw new AssertionError();
+        }
+        if (targetExecution.isIndexed()) {
+            builder.string("[" + targetExecution.getIndex() + "]");
+        }
+        return builder.getRoot();
+    }
+
+    private static String castValueName(Parameter parameter) {
+        return valueName(parameter) + "Cast";
+    }
+
+    private void addInternalValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame, boolean evaluated) {
+        if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
+            method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue"));
+        }
+        for (Parameter parameter : specialization.getParameters()) {
+            ParameterSpec spec = parameter.getSpecification();
+            if (forceFrame && spec.getName().equals("frame")) {
+                continue;
+            }
+            if (spec.isLocal()) {
+                continue;
+            }
+
+            String name = valueName(parameter);
+            if (evaluated && spec.isSignature()) {
+                name = valueNameEvaluated(parameter);
+            }
+
+            method.addParameter(new CodeVariableElement(parameter.getType(), name));
+        }
+    }
+
+    private static void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame,
+                    Map<String, String> customNames) {
+        if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
+            builder.string("frameValue");
+        }
+        for (Parameter parameter : specialization.getParameters()) {
+            ParameterSpec spec = parameter.getSpecification();
+            if (forceFrame && spec.getName().equals("frame")) {
+                continue;
+            }
+
+            if (parameter.getSpecification().isLocal()) {
+                continue;
+            }
+
+            Parameter sourceParameter = source.findParameter(parameter.getLocalName());
+
+            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));
+            } else {
+                builder.string(valueName(parameter));
+            }
+        }
+    }
+
+    private static String valueName(Parameter sourceParameter, Parameter targetParameter) {
+        if (!sourceParameter.getSpecification().isSignature()) {
+            return valueName(targetParameter);
+        } else if (sourceParameter.getTypeSystemType() != null && targetParameter.getTypeSystemType() != null) {
+            if (sourceParameter.getTypeSystemType().needsCastTo(targetParameter.getTypeSystemType())) {
+                return castValueName(targetParameter);
+            }
+        }
+        return valueName(targetParameter);
+    }
+
+    private static CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName,
+                    String... customSignatureValueNames) {
+        CodeTreeBuilder builder = parent.create();
+
+        boolean castedValues = sourceMethod != targetMethod;
+
+        builder.startGroup();
+        ExecutableElement method = targetMethod.getMethod();
+        if (method == null) {
+            throw new UnsupportedOperationException();
+        }
+        TypeElement targetClass = ElementUtils.findNearestEnclosingType(method.getEnclosingElement());
+        NodeData node = (NodeData) targetMethod.getTemplate();
+
+        if (target == null) {
+            boolean accessible = targetMethod.canBeAccessedByInstanceOf(node.getNodeType());
+            if (accessible) {
+                if (builder.findMethod().getModifiers().contains(STATIC)) {
+                    if (method.getModifiers().contains(STATIC)) {
+                        builder.type(targetClass.asType());
+                    } else {
+                        builder.string(THIS_NODE_LOCAL_VAR_NAME);
+                    }
+                } else {
+                    if (targetMethod instanceof ExecutableTypeData) {
+                        builder.string("this");
+                    } else {
+                        builder.string("super");
+                    }
+                }
+            } else {
+                if (method.getModifiers().contains(STATIC)) {
+                    builder.type(targetClass.asType());
+                } else {
+                    Parameter firstParameter = null;
+                    for (Parameter searchParameter : targetMethod.getParameters()) {
+                        if (searchParameter.getSpecification().isSignature()) {
+                            firstParameter = searchParameter;
+                            break;
+                        }
+                    }
+                    if (firstParameter == null) {
+                        throw new AssertionError();
+                    }
+
+                    Parameter sourceParameter = sourceMethod.findParameter(firstParameter.getLocalName());
+
+                    if (castedValues && sourceParameter != null) {
+                        builder.string(valueName(sourceParameter, firstParameter));
+                    } else {
+                        builder.string(valueName(firstParameter));
+                    }
+                }
+            }
+            builder.string(".");
+        } else {
+            builder.tree(target);
+        }
+        builder.startCall(method.getSimpleName().toString());
+
+        int signatureIndex = 0;
+
+        for (Parameter targetParameter : targetMethod.getParameters()) {
+            Parameter valueParameter = null;
+            if (sourceMethod != null) {
+                valueParameter = sourceMethod.findParameter(targetParameter.getLocalName());
+            }
+            if (valueParameter == null) {
+                valueParameter = targetParameter;
+            }
+            TypeMirror targetType = targetParameter.getType();
+            TypeMirror valueType = null;
+            if (valueParameter != null) {
+                valueType = valueParameter.getType();
+            }
+
+            if (signatureIndex < customSignatureValueNames.length && targetParameter.getSpecification().isSignature()) {
+                builder.string(customSignatureValueNames[signatureIndex]);
+                signatureIndex++;
+            } else if (targetParameter.getSpecification().isLocal()) {
+                builder.startGroup();
+                if (builder.findMethod().getModifiers().contains(Modifier.STATIC)) {
+                    builder.string(THIS_NODE_LOCAL_VAR_NAME).string(".");
+                } else {
+                    builder.string("this.");
+                }
+                builder.string(targetParameter.getSpecification().getName());
+                builder.end();
+            } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) {
+                builder.cast(targetParameter.getType(), CodeTreeBuilder.singleString("ex.getResult()"));
+            } else if (!ElementUtils.needsCastTo(valueType, targetType)) {
+                builder.startGroup();
+                builder.string(valueName(targetParameter));
+                builder.end();
+            } else {
+                builder.string(castValueName(targetParameter));
+            }
+        }
+
+        builder.end().end();
+
+        return builder.getRoot();
+    }
+
+    private static String baseClassName(NodeData node) {
+        String nodeid = resolveNodeId(node);
+        String name = ElementUtils.firstLetterUpperCase(nodeid);
+        name += "BaseNode";
+        return name;
+    }
+
+    private static CodeTree createCallTypeSystemMethod(CodeTreeBuilder parent, NodeData node, String methodName, CodeTree... args) {
+        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+        startCallTypeSystemMethod(builder, node.getTypeSystem(), methodName);
+        for (CodeTree arg : args) {
+            builder.tree(arg);
+        }
+        builder.end().end();
+        return builder.getRoot();
+    }
+
+    private static void startCallTypeSystemMethod(CodeTreeBuilder body, TypeSystemData typeSystem, String methodName) {
+        GeneratedTypeMirror typeMirror = new GeneratedTypeMirror(ElementUtils.getPackageName(typeSystem.getTemplateType()), TypeSystemCodeGenerator.typeName(typeSystem));
+        body.startGroup();
+        body.staticReference(typeMirror, TypeSystemCodeGenerator.singletonName(typeSystem));
+        body.string(".").startCall(methodName);
+    }
+
+    /**
+     * <pre>
+     * variant1 $condition != null
+     * 
+     * $type $name = defaultValue($type);
+     * if ($condition) {
+     *     $name = $value;
+     * }
+     * 
+     * variant2 $condition != null
+     * $type $name = $value;
+     * </pre>
+     *
+     * .
+     */
+    private static CodeTree createLazyAssignment(CodeTreeBuilder parent, String name, TypeMirror type, CodeTree condition, CodeTree value) {
+        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+        if (condition == null) {
+            builder.declaration(type, name, value);
+        } else {
+            builder.declaration(type, name, new CodeTreeBuilder(parent).defaultValue(type).getRoot());
+
+            builder.startIf().tree(condition).end();
+            builder.startBlock();
+            builder.startStatement();
+            builder.string(name);
+            builder.string(" = ");
+            builder.tree(value);
+            builder.end(); // statement
+            builder.end(); // block
+        }
+        return builder.getRoot();
+    }
+
+    private void emitEncounteredSynthetic(CodeTreeBuilder builder, TemplateMethod current) {
+        CodeTreeBuilder nodes = builder.create();
+        CodeTreeBuilder arguments = builder.create();
+        nodes.startCommaGroup();
+        arguments.startCommaGroup();
+        boolean empty = true;
+        for (Parameter parameter : current.getParameters()) {
+            NodeExecutionData executionData = parameter.getSpecification().getExecution();
+            if (executionData != null) {
+                if (executionData.isShortCircuit()) {
+                    nodes.nullLiteral();
+                    arguments.string(valueName(parameter.getPreviousParameter()));
+                }
+                nodes.tree(createAccessChild(executionData, "rootNode"));
+                arguments.string(valueName(parameter));
+                empty = false;
+            }
+        }
+        nodes.end();
+        arguments.end();
+        builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end();
+
+        builder.declaration(baseClassName(getModel()), "rootNode", builder.create().startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_FIND_ROOT).string("this").end());
+        builder.startThrow().startNew(getContext().getType(UnsupportedSpecializationException.class));
+        builder.string("rootNode");
+        builder.startNewArray(getContext().getTruffleTypes().getNodeArray(), null);
+        builder.tree(nodes.getRoot());
+        builder.end();
+        if (!empty) {
+            builder.tree(arguments.getRoot());
+        }
+        builder.end().end();
+    }
+
+    private static List<ExecutableElement> findUserConstructors(TypeMirror nodeType) {
+        List<ExecutableElement> constructors = new ArrayList<>();
+        for (ExecutableElement constructor : ElementFilter.constructorsIn(ElementUtils.fromTypeMirror(nodeType).getEnclosedElements())) {
+            if (constructor.getModifiers().contains(PRIVATE)) {
+                continue;
+            }
+            if (isCopyConstructor(constructor)) {
+                continue;
+            }
+            constructors.add(constructor);
+        }
+
+        if (constructors.isEmpty()) {
+            constructors.add(new CodeExecutableElement(null, ElementUtils.getSimpleName(nodeType)));
+        }
+
+        return constructors;
+    }
+
+    private static ExecutableElement findCopyConstructor(TypeMirror type) {
+        for (ExecutableElement constructor : ElementFilter.constructorsIn(ElementUtils.fromTypeMirror(type).getEnclosedElements())) {
+            if (constructor.getModifiers().contains(PRIVATE)) {
+                continue;
+            }
+            if (isCopyConstructor(constructor)) {
+                return constructor;
+            }
+        }
+
+        return null;
+    }
+
+    private static boolean isCopyConstructor(ExecutableElement element) {
+        if (element.getParameters().size() != 1) {
+            return false;
+        }
+        VariableElement var = element.getParameters().get(0);
+        TypeElement enclosingType = ElementUtils.findNearestEnclosingType(var);
+        if (ElementUtils.typeEquals(var.asType(), enclosingType.asType())) {
+            return true;
+        }
+        List<TypeElement> types = ElementUtils.getDirectSuperTypes(enclosingType);
+        for (TypeElement type : types) {
+            if (!(type instanceof CodeTypeElement)) {
+                // no copy constructors which are not generated types
+                return false;
+            }
+
+            if (ElementUtils.typeEquals(var.asType(), type.asType())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @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<>();
+        for (NodeData nodeChild : node.getEnclosingNodes()) {
+            NodeCodeGenerator generator = new NodeCodeGenerator();
+            childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements());
+        }
+
+        if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) {
+            NodeFactoryFactory factory = new NodeFactoryFactory(childTypes);
+            add(factory, node);
+            factory.getElement().getEnclosedElements().addAll(casts);
+        }
+    }
+
+    private static CodeTree createCastType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) {
+        if (targetType == null) {
+            return value;
+        } else if (sourceType != null && !sourceType.needsCastTo(targetType)) {
+            return value;
+        }
+
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        String targetMethodName;
+        if (expect) {
+            targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType);
+        } else {
+            targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType);
+        }
+        startCallTypeSystemMethod(builder, typeSystem, targetMethodName);
+        builder.tree(value);
+        builder.end().end();
+        return builder.getRoot();
+    }
+
+    private static CodeTree createExpectType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, CodeTree expression) {
+        return createCastType(typeSystem, sourceType, targetType, true, expression);
+    }
+
+    private CodeTree createDeoptimize(CodeTreeBuilder parent) {
+        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+        builder.startStatement();
+        builder.startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end();
+        builder.end();
+        return builder.getRoot();
+    }
+
+    private class NodeFactoryFactory extends AbstractClassElementFactory<NodeData> {
+
+        private final Map<NodeData, List<TypeElement>> childTypes;
+        private CodeTypeElement generatedNode;
+
+        public NodeFactoryFactory(Map<NodeData, List<TypeElement>> childElements) {
+            this.childTypes = childElements;
+        }
+
+        @Override
+        protected CodeTypeElement create(NodeData node) {
+            Modifier visibility = ElementUtils.getVisibility(node.getTemplateType().getModifiers());
+
+            CodeTypeElement clazz = createClass(node, modifiers(), factoryClassName(node), null, false);
+            if (visibility != null) {
+                clazz.getModifiers().add(visibility);
+            }
+            clazz.getModifiers().add(Modifier.FINAL);
+            return clazz;
+        }
+
+        @Override
+        protected void createChildren(NodeData node) {
+            CodeTypeElement clazz = getElement();
+
+            Modifier createVisibility = ElementUtils.getVisibility(clazz.getModifiers());
+
+            if (node.needsFactory()) {
+                NodeBaseFactory factory = new NodeBaseFactory();
+                add(factory, node.getGenericSpecialization() == null ? node.getSpecializations().get(0) : node.getGenericSpecialization());
+                generatedNode = factory.getElement();
+
+                createFactoryMethods(node, clazz, createVisibility);
+
+                for (SpecializationData specialization : node.getSpecializations()) {
+                    if (!specialization.isReachable() || specialization.isGeneric()) {
+                        continue;
+                    }
+
+                    if (specialization.isPolymorphic() && node.isPolymorphic(context)) {
+                        PolymorphicNodeFactory polymorphicFactory = new PolymorphicNodeFactory(generatedNode);
+                        add(polymorphicFactory, specialization);
+                        continue;
+                    }
+
+                    add(new SpecializedNodeFactory(generatedNode), specialization);
+                }
+
+                TypeMirror nodeFactory = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(getContext().getTruffleTypes().getNodeFactoryBase()), node.getNodeType());
+                clazz.setSuperClass(nodeFactory);
+                clazz.add(createNodeFactoryConstructor(node));
+                clazz.add(createCreateNodeMethod(node));
+                clazz.add(createGetInstanceMethod(node, createVisibility));
+                clazz.add(createInstanceConstant(node, clazz.asType()));
+            }
+
+            for (NodeData childNode : childTypes.keySet()) {
+                if (childNode.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) {
+                    continue;
+                }
+
+                for (TypeElement type : childTypes.get(childNode)) {
+                    Set<Modifier> typeModifiers = ((CodeTypeElement) type).getModifiers();
+                    Modifier visibility = ElementUtils.getVisibility(type.getModifiers());
+                    typeModifiers.clear();
+                    if (visibility != null) {
+                        typeModifiers.add(visibility);
+                    }
+
+                    typeModifiers.add(Modifier.STATIC);
+                    typeModifiers.add(Modifier.FINAL);
+                    clazz.add(type);
+                }
+            }
+
+            List<NodeData> children = node.getNodeDeclaringChildren();
+            if (node.getDeclaringNode() == null && children.size() > 0) {
+                clazz.add(createGetFactories(node));
+            }
+
+        }
+
+        private Element createNodeFactoryConstructor(NodeData node) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), null, factoryClassName(node));
+            CodeTreeBuilder builder = method.createBuilder();
+            builder.startStatement();
+            builder.startCall("super");
+
+            // node type
+            builder.typeLiteral(node.getNodeType());
+
+            // execution signature
+            builder.startGroup();
+            if (node.getChildExecutions().isEmpty()) {
+                builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY);
+            } else {
+                builder.startNewArray(new ArrayCodeTypeMirror(context.getType(Class.class)), null);
+                for (NodeExecutionData execution : node.getChildExecutions()) {
+                    builder.typeLiteral(execution.getNodeType());
+                }
+                builder.end();
+            }
+            builder.end();
+
+            // node signatures
+            builder.startGroup();
+            builder.startNewArray(new ArrayCodeTypeMirror(new ArrayCodeTypeMirror(context.getType(Class.class))), null);
+            List<ExecutableElement> constructors = findUserConstructors(generatedNode.asType());
+            for (ExecutableElement constructor : constructors) {
+                builder.startGroup();
+                if (constructor.getParameters().isEmpty()) {
+                    builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY);
+                } else {
+                    builder.startNewArray(new ArrayCodeTypeMirror(context.getType(Class.class)), null);
+                    for (VariableElement var : constructor.getParameters()) {
+                        builder.typeLiteral(var.asType());
+                    }
+                    builder.end();
+                }
+                builder.end();
+            }
+            builder.end();
+            builder.end();
+
+            builder.end().end().end();
+            return method;
+        }
+
+        private CodeExecutableElement createCreateNodeMethod(NodeData node) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNode");
+            CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Object.class), "arguments");
+            method.setVarArgs(true);
+            method.addParameter(arguments);
+
+            CodeTreeBuilder builder = method.createBuilder();
+            List<ExecutableElement> signatures = findUserConstructors(generatedNode.asType());
+            boolean ifStarted = false;
+
+            for (ExecutableElement element : signatures) {
+                ifStarted = builder.startIf(ifStarted);
+                builder.string("arguments.length == " + element.getParameters().size());
+
+                int index = 0;
+                for (VariableElement param : element.getParameters()) {
+                    if (ElementUtils.isObject(param.asType())) {
+                        continue;
+                    }
+                    builder.string(" && ");
+                    if (!param.asType().getKind().isPrimitive()) {
+                        builder.string("(arguments[" + index + "] == null || ");
+                    }
+                    builder.string("arguments[" + index + "] instanceof ");
+                    builder.type(ElementUtils.boxType(getContext(), param.asType()));
+                    if (!param.asType().getKind().isPrimitive()) {
+                        builder.string(")");
+                    }
+                    index++;
+                }
+                builder.end();
+                builder.startBlock();
+
+                builder.startReturn().startCall("create");
+                index = 0;
+                for (VariableElement param : element.getParameters()) {
+                    builder.startGroup();
+                    if (!ElementUtils.isObject(param.asType())) {
+                        builder.string("(").type(param.asType()).string(") ");
+                    }
+                    builder.string("arguments[").string(String.valueOf(index)).string("]");
+                    builder.end();
+                    index++;
+                }
+                builder.end().end();
+
+                builder.end(); // block
+            }
+
+            builder.startElseBlock();
+            builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class));
+            builder.doubleQuote("Invalid create signature.");
+            builder.end().end();
+            builder.end(); // else block
+            return method;
+        }
+
+        private ExecutableElement createGetInstanceMethod(NodeData node, Modifier visibility) {
+            TypeElement nodeFactoryType = ElementUtils.fromTypeMirror(getContext().getType(NodeFactory.class));
+            TypeMirror returnType = ElementUtils.getDeclaredType(nodeFactoryType, node.getNodeType());
+
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(), returnType, "getInstance");
+            if (visibility != null) {
+                method.getModifiers().add(visibility);
+            }
+            method.getModifiers().add(Modifier.STATIC);
+
+            String varName = instanceVarName(node);
+
+            CodeTreeBuilder builder = method.createBuilder();
+            builder.startIf();
+            builder.string(varName).string(" == null");
+            builder.end().startBlock();
+
+            builder.startStatement();
+            builder.string(varName);
+            builder.string(" = ");
+            builder.startNew(factoryClassName(node)).end();
+            builder.end();
+
+            builder.end();
+            builder.startReturn().string(varName).end();
+            return method;
+        }
+
+        private String instanceVarName(NodeData node) {
+            if (node.getDeclaringNode() != null) {
+                return ElementUtils.firstLetterLowerCase(factoryClassName(node)) + "Instance";
+            } else {
+                return "instance";
+            }
+        }
+
+        private CodeVariableElement createInstanceConstant(NodeData node, TypeMirror factoryType) {
+            String varName = instanceVarName(node);
+            CodeVariableElement var = new CodeVariableElement(modifiers(), factoryType, varName);
+            var.getModifiers().add(Modifier.PRIVATE);
+            var.getModifiers().add(Modifier.STATIC);
+            return var;
+        }
+
+        private ExecutableElement createGetFactories(NodeData node) {
+            List<NodeData> children = node.getNodeDeclaringChildren();
+            if (node.needsFactory()) {
+                children.add(node);
+            }
+
+            List<TypeMirror> nodeTypesList = new ArrayList<>();
+            TypeMirror prev = null;
+            boolean allSame = true;
+            for (NodeData child : children) {
+                nodeTypesList.add(child.getNodeType());
+                if (prev != null && !ElementUtils.typeEquals(child.getNodeType(), prev)) {
+                    allSame = false;
+                }
+                prev = child.getNodeType();
+            }
+            TypeMirror commonNodeSuperType = ElementUtils.getCommonSuperType(getContext(), nodeTypesList.toArray(new TypeMirror[nodeTypesList.size()]));
+
+            Types types = getContext().getEnvironment().getTypeUtils();
+            TypeMirror factoryType = getContext().getType(NodeFactory.class);
+            TypeMirror baseType;
+            if (allSame) {
+                baseType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(factoryType), commonNodeSuperType);
+            } else {
+                baseType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null));
+            }
+            TypeMirror listType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(getContext().getType(List.class)), baseType);
+
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), listType, "getFactories");
+
+            CodeTreeBuilder builder = method.createBuilder();
+            builder.startReturn();
+            builder.startStaticCall(getContext().getType(Arrays.class), "asList");
+
+            for (NodeData child : children) {
+                builder.startGroup();
+                NodeData childNode = child;
+                List<NodeData> factories = new ArrayList<>();
+                while (childNode.getDeclaringNode() != null) {
+                    factories.add(childNode);
+                    childNode = childNode.getDeclaringNode();
+                }
+                Collections.reverse(factories);
+                for (NodeData nodeData : factories) {
+                    builder.string(factoryClassName(nodeData)).string(".");
+                }
+                builder.string("getInstance()");
+                builder.end();
+            }
+            builder.end();
+            builder.end();
+            return method;
+        }
+
+        private void createFactoryMethods(NodeData node, CodeTypeElement clazz, Modifier createVisibility) {
+            List<ExecutableElement> constructors = findUserConstructors(generatedNode.asType());
+            for (ExecutableElement constructor : constructors) {
+                clazz.add(createCreateMethod(node, createVisibility, constructor));
+            }
+        }
+
+        private CodeExecutableElement createCreateMethod(NodeData node, Modifier visibility, ExecutableElement constructor) {
+            CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), constructor);
+            method.setSimpleName(CodeNames.of("create"));
+            method.getModifiers().clear();
+            if (visibility != null) {
+                method.getModifiers().add(visibility);
+            }
+            method.getModifiers().add(Modifier.STATIC);
+            method.setReturnType(node.getNodeType());
+
+            CodeTreeBuilder body = method.createBuilder();
+            body.startReturn();
+            if (node.getSpecializations().isEmpty()) {
+                body.nullLiteral();
+            } else {
+                body.startCall(nodeSpecializationClassName(node.getSpecializations().get(0)), FACTORY_METHOD_NAME);
+                for (VariableElement var : method.getParameters()) {
+                    body.string(var.getSimpleName().toString());
+                }
+                body.end();
+            }
+            body.end();
+            return method;
+        }
+
+    }
+
+    private class NodeBaseFactory extends AbstractClassElementFactory<SpecializationData> {
+
+        @Override
+        protected CodeTypeElement create(SpecializationData specialization) {
+            NodeData node = specialization.getNode();
+            CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, ABSTRACT, STATIC), baseClassName(node), node.getNodeType(), false);
+            clazz.getImplements().add(context.getTruffleTypes().getDslNode());
+
+            for (NodeChildData child : node.getChildren()) {
+                clazz.add(createChildField(child));
+
+                if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) {
+                    ExecutableElement getter = (ExecutableElement) child.getAccessElement();
+                    CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), getter);
+                    method.getModifiers().remove(Modifier.ABSTRACT);
+                    CodeTreeBuilder builder = method.createBuilder();
+                    builder.startReturn().string("this.").string(child.getName()).end();
+                    clazz.add(method);
+                }
+            }
+
+            for (NodeFieldData field : node.getFields()) {
+                if (!field.isGenerated()) {
+                    continue;
+                }
+
+                clazz.add(new CodeVariableElement(modifiers(PROTECTED, FINAL), field.getType(), field.getName()));
+                if (field.getGetter() != null && field.getGetter().getModifiers().contains(Modifier.ABSTRACT)) {
+                    CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), field.getGetter());
+                    method.getModifiers().remove(Modifier.ABSTRACT);
+                    method.createBuilder().startReturn().string("this.").string(field.getName()).end();
+                    clazz.add(method);
+                }
+            }
+
+            for (String assumption : node.getAssumptions()) {
+                clazz.add(createAssumptionField(assumption));
+            }
+
+            createConstructors(node, clazz);
+
+            return clazz;
+        }
+
+        @Override
+        protected void createChildren(SpecializationData specialization) {
+            NodeData node = specialization.getNode();
+            CodeTypeElement clazz = getElement();
+
+            SpecializationGroup rootGroup = createSpecializationGroups(node);
+
+            if (node.needsRewrites(context)) {
+                if (node.isPolymorphic(context)) {
+
+                    CodeVariableElement var = new CodeVariableElement(modifiers(PROTECTED), clazz.asType(), "next0");
+                    var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation()));
+                    clazz.add(var);
+
+                    CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getPolymorphicSpecialization());
+                    clazz.add(genericCachedExecute);
+
+                }
+
+                for (CodeExecutableElement method : createImplicitChildrenAccessors()) {
+                    clazz.add(method);
+                }
+                clazz.add(createInfoMessage(node));
+                clazz.add(createMonomorphicRewrite());
+                clazz.add(createCreateSpecializationMethod(node, rootGroup));
+            }
+
+            clazz.add(createAdoptChildren0());
+            clazz.add(createGetMetadata0(true));
+            clazz.add(createUpdateTypes0());
+            clazz.add(createGetNext());
+        }
+
+        private Element createGetNext() {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), context.getType(Node.class), "getNext0");
+            CodeTreeBuilder builder = method.createBuilder();
+            NodeData node = getModel().getNode();
+
+            if (node.isPolymorphic(context)) {
+                builder.startReturn().string("next0").end();
+            } else {
+                builder.returnNull();
+            }
+
+            return method;
+        }
+
+        protected final CodeExecutableElement createUpdateTypes0() {
+            ArrayType classArray = new ArrayCodeTypeMirror(context.getType(Class.class));
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(void.class), "updateTypes0");
+            method.getParameters().add(new CodeVariableElement(classArray, "types"));
+
+            if (getModel().isPolymorphic()) {
+                CodeTreeBuilder builder = method.createBuilder();
+
+                int index = 0;
+                for (NodeExecutionData execution : getModel().getNode().getChildExecutions()) {
+                    String fieldName = polymorphicTypeName(execution);
+
+                    builder.startStatement();
+                    builder.string(fieldName).string(" = ").string("types[").string(String.valueOf(index)).string("]");
+                    builder.end();
+                    index++;
+                }
+            }
+
+            return method;
+        }
+
+        protected final CodeExecutableElement createGetMetadata0(boolean empty) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getTruffleTypes().getDslMetadata(), "getMetadata0");
+            if (empty) {
+                method.createBuilder().startReturn().staticReference(context.getTruffleTypes().getDslMetadata(), "NONE").end();
+            } else {
+                method.createBuilder().startReturn().string(METADATA_FIELD_NAME).end();
+            }
+            return method;
+        }
+
+        private CodeExecutableElement createAdoptChildren0() {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), context.getType(void.class), "adoptChildren0");
+            method.getParameters().add(new CodeVariableElement(context.getTruffleTypes().getNode(), "other"));
+            method.getParameters().add(new CodeVariableElement(context.getTruffleTypes().getNode(), "newNext"));
+            NodeData node = getModel().getNode();
+            CodeTreeBuilder builder = method.createBuilder();
+            List<NodeExecutionData> executions = node.getChildExecutions();
+
+            if (executions.size() > 0) {
+                builder.startIf().string("other == null").end().startBlock();
+                for (NodeExecutionData execution : executions) {
+                    builder.startStatement().tree(createAccessChild(execution, "this")).string(" = null").end();
+                }
+                builder.end().startElseBlock();
+
+                String access;
+                if (executions.size() > 1) {
+                    builder.declaration(baseClassName(node), "otherCast", builder.create().cast(baseClassName(node)).string("other"));
+                    access = "otherCast";
+                } else {
+                    assert executions.size() == 1;
+                    access = "((" + baseClassName(node) + ") other)";
+                }
+                for (NodeExecutionData execution : executions) {
+                    builder.startStatement().tree(createAccessChild(execution, "this")).string(" = ").tree(createAccessChild(execution, access)).end();
+                }
+
+                builder.end();
+            }
+
+            if (getModel().getNode().isPolymorphic(context)) {
+                builder.startIf().string("newNext == null").end().startBlock();
+                builder.statement("this.next0 = null");
+                builder.end().startElseBlock();
+                builder.statement("this.next0 = (" + baseClassName(getModel().getNode()) + ") newNext");
+                builder.end();
+            }
+
+            return method;
+        }
+
+        private List<CodeExecutableElement> createImplicitChildrenAccessors() {
+            NodeData node = getModel().getNode();
+            List<Set<TypeData>> prototype = Collections.nCopies(node.getGenericSpecialization().getParameters().size(), null);
+            List<Set<TypeData>> expectTypes = new ArrayList<>(prototype);
+
+            for (ExecutableTypeData executableType : node.getExecutableTypes()) {
+                for (int i = 0; i < executableType.getEvaluatedCount(); i++) {
+                    Parameter parameter = executableType.getSignatureParameter(i);
+                    if (i >= expectTypes.size()) {
+                        break;
+                    }
+                    Set<TypeData> types = expectTypes.get(i);
+                    if (types == null) {
+                        types = new TreeSet<>();
+                        expectTypes.set(i, types);
+                    }
+                    types.add(parameter.getTypeSystemType());
+                }
+            }
+
+            List<CodeExecutableElement> methods = new ArrayList<>();
+            List<Set<TypeData>> visitedList = new ArrayList<>(prototype);
+            for (SpecializationData spec : node.getSpecializations()) {
+                int signatureIndex = -1;
+                for (Parameter param : spec.getParameters()) {
+                    if (!param.getSpecification().isSignature()) {
+                        continue;
+                    }
+                    signatureIndex++;
+                    Set<TypeData> visitedTypeData = visitedList.get(signatureIndex);
+                    if (visitedTypeData == null) {
+                        visitedTypeData = new TreeSet<>();
+                        visitedList.set(signatureIndex, visitedTypeData);
+                    }
+
+                    if (visitedTypeData.contains(param.getTypeSystemType())) {
+                        continue;
+                    }
+                    visitedTypeData.add(param.getTypeSystemType());
+
+                    Set<TypeData> expect = expectTypes.get(signatureIndex);
+                    if (expect == null) {
+                        expect = Collections.emptySet();
+                    }
+
+                    methods.addAll(createExecuteChilds(param, expect));
+                }
+            }
+            return methods;
+        }
+
+        private CodeTree truffleBooleanOption(CodeTreeBuilder parent, String name) {
+            CodeTreeBuilder builder = parent.create();
+            builder.staticReference(getContext().getTruffleTypes().getTruffleOptions(), name);
+            return builder.getRoot();
+        }
+
+        private Element createInfoMessage(NodeData node) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), getContext().getType(String.class), CREATE_INFO);
+            method.addParameter(new CodeVariableElement(getContext().getType(String.class), "message"));
+            addInternalValueParameters(method, node.getGenericSpecialization(), false, false);
+
+            CodeTreeBuilder builder = method.createBuilder();
+
+            builder.startIf().tree(truffleBooleanOption(builder, TruffleTypes.OPTION_DETAILED_REWRITE_REASONS)).end();
+            builder.startBlock();
+
+            builder.startStatement().string("StringBuilder builder = new StringBuilder(message)").end();
+            builder.startStatement().startCall("builder", "append").doubleQuote(" (").end().end();
+
+            String sep = null;
+            for (Parameter parameter : node.getGenericSpecialization().getSignatureParameters()) {
+                builder.startStatement();
+                builder.string("builder");
+                if (sep != null) {
+                    builder.startCall(".append").doubleQuote(sep).end();
+                }
+                builder.startCall(".append").doubleQuote(parameter.getLocalName()).end();
+                builder.startCall(".append").doubleQuote(" = ").end();
+                builder.startCall(".append").string(parameter.getLocalName()).end();
+                builder.end();
+
+                if (!ElementUtils.isPrimitive(parameter.getType())) {
+                    builder.startIf().string(parameter.getLocalName() + " != null").end();
+                    builder.startBlock();
+                }
+                builder.startStatement();
+                if (ElementUtils.isPrimitive(parameter.getType())) {
+                    builder.startCall("builder.append").doubleQuote(" (" + ElementUtils.getSimpleName(parameter.getType()) + ")").end();
+                } else {
+                    builder.startCall("builder.append").doubleQuote(" (").end();
+                    builder.startCall(".append").string(parameter.getLocalName() + ".getClass().getSimpleName()").end();
+                    builder.startCall(".append").doubleQuote(")").end();
+                }
+                builder.end();
+                if (!ElementUtils.isPrimitive(parameter.getType())) {
+                    builder.end();
+                }
+
+                sep = ", ";
+            }
+
+            builder.startStatement().startCall("builder", "append").doubleQuote(")").end().end();
+            builder.startReturn().string("builder.toString()").end();
+
+            builder.end();
+            builder.startElseBlock();
+            builder.startReturn().string("message").end();
+            builder.end();
+
+            return method;
+        }
+
+        private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph) {
+            CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), EXECUTE_CHAINED);
+            addInternalValueParameters(cachedExecute, polymorph, true, false);
+
+            ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0);
+            boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext());
+            if (sourceThrowsUnexpected && sourceExecutableType.getType().equals(node.getGenericSpecialization().getReturnType().getTypeSystemType())) {
+                sourceThrowsUnexpected = false;
+            }
+            if (sourceThrowsUnexpected) {
+                cachedExecute.getThrownTypes().add(getContext().getType(UnexpectedResultException.class));
+            }
+            return cachedExecute;
+
+        }
+
+        private void createConstructors(NodeData node, CodeTypeElement clazz) {
+            List<ExecutableElement> constructors = findUserConstructors(node.getNodeType());
+            ExecutableElement sourceSectionConstructor = null;
+            if (constructors.isEmpty()) {
+                clazz.add(createUserConstructor(clazz, null));
+            } else {
+                for (ExecutableElement constructor : constructors) {
+                    clazz.add(createUserConstructor(clazz, constructor));
+                    if (NodeParser.isSourceSectionConstructor(context, constructor)) {
+                        sourceSectionConstructor = constructor;
+                    }
+                }
+            }
+            if (node.needsRewrites(getContext())) {
+                ExecutableElement copyConstructor = findCopyConstructor(node.getNodeType());
+                clazz.add(createCopyConstructor(clazz, copyConstructor, sourceSectionConstructor));
+            }
+        }
+
+        private CodeExecutableElement createUserConstructor(CodeTypeElement type, ExecutableElement superConstructor) {
+            CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
+            CodeTreeBuilder builder = method.createBuilder();
+
+            NodeData node = getModel().getNode();
+
+            if (superConstructor != null) {
+                for (VariableElement param : superConstructor.getParameters()) {
+                    method.getParameters().add(CodeVariableElement.clone(param));
+                }
+            }
+
+            if (superConstructor != null) {
+                builder.startStatement().startSuperCall();
+                for (VariableElement param : superConstructor.getParameters()) {
+                    builder.string(param.getSimpleName().toString());
+                }
+                builder.end().end();
+            }
+
+            for (VariableElement var : type.getFields()) {
+                if (var.getModifiers().contains(STATIC)) {
+                    continue;
+                }
+                NodeChildData child = node.findChild(var.getSimpleName().toString());
+
+                if (child != null) {
+                    method.getParameters().add(new CodeVariableElement(child.getOriginalType(), child.getName()));
+                } else {
+                    method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString()));
+                }
+
+                builder.startStatement();
+                String fieldName = var.getSimpleName().toString();
+
+                CodeTree init = createStaticCast(builder, child, fieldName);
+
+                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 CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor, ExecutableElement sourceSectionConstructor) {
+            CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
+            CodeTreeBuilder builder = method.createBuilder();
+            method.getParameters().add(new CodeVariableElement(type.asType(), "copy"));
+
+            if (superConstructor != null) {
+                builder.startStatement().startSuperCall().string("copy").end().end();
+            } else if (sourceSectionConstructor != null) {
+                builder.startStatement().startSuperCall().string("copy.getSourceSection()").end().end();
+            }
+
+            for (VariableElement var : type.getFields()) {
+                if (var.getModifiers().contains(STATIC) || !var.getModifiers().contains(FINAL)) {
+                    continue;
+                }
+                final String varName = var.getSimpleName().toString();
+                final TypeMirror varType = var.asType();
+                if (ElementUtils.isAssignable(varType, getContext().getTruffleTypes().getNodeArray())) {
+                    CodeTree size = builder.create().string("copy.", varName, ".length").getRoot();
+                    builder.startStatement().string("this.").string(varName).string(" = ").startNewArray((ArrayType) varType, size).end().end();
+                } else {
+                    builder.startStatement().string("this.", varName, " = copy.", varName).end();
+                }
+            }
+
+            return method;
+        }
+
+        private CodeVariableElement createAssumptionField(String assumption) {
+            CodeVariableElement var = new CodeVariableElement(getContext().getTruffleTypes().getAssumption(), assumption);
+            var.getModifiers().add(Modifier.FINAL);
+            return var;
+        }
+
+        private CodeVariableElement createChildField(NodeChildData child) {
+            TypeMirror type = child.getNodeType();
+            CodeVariableElement var = new CodeVariableElement(type, child.getName());
+            var.getModifiers().add(Modifier.PROTECTED);
+
+            DeclaredType annotationType;
+            if (child.getCardinality() == Cardinality.MANY) {
+                var.getModifiers().add(Modifier.FINAL);
+                annotationType = getContext().getTruffleTypes().getChildrenAnnotation();
+            } else {
+                annotationType = getContext().getTruffleTypes().getChildAnnotation();
+            }
+
+            var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType));
+            return var;
+        }
+
+        private SpecializationGroup createSpecializationGroups(final NodeData node) {
+            List<SpecializationData> specializations = node.getSpecializations();
+            List<SpecializationData> filteredSpecializations = new ArrayList<>();
+            for (SpecializationData current : specializations) {
+                if (current.isUninitialized() || current.isPolymorphic() || !current.isReachable()) {
+                    continue;
+                }
+                filteredSpecializations.add(current);
+            }
+
+            return SpecializationGroup.create(filteredSpecializations);
+        }
+
+        protected final CodeExecutableElement createExecuteUninitialized() {
+            NodeData node = getModel().getNode();
+            SpecializationData generic = node.getGenericSpecialization();
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), generic.getReturnType().getType(), EXECUTE_UNINITIALIZED);
+            addInternalValueParameters(method, generic, true, false);
+            CodeTreeBuilder builder = method.createBuilder();
+
+            CodeTreeBuilder createSpecializationCall = builder.create();
+            createSpecializationCall.startCall(SPECIALIZE);
+            addInternalValueParameterNames(createSpecializationCall, generic, generic, null, node.needsFrame(getContext()), null);
+            createSpecializationCall.end();
+            builder.declaration(baseClassName(node), "newNode", createSpecializationCall);
+
+            if (generic.isReachable()) {
+                builder.startIf().string("newNode == null").end().startBlock();
+
+                builder.startIf().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "inInterpreter").end().end().startBlock();
+                builder.statement("containsFallback = true");
+                builder.end();
+                builder.tree(createGenericInvoke(builder, generic, generic));
+                builder.end();
+                builder.startElseBlock();
+                builder.tree(createDeoptimize(builder));
+                builder.end();
+            }
+
+            builder.startReturn();
+            builder.startStaticCall(context.getTruffleTypes().getDslShare(), "rewriteUninitialized").string("this").string("newNode").end();
+            builder.string(".").startCall(EXECUTE_CHAINED);
+            addInternalValueParameterNames(builder, generic, generic, null, true, null);
+            builder.end();
+            builder.end();
+
+            if (generic.isReachable()) {
+                builder.end();
+            }
+
+            return method;
+        }
+
+        private CodeTree createInfoCall(CodeTreeBuilder parent, SpecializationData specialization, String reason) {
+            CodeTreeBuilder builder = parent.create();
+            builder.startCall(CREATE_INFO).string(reason);
+            addInternalValueParameterNames(builder, specialization, specialization, null, false, null);
+            builder.end();
+            return builder.getRoot();
+        }
+
+        private CodeExecutableElement createMonomorphicRewrite() {
+            NodeData node = getModel().getNode();
+
+            SpecializationData generic = node.getGenericSpecialization();
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), generic.getReturnType().getType(), REWRITE);
+            addInternalValueParameters(method, generic, true, false);
+            method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason"));
+
+            CodeTreeBuilder builder = method.createBuilder();
+
+            builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end().end();
+            String baseClassName = baseClassName(getModel().getNode());
+            CodeTreeBuilder createSpecializationCall = builder.create();
+            createSpecializationCall.startCall(SPECIALIZE);
+            addInternalValueParameterNames(createSpecializationCall, generic, generic, null, node.needsFrame(getContext()), null);
+            createSpecializationCall.end();
+            builder.declaration(baseClassName, "newNode", createSpecializationCall);
+
+            builder.startIf().string("newNode == null").end().startBlock();
+            builder.startStatement();
+            String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization());
+            builder.string("newNode = ").startNew(uninitializedName).string("this").end();
+            builder.end();
+            if (node.isFallbackReachable()) {
+                builder.startStatement().string("((", uninitializedName, ") newNode).containsFallback = true").end();
+            }
+            builder.end();
+
+            builder.startStatement();
+            builder.type(getContext().getType(String.class)).string(" message = ").tree(createInfoCall(builder, generic, "reason"));
+            builder.end();
+
+            builder.declaration(baseClassName, "returnNode",
+                            builder.create().startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_REWRITE).string("this").string("newNode").string("message").end().getRoot());
+            builder.startIf().string("returnNode == null").end().startBlock();
+            builder.tree(createRewritePolymorphic(builder, node, "this"));
+            builder.end();
+
+            builder.startReturn();
+            builder.startCall("returnNode", EXECUTE_CHAINED);
+            addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, null);
+            builder.end();
+            builder.end();
+
+            return method;
+        }
+
+        private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node, String currentNode) {
+            String polyClassName = nodePolymorphicClassName(node);
+            CodeTreeBuilder builder = parent.create();
+
+            builder.startStatement().string("returnNode = ");
+            builder.startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_REWRITE_TO_POLYMORHPIC);
+            builder.string("this");
+            builder.tree(builder.create().startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string(currentNode).end().getRoot());
+            builder.tree(builder.create().startNew(polyClassName).string(currentNode).end().getRoot());
+            builder.startGroup().cast(baseClassName(node)).startCall("copy").end().end();
+            builder.string("newNode");
+            builder.string("message");
+            builder.end();
+            builder.end();
+
+            return builder.getRoot();
+        }
+
+        private CodeExecutableElement createCreateSpecializationMethod(NodeData node, SpecializationGroup group) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), new GeneratedTypeMirror(ElementUtils.getPackageName(node.getTemplateType()), baseClassName(node)),
+                            SPECIALIZE);
+            if (!node.needsFrame(getContext())) {
+                method.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getSlowPath()));
+            }
+
+            addInternalValueParameters(method, node.getGenericSpecialization(), node.needsFrame(getContext()), false);
+            final CodeTreeBuilder builder = method.createBuilder();
+            builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), group, new CodeBlock<SpecializationData>() {
+
+                public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
+                    return createCreateSpecializationMethodBody0(builder, current);
+                }
+            }, null, false, true, false, true));
+
+            emitUnreachableSpecializations(builder, node);
+
+            return method;
+        }
+
+        protected CodeTree createCreateSpecializationMethodBody0(CodeTreeBuilder parent, SpecializationData current) {
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            if (current.isGeneric()) {
+                builder.startReturn().nullLiteral().end();
+            } else {
+                String className = nodeSpecializationClassName(current);
+                if (!current.getExcludedBy().isEmpty()) {
+                    builder.startIf().string("!").startStaticCall(context.getTruffleTypes().getDslShare(), "isExcluded");
+                    builder.string("this").string(nodeSpecializationClassName(current), ".", METADATA_FIELD_NAME).end().end();
+                    builder.startBlock();
+                }
+
+                if (current.getNode().getGenericSpecialization().isReachable()) {
+                    builder.tree(createDeoptimize(builder));
+                }
+                builder.startReturn();
+                builder.cast(baseClassName(getModel().getNode()));
+                builder.startGroup().startCall(className, FACTORY_METHOD_NAME).string("this");
+                for (Parameter param : current.getSignatureParameters()) {
+                    NodeChildData child = param.getSpecification().getExecution().getChild();
+                    List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
+                    if (types.size() > 1) {
+                        builder.string(implicitTypeName(param));
+                    }
+                }
+                builder.end().end();
+                builder.end();
+
+                if (!current.getExcludedBy().isEmpty()) {
+                    builder.end();
+                }
+            }
+            return builder.getRoot();
+
+        }
+
+        private void emitUnreachableSpecializations(final CodeTreeBuilder builder, NodeData node) {
+            for (SpecializationData current : node.getSpecializations()) {
+                if (current.isReachable()) {
+                    continue;
+                }
+                builder.string("// unreachable ").string(current.getId()).newLine();
+            }
+        }
+
+        protected CodeTree createExecuteTree(CodeTreeBuilder outerParent, final SpecializationData source, final SpecializationGroup group, final CodeBlock<SpecializationData> guardedblock,
+                        final CodeTree elseBlock, boolean forceElse, final boolean emitAssumptions, final boolean typedCasts, final boolean castForGuardsOnly) {
+            return guard(outerParent, source, group, new CodeBlock<Integer>() {
+
+                public CodeTree create(CodeTreeBuilder parent, Integer ifCount) {
+                    CodeTreeBuilder builder = parent.create();
+
+                    if (group.getSpecialization() != null) {
+                        builder.tree(guardedblock.create(builder, group.getSpecialization()));
+
+                        assert group.getChildren().isEmpty() : "missed a specialization";
+
+                    } else {
+                        for (SpecializationGroup childGroup : group.getChildren()) {
+                            builder.tree(createExecuteTree(builder, source, childGroup, guardedblock, null, false, emitAssumptions, typedCasts, castForGuardsOnly));
+                        }
+                    }
+
+                    return builder.getRoot();
+                }
+            }, elseBlock, forceElse, emitAssumptions, typedCasts, castForGuardsOnly);
+        }
+
+        private CodeTree guard(CodeTreeBuilder parent, SpecializationData source, SpecializationGroup group, CodeBlock<Integer> bodyBlock, CodeTree elseBlock, boolean forceElse,
+                        boolean emitAssumptions, boolean typedCasts, boolean castForGuardsOnly) {
+            CodeTreeBuilder builder = parent.create();
+
+            int ifCount = emitGuards(builder, source, group, emitAssumptions, typedCasts, castForGuardsOnly);
+
+            if (isReachableGroup(group, ifCount)) {
+                builder.tree(bodyBlock.create(builder, ifCount));
+            }
+
+            builder.end(ifCount);
+
+            if (elseBlock != null) {
+                if (ifCount > 0 || forceElse) {
+                    builder.tree(elseBlock);
+                }
+            }
+
+            return builder.getRoot();
+        }
+
+        private boolean isReachableGroup(SpecializationGroup group, int ifCount) {
+            if (ifCount != 0) {
+                return true;
+            }
+            SpecializationGroup previous = group.getPreviousGroup();
+            if (previous == null || previous.findElseConnectableGuards().isEmpty()) {
+                return true;
+            }
+
+            /*
+             * Hacky else case. In this case the specialization is not reachable due to previous
+             * else branch. This is only true if the minimum state is not checked.
+             */
+            if (previous.getGuards().size() == 1 && previous.getTypeGuards().isEmpty() && previous.getAssumptions().isEmpty() &&
+                            (previous.getParent() == null || previous.getMaxSpecializationIndex() != previous.getParent().getMaxSpecializationIndex())) {
+                return false;
+            }
+
+            return true;
+        }
+
+        private int emitGuards(CodeTreeBuilder builder, SpecializationData source, SpecializationGroup group, boolean emitAssumptions, boolean typedCasts, boolean castForGuardsOnly) {
+            NodeData node = source.getNode();
+
+            CodeTreeBuilder guardsBuilder = builder.create();
+            CodeTreeBuilder castBuilder = builder.create();
+            CodeTreeBuilder guardsCastBuilder = builder.create();
+
+            String guardsAnd = "";
+            String guardsCastAnd = "";
+
+            if (emitAssumptions) {
+                for (String assumption : group.getAssumptions()) {
+                    guardsBuilder.string(guardsAnd);
+                    guardsBuilder.string("this");
+                    guardsBuilder.string(".").string(assumption).string(".isValid()");
+                    guardsAnd = " && ";
+                }
+            }
+
+            for (TypeGuard typeGuard : group.getTypeGuards()) {
+                Parameter valueParam = source.getSignatureParameter(typeGuard.getSignatureIndex());
+
+                if (valueParam == null) {
+                    /*
+                     * If used inside a execute evaluated method then the value param may not exist.
+                     * In that case we assume that the value is executed generic or of the current
+                     * specialization.
+                     */
+                    if (group.getSpecialization() != null) {
+                        valueParam = group.getSpecialization().getSignatureParameter(typeGuard.getSignatureIndex());
+                    } else {
+                        valueParam = node.getGenericSpecialization().getSignatureParameter(typeGuard.getSignatureIndex());
+                    }
+                }
+
+                NodeExecutionData execution = valueParam.getSpecification().getExecution();
+                CodeTree implicitGuard = createTypeGuard(guardsBuilder, execution, valueParam, typeGuard.getType(), typedCasts);
+                if (implicitGuard != null) {
+                    guardsBuilder.string(guardsAnd);
+                    guardsBuilder.tree(implicitGuard);
+                    guardsAnd = " && ";
+                }
+
+                CodeTree implicitGetType = null;
+                if (castForGuardsOnly) {
+                    implicitGetType = createGetImplicitType(builder, execution, valueParam, typeGuard.getType());
+                }
+
+                boolean performCast = true;
+                if (castForGuardsOnly) {
+                    // if cast for guards we just cast if the type guard is used inside a guard.
+                    performCast = group.isTypeGuardUsedInAnyGuardBelow(context, source, typeGuard);
+                }
+
+                if (performCast) {
+                    CodeTree cast = createCast(castBuilder, execution, valueParam, typeGuard.getType(), typedCasts);
+                    if (cast != null) {
+                        castBuilder.tree(cast);
+                    }
+                }
+                if (implicitGetType != null) {
+                    castBuilder.tree(implicitGetType);
+                }
+            }
+            List<GuardExpression> elseGuards = group.findElseConnectableGuards();
+
+            for (GuardExpression guard : group.getGuards()) {
+                if (elseGuards.contains(guard)) {
+                    continue;
+                }
+
+                if (needsTypeGuard(source, group, guard)) {
+                    guardsCastBuilder.tree(createMethodGuard(builder, guardsCastAnd, source, guard));
+                    guardsCastAnd = " && ";
+                } else {
+                    guardsBuilder.tree(createMethodGuard(builder, guardsAnd, source, guard));
+                    guardsAnd = " && ";
+                }
+            }
+
+            int ifCount = startGuardIf(builder, guardsBuilder, 0, elseGuards);
+            builder.tree(castBuilder.getRoot());
+            ifCount = startGuardIf(builder, guardsCastBuilder, ifCount, elseGuards);
+            return ifCount;
+        }
+
+        private int startGuardIf(CodeTreeBuilder builder, CodeTreeBuilder conditionBuilder, int ifCount, List<GuardExpression> elseGuard) {
+            int newIfCount = ifCount;
+
+            if (!conditionBuilder.isEmpty()) {
+                if (ifCount == 0 && !elseGuard.isEmpty()) {
+                    builder.startElseIf();
+                } else {
+                    builder.startIf();
+                }
+                builder.tree(conditionBuilder.getRoot());
+                builder.end().startBlock();
+                newIfCount++;
+            } else if (ifCount == 0 && !elseGuard.isEmpty()) {
+                builder.startElseBlock();
+                newIfCount++;
+            }
+            return newIfCount;
+        }
+
+        private boolean needsTypeGuard(SpecializationData source, SpecializationGroup group, GuardExpression guard) {
+            for (Parameter parameter : guard.getResolvedGuard().getParameters()) {
+                if (!parameter.getSpecification().isSignature()) {
+                    continue;
+                }
+
+                int signatureIndex = source.getNode().getChildExecutions().indexOf(parameter.getSpecification().getExecution());
+                if (signatureIndex == -1) {
+                    continue;
+                }
+
+                TypeGuard typeGuard = group.findTypeGuard(signatureIndex);
+                if (typeGuard != null) {
+                    TypeData requiredType = typeGuard.getType();
+
+                    Parameter sourceParameter = source.findParameter(parameter.getLocalName());
+                    if (sourceParameter == null) {
+                        sourceParameter = source.getNode().getGenericSpecialization().findParameter(parameter.getLocalName());
+                    }
+
+                    if (ElementUtils.needsCastTo(sourceParameter.getType(), requiredType.getPrimitiveType())) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+
+        private CodeTree createTypeGuard(CodeTreeBuilder parent, NodeExecutionData execution, Parameter source, TypeData targetType, boolean typedCasts) {
+            NodeData node = execution.getChild().getNodeData();
+
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+
+            TypeData sourceType = source.getTypeSystemType();
+
+            if (!sourceType.needsCastTo(targetType)) {
+                return null;
+            }
+
+            builder.startGroup();
+
+            if (execution.isShortCircuit()) {
+                Parameter shortCircuit = source.getPreviousParameter();
+                assert shortCircuit != null;
+                builder.string("(");
+                builder.string("!").string(valueName(shortCircuit));
+                builder.string(" || ");
+            }
+
+            String castMethodName;
+            String castTypeName = null;
+            List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
+            if (types.size() > 1) {
+                castMethodName = TypeSystemCodeGenerator.isImplicitTypeMethodName(targetType);
+                if (typedCasts) {
+                    castTypeName = implicitTypeName(source);
+                }
+            } else {
+                castMethodName = TypeSystemCodeGenerator.isTypeMethodName(targetType);
+            }
+
+            startCallTypeSystemMethod(builder, node.getTypeSystem(), castMethodName);
+            builder.string(valueName(source));
+            if (castTypeName != null) {
+                builder.string(castTypeName);
+            }
+            builder.end().end(); // call
+
+            if (execution.isShortCircuit()) {
+                builder.string(")");
+            }
+
+            builder.end(); // group
+
+            return builder.getRoot();
+        }
+
+        // TODO merge redundancies with #createTypeGuard
+        private CodeTree createCast(CodeTreeBuilder parent, NodeExecutionData execution, Parameter source, TypeData targetType, boolean typedCasts) {
+            NodeData node = execution.getChild().getNodeData();
+            TypeData sourceType = source.getTypeSystemType();
+
+            if (!sourceType.needsCastTo(targetType)) {
+                return null;
+            }
+
+            CodeTree condition = null;
+            if (execution.isShortCircuit()) {
+                Parameter shortCircuit = source.getPreviousParameter();
+                assert shortCircuit != null;
+                condition = CodeTreeBuilder.singleString(valueName(shortCircuit));
+            }
+
+            String castMethodName;
+            String castTypeName = null;
+            List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
+            if (types.size() > 1) {
+                castMethodName = TypeSystemCodeGenerator.asImplicitTypeMethodName(targetType);
+                if (typedCasts) {
+                    castTypeName = implicitTypeName(source);
+                }
+            } else {
+                castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType);
+            }
+
+            List<CodeTree> args = new ArrayList<>();
+            args.add(CodeTreeBuilder.singleString(valueName(source)));
+            if (castTypeName != null) {
+                args.add(CodeTreeBuilder.singleString(castTypeName));
+            }
+
+            CodeTree cast = createCallTypeSystemMethod(parent, node, castMethodName, args.toArray(new CodeTree[0]));
+
+            CodeTreeBuilder builder = parent.create();
+            builder.tree(createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, cast));
+
+            return builder.getRoot();
+        }
+
+        private CodeTree createGetImplicitType(CodeTreeBuilder parent, NodeExecutionData execution, Parameter source, TypeData targetType) {
+            CodeTree condition = null;
+            if (execution.isShortCircuit()) {
+                Parameter shortCircuit = source.getPreviousParameter();
+                assert shortCircuit != null;
+                condition = CodeTreeBuilder.singleString(valueName(shortCircuit));
+            }
+
+            CodeTreeBuilder builder = parent.create();
+            List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
+            if (types.size() > 1) {
+                CodeTree castType = createCallTypeSystemMethod(parent, execution.getChild().getNodeData(), TypeSystemCodeGenerator.getImplicitClass(targetType),
+                                CodeTreeBuilder.singleString(valueName(source)));
+                builder.tree(createLazyAssignment(builder, implicitTypeName(source), getContext().getType(Class.class), condition, castType));
+            }
+            return builder.getRoot();
+        }
+
+        private CodeTree createMethodGuard(CodeTreeBuilder parent, String prefix, SpecializationData source, GuardExpression guard) {
+            CodeTreeBuilder builder = parent.create();
+            builder.string(prefix);
+            if (guard.isNegated()) {
+                builder.string("!");
+            }
+            builder.tree(createTemplateMethodCall(builder, null, source, guard.getResolvedGuard(), null));
+            return builder.getRoot();
+        }
+
+        protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) {
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+
+            if (current.getMethod() == null) {
+                emitEncounteredSynthetic(builder, current);
+            } else {
+                builder.startReturn().tree(createTemplateMethodCall(builder, null, source, current, null)).end();
+            }
+
+            return encloseThrowsWithFallThrough(parent, current, builder.getRoot());
+        }
+
+        private CodeTree encloseThrowsWithFallThrough(CodeTreeBuilder parent, SpecializationData current, CodeTree tree) {
+            if (current.getExceptions().isEmpty()) {
+                return tree;
+            }
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+
+            builder.startTryBlock();
+            builder.tree(tree);
+            for (SpecializationThrowsData exception : current.getExceptions()) {
+                builder.end().startCatchBlock(exception.getJavaClass(), "rewriteEx");
+                builder.tree(createDeoptimize(builder));
+                builder.tree(createCallRewriteMonomorphic(builder, false, current.getNode().getGenericSpecialization().getReturnType().getTypeSystemType(), current, null,
+                                "Thrown " + ElementUtils.getSimpleName(exception.getJavaClass())));
+            }
+            builder.end();
+
+            return builder.getRoot();
+        }
+
+        protected CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) {
+            TypeData type = executable.getType();
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            NodeData node = specialization.getNode();
+
+            TypeData primaryType = castExecutable.getType();
+
+            boolean needsTry = castExecutable.hasUnexpectedValue(getContext());
+            boolean returnVoid = type.isVoid();
+
+            List<Parameter> executeParameters = new ArrayList<>();
+            for (Parameter sourceParameter : executable.getSignatureParameters()) {
+                Parameter targetParameter = castExecutable.findParameter(sourceParameter.getLocalName());
+                if (targetParameter != null) {
+                    executeParameters.add(targetParameter);
+                }
+            }
+
+            // execute names are enforced no cast
+            String[] executeParameterNames = new String[executeParameters.size()];
+            for (int i = 0; i < executeParameterNames.length; i++) {
+                executeParameterNames[i] = valueName(executeParameters.get(i));
+            }
+
+            builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null));
+            boolean hasUnexpected = executable.hasUnexpectedValue(getContext());
+
+            CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null, executeParameterNames);
+            if (needsTry) {
+                if (!returnVoid) {
+                    builder.declaration(primaryType.getPrimitiveType(), "value");
+                }
+                builder.startTryBlock();
+
+                if (returnVoid) {
+                    builder.statement(primaryExecuteCall);
+                } else {
+                    builder.startStatement();
+                    builder.string("value = ");
+                    builder.tree(primaryExecuteCall);
+                    builder.end();
+                }
+
+                builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
+                if (returnVoid) {
+                    builder.string("// ignore").newLine();
+                } else {
+                    builder.startReturn();
+                    builder.tree(createExpectExecutableType(node, specialization.getNode().getTypeSystem().getGenericTypeData(), hasUnexpected, executable.getType(),
+                                    CodeTreeBuilder.singleString("ex.getResult()")));
+                    builder.end();
+                }
+                builder.end();
+
+                if (!returnVoid) {
+                    builder.startReturn();
+                    builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), hasUnexpected, executable.getType(), CodeTreeBuilder.singleString("value")));
+                    builder.end();
+                }
+            } else {
+                if (returnVoid) {
+                    builder.statement(primaryExecuteCall);
+                } else {
+                    builder.startReturn();
+                    builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), hasUnexpected, executable.getType(), primaryExecuteCall));
+                    builder.end();
+                }
+            }
+
+            return builder.getRoot();
+        }
+
+        protected CodeTree createExpectExecutableType(NodeData node, TypeData sourceType, boolean hasUnexpected, TypeData exepctedType, CodeTree value) {
+            return createCastType(node.getTypeSystem(), sourceType, exepctedType, hasUnexpected, value);
+        }
+
+        protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List<Parameter> targetParameters,
+                        Parameter unexpectedParameter) {
+            CodeTreeBuilder builder = parent.create();
+            for (Parameter targetParameter : targetParameters) {
+                if (!targetParameter.getSpecification().isSignature()) {
+                    continue;
+                }
+                NodeExecutionData execution = targetParameter.getSpecification().getExecution();
+                CodeTree executionExpressions = createExecuteChild(builder, execution, sourceExecutable, targetParameter, unexpectedParameter);
+                CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpressions, specialization, sourceExecutable, targetParameter, execution.isShortCircuit(), unexpectedParameter);
+                CodeTree shortCircuitTree = createShortCircuitTree(builder, unexpectedTree, specialization, targetParameter, unexpectedParameter);
+
+                if (shortCircuitTree == executionExpressions) {
+                    if (containsNewLine(executionExpressions)) {
+                        builder.declaration(targetParameter.getType(), valueName(targetParameter));
+                        builder.tree(shortCircuitTree);
+                    } else {
+                        builder.startStatement().type(targetParameter.getType()).string(" ").tree(shortCircuitTree).end();
+                    }
+                } else {
+                    builder.tree(shortCircuitTree);
+                }
+
+            }
+            return builder.getRoot();
+        }
+
+        private ExecutableTypeData resolveExecutableType(NodeExecutionData execution, TypeData type) {
+            ExecutableTypeData targetExecutable = execution.getChild().findExecutableType(getContext(), type);
+            if (targetExecutable == null) {
+                targetExecutable = execution.getChild().findAnyGenericExecutableType(getContext());
+            }
+            return targetExecutable;
+        }
+
+        private CodeTree createExecuteChild(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData sourceExecutable, Parameter targetParameter, Parameter unexpectedParameter) {
+            SpecializationData specialization = getModel();
+            if (specialization.isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null) {
+                List<TypeData> possiblePolymorphicTypes = lookupPolymorphicTargetTypes(targetParameter);
+                if (possiblePolymorphicTypes.size() > 1) {
+                    CodeTreeBuilder builder = parent.create();
+
+                    boolean elseIf = false;
+                    for (TypeData possiblePolymoprhicType : possiblePolymorphicTypes) {
+                        if (possiblePolymoprhicType.isGeneric()) {
+                            continue;
+                        }
+                        elseIf = builder.startIf(elseIf);
+
+                        Parameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName());
+                        TypeData sourceType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null;
+                        builder.string(polymorphicTypeName(targetParameter.getSpecification().getExecution())).string(" == ").typeLiteral(possiblePolymoprhicType.getPrimitiveType());
+                        builder.end().startBlock();
+                        builder.startStatement();
+                        builder.tree(createExecuteChildExpression(parent, execution, sourceType, new Parameter(targetParameter, possiblePolymoprhicType), unexpectedParameter, null));
+                        builder.end();
+                        builder.end();
+                    }
+
+                    builder.startElseBlock();
+                    builder.startStatement().tree(createExecuteChildImplicit(parent, execution, sourceExecutable, targetParameter, unexpectedParameter)).end();
+                    builder.end();
+
+                    return builder.getRoot();
+                }
+            }
+            return createExecuteChildImplicit(parent, execution, sourceExecutable, targetParameter, unexpectedParameter);
+        }
+
+        protected final List<Parameter> getImplicitTypeParameters(SpecializationData model) {
+            List<Parameter> parameter = new ArrayList<>();
+            for (Parameter param : model.getSignatureParameters()) {
+                NodeChildData child = param.getSpecification().getExecution().getChild();
+                List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
+                if (types.size() > 1) {
+                    parameter.add(param);
+                }
+            }
+            return parameter;
+        }
+
+        protected final List<TypeData> lookupPolymorphicTargetTypes(Parameter param) {
+            SpecializationData specialization = getModel();
+            Set<TypeData> possiblePolymorphicTypes = new HashSet<>();
+            for (SpecializationData otherSpecialization : specialization.getNode().getSpecializations()) {
+                if (!otherSpecialization.isSpecialized()) {
+                    continue;
+                }
+                Parameter otherParameter = otherSpecialization.findParameter(param.getLocalName());
+                if (otherParameter != null) {
+                    possiblePolymorphicTypes.add(otherParameter.getTypeSystemType());
+                }
+            }
+            List<TypeData> types = new ArrayList<>(possiblePolymorphicTypes);
+            Collections.sort(types);
+            return types;
+        }
+
+        private CodeTree createExecuteChildImplicit(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData sourceExecutable, Parameter param, Parameter unexpectedParameter) {
+            CodeTreeBuilder builder = parent.create();
+            Parameter sourceParameter = sourceExecutable.findParameter(param.getLocalName());
+            String childExecuteName = createExecuteChildMethodName(param, sourceParameter != null);
+            if (childExecuteName != null) {
+                builder.string(valueName(param));
+                builder.string(" = ");
+                builder.startCall(childExecuteName);
+
+                for (Parameter parameters : sourceExecutable.getParameters()) {
+                    if (parameters.getSpecification().isSignature()) {
+                        continue;
+                    }
+                    builder.string(parameters.getLocalName());
+                }
+
+                if (sourceParameter != null) {
+                    builder.string(valueNameEvaluated(sourceParameter));
+                }
+
+                builder.string(implicitTypeName(param));
+
+                builder.end();
+            } else {
+                List<TypeData> sourceTypes = execution.getChild().getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
+                TypeData expectType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null;
+                if (sourceTypes.size() > 1) {
+                    builder.tree(createExecuteChildImplicitExpressions(parent, param, expectType));
+                } else {
+                    builder.tree(createExecuteChildExpression(parent, execution, expectType, param, unexpectedParameter, null));
+                }
+            }
+            return builder.getRoot();
+        }
+
+        private String createExecuteChildMethodName(Parameter param, boolean expect) {
+            NodeExecutionData execution = param.getSpecification().getExecution();
+            NodeChildData child = execution.getChild();
+            if (child.getExecuteWith().size() > 0) {
+                return null;
+            }
+            List<TypeData> sourceTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
+            if (sourceTypes.size() <= 1) {
+                return null;
+            }
+            String prefix = expect ? "expect" : "execute";
+            String suffix = execution.getIndex() > -1 ? String.valueOf(execution.getIndex()) : "";
+            return prefix + ElementUtils.firstLetterUpperCase(child.getName()) + ElementUtils.firstLetterUpperCase(ElementUtils.getSimpleName(param.getType())) + suffix;
+        }
+
+        private List<CodeExecutableElement> createExecuteChilds(Parameter param, Set<TypeData> expectTypes) {
+            CodeExecutableElement executeMethod = createExecuteChild(param, null);
+            if (executeMethod == null) {
+                return Collections.emptyList();
+            }
+            List<CodeExecutableElement> childs = new ArrayList<>();
+            childs.add(executeMethod);
+
+            for (TypeData expectType : expectTypes) {
+                CodeExecutableElement method = createExecuteChild(param, expectType);
+                if (method != null) {
+                    childs.add(method);
+                }
+            }
+            return childs;
+        }
+
+        private CodeExecutableElement createExecuteChild(Parameter param, TypeData expectType) {
+            String childExecuteName = createExecuteChildMethodName(param, expectType != null);
+            if (childExecuteName == null) {
+                return null;
+            }
+
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, expectType != null ? STATIC : FINAL), param.getType(), childExecuteName);
+            method.getThrownTypes().add(getContext().getTruffleTypes().getUnexpectedValueException());
+            method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue"));
+            if (expectType != null) {
+                method.addParameter(new CodeVariableElement(expectType.getPrimitiveType(), valueNameEvaluated(param)));
+            }
+            method.addParameter(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param)));
+
+            CodeTreeBuilder builder = method.createBuilder();
+            builder.declaration(param.getType(), valueName(param));
+            builder.tree(createExecuteChildImplicitExpressions(builder, param, expectType));
+            builder.startReturn().string(valueName(param)).end();
+
+            return method;
+        }
+
+        private CodeTree createExecuteChildImplicitExpressions(CodeTreeBuilder parent, Parameter targetParameter, TypeData expectType) {
+            CodeTreeBuilder builder = parent.create();
+            NodeData node = getModel().getNode();
+            NodeExecutionData execution = targetParameter.getSpecification().getExecution();
+            List<TypeData> sourceTypes = node.getTypeSystem().lookupSourceTypes(targetParameter.getTypeSystemType());
+            boolean elseIf = false;
+            int index = 0;
+            for (TypeData sourceType : sourceTypes) {
+                if (index < sourceTypes.size() - 1) {
+                    elseIf = builder.startIf(elseIf);
+                    builder.string(implicitTypeName(targetParameter)).string(" == ").typeLiteral(sourceType.getPrimitiveType());
+                    builder.end();
+                    builder.startBlock();
+                } else {
+                    builder.startElseBlock();
+                }
+
+                ExecutableTypeData implictExecutableTypeData = execution.getChild().findExecutableType(getContext(), sourceType);
+                if (implictExecutableTypeData == null) {
+                    /*
+                     * For children with executeWith.size() > 0 an executable type may not exist so
+                     * use the generic executable type which is guaranteed to exist. An expect call
+                     * is inserted automatically by #createExecuteExpression.
+                     */
+                    implictExecutableTypeData = execution.getChild().getNodeData().findExecutableType(node.getTypeSystem().getGenericTypeData(), execution.getChild().getExecuteWith().size());
+                }
+
+                ImplicitCastData cast = execution.getChild().getNodeData().getTypeSystem().lookupCast(sourceType, targetParameter.getTypeSystemType());
+                CodeTree execute = createExecuteChildExpression(builder, execution, expectType, targetParameter, null, cast);
+                builder.statement(execute);
+                builder.end();
+                index++;
+            }
+            return builder.getRoot();
+        }
+
+        private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData execution, TypeData sourceParameterType, Parameter targetParameter, Parameter unexpectedParameter,
+                        ImplicitCastData cast) {
+            // assignments: targetType <- castTargetType <- castSourceType <- sourceType
+            TypeData sourceType = sourceParameterType;
+            TypeData targetType = targetParameter.getTypeSystemType();
+            TypeData castSourceType = targetType;
+            TypeData castTargetType = targetType;
+
+            if (cast != null) {
+                castSourceType = cast.getSourceType();
+                castTargetType = cast.getTargetType();
+            }
+
+            CodeTree expression;
+            if (sourceType == null) {
+                ExecutableTypeData targetExecutable = resolveExecutableType(execution, castSourceType);
+                expression = createExecuteChildExpression(parent, execution, targetExecutable, unexpectedParameter);
+                sourceType = targetExecutable.getType();
+            } else {
+                expression = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter));
+            }
+
+            // target = expectTargetType(implicitCast(expectCastSourceType(source)))
+            TypeSystemData typeSystem = execution.getChild().getNodeData().getTypeSystem();
+            expression = createExpectType(typeSystem, sourceType, castSourceType, expression);
+            expression = createImplicitCast(parent, typeSystem, cast, expression);
+            expression = createExpectType(typeSystem, castTargetType, targetType, expression);
+
+            CodeTreeBuilder builder = parent.create();
+            builder.string(valueName(targetParameter));
+            builder.string(" = ");
+            builder.tree(expression);
+            return builder.getRoot();
+        }
+
+        private CodeTree createImplicitCast(CodeTreeBuilder parent, TypeSystemData typeSystem, ImplicitCastData cast, CodeTree expression) {
+            if (cast == null) {
+                return expression;
+            }
+            CodeTreeBuilder builder = parent.create();
+            startCallTypeSystemMethod(builder, typeSystem, cast.getMethodName());
+            builder.tree(expression);
+            builder.end().end();
+            return builder.getRoot();
+        }
+
+        private boolean containsNewLine(CodeTree tree) {
+            if (tree.getCodeKind() == CodeTreeKind.NEW_LINE) {
+                return true;
+            }
+
+            List<CodeTree> enclosing = tree.getEnclosedElements();
+            if (enclosing != null) {
+                for (CodeTree codeTree : enclosing) {
+                    if (containsNewLine(codeTree)) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+
+        private boolean hasUnexpected(Parameter sourceParameter, Parameter targetParameter, Parameter unexpectedParameter) {
+            NodeExecutionData execution = targetParameter.getSpecification().getExecution();
+
+            if (getModel().isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null) {
+                // check for other polymorphic types
+                List<TypeData> polymorphicTargetTypes = lookupPolymorphicTargetTypes(targetParameter);
+                if (polymorphicTargetTypes.size() > 1) {
+                    for (TypeData polymorphicTargetType : polymorphicTargetTypes) {
+                        if (hasUnexpectedType(execution, sourceParameter, polymorphicTargetType)) {
+                            return true;
+                        }
+                    }
+                }
+            }
+
+            if (hasUnexpectedType(execution, sourceParameter, targetParameter.getTypeSystemType())) {
+                return true;
+            }
+            return false;
+        }
+
+        private boolean hasUnexpectedType(NodeExecutionData execution, Parameter sourceParameter, TypeData targetType) {
+            List<TypeData> implicitSourceTypes = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
+
+            for (TypeData implicitSourceType : implicitSourceTypes) {
+                TypeData sourceType;
+                ExecutableTypeData targetExecutable = resolveExecutableType(execution, implicitSourceType);
+                if (sourceParameter != null) {
+                    sourceType = sourceParameter.getTypeSystemType();
+                } else {
+                    if (targetExecutable.hasUnexpectedValue(getContext())) {
+                        return true;
+                    }
+                    sourceType = targetExecutable.getType();
+                }
+
+                ImplicitCastData cast = getModel().getNode().getTypeSystem().lookupCast(implicitSourceType, targetType);
+                if (cast != null) {
+                    if (cast.getSourceType().needsCastTo(targetType)) {
+                        return true;
+                    }
+                }
+
+                if (sourceType.needsCastTo(targetType)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, ExecutableTypeData currentExecutable, Parameter param,
+                        boolean shortCircuit, Parameter unexpectedParameter) {
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            Parameter sourceParameter = currentExecutable.findParameter(param.getLocalName());
+            boolean unexpected = hasUnexpected(sourceParameter, param, unexpectedParameter);
+            if (!unexpected) {
+                return body;
+            }
+
+            if (!shortCircuit) {
+                builder.declaration(param.getType(), valueName(param));
+            }
+            builder.startTryBlock();
+
+            if (containsNewLine(body)) {
+                builder.tree(body);
+            } else {
+                builder.statement(body);
+            }
+
+            builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
+            SpecializationData generic = specialization.getNode().getGenericSpecialization();
+            Parameter genericParameter = generic.findParameter(param.getLocalName());
+
+            List<Parameter> genericParameters = generic.getParametersAfter(genericParameter);
+            builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter));
+            if (specialization.isPolymorphic()) {
+                builder.tree(createReturnOptimizeTypes(builder, currentExecutable, specialization, param));
+            } else {
+                builder.tree(createCallRewriteMonomorphic(builder, currentExecutable.hasUnexpectedValue(context), currentExecutable.getType(), specialization, param,
+                                "Expected " + param.getLocalName() + " instanceof " + ElementUtils.getSimpleName(param.getType())));
+            }
+            builder.end(); // catch block
+
+            return builder.getRoot();
+        }
+
+        private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, Parameter param) {
+            NodeData node = specialization.getNode();
+            SpecializationData polymorphic = node.getPolymorphicSpecialization();
+
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            builder.startStatement().string(polymorphicTypeName(param.getSpecification().getExecution())).string(" = ").typeLiteral(getContext().getType(Object.class)).end();
+
+            builder.startReturn();
+
+            CodeTreeBuilder execute = new CodeTreeBuilder(builder);
+            execute.startCall("next0", EXECUTE_CHAINED);
+            addInternalValueParameterNames(execute, specialization, polymorphic, param.getLocalName(), true, null);
+            execute.end();
+
+            TypeData sourceType = polymorphic.getReturnType().getTypeSystemType();
+
+            builder.tree(createExpectExecutableType(node, sourceType, currentExecutable.hasUnexpectedValue(context), currentExecutable.getType(), execute.getRoot()));
+
+            builder.end();
+            return builder.getRoot();
+        }
+
+        private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData targetExecution, ExecutableTypeData targetExecutable, Parameter unexpectedParameter) {
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            if (targetExecution != null) {
+                builder.tree(createAccessChild(targetExecution, null));
+                builder.string(".");
+            }
+
+            builder.startCall(targetExecutable.getMethodName());
+
+            // TODO this should be merged with #createTemplateMethodCall
+            int index = 0;
+            for (Parameter parameter : targetExecutable.getParameters()) {
+
+                if (!parameter.getSpecification().isSignature()) {
+                    builder.string(parameter.getLocalName());
+                } else {
+
+                    if (index < targetExecution.getChild().getExecuteWith().size()) {
+                        NodeChildData child = targetExecution.getChild().getExecuteWith().get(index);
+
+                        ParameterSpec spec = getModel().getSpecification().findParameterSpec(child.getName());
+                        List<Parameter> specializationParams = getModel().findParameters(spec);
+
+                        if (specializationParams.isEmpty()) {
+                            builder.defaultValue(parameter.getType());
+                            continue;
+                        }
+
+                        Parameter specializationParam = specializationParams.get(0);
+
+                        TypeData targetType = parameter.getTypeSystemType();
+                        TypeData sourceType = specializationParam.getTypeSystemType();
+                        String localName = specializationParam.getLocalName();
+
+                        if (unexpectedParameter != null && unexpectedParameter.getLocalName().equals(specializationParam.getLocalName())) {
+                            localName = "ex.getResult()";
+                            sourceType = getModel().getNode().getTypeSystem().getGenericTypeData();
+                        }
+
+                        CodeTree value = CodeTreeBuilder.singleString(localName);
+
+                        if (sourceType.needsCastTo(targetType)) {
+                            value = createCallTypeSystemMethod(builder, getModel().getNode(), TypeSystemCodeGenerator.asTypeMethodName(targetType), value);
+                        }
+                        builder.tree(value);
+                    } else {
+                        builder.defaultValue(parameter.getType());
+                    }
+                    index++;
+                }
+            }
+
+            builder.end();
+
+            return builder.getRoot();
+        }
+
+        private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, Parameter parameter, Parameter exceptionParam) {
+            NodeExecutionData execution = parameter.getSpecification().getExecution();
+            if (execution == null || !execution.isShortCircuit()) {
+                return body;
+            }
+
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            Parameter shortCircuitParam = specialization.getPreviousParam(parameter);
+            builder.tree(createShortCircuitValue(builder, specialization, execution, shortCircuitParam, exceptionParam));
+            builder.declaration(parameter.getType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getType()));
+            builder.startIf().string(shortCircuitParam.getLocalName()).end();
+            builder.startBlock();
+
+            if (containsNewLine(body)) {
+                builder.tree(body);
+            } else {
+                builder.statement(body);
+            }
+            builder.end();
+
+            return builder.getRoot();
+        }
+
+        private CodeTree createShortCircuitValue(CodeTreeBuilder parent, SpecializationData specialization, NodeExecutionData execution, Parameter shortCircuitParam, Parameter exceptionParam) {
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            int shortCircuitIndex = 0;
+            for (NodeExecutionData otherExectuion : specialization.getNode().getChildExecutions()) {
+                if (otherExectuion.isShortCircuit()) {
+                    if (otherExectuion == execution) {
+                        break;
+                    }
+                    shortCircuitIndex++;
+                }
+            }
+
+            builder.startStatement().type(shortCircuitParam.getType()).string(" ").string(valueName(shortCircuitParam)).string(" = ");
+            ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex);
+            builder.tree(createTemplateMethodCall(builder, null, specialization, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null));
+            builder.end(); // statement
+
+            return builder.getRoot();
+        }
+
+        protected CodeTree createCallRewriteMonomorphic(CodeTreeBuilder parent, boolean hasUnexpected, TypeData returnType, SpecializationData current, Parameter exceptionParam, String reason) {
+            NodeData node = current.getNode();
+            SpecializationData generic = node.getGenericSpecialization();
+            CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent);
+            specializeCall.startCall(REWRITE);
+            addInternalValueParameterNames(specializeCall, generic, node.getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, null);
+            specializeCall.doubleQuote(reason);
+            specializeCall.end().end();
+
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+
+            builder.startReturn();
+            builder.tree(createExpectExecutableType(node, generic.getReturnType().getTypeSystemType(), hasUnexpected, returnType, specializeCall.getRoot()));
+            builder.end();
+
+            return builder.getRoot();
+        }
+
+    }
+
+    private class PolymorphicNodeFactory extends SpecializedNodeFactory {
+
+        public PolymorphicNodeFactory(CodeTypeElement nodeGen) {
+            super(nodeGen);
+        }
+
+        @Override
+        public CodeTypeElement create(SpecializationData polymorph) {
+            NodeData node = polymorph.getNode();
+            TypeMirror baseType = node.getNodeType();
+            if (nodeGen != null) {
+                baseType = nodeGen.asType();
+            }
+            CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodePolymorphicClassName(node), baseType, false);
+
+            clazz.getAnnotationMirrors().add(createNodeInfo(node, NodeCost.POLYMORPHIC));
+
+            for (Parameter polymorphParameter : polymorph.getSignatureParameters()) {
+                if (!polymorphParameter.getTypeSystemType().isGeneric()) {
+                    continue;
+                }
+                Set<TypeData> types = new HashSet<>();
+                for (SpecializationData specialization : node.getSpecializations()) {
+                    if (!specialization.isSpecialized()) {
+                        continue;
+                    }
+                    Parameter parameter = specialization.findParameter(polymorphParameter.getLocalName());
+                    assert parameter != null;
+                    types.add(parameter.getTypeSystemType());
+                }
+
+            }
+
+            for (NodeExecutionData execution : getModel().getNode().getChildExecutions()) {
+                String fieldName = polymorphicTypeName(execution);
+                CodeVariableElement var = new CodeVariableElement(modifiers(PRIVATE), getContext().getType(Class.class), fieldName);
+                var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getCompilationFinal()));
+                clazz.add(var);
+            }
+
+            return clazz;
+        }
+
+        @Override
+        protected void createChildren(SpecializationData specialization) {
+            CodeTypeElement clazz = getElement();
+
+            createConstructors(clazz);
+            createExecuteMethods(specialization);
+
+            clazz.add(createUpdateTypes0());
+            createCachedExecuteMethods(specialization);
+        }
+
+    }
+
+    private class SpecializedNodeFactory extends NodeBaseFactory {
+
+        protected final CodeTypeElement nodeGen;
+
+        public SpecializedNodeFactory(CodeTypeElement nodeGen) {
+            this.nodeGen = nodeGen;
+        }
+
+        @Override
+        public CodeTypeElement create(SpecializationData specialization) {
+            NodeData node = specialization.getNode();
+            TypeMirror baseType = node.getNodeType();
+            if (nodeGen != null) {
+                baseType = nodeGen.asType();
+            }
+            CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false);
+
+            if (specialization.isSpecialized() || specialization.isUninitialized()) {
+                clazz.add(createGetMetadata0(false));
+                clazz.add(createMetadataLiteral());
+            }
+
+            NodeCost cost;
+            if (specialization.isGeneric()) {
+                cost = NodeCost.MEGAMORPHIC;
+            } else if (specialization.isUninitialized()) {
+                cost = NodeCost.UNINITIALIZED;
+            } else if (specialization.isPolymorphic()) {
+                cost = NodeCost.POLYMORPHIC;
+            } else if (specialization.isSpecialized()) {
+                cost = NodeCost.MONOMORPHIC;
+            } else {
+                throw new AssertionError();
+            }
+            clazz.getAnnotationMirrors().add(createNodeInfo(node, cost));
+
+            if (specialization.isUninitialized() && node.getGenericSpecialization().isReachable()) {
+                clazz.add(createUninitializedGetCostOverride());
+            }
+
+            return clazz;
+        }
+
+        private Element createUninitializedGetCostOverride() {
+            TypeMirror returnType = context.getTruffleTypes().getNodeCost();
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getCost");
+            CodeTreeBuilder builder = method.createBuilder();
+            builder.startIf().string(CONTAINS_FALLBACK).end().startBlock();
+            builder.startReturn().staticReference(returnType, "MONOMORPHIC").end();
+            builder.end();
+            builder.startReturn().string("super.getCost()").end();
+            return method;
+        }
+
+        private CodeVariableElement createMetadataLiteral() {
+            CodeVariableElement includes = new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), context.getTruffleTypes().getDslMetadata(), METADATA_FIELD_NAME);
+
+            CodeTreeBuilder builder = includes.createInitBuilder();
+
+            SpecializationData specialization = getModel();
+            NodeData node = specialization.getNode();
+
+            Set<SpecializationData> contains = specialization.getContains();
+            if (specialization.isUninitialized()) {
+                contains = new HashSet<>();
+
+                SpecializationData polymorphic = node.getPolymorphicSpecialization();
+                if (polymorphic != null) {
+                    contains.addAll(polymorphic.getContains());
+                }
+                SpecializationData generic = node.getGenericSpecialization();
+                if (generic != null) {
+                    contains.addAll(generic.getContains());
+                }
+            }
+
+            builder.startNew(context.getTruffleTypes().getDslMetadata());
+            builder.startGroup().string(nodeSpecializationClassName(getModel()), ".class").end();
+            builder.tree(createSpecializationListLiteral(builder, contains));
+            builder.tree(createSpecializationListLiteral(builder, getModel().getExcludedBy()));
+            builder.tree(createSpecializationTypeLiteral(builder, SpecializationData.getSignatureTypes(getModel())));
+            builder.string("0").string("0");
+            builder.end();
+            return includes;
+        }
+
+        private CodeTree createSpecializationTypeLiteral(CodeTreeBuilder parent, List<TypeMirror> list) {
+            ArrayType classArray = new ArrayCodeTypeMirror(context.getType(Class.class));
+            CodeTreeBuilder builder = parent.create();
+
+            if (list.isEmpty()) {
+                builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY);
+            } else {
+                builder.startNewArray(classArray, null);
+                for (TypeMirror type : list) {
+                    builder.typeLiteral(type);
+                }
+                builder.end();
+            }
+
+            return builder.getRoot();
+        }
+
+        private CodeTree createSpecializationListLiteral(CodeTreeBuilder parent, Set<SpecializationData> list) {
+            ArrayType classArray = new ArrayCodeTypeMirror(context.getType(Class.class));
+            CodeTreeBuilder builder = parent.create();
+
+            if (list.isEmpty()) {
+                builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY);
+            } else {
+                builder.startNewArray(classArray, null);
+                for (SpecializationData specialization : list) {
+                    if (specialization.isGeneric() || specialization.isPolymorphic()) {
+                        specialization = getModel().getNode().getUninitializedSpecialization();
+                    }
+                    builder.startGroup().string(nodeSpecializationClassName(specialization)).string(".class").end();
+                }
+                builder.end();
+            }
+
+            return builder.getRoot();
+        }
+
+        protected CodeAnnotationMirror createNodeInfo(NodeData node, NodeCost cost) {
+            String shortName = node.getShortName();
+            CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(getContext().getTruffleTypes().getNodeInfoAnnotation());
+            if (shortName != null) {
+                nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("shortName"), new CodeAnnotationValue(shortName));
+            }
+
+            DeclaredType nodeinfoCost = getContext().getTruffleTypes().getNodeCost();
+            VariableElement varKind = ElementUtils.findVariableElement(nodeinfoCost, cost.name());
+
+            nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("cost"), new CodeAnnotationValue(varKind));
+            return nodeInfoMirror;
+        }
+
+        @Override
+        protected void createChildren(SpecializationData specialization) {
+            CodeTypeElement clazz = getElement();
+            createConstructors(clazz);
+
+            createExecuteMethods(specialization);
+            createCachedExecuteMethods(specialization);
+
+            if (specialization.isUninitialized()) {
+                if (specialization.getNode().isFallbackReachable()) {
+                    CodeVariableElement var = new CodeVariableElement(modifiers(Modifier.PRIVATE), context.getType(boolean.class), CONTAINS_FALLBACK);
+                    var.addAnnotationMirror(new CodeAnnotationMirror(context.getTruffleTypes().getCompilationFinal()));
+                    clazz.add(var);
+                }
+                clazz.add(createExecuteUninitialized());
+            }
+
+            if (!specialization.isUninitialized() && specialization.getNode().needsRewrites(context)) {
+                clazz.add(createCopyConstructorFactoryMethod(nodeGen.asType(), specialization));
+            } else {
+                for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) {
+                    if (constructor.getParameters().size() == 1 && ((CodeVariableElement) constructor.getParameters().get(0)).getType().equals(nodeGen.asType())) {
+                        // skip copy constructor - not used
+                        continue;
+                    }
+                    clazz.add(createConstructorFactoryMethod(specialization, constructor));
+                }
+            }
+        }
+
+        protected void createConstructors(CodeTypeElement clazz) {
+            TypeElement superTypeElement = ElementUtils.fromTypeMirror(clazz.getSuperclass());
+            SpecializationData specialization = getModel();
+            NodeData node = specialization.getNode();
+            for (ExecutableElement constructor : ElementFilter.constructorsIn(superTypeElement.getEnclosedElements())) {
+                if (specialization.isUninitialized()) {
+                    // ignore copy constructors for uninitialized if not polymorphic
+                    if (isCopyConstructor(constructor) && !node.isPolymorphic(context)) {
+                        continue;
+                    }
+                } else if (node.getUninitializedSpecialization() != null) {
+                    // ignore others than copy constructors for specialized nodes
+                    if (!isCopyConstructor(constructor)) {
+                        continue;
+                    }
+                }
+
+                CodeExecutableElement superConstructor = createSuperConstructor(clazz, constructor);
+                if (superConstructor == null) {
+                    continue;
+                }
+                CodeTree body = superConstructor.getBodyTree();
+                CodeTreeBuilder builder = superConstructor.createBuilder();
+                builder.tree(body);
+
+                if (superConstructor != null) {
+                    for (Parameter param : getImplicitTypeParameters(getModel())) {
+                        clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), implicitTypeName(param)));
+                        superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param)));
+
+                        builder.startStatement();
+                        builder.string("this.").string(implicitTypeName(param)).string(" = ").string(implicitTypeName(param));
+                        builder.end();
+                    }
+
+                    clazz.add(superConstructor);
+                }
+            }
+        }
+
+        protected void createExecuteMethods(SpecializationData specialization) {
+            NodeData node = specialization.getNode();
+            CodeTypeElement clazz = getElement();
+
+            List<ExecutableTypeData> primaryExecutes = null;
+            int lastEvaluatedCount = -1;
+
+            for (ExecutableTypeData execType : node.getExecutableTypes()) {
+                if (execType.isFinal()) {
+                    continue;
+                }
+                if (execType.getEvaluatedCount() != lastEvaluatedCount) {
+                    lastEvaluatedCount = execType.getEvaluatedCount();
+                    primaryExecutes = findFunctionalExecutableType(specialization, lastEvaluatedCount);
+                }
+
+                CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, true);
+                clazz.add(executeMethod);
+                CodeTreeBuilder builder = executeMethod.getBuilder();
+                CodeTree result = createExecuteBody(builder, specialization, execType, primaryExecutes);
+                if (result != null) {
+                    builder.tree(result);
+                } else {
+                    clazz.remove(executeMethod);
+                }
+            }
+        }
+
+        protected void createCachedExecuteMethods(SpecializationData specialization) {
+            NodeData node = specialization.getNode();
+            if (!node.isPolymorphic(context)) {
+                return;
+            }
+
+            CodeTypeElement clazz = getElement();
+
+            final SpecializationData polymorphic = node.getPolymorphicSpecialization();
+            ExecutableElement executeCached = nodeGen.getMethod(EXECUTE_CHAINED);
+            CodeExecutableElement executeMethod = CodeExecutableElement.clone(getContext().getEnvironment(), executeCached);
+            executeMethod.getModifiers().remove(Modifier.ABSTRACT);
+            CodeTreeBuilder builder = executeMethod.createBuilder();
+
+            if (specialization.isPolymorphic()) {
+                builder.startReturn().startCall("this.next0", EXECUTE_CHAINED);
+                addInternalValueParameterNames(builder, polymorphic, polymorphic, null, true, null);
+                builder.end().end();
+            } else if (specialization.isUninitialized()) {
+                builder.tree(createDeoptimizeUninitialized(node, builder));
+                builder.startReturn().startCall("this", EXECUTE_UNINITIALIZED);
+                addInternalValueParameterNames(builder, polymorphic, polymorphic, null, true, null);
+                builder.end().end();
+            } else {
+                CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder);
+                elseBuilder.startReturn().startCall("this.next0", EXECUTE_CHAINED);
+                addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, null);
+                elseBuilder.end().end();
+
+                builder.tree(createExecuteTree(builder, polymorphic, SpecializationGroup.create(specialization), new CodeBlock<SpecializationData>() {
+
+                    public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
+                        return createGenericInvoke(b, polymorphic, current);
+                    }
+                }, elseBuilder.getRoot(), false, true, true, false));
+            }
+            clazz.add(executeMethod);
+        }
+
+        private CodeTree createDeoptimizeUninitialized(NodeData node, CodeTreeBuilder parent) {
+            CodeTreeBuilder builder = parent.create();
+            if (node.getGenericSpecialization().isReachable()) {
+                builder.startIf().string("!containsFallback").end().startBlock();
+                builder.tree(createDeoptimize(builder));
+                builder.end();
+            } else {
+                builder.tree(createDeoptimize(builder));
+            }
+            return builder.getRoot();
+        }
+
+        private CodeTree createExecuteBody(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData execType, List<ExecutableTypeData> primaryExecutes) {
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+
+            if (primaryExecutes.contains(execType) || primaryExecutes.isEmpty()) {
+                builder.tree(createFunctionalExecute(builder, specialization, execType));
+            } else if (needsCastingExecuteMethod(execType)) {
+                assert !primaryExecutes.isEmpty();
+                builder.tree(createCastingExecute(builder, specialization, execType, primaryExecutes.get(0)));
+            } else {
+                return null;
+            }
+
+            return builder.getRoot();
+        }
+
+        private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType, boolean evaluated) {
+            CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod());
+
+            method.getAnnotationMirrors().clear();
+            for (VariableElement variable : method.getParameters()) {
+                variable.getAnnotationMirrors().clear();
+            }
+
+            CodeTreeBuilder builder = method.createBuilder();
+            int i = 0;
+            int signatureIndex = -1;
+            for (VariableElement param : method.getParameters()) {
+                CodeVariableElement var = CodeVariableElement.clone(param);
+                Parameter actualParameter = i < execType.getParameters().size() ? execType.getParameters().get(i) : null;
+                String name;
+                if (actualParameter != null) {
+                    if (actualParameter.getSpecification().isSignature()) {
+                        signatureIndex++;
+                    }
+
+                    if (evaluated && actualParameter.getSpecification().isSignature()) {
+                        name = valueNameEvaluated(actualParameter);
+                    } else {
+                        name = valueName(actualParameter);
+                    }
+
+                    int varArgCount = getModel().getSignatureSize() - signatureIndex;
+                    if (evaluated && actualParameter.isTypeVarArgs()) {
+                        Parameter baseVarArgs = actualParameter;
+                        name = valueName(baseVarArgs) + "Args";
+
+                        builder.startAssert().string(name).string(" != null").end();
+                        builder.startAssert().string(name).string(".length == ").string(String.valueOf(varArgCount)).end();
+                        if (varArgCount > 0) {
+                            List<Parameter> varArgsParameter = execType.getParameters().subList(i, execType.getParameters().size());
+                            for (Parameter varArg : varArgsParameter) {
+                                if (varArgCount <= 0) {
+                                    break;
+                                }
+                                TypeMirror type = baseVarArgs.getType();
+                                if (type.getKind() == TypeKind.ARRAY) {
+                                    type = ((ArrayType) type).getComponentType();
+                                }
+                                builder.declaration(type, valueNameEvaluated(varArg), name + "[" + varArg.getTypeVarArgsIndex() + "]");
+                                varArgCount--;
+                            }
+                        }
+                    }
+                } else {
+                    name = "arg" + i;
+                }
+                var.setName(name);
+                method.getParameters().set(i, var);
+                i++;
+            }
+
+            method.getAnnotationMirrors().clear();
+            method.getModifiers().remove(Modifier.ABSTRACT);
+            return method;
+        }
+
+        private boolean needsCastingExecuteMethod(ExecutableTypeData execType) {
+            if (execType.isAbstract()) {
+                return true;
+            }
+            if (execType.getType().isGeneric()) {
+                return true;
+            }
+            return false;
+        }
+
+        private List<ExecutableTypeData> findFunctionalExecutableType(SpecializationData specialization, int evaluatedCount) {
+            TypeData primaryType = specialization.getReturnType().getTypeSystemType();
+            List<ExecutableTypeData> otherTypes = specialization.getNode().getExecutableTypes(evaluatedCount);
+
+            List<ExecutableTypeData> filteredTypes = new ArrayList<>();
+            for (ExecutableTypeData compareType : otherTypes) {
+                if (ElementUtils.typeEquals(compareType.getType().getPrimitiveType(), primaryType.getPrimitiveType())) {
+                    filteredTypes.add(compareType);
+                }
+            }
+
+            // no direct matches found use generic where the type is Object
+            if (filteredTypes.isEmpty()) {
+                for (ExecutableTypeData compareType : otherTypes) {
+                    if (compareType.getType().isGeneric() && !compareType.hasUnexpectedValue(getContext())) {
+                        filteredTypes.add(compareType);
+                    }
+                }
+            }
+
+            if (filteredTypes.isEmpty()) {
+                for (ExecutableTypeData compareType : otherTypes) {
+                    if (compareType.getType().isGeneric()) {
+                        filteredTypes.add(compareType);
+                    }
+                }
+            }
+
+            return filteredTypes;
+        }
+
+        private CodeTree createFunctionalExecute(CodeTreeBuilder parent, final SpecializationData specialization, final ExecutableTypeData executable) {
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+
+            if (specialization.isUninitialized()) {
+                builder.tree(createDeoptimizeUninitialized(specialization.getNode(), builder));
+            }
+
+            builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null));
+
+            CodeTree returnSpecialized = null;
+
+            if (specialization.findNextSpecialization() != null) {
+                CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder);
+                returnBuilder.tree(createDeoptimize(builder));
+                returnBuilder.tree(createCallRewriteMonomorphic(builder, executable.hasUnexpectedValue(context), executable.getType(), specialization, null,
+                                "One of guards " + specialization.getGuards() + " failed"));
+                returnSpecialized = returnBuilder.getRoot();
+            }
+
+            builder.tree(createExecuteTree(builder, specialization, SpecializationGroup.create(specialization), new CodeBlock<SpecializationData>() {
+
+                public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
+                    return createExecute(b, executable, specialization);
+                }
+            }, returnSpecialized, false, false, false, false));
+
+            return builder.getRoot();
+        }
+
+        private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) {
+            NodeData node = specialization.getNode();
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            if (!specialization.getExceptions().isEmpty() || !specialization.getAssumptions().isEmpty()) {
+                builder.startTryBlock();
+            }
+
+            for (String assumption : specialization.getAssumptions()) {
+                builder.startStatement();
+                builder.string("this.").string(assumption).string(".check()");
+                builder.end();
+            }
+
+            CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent);
+            if (specialization.isPolymorphic()) {
+                returnBuilder.startCall("next0", EXECUTE_CHAINED);
+                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, null);
+                returnBuilder.end();
+            } else if (specialization.isUninitialized()) {
+                returnBuilder.startCall(EXECUTE_UNINITIALIZED);
+                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, null);
+                returnBuilder.end();
+            } else if (specialization.getMethod() == null && !node.needsRewrites(context)) {
+                emitEncounteredSynthetic(builder, specialization);
+            } else {
+                returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null));
+            }
+
+            if (!returnBuilder.isEmpty()) {
+                TypeData targetType = node.getTypeSystem().findTypeData(builder.findMethod().getReturnType());
+                TypeData sourceType = specialization.getReturnType().getTypeSystemType();
+
+                builder.startReturn();
+                if (targetType == null || sourceType == null) {
+                    builder.tree(returnBuilder.getRoot());
+                } else if (sourceType.needsCastTo(targetType)) {
+                    String castMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType);
+                    if (!executable.hasUnexpectedValue(context)) {
+                        castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType);
+                    }
+                    builder.tree(createCallTypeSystemMethod(parent, node, castMethodName, returnBuilder.getRoot()));
+                } else {
+                    builder.tree(returnBuilder.getRoot());
+                }
+                builder.end();
+            }
+
+            if (!specialization.getExceptions().isEmpty()) {
+                for (SpecializationThrowsData exception : specialization.getExceptions()) {
+                    builder.end().startCatchBlock(exception.getJavaClass(), "ex");
+                    builder.tree(createDeoptimize(builder));
+                    builder.tree(createCallRewriteMonomorphic(parent, executable.hasUnexpectedValue(context), executable.getType(), specialization, null,
+                                    "Thrown " + ElementUtils.getSimpleName(exception.getJavaClass())));
+                }
+                builder.end();
+            }
+            if (!specialization.getAssumptions().isEmpty()) {
+                builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex");
+                builder.tree(createCallRewriteMonomorphic(parent, executable.hasUnexpectedValue(context), executable.getType(), specialization, null, "Assumption failed"));
+                builder.end();
+            }
+
+            return builder.getRoot();
+        }
+
+        protected CodeExecutableElement createCopyConstructorFactoryMethod(TypeMirror baseType, SpecializationData specialization) {
+            List<Parameter> implicitTypeParams = getImplicitTypeParameters(specialization);
+            String baseName = "current";
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), FACTORY_METHOD_NAME);
+            method.addParameter(new CodeVariableElement(specialization.getNode().getNodeType(), baseName));
+            for (Parameter implicitTypeParam : implicitTypeParams) {
+                method.addParameter(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(implicitTypeParam)));
+            }
+            CodeTreeBuilder builder = method.createBuilder();
+            builder.startReturn();
+            builder.startNew(getElement().asType());
+            builder.startGroup().cast(baseType, CodeTreeBuilder.singleString(baseName)).end();
+            for (Parameter param : implicitTypeParams) {
+                builder.string(implicitTypeName(param));
+            }
+            builder.end().end();
+            return method;
+        }
+
+        protected CodeExecutableElement createConstructorFactoryMethod(SpecializationData specialization, ExecutableElement constructor) {
+            List<? extends VariableElement> parameters = constructor.getParameters();
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), FACTORY_METHOD_NAME,
+                            parameters.toArray(new CodeVariableElement[parameters.size()]));
+            CodeTreeBuilder builder = method.createBuilder();
+            builder.startReturn();
+            builder.startNew(getElement().asType());
+            for (VariableElement param : parameters) {
+                builder.string(((CodeVariableElement) param).getName());
+            }
+            builder.end().end();
+            return method;
+        }
+    }
+
+    private interface CodeBlock<T> {
+
+        CodeTree create(CodeTreeBuilder parent, T value);
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.generator;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+import static javax.lang.model.element.Modifier.*;
+
+import java.util.*;
+
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class TypeSystemCodeGenerator extends AbstractCompilationUnitFactory<TypeSystemData> {
+
+    public static String isTypeMethodName(TypeData type) {
+        return "is" + ElementUtils.getTypeId(type.getBoxedType());
+    }
+
+    public static String isImplicitTypeMethodName(TypeData type) {
+        return "isImplicit" + ElementUtils.getTypeId(type.getBoxedType());
+    }
+
+    public static String asTypeMethodName(TypeData type) {
+        return "as" + ElementUtils.getTypeId(type.getBoxedType());
+    }
+
+    public static String asImplicitTypeMethodName(TypeData type) {
+        return "asImplicit" + ElementUtils.getTypeId(type.getBoxedType());
+    }
+
+    public static String getImplicitClass(TypeData type) {
+        return "getImplicit" + ElementUtils.getTypeId(type.getBoxedType()) + "Class";
+    }
+
+    public static String expectTypeMethodName(TypeData type) {
+        return "expect" + ElementUtils.getTypeId(type.getBoxedType());
+    }
+
+    public static String typeName(TypeSystemData typeSystem) {
+        String name = getSimpleName(typeSystem.getTemplateType());
+        return name + "Gen";
+    }
+
+    public static String singletonName(TypeSystemData type) {
+        return createConstantName(getSimpleName(type.getTemplateType().asType()));
+    }
+
+    @Override
+    protected void createChildren(TypeSystemData m) {
+        add(new TypeClassFactory(), m);
+    }
+
+    private static class TypeClassFactory extends AbstractClassElementFactory<TypeSystemData> {
+
+        private static final String LOCAL_VALUE = "value";
+
+        @Override
+        public CodeTypeElement create(TypeSystemData typeSystem) {
+            String name = typeName(typeSystem);
+            CodeTypeElement clazz = createClass(typeSystem, modifiers(PUBLIC, FINAL), name, typeSystem.getTemplateType().asType(), false);
+
+            clazz.add(createConstructorUsingFields(modifiers(PROTECTED), clazz));
+            CodeVariableElement singleton = createSingleton(clazz);
+            clazz.add(singleton);
+
+            for (TypeData type : typeSystem.getTypes()) {
+                if (type.isGeneric() || type.isVoid()) {
+                    continue;
+                }
+                clazz.addOptional(createIsTypeMethod(type));
+                clazz.addOptional(createAsTypeMethod(type));
+
+                for (TypeData sourceType : collectExpectSourceTypes(type)) {
+                    clazz.addOptional(createExpectTypeMethod(type, sourceType));
+                }
+
+                clazz.addOptional(createAsImplicitTypeMethod(type, true));
+                clazz.addOptional(createAsImplicitTypeMethod(type, false));
+                clazz.addOptional(createIsImplicitTypeMethod(type, true));
+                clazz.addOptional(createIsImplicitTypeMethod(type, false));
+                clazz.addOptional(createGetTypeIndex(type));
+            }
+
+            return clazz;
+        }
+
+        private static List<TypeData> collectExpectSourceTypes(TypeData type) {
+            Set<TypeData> sourceTypes = new HashSet<>();
+            sourceTypes.add(type.getTypeSystem().getGenericTypeData());
+            for (TypeCastData cast : type.getTypeCasts()) {
+                sourceTypes.add(cast.getSourceType());
+            }
+            for (TypeCheckData cast : type.getTypeChecks()) {
+                sourceTypes.add(cast.getCheckedType());
+            }
+            return new ArrayList<>(sourceTypes);
+        }
+
+        private CodeVariableElement createSingleton(CodeTypeElement clazz) {
+            CodeVariableElement field = new CodeVariableElement(modifiers(PUBLIC, STATIC, FINAL), clazz.asType(), singletonName(getModel()));
+            field.createInitBuilder().startNew(clazz.asType()).end();
+            return field;
+        }
+
+        private CodeExecutableElement createIsImplicitTypeMethod(TypeData type, boolean typed) {
+            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));
+            if (typed) {
+                method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "typeHint"));
+            }
+            CodeTreeBuilder builder = method.createBuilder();
+
+            List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
+
+            builder.startReturn();
+            String sep = "";
+            for (TypeData sourceType : sourceTypes) {
+                builder.string(sep);
+                if (typed) {
+                    builder.string("(typeHint == ").typeLiteral(sourceType.getPrimitiveType()).string(" && ");
+                }
+                builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end();
+                if (typed) {
+                    builder.string(")");
+                }
+                if (sourceTypes.lastIndexOf(sourceType) != sourceTypes.size() - 1) {
+                    builder.newLine();
+                }
+                if (sep.equals("")) {
+                    builder.startIndention();
+                }
+                sep = " || ";
+            }
+            builder.end();
+            builder.end();
+            return method;
+        }
+
+        private CodeExecutableElement createAsImplicitTypeMethod(TypeData type, boolean typed) {
+            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));
+            if (typed) {
+                method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "typeHint"));
+            }
+
+            List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
+
+            CodeTreeBuilder builder = method.createBuilder();
+            boolean elseIf = false;
+            for (TypeData sourceType : sourceTypes) {
+                elseIf = builder.startIf(elseIf);
+                if (typed) {
+                    builder.string("typeHint == ").typeLiteral(sourceType.getPrimitiveType());
+                } else {
+                    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(), "transferToInterpreterAndInvalidate").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(), "transferToInterpreterAndInvalidate").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;
+            }
+
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(boolean.class), TypeSystemCodeGenerator.isTypeMethodName(type));
+            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
+
+            DeclaredType suppressWarnings = (DeclaredType) getContext().getType(SuppressWarnings.class);
+            CodeAnnotationMirror annotationMirror = new CodeAnnotationMirror(suppressWarnings);
+            annotationMirror.setElementValue(annotationMirror.findExecutableElement("value"), new CodeAnnotationValue("static-method"));
+            method.getAnnotationMirrors().add(annotationMirror);
+
+            CodeTreeBuilder body = method.createBuilder();
+            body.startReturn().instanceOf(LOCAL_VALUE, type.getBoxedType()).end();
+
+            return method;
+        }
+
+        private CodeExecutableElement createAsTypeMethod(TypeData type) {
+            if (!type.getTypeCasts().isEmpty()) {
+                return null;
+            }
+
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asTypeMethodName(type));
+            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
+
+            CodeTreeBuilder body = method.createBuilder();
+            String assertMessage = typeName(getModel()) + "." + asTypeMethodName(type) + ": " + ElementUtils.getSimpleName(type.getBoxedType()) + " expected";
+            body.startAssert().startCall(isTypeMethodName(type)).string(LOCAL_VALUE).end().string(" : ").doubleQuote(assertMessage).end();
+            body.startReturn().cast(type.getPrimitiveType(), body.create().string(LOCAL_VALUE).getTree()).end();
+
+            return method;
+        }
+
+        private CodeExecutableElement createExpectTypeMethod(TypeData expectedType, TypeData sourceType) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), expectedType.getPrimitiveType(), TypeSystemCodeGenerator.expectTypeMethodName(expectedType));
+            method.addParameter(new CodeVariableElement(sourceType.getPrimitiveType(), LOCAL_VALUE));
+            method.addThrownType(getContext().getTruffleTypes().getUnexpectedValueException());
+
+            CodeTreeBuilder body = method.createBuilder();
+            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();
+
+            return method;
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,1069 @@
+/*
+ * 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.truffle.dsl.processor.java;
+
+import java.io.*;
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror;
+import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.WildcardTypeMirror;
+
+/**
+ * THIS IS NOT PUBLIC API.
+ */
+public class ElementUtils {
+
+    public static TypeMirror getType(ProcessingEnvironment processingEnv, Class<?> element) {
+        if (element.isPrimitive()) {
+            if (element == void.class) {
+                return processingEnv.getTypeUtils().getNoType(TypeKind.VOID);
+            }
+            TypeKind typeKind;
+            if (element == boolean.class) {
+                typeKind = TypeKind.BOOLEAN;
+            } else if (element == byte.class) {
+                typeKind = TypeKind.BYTE;
+            } else if (element == short.class) {
+                typeKind = TypeKind.SHORT;
+            } else if (element == char.class) {
+                typeKind = TypeKind.CHAR;
+            } else if (element == int.class) {
+                typeKind = TypeKind.INT;
+            } else if (element == long.class) {
+                typeKind = TypeKind.LONG;
+            } else if (element == float.class) {
+                typeKind = TypeKind.FLOAT;
+            } else if (element == double.class) {
+                typeKind = TypeKind.DOUBLE;
+            } else {
+                assert false;
+                return null;
+            }
+            return processingEnv.getTypeUtils().getPrimitiveType(typeKind);
+        } else {
+            TypeElement typeElement = processingEnv.getElementUtils().getTypeElement(element.getCanonicalName());
+            if (typeElement == null) {
+                return null;
+            }
+            return typeElement.asType();
+        }
+    }
+
+    public static ExecutableElement findExecutableElement(DeclaredType type, String name) {
+        List<? extends ExecutableElement> elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements());
+        for (ExecutableElement executableElement : elements) {
+            if (executableElement.getSimpleName().toString().equals(name)) {
+                return executableElement;
+            }
+        }
+        return null;
+    }
+
+    public static boolean needsCastTo(TypeMirror sourceType, TypeMirror targetType) {
+        if (typeEquals(sourceType, targetType)) {
+            return false;
+        } else if (isObject(targetType)) {
+            return false;
+        } else if (isVoid(targetType)) {
+            return false;
+        } else if (isAssignable(sourceType, targetType)) {
+            return false;
+        }
+        return true;
+    }
+
+    public static String createReferenceName(ExecutableElement method) {
+        StringBuilder b = new StringBuilder();
+
+        b.append(method.getSimpleName().toString());
+        b.append("(");
+
+        String sep = "";
+        for (VariableElement parameter : method.getParameters()) {
+            b.append(sep);
+            b.append(ElementUtils.getSimpleName(parameter.asType()));
+            sep = ", ";
+        }
+
+        b.append(")");
+        return b.toString();
+    }
+
+    public static VariableElement findVariableElement(DeclaredType type, String name) {
+        List<? extends VariableElement> elements = ElementFilter.fieldsIn(type.asElement().getEnclosedElements());
+        for (VariableElement variableElement : elements) {
+            if (variableElement.getSimpleName().toString().equals(name)) {
+                return variableElement;
+            }
+        }
+        return null;
+    }
+
+    public static TypeMirror boxType(ProcessorContext context, TypeMirror primitiveType) {
+        TypeMirror boxedType = primitiveType;
+        if (boxedType.getKind().isPrimitive()) {
+            boxedType = context.getEnvironment().getTypeUtils().boxedClass((PrimitiveType) boxedType).asType();
+        }
+        return boxedType;
+    }
+
+    public static DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs) {
+        return new DeclaredCodeTypeMirror(typeElem, Arrays.asList(typeArgs));
+    }
+
+    public static List<AnnotationMirror> collectAnnotations(ProcessorContext context, AnnotationMirror markerAnnotation, String elementName, Element element,
+                    Class<? extends Annotation> annotationClass) {
+        List<AnnotationMirror> result = new ArrayList<>();
+        if (markerAnnotation != null) {
+            result.addAll(ElementUtils.getAnnotationValueList(AnnotationMirror.class, markerAnnotation, elementName));
+        }
+        AnnotationMirror explicit = ElementUtils.findAnnotationMirror(context.getEnvironment(), element, annotationClass);
+        if (explicit != null) {
+            result.add(explicit);
+        }
+        return result;
+    }
+
+    public static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror[] types) {
+        if (types.length == 0) {
+            return context.getType(Object.class);
+        }
+        TypeMirror prev = types[0];
+        for (int i = 1; i < types.length; i++) {
+            prev = getCommonSuperType(context, prev, types[i]);
+        }
+        return prev;
+    }
+
+    private static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror type1, TypeMirror type2) {
+        if (typeEquals(type1, type2)) {
+            return type1;
+        }
+        TypeElement element1 = fromTypeMirror(type1);
+        TypeElement element2 = fromTypeMirror(type2);
+        if (element1 == null || element2 == null) {
+            return context.getType(Object.class);
+        }
+
+        List<TypeElement> element1Types = getDirectSuperTypes(element1);
+        element1Types.add(0, element1);
+        List<TypeElement> element2Types = getDirectSuperTypes(element2);
+        element2Types.add(0, element2);
+
+        for (TypeElement superType1 : element1Types) {
+            for (TypeElement superType2 : element2Types) {
+                if (typeEquals(superType1.asType(), superType2.asType())) {
+                    return superType2.asType();
+                }
+            }
+        }
+        return context.getType(Object.class);
+    }
+
+    public static String getReadableSignature(ExecutableElement method) {
+        // TODO toString does not guarantee a good signature
+        return method.toString();
+    }
+
+    public static boolean hasError(TypeMirror mirror) {
+        switch (mirror.getKind()) {
+            case BOOLEAN:
+            case BYTE:
+            case CHAR:
+            case DOUBLE:
+            case FLOAT:
+            case INT:
+            case SHORT:
+            case LONG:
+            case DECLARED:
+            case VOID:
+            case TYPEVAR:
+                return false;
+            case ARRAY:
+                return hasError(((ArrayType) mirror).getComponentType());
+            case ERROR:
+                return true;
+            default:
+                throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
+        }
+    }
+
+    public static boolean isSubtype(TypeMirror type1, TypeMirror type2) {
+        if (type1 instanceof CodeTypeMirror && type2 instanceof CodeTypeMirror) {
+            throw new UnsupportedOperationException();
+        }
+        return ProcessorContext.getInstance().getEnvironment().getTypeUtils().isSubtype(type1, type2);
+    }
+
+    public static boolean isAssignable(TypeMirror from, TypeMirror to) {
+        ProcessorContext context = ProcessorContext.getInstance();
+
+        if (!(from instanceof CodeTypeMirror) && !(to instanceof CodeTypeMirror)) {
+            return context.getEnvironment().getTypeUtils().isAssignable(context.reloadType(from), context.reloadType(to));
+        } else {
+            return isAssignableImpl(from, to);
+        }
+    }
+
+    private static boolean isAssignableImpl(TypeMirror from, TypeMirror to) {
+        // JLS 5.1.1 identity conversion
+        if (ElementUtils.typeEquals(from, to)) {
+            return true;
+        }
+
+        if (isObject(to)) {
+            return true;
+        }
+
+        // JLS 5.1.2 widening primitives
+        if (ElementUtils.isPrimitive(from) && ElementUtils.isPrimitive(to)) {
+            TypeKind fromKind = from.getKind();
+            TypeKind toKind = to.getKind();
+            switch (fromKind) {
+                case BYTE:
+                    switch (toKind) {
+                        case SHORT:
+                        case INT:
+                        case LONG:
+                        case FLOAT:
+                        case DOUBLE:
+                            return true;
+                    }
+                    break;
+                case SHORT:
+                    switch (toKind) {
+                        case INT:
+                        case LONG:
+                        case FLOAT:
+                        case DOUBLE:
+                            return true;
+                    }
+                    break;
+                case CHAR:
+                    switch (toKind) {
+                        case INT:
+                        case LONG:
+                        case FLOAT:
+                        case DOUBLE:
+                            return true;
+                    }
+                    break;
+                case INT:
+                    switch (toKind) {
+                        case LONG:
+                        case FLOAT:
+                        case DOUBLE:
+                            return true;
+                    }
+                    break;
+                case LONG:
+                    switch (toKind) {
+                        case FLOAT:
+                        case DOUBLE:
+                            return true;
+                    }
+                    break;
+                case FLOAT:
+                    switch (toKind) {
+                        case DOUBLE:
+                            return true;
+                    }
+                    break;
+
+            }
+            return false;
+        } else if (ElementUtils.isPrimitive(from) || ElementUtils.isPrimitive(to)) {
+            return false;
+        }
+
+        if (from instanceof ArrayType && to instanceof ArrayType) {
+            return isAssignable(((ArrayType) from).getComponentType(), ((ArrayType) to).getComponentType());
+        }
+
+        if (from instanceof ArrayType || to instanceof ArrayType) {
+            return false;
+        }
+
+        TypeElement fromType = ElementUtils.fromTypeMirror(from);
+        TypeElement toType = ElementUtils.fromTypeMirror(to);
+        if (fromType == null || toType == null) {
+            return false;
+        }
+        // JLS 5.1.6 narrowing reference conversion
+
+        List<TypeElement> superTypes = ElementUtils.getSuperTypes(fromType);
+        for (TypeElement superType : superTypes) {
+            if (ElementUtils.typeEquals(superType.asType(), to)) {
+                return true;
+            }
+        }
+
+        // TODO more spec
+        return false;
+    }
+
+    public static Set<Modifier> modifiers(Modifier... modifier) {
+        return new LinkedHashSet<>(Arrays.asList(modifier));
+    }
+
+    public static String getTypeId(TypeMirror mirror) {
+        switch (mirror.getKind()) {
+            case BOOLEAN:
+                return "Boolean";
+            case BYTE:
+                return "Byte";
+            case CHAR:
+                return "Char";
+            case DOUBLE:
+                return "Double";
+            case FLOAT:
+                return "Float";
+            case SHORT:
+                return "Short";
+            case INT:
+                return "Int";
+            case LONG:
+                return "Long";
+            case DECLARED:
+                return fixECJBinaryNameIssue(((DeclaredType) mirror).asElement().getSimpleName().toString());
+            case ARRAY:
+                return getTypeId(((ArrayType) mirror).getComponentType()) + "Array";
+            case VOID:
+                return "Void";
+            case WILDCARD:
+                StringBuilder b = new StringBuilder();
+                WildcardType type = (WildcardType) mirror;
+                if (type.getExtendsBound() != null) {
+                    b.append("Extends").append(getTypeId(type.getExtendsBound()));
+                } else if (type.getSuperBound() != null) {
+                    b.append("Super").append(getTypeId(type.getExtendsBound()));
+                }
+                return b.toString();
+            case TYPEVAR:
+                return "Any";
+            case ERROR:
+                throw new CompileErrorException("Type error " + mirror);
+            default:
+                throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
+        }
+    }
+
+    public static String getSimpleName(TypeElement element) {
+        return getSimpleName(element.asType());
+    }
+
+    public static String getSimpleName(TypeMirror mirror) {
+        switch (mirror.getKind()) {
+            case BOOLEAN:
+                return "boolean";
+            case BYTE:
+                return "byte";
+            case CHAR:
+                return "char";
+            case DOUBLE:
+                return "double";
+            case FLOAT:
+                return "float";
+            case SHORT:
+                return "short";
+            case INT:
+                return "int";
+            case LONG:
+                return "long";
+            case DECLARED:
+                return getDeclaredName((DeclaredType) mirror, true);
+            case ARRAY:
+                return getSimpleName(((ArrayType) mirror).getComponentType()) + "[]";
+            case VOID:
+                return "void";
+            case WILDCARD:
+                return getWildcardName((WildcardType) mirror);
+            case TYPEVAR:
+                return "?";
+            case ERROR:
+                throw new CompileErrorException("Type error " + mirror);
+            default:
+                throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
+        }
+    }
+
+    private static String getWildcardName(WildcardType type) {
+        StringBuilder b = new StringBuilder();
+        if (type.getExtendsBound() != null) {
+            b.append("? extends ").append(getSimpleName(type.getExtendsBound()));
+        } else if (type.getSuperBound() != null) {
+            b.append("? super ").append(getSimpleName(type.getExtendsBound()));
+        }
+        return b.toString();
+    }
+
+    public static String getDeclaredName(DeclaredType element, boolean includeTypeVariables) {
+        String simpleName = fixECJBinaryNameIssue(element.asElement().getSimpleName().toString());
+
+        if (!includeTypeVariables || element.getTypeArguments().size() == 0) {
+            return simpleName;
+        }
+
+        StringBuilder b = new StringBuilder(simpleName);
+        b.append("<");
+        if (element.getTypeArguments().size() > 0) {
+            for (int i = 0; i < element.getTypeArguments().size(); i++) {
+                b.append(getSimpleName(element.getTypeArguments().get(i)));
+                if (i < element.getTypeArguments().size() - 1) {
+                    b.append(", ");
+                }
+            }
+        }
+        b.append(">");
+        return b.toString();
+    }
+
+    public static String fixECJBinaryNameIssue(String name) {
+        if (name.contains("$")) {
+            int lastIndex = name.lastIndexOf('$');
+            return name.substring(lastIndex + 1, name.length());
+        }
+        return name;
+    }
+
+    public static String getQualifiedName(TypeElement element) {
+        String qualifiedName = element.getQualifiedName().toString();
+        if (qualifiedName.contains("$")) {
+            /*
+             * If a class gets loaded in its binary form by the ECJ compiler it fails to produce the
+             * proper canonical class name. It leaves the $ in the qualified name of the class. So
+             * one instance of a TypeElement may be loaded in binary and one in source form. The
+             * current type comparison in #typeEquals compares by the qualified name so the
+             * qualified name must match. This is basically a hack to fix the returned qualified
+             * name of eclipse.
+             */
+            qualifiedName = qualifiedName.replace('$', '.');
+        }
+        return qualifiedName;
+    }
+
+    public static String getQualifiedName(TypeMirror mirror) {
+        switch (mirror.getKind()) {
+            case BOOLEAN:
+                return "boolean";
+            case BYTE:
+                return "byte";
+            case CHAR:
+                return "char";
+            case DOUBLE:
+                return "double";
+            case SHORT:
+                return "short";
+            case FLOAT:
+                return "float";
+            case INT:
+                return "int";
+            case LONG:
+                return "long";
+            case DECLARED:
+                return getQualifiedName(fromTypeMirror(mirror));
+            case ARRAY:
+                return getQualifiedName(((ArrayType) mirror).getComponentType());
+            case VOID:
+                return "void";
+            case TYPEVAR:
+                return getSimpleName(mirror);
+            case ERROR:
+                throw new CompileErrorException("Type error " + mirror);
+            case EXECUTABLE:
+                return ((ExecutableType) mirror).toString();
+            case NONE:
+                return "$none";
+            default:
+                throw new RuntimeException("Unknown type specified " + mirror + " mirror: " + mirror);
+        }
+    }
+
+    public static boolean isVoid(TypeMirror mirror) {
+        return mirror != null && mirror.getKind() == TypeKind.VOID;
+    }
+
+    public static boolean isPrimitive(TypeMirror mirror) {
+        return mirror != null && mirror.getKind().isPrimitive();
+    }
+
+    public static List<String> getQualifiedSuperTypeNames(TypeElement element) {
+        List<TypeElement> types = getSuperTypes(element);
+        List<String> qualifiedNames = new ArrayList<>();
+        for (TypeElement type : types) {
+            qualifiedNames.add(getQualifiedName(type));
+        }
+        return qualifiedNames;
+    }
+
+    public static List<TypeElement> getDeclaredTypes(TypeElement element) {
+        return ElementFilter.typesIn(element.getEnclosedElements());
+    }
+
+    public static boolean isEnclosedIn(Element enclosedIn, Element element) {
+        if (element == null) {
+            return false;
+        } else if (typeEquals(enclosedIn.asType(), element.asType())) {
+            return true;
+        } else {
+            return isEnclosedIn(enclosedIn, element.getEnclosingElement());
+        }
+    }
+
+    public static TypeElement findRootEnclosingType(Element element) {
+        List<Element> elements = getElementHierarchy(element);
+
+        for (int i = elements.size() - 1; i >= 0; i--) {
+            if (elements.get(i).getKind().isClass()) {
+                return (TypeElement) elements.get(i);
+            }
+        }
+
+        return null;
+    }
+
+    public static List<Element> getElementHierarchy(Element e) {
+        List<Element> elements = new ArrayList<>();
+        elements.add(e);
+
+        Element enclosing = e.getEnclosingElement();
+        while (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE) {
+            elements.add(enclosing);
+            enclosing = enclosing.getEnclosingElement();
+        }
+        if (enclosing != null) {
+            elements.add(enclosing);
+        }
+        return elements;
+    }
+
+    public static TypeElement findNearestEnclosingType(Element element) {
+        List<Element> elements = getElementHierarchy(element);
+        for (Element e : elements) {
+            if (e.getKind().isClass()) {
+                return (TypeElement) e;
+            }
+        }
+        return null;
+    }
+
+    public static List<TypeElement> getDirectSuperTypes(TypeElement element) {
+        List<TypeElement> types = new ArrayList<>();
+        TypeElement superElement = getSuperType(element);
+        if (superElement != null) {
+            types.add(superElement);
+            types.addAll(getDirectSuperTypes(superElement));
+        }
+
+        return types;
+    }
+
+    public static List<TypeMirror> getAssignableTypes(ProcessorContext context, TypeMirror type) {
+        if (isPrimitive(type)) {
+            return Arrays.asList(type, boxType(context, type), context.getType(Object.class));
+        } else if (type.getKind() == TypeKind.ARRAY) {
+            return Arrays.asList(type, context.getType(Object.class));
+        } else if (type.getKind() == TypeKind.DECLARED) {
+            DeclaredType declaredType = (DeclaredType) type;
+            TypeElement typeElement = fromTypeMirror(declaredType);
+            List<TypeElement> types = getSuperTypes(typeElement);
+            List<TypeMirror> mirrors = new ArrayList<>(types.size());
+            mirrors.add(type);
+            for (TypeElement superTypeElement : types) {
+                mirrors.add(superTypeElement.asType());
+            }
+            if (typeElement.getKind().isInterface()) {
+                mirrors.add(getType(context.getEnvironment(), Object.class));
+            }
+            return mirrors;
+        } else {
+            return Collections.emptyList();
+        }
+    }
+
+    /**
+     * Gets the element representing the {@linkplain TypeElement#getSuperclass() super class} of a
+     * given type element.
+     */
+    public static TypeElement getSuperType(TypeElement element) {
+        if (element.getSuperclass() != null) {
+            return fromTypeMirror(element.getSuperclass());
+        }
+        return null;
+    }
+
+    public static List<TypeElement> getSuperTypes(TypeElement element) {
+        List<TypeElement> types = new ArrayList<>();
+        List<TypeElement> superTypes = null;
+        List<TypeElement> superInterfaces = null;
+        TypeElement superElement = getSuperType(element);
+        if (superElement != null) {
+            types.add(superElement);
+            superTypes = getSuperTypes(superElement);
+        }
+        for (TypeMirror interfaceMirror : element.getInterfaces()) {
+            TypeElement interfaceElement = fromTypeMirror(interfaceMirror);
+            if (interfaceElement != null) {
+                types.add(interfaceElement);
+                if (superInterfaces == null) {
+                    superInterfaces = getSuperTypes(interfaceElement);
+                } else {
+                    superInterfaces.addAll(getSuperTypes(interfaceElement));
+                }
+            }
+        }
+
+        if (superTypes != null) {
+            types.addAll(superTypes);
+        }
+
+        if (superInterfaces != null) {
+            types.addAll(superInterfaces);
+        }
+
+        return types;
+    }
+
+    public static String getPackageName(TypeElement element) {
+        return findPackageElement(element).getQualifiedName().toString();
+    }
+
+    public static String getEnclosedQualifiedName(DeclaredType mirror) {
+        Element e = ((TypeElement) mirror.asElement()).getEnclosingElement();
+        if (e.getKind() == ElementKind.PACKAGE) {
+            return ((PackageElement) e).getQualifiedName().toString();
+        } else if (e.getKind().isInterface() || e.getKind().isClass()) {
+            return getQualifiedName((TypeElement) e);
+        } else {
+            return null;
+        }
+    }
+
+    public static String getPackageName(TypeMirror mirror) {
+        switch (mirror.getKind()) {
+            case BOOLEAN:
+            case BYTE:
+            case CHAR:
+            case DOUBLE:
+            case FLOAT:
+            case SHORT:
+            case INT:
+            case LONG:
+            case VOID:
+            case TYPEVAR:
+                return null;
+            case DECLARED:
+                PackageElement pack = findPackageElement(fromTypeMirror(mirror));
+                if (pack == null) {
+                    throw new IllegalArgumentException("No package element found for declared type " + getSimpleName(mirror));
+                }
+                return pack.getQualifiedName().toString();
+            case ARRAY:
+                return getSimpleName(((ArrayType) mirror).getComponentType());
+            default:
+                throw new RuntimeException("Unknown type specified " + mirror.getKind());
+        }
+    }
+
+    public static String createConstantName(String simpleName) {
+        // TODO use camel case to produce underscores.
+        return simpleName.toString().toUpperCase();
+    }
+
+    public static TypeElement fromTypeMirror(TypeMirror mirror) {
+        switch (mirror.getKind()) {
+            case DECLARED:
+                return (TypeElement) ((DeclaredType) mirror).asElement();
+            case ARRAY:
+                return fromTypeMirror(((ArrayType) mirror).getComponentType());
+            default:
+                return null;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> List<T> getAnnotationValueList(Class<T> expectedListType, AnnotationMirror mirror, String name) {
+        List<? extends AnnotationValue> values = getAnnotationValue(List.class, mirror, name);
+        List<T> result = new ArrayList<>();
+
+        if (values != null) {
+            for (AnnotationValue value : values) {
+                T annotationValue = resolveAnnotationValue(expectedListType, value);
+                if (annotationValue != null) {
+                    result.add(annotationValue);
+                }
+            }
+        }
+        return result;
+    }
+
+    public static <T> T getAnnotationValue(Class<T> expectedType, AnnotationMirror mirror, String name) {
+        return resolveAnnotationValue(expectedType, getAnnotationValue(mirror, name));
+    }
+
+    @SuppressWarnings({"unchecked"})
+    private static <T> T resolveAnnotationValue(Class<T> expectedType, AnnotationValue value) {
+        if (value == null) {
+            return null;
+        }
+
+        Object unboxedValue = value.accept(new AnnotationValueVisitorImpl(), null);
+        if (unboxedValue != null) {
+            if (expectedType == TypeMirror.class && unboxedValue instanceof String) {
+                return null;
+            }
+            if (!expectedType.isAssignableFrom(unboxedValue.getClass())) {
+                throw new ClassCastException(unboxedValue.getClass().getName() + " not assignable from " + expectedType.getName());
+            }
+        }
+        return (T) unboxedValue;
+    }
+
+    public static AnnotationValue getAnnotationValue(AnnotationMirror mirror, String name) {
+        ExecutableElement valueMethod = null;
+        for (ExecutableElement method : ElementFilter.methodsIn(mirror.getAnnotationType().asElement().getEnclosedElements())) {
+            if (method.getSimpleName().toString().equals(name)) {
+                valueMethod = method;
+                break;
+            }
+        }
+
+        if (valueMethod == null) {
+            return null;
+        }
+
+        AnnotationValue value = mirror.getElementValues().get(valueMethod);
+        if (value == null) {
+            value = valueMethod.getDefaultValue();
+        }
+
+        return value;
+    }
+
+    private static class AnnotationValueVisitorImpl extends AbstractAnnotationValueVisitor7<Object, Void> {
+
+        @Override
+        public Object visitBoolean(boolean b, Void p) {
+            return Boolean.valueOf(b);
+        }
+
+        @Override
+        public Object visitByte(byte b, Void p) {
+            return Byte.valueOf(b);
+        }
+
+        @Override
+        public Object visitChar(char c, Void p) {
+            return c;
+        }
+
+        @Override
+        public Object visitDouble(double d, Void p) {
+            return d;
+        }
+
+        @Override
+        public Object visitFloat(float f, Void p) {
+            return f;
+        }
+
+        @Override
+        public Object visitInt(int i, Void p) {
+            return i;
+        }
+
+        @Override
+        public Object visitLong(long i, Void p) {
+            return i;
+        }
+
+        @Override
+        public Object visitShort(short s, Void p) {
+            return s;
+        }
+
+        @Override
+        public Object visitString(String s, Void p) {
+            return s;
+        }
+
+        @Override
+        public Object visitType(TypeMirror t, Void p) {
+            return t;
+        }
+
+        @Override
+        public Object visitEnumConstant(VariableElement c, Void p) {
+            return c;
+        }
+
+        @Override
+        public Object visitAnnotation(AnnotationMirror a, Void p) {
+            return a;
+        }
+
+        @Override
+        public Object visitArray(List<? extends AnnotationValue> vals, Void p) {
+            return vals;
+        }
+
+    }
+
+    public static String printException(Throwable e) {
+        StringWriter string = new StringWriter();
+        PrintWriter writer = new PrintWriter(string);
+        e.printStackTrace(writer);
+        writer.flush();
+        return e.getMessage() + "\r\n" + string.toString();
+    }
+
+    public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, Element element, Class<?> annotationClass) {
+        return findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), annotationClass);
+    }
+
+    public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, List<? extends AnnotationMirror> mirrors, Class<?> annotationClass) {
+        TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName());
+        return findAnnotationMirror(mirrors, expectedAnnotationType);
+    }
+
+    public static AnnotationMirror findAnnotationMirror(List<? extends AnnotationMirror> mirrors, TypeElement expectedAnnotationType) {
+        for (AnnotationMirror mirror : mirrors) {
+            DeclaredType annotationType = mirror.getAnnotationType();
+            TypeElement actualAnnotationType = (TypeElement) annotationType.asElement();
+            if (actualAnnotationType.equals(expectedAnnotationType)) {
+                return mirror;
+            }
+        }
+        return null;
+    }
+
+    public static PackageElement findPackageElement(Element type) {
+        List<Element> hierarchy = getElementHierarchy(type);
+        for (Element element : hierarchy) {
+            if (element.getKind() == ElementKind.PACKAGE) {
+                return (PackageElement) element;
+            }
+        }
+        return null;
+    }
+
+    public static String firstLetterUpperCase(String name) {
+        if (name == null || name.isEmpty()) {
+            return name;
+        }
+        return Character.toUpperCase(name.charAt(0)) + name.substring(1, name.length());
+    }
+
+    public static String firstLetterLowerCase(String name) {
+        if (name == null || name.isEmpty()) {
+            return name;
+        }
+        return Character.toLowerCase(name.charAt(0)) + name.substring(1, name.length());
+    }
+
+    private static ExecutableElement getDeclaredMethod(TypeElement element, String name, TypeMirror[] params) {
+        List<ExecutableElement> methods = ElementFilter.methodsIn(element.getEnclosedElements());
+        method: for (ExecutableElement method : methods) {
+            if (!method.getSimpleName().toString().equals(name)) {
+                continue;
+            }
+            if (method.getParameters().size() != params.length) {
+                continue;
+            }
+            for (int i = 0; i < params.length; i++) {
+                TypeMirror param1 = params[i];
+                TypeMirror param2 = method.getParameters().get(i).asType();
+                if (param1.getKind() != TypeKind.TYPEVAR && param2.getKind() != TypeKind.TYPEVAR) {
+                    if (!getQualifiedName(param1).equals(getQualifiedName(param2))) {
+                        continue method;
+                    }
+                }
+            }
+            return method;
+        }
+        return null;
+    }
+
+    public static boolean isDeclaredMethodInSuperType(TypeElement element, String name, TypeMirror[] params) {
+        return !getDeclaredMethodsInSuperTypes(element, name, params).isEmpty();
+    }
+
+    /**
+     * Gets the methods in the super type hierarchy (excluding interfaces) that are overridden by a
+     * method in a subtype.
+     *
+     * @param declaringElement the subtype element declaring the method
+     * @param name the name of the method
+     * @param params the signature of the method
+     */
+    public static List<ExecutableElement> getDeclaredMethodsInSuperTypes(TypeElement declaringElement, String name, TypeMirror... params) {
+        List<ExecutableElement> superMethods = new ArrayList<>();
+        List<TypeElement> superElements = getSuperTypes(declaringElement);
+
+        for (TypeElement superElement : superElements) {
+            ExecutableElement superMethod = getDeclaredMethod(superElement, name, params);
+            if (superMethod != null) {
+                superMethods.add(superMethod);
+            }
+        }
+        return superMethods;
+    }
+
+    public static boolean typeEquals(TypeMirror type1, TypeMirror type2) {
+        if (type1 == type2) {
+            return true;
+        } else if (type1 == null || type2 == null) {
+            return false;
+        } else {
+            if (type1.getKind() == type2.getKind()) {
+                return getUniqueIdentifier(type1).equals(getUniqueIdentifier(type2));
+            } else {
+                return false;
+            }
+        }
+    }
+
+    public static String getUniqueIdentifier(TypeMirror typeMirror) {
+        if (typeMirror.getKind() == TypeKind.ARRAY) {
+            return getUniqueIdentifier(((ArrayType) typeMirror).getComponentType()) + "[]";
+        } else {
+            return getQualifiedName(typeMirror);
+        }
+    }
+
+    public static int compareByTypeHierarchy(TypeMirror t1, TypeMirror t2) {
+        if (typeEquals(t1, t2)) {
+            return 0;
+        }
+        Set<String> t1SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t1)));
+        if (t1SuperSet.contains(getQualifiedName(t2))) {
+            return -1;
+        }
+
+        Set<String> t2SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t2)));
+        if (t2SuperSet.contains(getQualifiedName(t1))) {
+            return 1;
+        }
+        return 0;
+    }
+
+    public static boolean canThrowType(List<? extends TypeMirror> thrownTypes, TypeMirror exceptionType) {
+        if (ElementUtils.containsType(thrownTypes, exceptionType)) {
+            return true;
+        }
+
+        if (isRuntimeException(exceptionType)) {
+            return true;
+        }
+
+        // search for any super types
+        TypeElement exceptionTypeElement = fromTypeMirror(exceptionType);
+        List<TypeElement> superTypes = getSuperTypes(exceptionTypeElement);
+        for (TypeElement typeElement : superTypes) {
+            if (ElementUtils.containsType(thrownTypes, typeElement.asType())) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public static Modifier getVisibility(Set<Modifier> modifier) {
+        for (Modifier mod : modifier) {
+            if (mod == Modifier.PUBLIC || mod == Modifier.PRIVATE || mod == Modifier.PROTECTED) {
+                return mod;
+            }
+        }
+        return null;
+    }
+
+    private static boolean isRuntimeException(TypeMirror type) {
+        Set<String> typeSuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(type)));
+        String typeName = getQualifiedName(type);
+        if (!typeSuperSet.contains(Throwable.class.getCanonicalName()) && !typeName.equals(Throwable.class.getCanonicalName())) {
+            throw new IllegalArgumentException("Given type does not extend Throwable.");
+        }
+        return typeSuperSet.contains(RuntimeException.class.getCanonicalName()) || typeName.equals(RuntimeException.class.getCanonicalName());
+    }
+
+    private static boolean containsType(Collection<? extends TypeMirror> collection, TypeMirror type) {
+        for (TypeMirror otherTypeMirror : collection) {
+            if (typeEquals(otherTypeMirror, type)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static boolean isTopLevelClass(TypeMirror importType) {
+        TypeElement type = fromTypeMirror(importType);
+        if (type != null && type.getEnclosingElement() != null) {
+            return !type.getEnclosingElement().getKind().isClass();
+        }
+        return true;
+    }
+
+    public static boolean isObject(TypeMirror actualType) {
+        return actualType.getKind() == TypeKind.DECLARED && getQualifiedName(actualType).equals("java.lang.Object");
+    }
+
+    public static TypeMirror fillInGenericWildcards(TypeMirror type) {
+        if (type.getKind() != TypeKind.DECLARED) {
+            return type;
+        }
+        DeclaredType declaredType = (DeclaredType) type;
+        TypeElement element = (TypeElement) declaredType.asElement();
+        if (element == null) {
+            return type;
+        }
+        int typeParameters = element.getTypeParameters().size();
+        if (typeParameters > 0 && declaredType.getTypeArguments().size() != typeParameters) {
+            List<TypeMirror> genericTypes = new ArrayList<>();
+            for (int i = 0; i < typeParameters; i++) {
+                genericTypes.add(new WildcardTypeMirror(null, null));
+            }
+            return new DeclaredCodeTypeMirror(element, genericTypes);
+        }
+        return type;
+    }
+
+    public static TypeMirror eraseGenericTypes(TypeMirror type) {
+        if (type.getKind() != TypeKind.DECLARED) {
+            return type;
+        }
+        DeclaredType declaredType = (DeclaredType) type;
+        if (declaredType.getTypeArguments().size() == 0) {
+            return type;
+        }
+        return new DeclaredCodeTypeMirror((TypeElement) declaredType.asElement());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/AbstractCompiler.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,83 @@
+/*
+ * 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.truffle.dsl.processor.java.compiler;
+
+import java.lang.reflect.*;
+
+public abstract class AbstractCompiler implements Compiler {
+
+    protected static Object method(Object o, String methodName) throws Exception {
+        Method method = o.getClass().getMethod(methodName);
+        method.setAccessible(true);
+        return method.invoke(o);
+    }
+
+    protected static Object method(Object o, String methodName, Class<?>[] paramTypes, Object... values) throws Exception {
+        Method method = o.getClass().getMethod(methodName, paramTypes);
+        method.setAccessible(true);
+        return method.invoke(o, values);
+    }
+
+    protected static Object field(Object o, String fieldName) throws Exception {
+        if (o == null) {
+            return null;
+        }
+        Class<?> clazz = o.getClass();
+        Field field = null;
+        try {
+            field = clazz.getField(fieldName);
+        } catch (NoSuchFieldException e) {
+            while (clazz != null) {
+                try {
+                    field = clazz.getDeclaredField(fieldName);
+                    break;
+                } catch (NoSuchFieldException e1) {
+                    clazz = clazz.getSuperclass();
+                }
+            }
+            if (field == null) {
+                throw e;
+            }
+        }
+        field.setAccessible(true);
+        return field.get(o);
+    }
+
+    protected static String parseHeader(String content) {
+        int index = content.indexOf("/*");
+        if (index == -1) {
+            return null;
+        }
+        if (!content.substring(0, index).trim().equals("")) {
+            // just whitespace before
+            return null;
+        }
+
+        int endIndex = content.indexOf("*/", index);
+        if (endIndex == -1) {
+            return null;
+        }
+        return content.substring(index, endIndex + 2);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/Compiler.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,40 @@
+/*
+ * 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.truffle.dsl.processor.java.compiler;
+
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+
+public interface Compiler {
+
+    String getMethodBody(ProcessingEnvironment env, ExecutableElement method);
+
+    String getHeaderComment(ProcessingEnvironment env, Element type);
+
+    List<? extends Element> getEnclosedElementsInDeclarationOrder(TypeElement type);
+
+    List<? extends Element> getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/CompilerFactory.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,48 @@
+/*
+ * 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.truffle.dsl.processor.java.compiler;
+
+import javax.lang.model.element.*;
+
+public class CompilerFactory {
+
+    private static Compiler javac;
+    private static Compiler jdt;
+
+    public static Compiler getCompiler(Element currentElement) {
+        if (JavaCCompiler.isValidElement(currentElement)) {
+            if (javac == null) {
+                javac = new JavaCCompiler();
+            }
+            return javac;
+        } else if (JDTCompiler.isValidElement(currentElement)) {
+            if (jdt == null) {
+                jdt = new JDTCompiler();
+            }
+            return jdt;
+        } else {
+            throw new UnsupportedOperationException("Unsupported compiler for element " + currentElement.getClass().getName() + ".");
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,283 @@
+/*
+ * 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.truffle.dsl.processor.java.compiler;
+
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class JDTCompiler extends AbstractCompiler {
+
+    public static boolean isValidElement(Element currentElement) {
+        try {
+            Class<?> elementClass = Class.forName("org.eclipse.jdt.internal.compiler.apt.model.ElementImpl");
+            return elementClass.isAssignableFrom(currentElement.getClass());
+        } catch (ClassNotFoundException e) {
+            return false;
+        }
+    }
+
+    public List<? extends Element> getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type) {
+        return sortBySourceOrder(new ArrayList<>(environment.getElementUtils().getAllMembers(type)));
+    }
+
+    public List<? extends Element> getEnclosedElementsInDeclarationOrder(TypeElement type) {
+        return sortBySourceOrder(new ArrayList<>(type.getEnclosedElements()));
+    }
+
+    private static List<? extends Element> sortBySourceOrder(List<Element> elements) {
+        final Map<TypeElement, List<Object>> declarationOrders = new HashMap<>();
+
+        Collections.sort(elements, new Comparator<Element>() {
+            public int compare(Element o1, Element o2) {
+                try {
+                    TypeMirror enclosing1 = o1.getEnclosingElement().asType();
+                    TypeMirror enclosing2 = o2.getEnclosingElement().asType();
+
+                    if (ElementUtils.typeEquals(enclosing1, enclosing2)) {
+                        List<Object> declarationOrder = lookupDeclarationOrder(declarationOrders, (TypeElement) o1.getEnclosingElement());
+                        if (declarationOrder == null) {
+                            return 0;
+                        }
+                        Object o1Binding = field(o1, "_binding");
+                        Object o2Binding = field(o2, "_binding");
+
+                        int i1 = declarationOrder.indexOf(o1Binding);
+                        int i2 = declarationOrder.indexOf(o2Binding);
+
+                        return i1 - i2;
+                    } else {
+                        if (ElementUtils.isSubtype(enclosing1, enclosing2)) {
+                            return 1;
+                        } else if (ElementUtils.isSubtype(enclosing2, enclosing1)) {
+                            return -1;
+                        } else {
+                            return 0;
+                        }
+                    }
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        });
+        return elements;
+    }
+
+    private static List<Object> lookupDeclarationOrder(Map<TypeElement, List<Object>> declarationOrders, TypeElement type) throws Exception, ClassNotFoundException {
+        if (declarationOrders.containsKey(type)) {
+            return declarationOrders.get(type);
+        }
+
+        Object binding = field(type, "_binding");
+        Class<?> sourceTypeBinding = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding");
+        Class<?> binaryTypeBinding = Class.forName("org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding");
+
+        List<Object> declarationOrder = null;
+        if (sourceTypeBinding.isAssignableFrom(binding.getClass())) {
+            declarationOrder = findSourceTypeOrder(binding);
+        } else if (binaryTypeBinding.isAssignableFrom(binding.getClass())) {
+            declarationOrder = findBinaryTypeOrder(binding);
+        }
+
+        declarationOrders.put(type, declarationOrder);
+
+        return declarationOrder;
+    }
+
+    private static List<Object> findBinaryTypeOrder(Object binding) throws Exception {
+        Object binaryType = lookupBinaryType(binding);
+        final Object[] sortedMethods = (Object[]) method(binaryType, "getMethods");
+
+        List<Object> sortedElements = new ArrayList<>();
+        if (sortedMethods != null) {
+            sortedElements.addAll(Arrays.asList(sortedMethods));
+        }
+        final Object[] sortedFields = (Object[]) method(binaryType, "getFields");
+        if (sortedFields != null) {
+            sortedElements.addAll(Arrays.asList(sortedFields));
+        }
+        final Object[] sortedTypes = (Object[]) method(binaryType, "getMemberTypes", new Class[0]);
+        if (sortedTypes != null) {
+            sortedElements.addAll(Arrays.asList(sortedTypes));
+        }
+
+        Collections.sort(sortedElements, new Comparator<Object>() {
+            public int compare(Object o1, Object o2) {
+                try {
+                    int structOffset1 = (int) field(o1, "structOffset");
+                    int structOffset2 = (int) field(o2, "structOffset");
+                    return structOffset1 - structOffset2;
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        });
+
+        Class<?> binaryMethod = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryMethod");
+        Class<?> binaryField = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryField");
+        Class<?> nestedType = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryNestedType");
+
+        List<Object> bindings = new ArrayList<>();
+        for (Object sortedElement : sortedElements) {
+            Class<?> elementClass = sortedElement.getClass();
+            if (binaryMethod.isAssignableFrom(elementClass)) {
+                char[] selector = (char[]) method(sortedElement, "getSelector");
+                Object[] foundBindings = (Object[]) method(binding, "getMethods", new Class[]{char[].class}, selector);
+                if (foundBindings == null || foundBindings.length == 0) {
+                    continue;
+                } else if (foundBindings.length == 1) {
+                    bindings.add(foundBindings[0]);
+                } else {
+                    char[] idescriptor = (char[]) method(sortedElement, "getMethodDescriptor");
+                    for (Object foundBinding : foundBindings) {
+                        char[] descriptor = (char[]) method(foundBinding, "signature");
+                        if (descriptor == null && idescriptor == null || Arrays.equals(descriptor, idescriptor)) {
+                            bindings.add(foundBinding);
+                            break;
+                        }
+                    }
+                }
+            } else if (binaryField.isAssignableFrom(elementClass)) {
+                char[] selector = (char[]) method(sortedElement, "getName");
+                Object foundField = method(binding, "getField", new Class[]{char[].class, boolean.class}, selector, true);
+                if (foundField != null) {
+                    bindings.add(foundField);
+                }
+            } else if (nestedType.isAssignableFrom(elementClass)) {
+                char[] selector = (char[]) method(sortedElement, "getSourceName");
+                Object foundType = method(binding, "getMemberType", new Class[]{char[].class}, selector);
+                if (foundType != null) {
+                    bindings.add(foundType);
+                }
+            } else {
+                throw new AssertionError("Unexpected encountered type " + elementClass);
+            }
+        }
+
+        return bindings;
+    }
+
+    private static Object lookupBinaryType(Object binding) throws Exception {
+        Object lookupEnvironment = field(binding, "environment");
+        Object compoundClassName = field(binding, "compoundName");
+        Object nameEnvironment = field(lookupEnvironment, "nameEnvironment");
+        Object nameEnvironmentAnswer = method(nameEnvironment, "findType", new Class[]{char[][].class}, compoundClassName);
+        Object binaryType = method(nameEnvironmentAnswer, "getBinaryType", new Class[0]);
+        return binaryType;
+    }
+
+    private static List<Object> findSourceTypeOrder(Object binding) throws Exception {
+        Object referenceContext = field(field(binding, "scope"), "referenceContext");
+
+        TreeMap<Integer, Object> orderedBindings = new TreeMap<>();
+
+        collectSourceOrder(orderedBindings, referenceContext, "methods");
+        collectSourceOrder(orderedBindings, referenceContext, "fields");
+        collectSourceOrder(orderedBindings, referenceContext, "memberTypes");
+
+        return new ArrayList<>(orderedBindings.values());
+    }
+
+    private static void collectSourceOrder(TreeMap<Integer, Object> orderedBindings, Object referenceContext, String fieldName) throws Exception {
+        Object[] declarations = (Object[]) field(referenceContext, fieldName);
+        if (declarations != null) {
+            for (int i = 0; i < declarations.length; i++) {
+                Integer declarationSourceStart = (Integer) field(declarations[i], "declarationSourceStart");
+                orderedBindings.put(declarationSourceStart, field(declarations[i], "binding"));
+            }
+        }
+    }
+
+    @Override
+    public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) {
+        try {
+
+            char[] source = getSource(method);
+            if (source == null) {
+                return null;
+            }
+
+            /*
+             * AbstractMethodDeclaration decl =
+             * ((MethodBinding)(((ElementImpl)method)._binding)).sourceMethod(); int bodyStart =
+             * decl.bodyStart; int bodyEnd = decl.bodyEnd;
+             */
+            Object decl = method(field(method, "_binding"), "sourceMethod");
+            int bodyStart = (int) field(decl, "bodyStart");
+            int bodyEnd = (int) field(decl, "bodyEnd");
+
+            int length = bodyEnd - bodyStart;
+            char[] target = new char[length];
+            System.arraycopy(source, bodyStart, target, 0, length);
+
+            return new String(target);
+        } catch (Exception e) {
+            return ElementUtils.printException(e);
+        }
+    }
+
+    private static char[] getSource(Element element) throws Exception {
+        /*
+         * Binding binding = ((ElementImpl)element)._binding; char[] source = null; if (binding
+         * instanceof MethodBinding) { source = ((MethodBinding)
+         * binding).sourceMethod().compilationResult.getCompilationUnit().getContents(); } else if
+         * (binding instanceof SourceTypeBinding) { source =
+         * ((SourceTypeBinding)binding).scope.referenceContext
+         * .compilationResult.compilationUnit.getContents(); } return source;
+         */
+
+        Object binding = field(element, "_binding");
+        Class<?> methodBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.MethodBinding");
+        Class<?> referenceBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding");
+
+        char[] source = null;
+        if (methodBindingClass.isAssignableFrom(binding.getClass())) {
+            Object sourceMethod = method(binding, "sourceMethod");
+            if (sourceMethod == null) {
+                return null;
+            }
+            source = (char[]) method(method(field(sourceMethod, "compilationResult"), "getCompilationUnit"), "getContents");
+        } else if (referenceBindingClass.isAssignableFrom(binding.getClass())) {
+            source = (char[]) method(field(field(field(field(binding, "scope"), "referenceContext"), "compilationResult"), "compilationUnit"), "getContents");
+        }
+        return source;
+    }
+
+    @Override
+    public String getHeaderComment(ProcessingEnvironment env, Element type) {
+        try {
+            char[] source = getSource(type);
+            if (source == null) {
+                return null;
+            }
+            return parseHeader(new String(source));
+        } catch (Exception e) {
+            return ElementUtils.printException(e);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JavaCCompiler.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,101 @@
+/*
+ * 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.truffle.dsl.processor.java.compiler;
+
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class JavaCCompiler extends AbstractCompiler {
+
+    public static boolean isValidElement(Element currentElement) {
+        try {
+            Class<?> elementClass = Class.forName("com.sun.tools.javac.code.Symbol");
+            return elementClass.isAssignableFrom(currentElement.getClass());
+        } catch (ClassNotFoundException e) {
+            return false;
+        }
+    }
+
+    public List<? extends Element> getEnclosedElementsInDeclarationOrder(TypeElement type) {
+        return type.getEnclosedElements();
+    }
+
+    public List<? extends Element> getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type) {
+        return environment.getElementUtils().getAllMembers(type);
+    }
+
+    private static final Class<?>[] getTreeAndTopLevelSignature = new Class[]{Element.class, AnnotationMirror.class, AnnotationValue.class};
+    private static final Class<?>[] getCharContentSignature = new Class[]{boolean.class};
+
+    @Override
+    public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) {
+        try {
+            /*
+             * if (false) { Pair<JCTree, JCCompilationUnit> treeAndTopLevel = ((JavacElements)
+             * env.getElementUtils()).getTreeAndTopLevel(method, null, null); JCBlock block =
+             * ((JCMethodDecl) treeAndTopLevel.fst).getBody(); int startPos = block.pos; int endPos
+             * = block.endpos; String methodBody =
+             * treeAndTopLevel.snd.getSourceFile().getCharContent(true).subSequence(startPos + 1,
+             * endPos).toString(); return methodBody; }
+             */
+
+            Object treeAndTopLevel = getTreeAndTopLevel(env, method);
+            Object block = method(field(treeAndTopLevel, "fst"), "getBody");
+            int startPos = (int) field(block, "pos");
+            int endPos = (int) field(block, "endpos");
+            return getContent(treeAndTopLevel).subSequence(startPos + 1, endPos).toString();
+        } catch (Exception e) {
+            return ElementUtils.printException(e);
+        }
+    }
+
+    private static CharSequence getContent(Object treeAndTopLevel) throws Exception {
+        /*
+         * CharSequence content = treeAndTopLevel.snd.getSourceFile().getCharContent(true);
+         */
+        return (CharSequence) method(method(field(treeAndTopLevel, "snd"), "getSourceFile"), "getCharContent", getCharContentSignature, true);
+    }
+
+    private static Object getTreeAndTopLevel(ProcessingEnvironment env, Element element) throws Exception {
+        /*
+         * Pair<JCTree, JCCompilationUnit> treeAndTopLevel = ((JavacElements)
+         * env.getElementUtils()).getTreeAndTopLevel(method, null, null);
+         */
+        return method(method(env, "getElementUtils"), "getTreeAndTopLevel", getTreeAndTopLevelSignature, element, null, null);
+    }
+
+    @Override
+    public String getHeaderComment(ProcessingEnvironment env, Element type) {
+        try {
+            String content = getContent(getTreeAndTopLevel(env, type)).toString();
+            return parseHeader(content);
+        } catch (Exception e) {
+            return ElementUtils.printException(e);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeAnnotationMirror.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class CodeAnnotationMirror implements AnnotationMirror {
+
+    private final DeclaredType annotationType;
+    private final Map<ExecutableElement, AnnotationValue> values = new LinkedHashMap<>();
+
+    public CodeAnnotationMirror(DeclaredType annotationType) {
+        this.annotationType = annotationType;
+    }
+
+    @Override
+    public DeclaredType getAnnotationType() {
+        return annotationType;
+    }
+
+    @Override
+    public Map<? extends ExecutableElement, ? extends AnnotationValue> getElementValues() {
+        return values;
+    }
+
+    public void setElementValue(ExecutableElement method, AnnotationValue value) {
+        values.put(method, value);
+    }
+
+    public ExecutableElement findExecutableElement(String name) {
+        return ElementUtils.findExecutableElement(annotationType, name);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeAnnotationValue.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,84 @@
+/*
+ * 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.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public class CodeAnnotationValue implements AnnotationValue {
+
+    private final Object value;
+
+    public CodeAnnotationValue(Object value) {
+        Objects.requireNonNull(value);
+        if ((value instanceof AnnotationMirror) || (value instanceof List<?>) || (value instanceof Boolean) || (value instanceof Byte) || (value instanceof Character) || (value instanceof Double) ||
+                        (value instanceof VariableElement) || (value instanceof Float) || (value instanceof Integer) || (value instanceof Long) || (value instanceof Short) ||
+                        (value instanceof String) || (value instanceof TypeMirror)) {
+            this.value = value;
+        } else {
+            throw new IllegalArgumentException("Invalid annotation value type " + value.getClass().getName());
+        }
+    }
+
+    @Override
+    public Object getValue() {
+        return value;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
+        if (value instanceof AnnotationMirror) {
+            return v.visitAnnotation((AnnotationMirror) value, p);
+        } else if (value instanceof List<?>) {
+            return v.visitArray((List<? extends AnnotationValue>) value, p);
+        } else if (value instanceof Boolean) {
+            return v.visitBoolean((boolean) value, p);
+        } else if (value instanceof Byte) {
+            return v.visitByte((byte) value, p);
+        } else if (value instanceof Character) {
+            return v.visitChar((char) value, p);
+        } else if (value instanceof Double) {
+            return v.visitDouble((double) value, p);
+        } else if (value instanceof VariableElement) {
+            return v.visitEnumConstant((VariableElement) value, p);
+        } else if (value instanceof Float) {
+            return v.visitFloat((float) value, p);
+        } else if (value instanceof Integer) {
+            return v.visitInt((int) value, p);
+        } else if (value instanceof Long) {
+            return v.visitLong((long) value, p);
+        } else if (value instanceof Short) {
+            return v.visitShort((short) value, p);
+        } else if (value instanceof String) {
+            return v.visitString((String) value, p);
+        } else if (value instanceof TypeMirror) {
+            return v.visitType((TypeMirror) value, p);
+        } else {
+            return v.visitUnknown(this, p);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeCompilationUnit.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,63 @@
+/*
+ * 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.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public class CodeCompilationUnit extends CodeElement<TypeElement> {
+
+    public CodeCompilationUnit() {
+        super(Collections.<Modifier> emptySet());
+    }
+
+    @Override
+    public TypeMirror asType() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ElementKind getKind() {
+        return ElementKind.OTHER;
+    }
+
+    @Override
+    public Name getSimpleName() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+        for (Element type : getEnclosedElements()) {
+            if (type.getKind().isClass()) {
+                type.accept(v, p);
+            } else {
+                throw new ClassCastException(type.getClass().getName());
+            }
+        }
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeElement.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,357 @@
+/*
+ * 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.truffle.dsl.processor.java.model;
+
+import java.io.*;
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.java.transform.*;
+
+public abstract class CodeElement<E extends Element> implements Element, GeneratedElement {
+
+    private final Set<Modifier> modifiers;
+    private List<AnnotationMirror> annotations;
+    private List<E> enclosedElements;
+
+    private Element enclosingElement;
+
+    private Element generatorElement;
+    private AnnotationMirror generatorAnnotationMirror;
+
+    public CodeElement(Set<Modifier> modifiers) {
+        this.modifiers = new LinkedHashSet<>(modifiers);
+    }
+
+    @Override
+    public void setGeneratorAnnotationMirror(AnnotationMirror mirror) {
+        this.generatorAnnotationMirror = mirror;
+    }
+
+    @Override
+    public void setGeneratorElement(Element element) {
+        this.generatorElement = element;
+    }
+
+    @Override
+    public AnnotationMirror getGeneratorAnnotationMirror() {
+        return generatorAnnotationMirror;
+    }
+
+    @Override
+    public Element getGeneratorElement() {
+        return generatorElement;
+    }
+
+    public E add(E element) {
+        if (element == null) {
+            throw new NullPointerException();
+        }
+        getEnclosedElements().add(element);
+        return element;
+    }
+
+    public E addOptional(E element) {
+        if (element != null) {
+            add(element);
+        }
+        return element;
+    }
+
+    public void remove(E element) {
+        getEnclosedElements().remove(element);
+    }
+
+    @Override
+    public Set<Modifier> getModifiers() {
+        return modifiers;
+    }
+
+    @Override
+    public List<E> getEnclosedElements() {
+        if (enclosedElements == null) {
+            enclosedElements = parentableList(this, new ArrayList<E>());
+        }
+        return enclosedElements;
+    }
+
+    @Override
+    public List<AnnotationMirror> getAnnotationMirrors() {
+        if (annotations == null) {
+            annotations = parentableList(this, new ArrayList<AnnotationMirror>());
+        }
+        return annotations;
+    }
+
+    /**
+     * Support JDK8 langtools.
+     *
+     * @param annotationType
+     */
+    public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Support for some JDK8 builds. (remove after jdk8 is released)
+     *
+     * @param annotationType
+     */
+    public <A extends Annotation> A[] getAnnotations(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Support for some JDK8 builds. (remove after jdk8 is released)
+     *
+     * @param annotationType
+     */
+    public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
+
+    public void addAnnotationMirror(AnnotationMirror annotationMirror) {
+        getAnnotationMirrors().add(annotationMirror);
+    }
+
+    public void setEnclosingElement(Element parent) {
+        this.enclosingElement = parent;
+    }
+
+    public Element getEnclosingElement() {
+        return enclosingElement;
+    }
+
+    public CodeTypeElement getEnclosingClass() {
+        Element p = enclosingElement;
+        while (p != null && p.getKind() != ElementKind.CLASS && p.getKind() != ElementKind.ENUM) {
+            p = p.getEnclosingElement();
+        }
+        return (CodeTypeElement) p;
+    }
+
+    <T> List<T> parentableList(Element parent, List<T> list) {
+        return new ParentableList<>(parent, list);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilderCodeWriter codeWriter = new StringBuilderCodeWriter();
+        accept(codeWriter, null);
+        return codeWriter.getString();
+    }
+
+    private static class StringBuilderCodeWriter extends AbstractCodeWriter {
+
+        public StringBuilderCodeWriter() {
+            this.writer = new CharArrayWriter();
+        }
+
+        @Override
+        protected Writer createWriter(CodeTypeElement clazz) throws IOException {
+            return writer;
+        }
+
+        public String getString() {
+            return new String(((CharArrayWriter) writer).toCharArray()).trim();
+        }
+
+    }
+
+    private static class ParentableList<T> implements List<T> {
+
+        private final Element parent;
+        private final List<T> delegate;
+
+        public ParentableList(Element parent, List<T> delegate) {
+            this.parent = parent;
+            this.delegate = delegate;
+        }
+
+        private void addImpl(T element) {
+            if (element != null) {
+                if (element instanceof CodeElement<?>) {
+                    ((CodeElement<?>) element).setEnclosingElement(parent);
+                }
+            }
+        }
+
+        private static void removeImpl(Object element) {
+            if (element instanceof CodeElement<?>) {
+                ((CodeElement<?>) element).setEnclosingElement(null);
+            }
+        }
+
+        @Override
+        public int size() {
+            return delegate.size();
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return delegate.isEmpty();
+        }
+
+        @Override
+        public boolean contains(Object o) {
+            return delegate.contains(o);
+        }
+
+        @Override
+        public Iterator<T> iterator() {
+            return delegate.iterator();
+        }
+
+        @Override
+        public Object[] toArray() {
+            return delegate.toArray();
+        }
+
+        @Override
+        public <E> E[] toArray(E[] a) {
+            return delegate.toArray(a);
+        }
+
+        @Override
+        public boolean add(T e) {
+            addImpl(e);
+            return delegate.add(e);
+        }
+
+        @Override
+        public boolean remove(Object o) {
+            boolean removed = delegate.remove(o);
+            if (removed) {
+                removeImpl(o);
+            }
+            return removed;
+        }
+
+        @Override
+        public boolean containsAll(Collection<?> c) {
+            return delegate.containsAll(c);
+        }
+
+        @Override
+        public boolean addAll(Collection<? extends T> c) {
+            if (c != null) {
+                for (T t : c) {
+                    addImpl(t);
+                }
+            }
+            return delegate.addAll(c);
+        }
+
+        @Override
+        public boolean addAll(int index, Collection<? extends T> c) {
+            if (c != null) {
+                for (T t : c) {
+                    addImpl(t);
+                }
+            }
+            return delegate.addAll(index, c);
+        }
+
+        @Override
+        public boolean removeAll(Collection<?> c) {
+            if (c != null) {
+                for (Object t : c) {
+                    removeImpl(t);
+                }
+            }
+            return delegate.removeAll(c);
+        }
+
+        @Override
+        public String toString() {
+            return delegate.toString();
+        }
+
+        @Override
+        public boolean retainAll(Collection<?> c) {
+            throw new UnsupportedOperationException("Not supported by parentable list");
+        }
+
+        @Override
+        public void clear() {
+            for (Object e : this) {
+                removeImpl(e);
+            }
+            delegate.clear();
+        }
+
+        @Override
+        public T get(int index) {
+            return delegate.get(index);
+        }
+
+        @Override
+        public T set(int index, T element) {
+            removeImpl(delegate.get(index));
+            addImpl(element);
+            return delegate.set(index, element);
+        }
+
+        @Override
+        public void add(int index, T element) {
+            addImpl(element);
+            delegate.add(index, element);
+        }
+
+        @Override
+        public T remove(int index) {
+            T element = delegate.remove(index);
+            removeImpl(element);
+            return element;
+        }
+
+        @Override
+        public int indexOf(Object o) {
+            return delegate.indexOf(o);
+        }
+
+        @Override
+        public int lastIndexOf(Object o) {
+            return delegate.lastIndexOf(o);
+        }
+
+        @Override
+        public ListIterator<T> listIterator() {
+            return delegate.listIterator();
+        }
+
+        @Override
+        public ListIterator<T> listIterator(int index) {
+            return delegate.listIterator(index);
+        }
+
+        @Override
+        public List<T> subList(int fromIndex, int toIndex) {
+            return new ParentableList<>(parent, delegate.subList(fromIndex, toIndex));
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeElementScanner.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,92 @@
+/*
+ * 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.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.util.*;
+
+public abstract class CodeElementScanner<R, P> extends ElementScanner7<R, P> {
+
+    @Override
+    public final R visitExecutable(ExecutableElement e, P p) {
+        return visitExecutable(cast(e, CodeExecutableElement.class), p);
+    }
+
+    public R visitExecutable(CodeExecutableElement e, P p) {
+        R ret = super.visitExecutable(e, p);
+        if (e.getBodyTree() != null) {
+            visitTree(e.getBodyTree(), p, e);
+        }
+        return ret;
+    }
+
+    @Override
+    public R visitVariable(VariableElement e, P p) {
+        if (e instanceof CodeVariableElement) {
+            CodeTree init = ((CodeVariableElement) e).getInit();
+            if (init != null) {
+                visitTree(init, p, e);
+            }
+        }
+        return super.visitVariable(e, p);
+    }
+
+    @Override
+    public R visitPackage(PackageElement e, P p) {
+        return super.visitPackage(e, p);
+    }
+
+    @Override
+    public final R visitType(TypeElement e, P p) {
+        return visitType(cast(e, CodeTypeElement.class), p);
+    }
+
+    public R visitType(CodeTypeElement e, P p) {
+        return super.visitType(e, p);
+    }
+
+    @Override
+    public R visitTypeParameter(TypeParameterElement e, P p) {
+        return super.visitTypeParameter(e, p);
+    }
+
+    private static <E> E cast(Element element, Class<E> clazz) {
+        return clazz.cast(element);
+    }
+
+    public void visitTree(CodeTree e, P p, Element parent) {
+        List<CodeTree> elements = e.getEnclosedElements();
+        if (elements != null) {
+            for (CodeTree tree : e.getEnclosedElements()) {
+                visitTree(tree, p, parent);
+            }
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public void visitImport(CodeImport e, P p) {
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeExecutableElement.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,204 @@
+/*
+ * 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.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class CodeExecutableElement extends CodeElement<Element> implements ExecutableElement {
+
+    private final List<TypeMirror> throwables = new ArrayList<>();
+    private final List<VariableElement> parameters = parentableList(this, new ArrayList<VariableElement>());
+
+    private TypeMirror returnType;
+    private Name name;
+
+    private CodeTree bodyTree;
+    private String body;
+    private AnnotationValue defaultValue;
+    private boolean varArgs;
+
+    public CodeExecutableElement(TypeMirror returnType, String name) {
+        super(ElementUtils.modifiers());
+        this.returnType = returnType;
+        this.name = CodeNames.of(name);
+    }
+
+    public CodeExecutableElement(Set<Modifier> modifiers, TypeMirror returnType, String name, CodeVariableElement... parameters) {
+        super(modifiers);
+        this.returnType = returnType;
+        this.name = CodeNames.of(name);
+        for (CodeVariableElement codeParameter : parameters) {
+            addParameter(codeParameter);
+        }
+    }
+
+    /* Support JDK8 langtools. */
+    public boolean isDefault() {
+        return false;
+    }
+
+    @Override
+    public List<TypeMirror> getThrownTypes() {
+        return throwables;
+    }
+
+    @Override
+    public TypeMirror asType() {
+        return returnType;
+    }
+
+    @Override
+    public ElementKind getKind() {
+        if (getReturnType() == null) {
+            return ElementKind.CONSTRUCTOR;
+        } else {
+            return ElementKind.METHOD;
+        }
+    }
+
+    @Override
+    public List<? extends TypeParameterElement> getTypeParameters() {
+        return Collections.emptyList();
+    }
+
+    public void setVarArgs(boolean varargs) {
+        this.varArgs = varargs;
+    }
+
+    @Override
+    public boolean isVarArgs() {
+        return varArgs;
+    }
+
+    public void setDefaultValue(AnnotationValue defaultValue) {
+        this.defaultValue = defaultValue;
+    }
+
+    @Override
+    public AnnotationValue getDefaultValue() {
+        return defaultValue;
+    }
+
+    @Override
+    public Name getSimpleName() {
+        return name;
+    }
+
+    public CodeTreeBuilder getBuilder() {
+        CodeTree tree = this.bodyTree;
+        return createBuilder().tree(tree);
+    }
+
+    public CodeTreeBuilder createBuilder() {
+        CodeTreeBuilder builder = new CodeTreeBuilder(null);
+        builder.setEnclosingElement(this);
+        this.bodyTree = builder.getTree();
+        this.body = null;
+        return builder;
+    }
+
+    public void setBodyTree(CodeTree body) {
+        this.bodyTree = body;
+    }
+
+    public CodeTree getBodyTree() {
+        return bodyTree;
+    }
+
+    public TypeMirror getReturnType() {
+        return returnType;
+    }
+
+    @Override
+    public List<VariableElement> getParameters() {
+        return parameters;
+    }
+
+    public TypeMirror[] getParameterTypes() {
+        TypeMirror[] types = new TypeMirror[getParameters().size()];
+        for (int i = 0; i < types.length; i++) {
+            types[i] = parameters.get(i).asType();
+        }
+        return types;
+    }
+
+    public void setReturnType(TypeMirror type) {
+        returnType = type;
+    }
+
+    public void addParameter(VariableElement parameter) {
+        parameters.add(parameter);
+    }
+
+    public void addThrownType(TypeMirror thrownType) {
+        throwables.add(thrownType);
+    }
+
+    public void setSimpleName(Name name) {
+        this.name = name;
+    }
+
+    public void setBody(String body) {
+        this.body = body;
+    }
+
+    public String getBody() {
+        return body;
+    }
+
+    @Override
+    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+        return v.visitExecutable(this, p);
+    }
+
+    public static CodeExecutableElement clone(@SuppressWarnings("unused") ProcessingEnvironment env, ExecutableElement method) {
+        CodeExecutableElement copy = new CodeExecutableElement(method.getReturnType(), method.getSimpleName().toString());
+        for (TypeMirror thrownType : method.getThrownTypes()) {
+            copy.addThrownType(thrownType);
+        }
+        copy.setDefaultValue(method.getDefaultValue());
+
+        for (AnnotationMirror mirror : method.getAnnotationMirrors()) {
+            copy.addAnnotationMirror(mirror);
+        }
+        for (VariableElement var : method.getParameters()) {
+            copy.addParameter(CodeVariableElement.clone(var));
+        }
+        for (Element element : method.getEnclosedElements()) {
+            copy.add(element);
+        }
+        copy.getModifiers().addAll(method.getModifiers());
+        copy.setVarArgs(method.isVarArgs());
+        return copy;
+    }
+
+    public TypeMirror getReceiverType() {
+        throw new UnsupportedOperationException();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeImport.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,84 @@
+/*
+ * 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.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+public class CodeImport implements Comparable<CodeImport> {
+
+    private final String packageName;
+    private final String symbolName;
+    private final boolean staticImport;
+
+    public CodeImport(String packageName, String symbolName, boolean staticImport) {
+        this.packageName = packageName;
+        this.symbolName = symbolName;
+        this.staticImport = staticImport;
+    }
+
+    public String getPackageName() {
+        return packageName;
+    }
+
+    public String getSymbolName() {
+        return symbolName;
+    }
+
+    public boolean isStaticImport() {
+        return staticImport;
+    }
+
+    @Override
+    public int compareTo(CodeImport o) {
+        if (staticImport && !o.staticImport) {
+            return 1;
+        } else if (!staticImport && o.staticImport) {
+            return -1;
+        } else {
+            int result = getPackageName().compareTo(o.getPackageName());
+            if (result == 0) {
+                return getSymbolName().compareTo(o.getSymbolName());
+            }
+            return result;
+        }
+    }
+
+    public <P> void accept(CodeElementScanner<?, P> s, P p) {
+        s.visitImport(this, p);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(packageName, symbolName, staticImport);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof CodeImport) {
+            CodeImport otherImport = (CodeImport) obj;
+            return getPackageName().equals(otherImport.getPackageName()) && getSymbolName().equals(otherImport.getSymbolName()) //
+                            && staticImport == otherImport.staticImport;
+        }
+        return super.equals(obj);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeNames.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,90 @@
+/*
+ * 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.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+public abstract class CodeNames {
+
+    private static Map<String, Name> names = new HashMap<>();
+
+    public static Name of(String value) {
+        Name name = names.get(value);
+        if (name == null) {
+            name = new NameImpl(value);
+            names.put(value, name);
+        }
+        return name;
+    }
+
+    private static class NameImpl implements Name {
+
+        private final String name;
+
+        public NameImpl(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public int length() {
+            return name.length();
+        }
+
+        @Override
+        public char charAt(int index) {
+            return name.charAt(index);
+        }
+
+        @Override
+        public CharSequence subSequence(int start, int end) {
+            return name.subSequence(start, end);
+        }
+
+        @Override
+        public boolean contentEquals(CharSequence cs) {
+            return name.contentEquals(cs);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof Name) {
+                return ((Name) obj).contentEquals(name);
+            }
+            return super.equals(obj);
+        }
+
+        @Override
+        public int hashCode() {
+            return name.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTree.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,83 @@
+/*
+ * 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.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.type.*;
+
+public class CodeTree {
+
+    private final CodeTreeKind kind;
+
+    private CodeTree parent;
+
+    private TypeMirror type;
+    private final String string;
+
+    private List<CodeTree> children;
+
+    CodeTree(CodeTree parent, CodeTreeKind kind, TypeMirror type, String string) {
+        this.parent = parent;
+        this.kind = kind;
+        this.type = type;
+        this.string = string;
+    }
+
+    public void setParent(CodeTree parent) {
+        this.parent = parent;
+    }
+
+    public CodeTree getParent() {
+        return parent;
+    }
+
+    public TypeMirror getType() {
+        return type;
+    }
+
+    public void add(CodeTree element) {
+        if (children == null) {
+            children = new ArrayList<>();
+        }
+        element.setParent(this);
+        children.add(element);
+    }
+
+    public final List<CodeTree> getEnclosedElements() {
+        return children;
+    }
+
+    public final CodeTreeKind getCodeKind() {
+        return kind;
+    }
+
+    public String getString() {
+        return string;
+    }
+
+    public void setType(TypeMirror type) {
+        this.type = type;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,893 @@
+/*
+ * 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.truffle.dsl.processor.java.model;
+
+import static com.oracle.truffle.dsl.processor.java.model.CodeTreeKind.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class CodeTreeBuilder {
+
+    private BuilderCodeTree currentElement;
+    private final BuilderCodeTree root;
+
+    private int treeCount;
+    private Element enclosingElement;
+
+    public CodeTreeBuilder(CodeTreeBuilder parent) {
+        this.root = new BuilderCodeTree(null, GROUP, null, null);
+        this.currentElement = root;
+        if (parent != null) {
+            this.enclosingElement = parent.enclosingElement;
+        }
+    }
+
+    public void setEnclosingElement(Element enclosingElement) {
+        this.enclosingElement = enclosingElement;
+    }
+
+    @Override
+    public String toString() {
+        return root.toString();
+    }
+
+    public int getTreeCount() {
+        return treeCount;
+    }
+
+    public boolean isEmpty() {
+        return treeCount == 0;
+    }
+
+    public CodeTreeBuilder statement(String statement) {
+        return startStatement().string(statement).end();
+    }
+
+    public CodeTreeBuilder statement(CodeTree statement) {
+        return startStatement().tree(statement).end();
+    }
+
+    public static CodeTreeBuilder createBuilder() {
+        return new CodeTreeBuilder(null);
+    }
+
+    public static CodeTree singleString(String s) {
+        return new CodeTreeBuilder(null).string(s).getTree();
+    }
+
+    public static CodeTree singleType(TypeMirror s) {
+        return new CodeTreeBuilder(null).type(s).getTree();
+    }
+
+    private CodeTreeBuilder push(CodeTreeKind kind) {
+        return push(new BuilderCodeTree(currentElement, kind, null, null), kind == NEW_LINE);
+    }
+
+    private CodeTreeBuilder push(String string) {
+        return push(new BuilderCodeTree(currentElement, CodeTreeKind.STRING, null, string), false);
+    }
+
+    private CodeTreeBuilder push(TypeMirror type) {
+        return push(new BuilderCodeTree(currentElement, CodeTreeKind.TYPE, type, null), false);
+    }
+
+    private CodeTreeBuilder push(CodeTreeKind kind, TypeMirror type, String string) {
+        return push(new BuilderCodeTree(currentElement, kind, type, string), kind == NEW_LINE);
+    }
+
+    private CodeTreeBuilder push(BuilderCodeTree tree, boolean removeLast) {
+        if (currentElement != null) {
+            if (removeLast && !removeLastIfEnqueued(tree)) {
+                return this;
+            }
+            currentElement.add(tree);
+        }
+        switch (tree.getCodeKind()) {
+            case COMMA_GROUP:
+            case GROUP:
+            case INDENT:
+                currentElement = tree;
+                break;
+        }
+        treeCount++;
+        return this;
+    }
+
+    private boolean removeLastIfEnqueued(BuilderCodeTree tree) {
+        if (tree.getCodeKind() == REMOVE_LAST) {
+            return !clearLastRec(tree.removeLast, currentElement.getEnclosedElements());
+        }
+        List<CodeTree> childTree = tree.getEnclosedElements();
+        if (childTree != null && !childTree.isEmpty()) {
+            CodeTree last = childTree.get(0);
+            if (last instanceof BuilderCodeTree) {
+                if (!removeLastIfEnqueued((BuilderCodeTree) last)) {
+                    childTree.remove(0);
+                }
+            }
+        }
+        return true;
+    }
+
+    private void clearLast(CodeTreeKind kind) {
+        if (clearLastRec(kind, currentElement.getEnclosedElements())) {
+            treeCount--;
+        } else {
+            // delay clearing the last
+            BuilderCodeTree tree = new BuilderCodeTree(currentElement, REMOVE_LAST, null, null);
+            tree.removeLast = kind;
+            push(tree, false);
+        }
+    }
+
+    public CodeTreeBuilder startStatement() {
+        startGroup();
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+                string(";").newLine();
+            }
+
+            @Override
+            public void afterEnd() {
+            }
+        });
+        return this;
+    }
+
+    public CodeTreeBuilder startGroup() {
+        return push(CodeTreeKind.GROUP);
+    }
+
+    public CodeTreeBuilder startCommaGroup() {
+        return push(CodeTreeKind.COMMA_GROUP);
+    }
+
+    public CodeTreeBuilder startCall(String 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().tree(receiver).string(".").string(callSite).startParanthesesCommaGroup().endAfter();
+        }
+    }
+
+    public CodeTreeBuilder startStaticCall(TypeMirror type, String methodName) {
+        return startGroup().push(CodeTreeKind.STATIC_METHOD_REFERENCE, type, methodName).startParanthesesCommaGroup().endAfter();
+    }
+
+    public CodeTreeBuilder startStaticCall(ExecutableElement method) {
+        return startStaticCall(ElementUtils.findNearestEnclosingType(method).asType(), method.getSimpleName().toString());
+    }
+
+    public CodeTreeBuilder staticReference(TypeMirror type, String fieldName) {
+        return push(CodeTreeKind.STATIC_FIELD_REFERENCE, type, fieldName);
+    }
+
+    private CodeTreeBuilder endAndWhitespaceAfter() {
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+            }
+
+            @Override
+            public void afterEnd() {
+                string(" ");
+                end();
+            }
+        });
+        return this;
+    }
+
+    private CodeTreeBuilder endAfter() {
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+            }
+
+            @Override
+            public void afterEnd() {
+                end();
+            }
+        });
+        return this;
+    }
+
+    private CodeTreeBuilder startParanthesesCommaGroup() {
+        startGroup();
+        string("(").startCommaGroup();
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+            }
+
+            @Override
+            public void afterEnd() {
+                string(")");
+            }
+        });
+        endAfter();
+        return this;
+    }
+
+    private CodeTreeBuilder startCurlyBracesCommaGroup() {
+        startGroup();
+        string("{").startCommaGroup();
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+            }
+
+            @Override
+            public void afterEnd() {
+                string("}");
+            }
+        });
+        endAfter();
+        return this;
+    }
+
+    public CodeTreeBuilder startParantheses() {
+        startGroup();
+        string("(").startGroup();
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+            }
+
+            @Override
+            public void afterEnd() {
+                string(")");
+            }
+        });
+        endAfter();
+        return this;
+    }
+
+    public CodeTreeBuilder doubleQuote(String s) {
+        return startGroup().string("\"" + s + "\"").end();
+    }
+
+    public CodeTreeBuilder string(String chunk1) {
+        return push(chunk1);
+    }
+
+    public CodeTreeBuilder string(String chunk1, String chunk2) {
+        return push(GROUP).string(chunk1).string(chunk2).end();
+    }
+
+    public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3) {
+        return push(GROUP).string(chunk1).string(chunk2).string(chunk3).end();
+    }
+
+    public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4) {
+        return push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4).end();
+    }
+
+    public CodeTreeBuilder tree(CodeTree treeToAdd) {
+        if (treeToAdd instanceof BuilderCodeTree) {
+            return push((BuilderCodeTree) treeToAdd, true).end();
+        } else {
+            BuilderCodeTree tree = new BuilderCodeTree(currentElement, GROUP, null, null);
+            currentElement.add(treeToAdd);
+            return push(tree, true).end();
+        }
+    }
+
+    public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4, String... chunks) {
+        push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4);
+        for (int i = 0; i < chunks.length; i++) {
+            string(chunks[i]);
+        }
+        return end();
+    }
+
+    public CodeTreeBuilder dot() {
+        return string(".");
+    }
+
+    public CodeTreeBuilder newLine() {
+        return push(NEW_LINE);
+    }
+
+    public CodeTreeBuilder startWhile() {
+        return startGroup().string("while ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter();
+    }
+
+    public CodeTreeBuilder startDoBlock() {
+        return startGroup().string("do ").startBlock();
+    }
+
+    public CodeTreeBuilder startDoWhile() {
+        clearLast(CodeTreeKind.NEW_LINE);
+        return startStatement().string(" while ").startParanthesesCommaGroup().endAfter().startGroup().endAfter();
+    }
+
+    public CodeTreeBuilder startIf() {
+        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();
+        } else {
+            startIf();
+        }
+        return true;
+    }
+
+    public CodeTreeBuilder startElseIf() {
+        clearLast(CodeTreeKind.NEW_LINE);
+        return startGroup().string(" else if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter();
+    }
+
+    public CodeTreeBuilder startElseBlock() {
+        clearLast(CodeTreeKind.NEW_LINE);
+        return startGroup().string(" else ").startBlock().endAfter();
+    }
+
+    private boolean clearLastRec(CodeTreeKind kind, List<CodeTree> children) {
+        if (children == null) {
+            return false;
+        }
+        for (int i = children.size() - 1; i >= 0; i--) {
+            CodeTree child = children.get(i);
+            if (child.getCodeKind() == kind) {
+                children.remove(children.get(i));
+                return true;
+            } else {
+                if (clearLastRec(kind, child.getEnclosedElements())) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public CodeTreeBuilder startCase() {
+        startGroup().string("case ");
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+                string(" :").newLine();
+            }
+
+            @Override
+            public void afterEnd() {
+            }
+        });
+        return this;
+    }
+
+    public CodeTreeBuilder caseDefault() {
+        return startGroup().string("default :").newLine().end();
+    }
+
+    public CodeTreeBuilder startSwitch() {
+        return startGroup().string("switch ").startParanthesesCommaGroup().endAndWhitespaceAfter();
+    }
+
+    public CodeTreeBuilder startReturn() {
+        ExecutableElement method = findMethod();
+        if (method != null && ElementUtils.isVoid(method.getReturnType())) {
+            startGroup();
+            registerCallBack(new EndCallback() {
+
+                @Override
+                public void beforeEnd() {
+                    string(";").newLine(); // complete statement to execute
+                }
+
+                @Override
+                public void afterEnd() {
+                    string("return").string(";").newLine(); // emit a return;
+                }
+            });
+            return this;
+        } else {
+            return startStatement().string("return ");
+        }
+    }
+
+    public CodeTreeBuilder startAssert() {
+        return startStatement().string("assert ");
+    }
+
+    public CodeTreeBuilder startNewArray(ArrayType arrayType, CodeTree size) {
+        startGroup().string("new ").type(arrayType.getComponentType()).string("[");
+        if (size != null) {
+            tree(size);
+        }
+        string("]");
+        if (size == null) {
+            string(" ");
+            startCurlyBracesCommaGroup().endAfter();
+        }
+        return this;
+    }
+
+    public CodeTreeBuilder startNew(TypeMirror uninializedNodeClass) {
+        return startGroup().string("new ").type(uninializedNodeClass).startParanthesesCommaGroup().endAfter();
+    }
+
+    public CodeTreeBuilder startNew(String typeName) {
+        return startGroup().string("new ").string(typeName).startParanthesesCommaGroup().endAfter();
+    }
+
+    public CodeTreeBuilder startIndention() {
+        return push(CodeTreeKind.INDENT);
+    }
+
+    public CodeTreeBuilder end(int times) {
+        for (int i = 0; i < times; i++) {
+            end();
+        }
+        return this;
+    }
+
+    public CodeTreeBuilder end() {
+        BuilderCodeTree tree = currentElement;
+        EndCallback callback = tree.getAtEndListener();
+        if (callback != null) {
+            callback.beforeEnd();
+            toParent();
+            callback.afterEnd();
+        } else {
+            toParent();
+        }
+        return this;
+    }
+
+    private void toParent() {
+        CodeTree parentElement = currentElement.getParent();
+        if (currentElement != root) {
+            this.currentElement = (BuilderCodeTree) parentElement;
+        } else {
+            this.currentElement = root;
+        }
+    }
+
+    public CodeTreeBuilder startBlock() {
+        startGroup();
+        string("{").newLine().startIndention();
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+            }
+
+            @Override
+            public void afterEnd() {
+                string("}").newLine();
+            }
+        });
+        endAfter();
+        return this;
+    }
+
+    private void registerCallBack(EndCallback callback) {
+        currentElement.registerAtEnd(callback);
+    }
+
+    public CodeTreeBuilder defaultDeclaration(TypeMirror type, String name) {
+        if (!ElementUtils.isVoid(type)) {
+            startStatement();
+            type(type);
+            string(" ");
+            string(name);
+            string(" = ");
+            defaultValue(type);
+            end(); // statement
+        }
+        return this;
+    }
+
+    public CodeTreeBuilder declaration(TypeMirror type, String name, String init) {
+        return declaration(type, name, singleString(init));
+    }
+
+    public CodeTreeBuilder declaration(String type, String name, CodeTree init) {
+        startStatement();
+        string(type);
+        string(" ");
+        string(name);
+        if (init != null) {
+            string(" = ");
+            tree(init);
+        }
+        end(); // statement
+        return this;
+    }
+
+    public CodeTreeBuilder declaration(String type, String name, String init) {
+        return declaration(type, name, singleString(init));
+    }
+
+    public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTree init) {
+        if (ElementUtils.isVoid(type)) {
+            startStatement();
+            tree(init);
+            end();
+        } else {
+            startStatement();
+            type(type);
+            string(" ");
+            string(name);
+            if (init != null) {
+                string(" = ");
+                tree(init);
+            }
+            end(); // statement
+        }
+        return this;
+    }
+
+    public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTreeBuilder init) {
+        if (init == this) {
+            throw new IllegalArgumentException("Recursive builder usage.");
+        }
+        return declaration(type, name, init.getTree());
+    }
+
+    public CodeTreeBuilder declaration(String type, String name, CodeTreeBuilder init) {
+        if (init == this) {
+            throw new IllegalArgumentException("Recursive builder usage.");
+        }
+        return declaration(type, name, init.getTree());
+    }
+
+    public CodeTreeBuilder declaration(TypeMirror type, String name) {
+        return declaration(type, name, (CodeTree) null);
+    }
+
+    public CodeTreeBuilder create() {
+        return new CodeTreeBuilder(this);
+    }
+
+    public CodeTreeBuilder type(TypeMirror type) {
+        return push(type);
+    }
+
+    public CodeTreeBuilder typeLiteral(TypeMirror type) {
+        return startGroup().type(ElementUtils.eraseGenericTypes(type)).string(".class").end();
+    }
+
+    private void assertRoot() {
+        if (currentElement != root) {
+            throw new IllegalStateException("CodeTreeBuilder was not ended properly.");
+        }
+    }
+
+    public CodeTreeBuilder startCaseBlock() {
+        return startIndention();
+    }
+
+    public CodeTreeBuilder startThrow() {
+        return startStatement().string("throw ");
+    }
+
+    public CodeTree getTree() {
+        assertRoot();
+        return root;
+    }
+
+    public CodeTree getRoot() {
+        return root;
+    }
+
+    public CodeTreeBuilder cast(String baseClassName) {
+        string("(").string(baseClassName).string(") ");
+        return this;
+    }
+
+    public CodeTreeBuilder cast(TypeMirror type, CodeTree content) {
+        if (ElementUtils.isVoid(type)) {
+            tree(content);
+            return this;
+        } else if (type.getKind() == TypeKind.DECLARED && ElementUtils.getQualifiedName(type).equals("java.lang.Object")) {
+            tree(content);
+            return this;
+        } else {
+            return startGroup().string("(").type(type).string(")").string(" ").tree(content).end();
+        }
+    }
+
+    public CodeTreeBuilder startSuperCall() {
+        return string("super").startParanthesesCommaGroup();
+    }
+
+    public CodeTreeBuilder returnFalse() {
+        return startReturn().string("false").end();
+    }
+
+    public CodeTreeBuilder returnStatement() {
+        return statement("return");
+    }
+
+    public ExecutableElement findMethod() {
+        if (enclosingElement != null && (enclosingElement.getKind() == ElementKind.METHOD || enclosingElement.getKind() == ElementKind.CONSTRUCTOR)) {
+            return (ExecutableElement) enclosingElement;
+        }
+        return null;
+    }
+
+    public CodeTreeBuilder returnNull() {
+        return startReturn().string("null").end();
+    }
+
+    public CodeTreeBuilder returnTrue() {
+        return startReturn().string("true").end();
+    }
+
+    public CodeTreeBuilder instanceOf(CodeTree var, CodeTree type) {
+        tree(var).string(" instanceof ").tree(type);
+        return this;
+    }
+
+    public CodeTreeBuilder instanceOf(String var, String type) {
+        return instanceOf(singleString(var), singleString(type));
+    }
+
+    public CodeTreeBuilder instanceOf(String var, TypeMirror type) {
+        TypeElement element = ElementUtils.fromTypeMirror(type);
+        if (element == null) {
+            throw new IllegalArgumentException("Cannot call instanceof for a non supported type: " + type.getKind());
+        }
+        return instanceOf(singleString(var), singleType(type));
+    }
+
+    public CodeTreeBuilder defaultValue(TypeMirror mirror) {
+        switch (mirror.getKind()) {
+            case VOID:
+                return string("");
+            case ARRAY:
+            case DECLARED:
+            case PACKAGE:
+            case NULL:
+                return string("null");
+            case BOOLEAN:
+                return string("false");
+            case BYTE:
+                return string("(byte) 0");
+            case CHAR:
+                return string("(char) 0");
+            case DOUBLE:
+                return string("0.0D");
+            case LONG:
+                return string("0L");
+            case INT:
+                return string("0");
+            case FLOAT:
+                return string("0.0F");
+            case SHORT:
+                return string("(short) 0");
+            default:
+                throw new AssertionError();
+        }
+    }
+
+    public CodeTreeBuilder assertFalse() {
+        return startAssert().string("false").end();
+    }
+
+    public CodeTreeBuilder breakStatement() {
+        return statement("break");
+    }
+
+    public CodeTreeBuilder isNull() {
+        return string(" == null");
+    }
+
+    public CodeTreeBuilder isNotNull() {
+        return string(" != null");
+    }
+
+    public CodeTreeBuilder is(CodeTree tree) {
+        return string(" == ").tree(tree);
+    }
+
+    public CodeTreeBuilder startTryBlock() {
+        return string("try ").startBlock();
+    }
+
+    public CodeTreeBuilder startCatchBlock(TypeMirror exceptionType, String localVarName) {
+        clearLast(CodeTreeKind.NEW_LINE);
+        string(" catch (").type(exceptionType).string(" ").string(localVarName).string(") ");
+        return startBlock();
+    }
+
+    public CodeTreeBuilder startFinallyBlock() {
+        clearLast(CodeTreeKind.NEW_LINE);
+        string(" finally ");
+        return startBlock();
+    }
+
+    public CodeTreeBuilder nullLiteral() {
+        return string("null");
+    }
+
+    private static class BuilderCodeTree extends CodeTree {
+
+        private EndCallback atEndListener;
+        private CodeTreeKind removeLast;
+
+        public BuilderCodeTree(CodeTree parent, CodeTreeKind kind, TypeMirror type, String string) {
+            super(parent, kind, type, string);
+        }
+
+        public void registerAtEnd(EndCallback atEnd) {
+            if (this.atEndListener != null) {
+                this.atEndListener = new CompoundCallback(this.atEndListener, atEnd);
+            } else {
+                this.atEndListener = atEnd;
+            }
+        }
+
+        public EndCallback getAtEndListener() {
+            return atEndListener;
+        }
+
+        @Override
+        public String toString() {
+            final StringBuilder b = new StringBuilder();
+            new Printer(b).visitTree(this, null, null);
+            return b.toString();
+        }
+
+        private static class CompoundCallback implements EndCallback {
+
+            private final EndCallback callback1;
+            private final EndCallback callback2;
+
+            public CompoundCallback(EndCallback callback1, EndCallback callback2) {
+                this.callback1 = callback1;
+                this.callback2 = callback2;
+            }
+
+            @Override
+            public void afterEnd() {
+                callback1.afterEnd();
+                callback2.afterEnd();
+            }
+
+            @Override
+            public void beforeEnd() {
+                callback1.beforeEnd();
+                callback1.beforeEnd();
+            }
+        }
+
+    }
+
+    private interface EndCallback {
+
+        void beforeEnd();
+
+        void afterEnd();
+    }
+
+    private static class Printer extends CodeElementScanner<Void, Void> {
+
+        private int indent;
+        private boolean newLine;
+        private final String ln = "\n";
+
+        private final StringBuilder b;
+
+        Printer(StringBuilder b) {
+            this.b = b;
+        }
+
+        @Override
+        public void visitTree(CodeTree e, Void p, Element enclosingElement) {
+            switch (e.getCodeKind()) {
+                case COMMA_GROUP:
+                    List<CodeTree> children = e.getEnclosedElements();
+                    if (children != null) {
+                        for (int i = 0; i < children.size(); i++) {
+                            visitTree(children.get(i), p, enclosingElement);
+                            if (i < e.getEnclosedElements().size() - 1) {
+                                b.append(", ");
+                            }
+                        }
+                    }
+                    break;
+                case GROUP:
+                    super.visitTree(e, p, enclosingElement);
+                    break;
+                case INDENT:
+                    indent();
+                    super.visitTree(e, p, enclosingElement);
+                    dedent();
+                    break;
+                case NEW_LINE:
+                    writeLn();
+                    break;
+                case STRING:
+                    if (e.getString() != null) {
+                        write(e.getString());
+                    } else {
+                        write("null");
+                    }
+                    break;
+                case TYPE:
+                    write(ElementUtils.getSimpleName(e.getType()));
+                    break;
+                default:
+                    assert false;
+                    return;
+            }
+        }
+
+        private void indent() {
+            indent++;
+        }
+
+        private void dedent() {
+            indent--;
+        }
+
+        private void writeLn() {
+            write(ln);
+            newLine = true;
+        }
+
+        private void write(String m) {
+            if (newLine && m != ln) {
+                writeIndent();
+                newLine = false;
+            }
+            b.append(m);
+        }
+
+        private void writeIndent() {
+            for (int i = 0; i < indent; i++) {
+                b.append("    ");
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeKind.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,35 @@
+/*
+ * 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.truffle.dsl.processor.java.model;
+
+public enum CodeTreeKind {
+    STATIC_FIELD_REFERENCE,
+    STATIC_METHOD_REFERENCE,
+    GROUP,
+    COMMA_GROUP,
+    REMOVE_LAST,
+    INDENT,
+    STRING,
+    NEW_LINE,
+    TYPE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeElement.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,203 @@
+/*
+ * 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.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror;
+
+public class CodeTypeElement extends CodeElement<Element> implements TypeElement {
+
+    private final List<? extends CodeImport> imports = parentableList(this, new ArrayList<CodeImport>());
+
+    private final PackageElement packageElement;
+
+    private final Name simpleName;
+    private final Name packageName;
+    private Name qualifiedName;
+
+    private final List<TypeMirror> implementsInterfaces = new ArrayList<>();
+    private final ElementKind kind;
+    private TypeMirror superClass;
+
+    private final DeclaredCodeTypeMirror mirror = new DeclaredCodeTypeMirror(this);
+
+    public CodeTypeElement(Set<Modifier> modifiers, ElementKind kind, PackageElement packageElement, String simpleName) {
+        super(modifiers);
+        this.kind = kind;
+        this.packageElement = packageElement;
+        this.simpleName = CodeNames.of(simpleName);
+        if (this.packageElement != null) {
+            this.packageName = packageElement.getQualifiedName();
+        } else {
+            this.packageName = CodeNames.of("default");
+        }
+        this.qualifiedName = createQualifiedName();
+    }
+
+    @Override
+    public TypeMirror asType() {
+        return mirror;
+    }
+
+    @Override
+    public ElementKind getKind() {
+        return kind;
+    }
+
+    public boolean containsField(String name) {
+        for (VariableElement field : getFields()) {
+            if (field.getSimpleName().toString().equals(name)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public NestingKind getNestingKind() {
+        return isTopLevelClass() ? NestingKind.TOP_LEVEL : NestingKind.LOCAL;
+    }
+
+    @Override
+    public Element getEnclosingElement() {
+        if (isTopLevelClass()) {
+            return packageElement;
+        } else {
+            return super.getEnclosingElement();
+        }
+    }
+
+    @Override
+    public TypeMirror getSuperclass() {
+        return superClass;
+    }
+
+    @Override
+    public List<TypeMirror> getInterfaces() {
+        return implementsInterfaces;
+    }
+
+    @Override
+    public List<? extends TypeParameterElement> getTypeParameters() {
+        return Collections.emptyList();
+    }
+
+    public boolean isTopLevelClass() {
+        return super.getEnclosingElement() instanceof CodeCompilationUnit;
+    }
+
+    private Name createQualifiedName() {
+        TypeElement enclosingType = getEnclosingClass();
+        if (enclosingType == null) {
+            return CodeNames.of(packageName + "." + simpleName);
+        } else {
+            return CodeNames.of(enclosingType.getQualifiedName() + "." + simpleName);
+        }
+    }
+
+    @Override
+    public void setEnclosingElement(Element element) {
+        super.setEnclosingElement(element);
+
+        // update qualified name on container change
+        this.qualifiedName = createQualifiedName();
+    }
+
+    public Name getPackageName() {
+        return packageName;
+    }
+
+    @Override
+    public Name getQualifiedName() {
+        return qualifiedName;
+    }
+
+    @Override
+    public Name getSimpleName() {
+        return simpleName;
+    }
+
+    public void setSuperClass(TypeMirror superType) {
+        this.superClass = superType;
+    }
+
+    public List<? extends CodeImport> getImports() {
+        return imports;
+    }
+
+    public List<TypeMirror> getImplements() {
+        return implementsInterfaces;
+    }
+
+    @Override
+    public int hashCode() {
+        return getQualifiedName().hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        } else if (obj instanceof TypeElement) {
+            return getQualifiedName().equals(((TypeElement) obj).getQualifiedName());
+        }
+        return false;
+    }
+
+    public List<VariableElement> getFields() {
+        return ElementFilter.fieldsIn(getEnclosedElements());
+    }
+
+    public ExecutableElement getMethod(String name) {
+        for (Element element : getEnclosedElements()) {
+            if (element.getKind() == ElementKind.METHOD && element.getSimpleName().toString().equals(name)) {
+                return (ExecutableElement) element;
+            }
+        }
+        return null;
+    }
+
+    public List<ExecutableElement> getMethods() {
+        return ElementFilter.methodsIn(getEnclosedElements());
+    }
+
+    public List<TypeElement> getInnerClasses() {
+        return ElementFilter.typesIn(getEnclosedElements());
+    }
+
+    @Override
+    public String toString() {
+        return getQualifiedName().toString();
+    }
+
+    @Override
+    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+        return v.visitType(this, p);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeMirror.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,140 @@
+/*
+ * 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.truffle.dsl.processor.java.model;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public class CodeTypeMirror implements TypeMirror {
+
+    private final TypeKind kind;
+
+    public CodeTypeMirror(TypeKind kind) {
+        this.kind = kind;
+    }
+
+    @Override
+    public TypeKind getKind() {
+        return kind;
+    }
+
+    @Override
+    public <R, P> R accept(TypeVisitor<R, P> v, P p) {
+        throw new UnsupportedOperationException();
+    }
+
+    public static class WildcardTypeMirror extends CodeTypeMirror implements WildcardType {
+
+        private final TypeMirror extendsBounds;
+        private final TypeMirror superBounds;
+
+        public WildcardTypeMirror(TypeMirror extendsBounds, TypeMirror superBounds) {
+            super(TypeKind.WILDCARD);
+            this.extendsBounds = extendsBounds;
+            this.superBounds = superBounds;
+        }
+
+        public TypeMirror getExtendsBound() {
+            return extendsBounds;
+        }
+
+        public TypeMirror getSuperBound() {
+            return superBounds;
+        }
+
+    }
+
+    public static class ArrayCodeTypeMirror extends CodeTypeMirror implements ArrayType {
+
+        private final TypeMirror component;
+
+        public ArrayCodeTypeMirror(TypeMirror component) {
+            super(TypeKind.ARRAY);
+            this.component = component;
+        }
+
+        @Override
+        public TypeMirror getComponentType() {
+            return component;
+        }
+
+    }
+
+    public static class DeclaredCodeTypeMirror extends CodeTypeMirror implements DeclaredType {
+
+        private final TypeElement clazz;
+        private final List<TypeMirror> typeArguments;
+
+        public DeclaredCodeTypeMirror(TypeElement clazz) {
+            this(clazz, Collections.<TypeMirror> emptyList());
+        }
+
+        public DeclaredCodeTypeMirror(TypeElement clazz, List<TypeMirror> typeArguments) {
+            super(TypeKind.DECLARED);
+            this.clazz = clazz;
+            this.typeArguments = typeArguments;
+        }
+
+        @Override
+        public Element asElement() {
+            return clazz;
+        }
+
+        @Override
+        public TypeMirror getEnclosingType() {
+            return clazz.getEnclosingElement().asType();
+        }
+
+        @Override
+        public List<TypeMirror> getTypeArguments() {
+            return typeArguments;
+        }
+
+        @Override
+        public String toString() {
+            return clazz.getQualifiedName().toString();
+        }
+
+    }
+
+    public List<? extends AnnotationMirror> getAnnotationMirrors() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @param annotationType
+     */
+    public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @param annotationType
+     */
+    public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeVariableElement.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,140 @@
+/*
+ * 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.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public final class CodeVariableElement extends CodeElement<Element> implements VariableElement {
+
+    private Name name;
+    private TypeMirror type;
+    private Object constantValue;
+
+    private CodeTree init;
+
+    public CodeVariableElement(TypeMirror type, String name) {
+        super(ElementUtils.modifiers());
+        this.type = type;
+        this.name = CodeNames.of(name);
+    }
+
+    public CodeVariableElement(Set<Modifier> modifiers, TypeMirror type, String name) {
+        super(modifiers);
+        this.type = type;
+        this.name = CodeNames.of(name);
+    }
+
+    public CodeVariableElement(Set<Modifier> modifiers, TypeMirror type, String name, String init) {
+        this(modifiers, type, name);
+        if (init != null) {
+            this.init = new CodeTree(null, CodeTreeKind.STRING, null, init);
+        }
+    }
+
+    public CodeTreeBuilder createInitBuilder() {
+        CodeTreeBuilder builder = new CodeTreeBuilder(null);
+        builder.setEnclosingElement(this);
+        init = builder.getTree();
+        return builder;
+    }
+
+    public void setInit(CodeTree init) {
+        this.init = init;
+    }
+
+    public CodeTree getInit() {
+        return init;
+    }
+
+    public Name getSimpleName() {
+        return name;
+    }
+
+    public TypeMirror getType() {
+        return type;
+    }
+
+    @Override
+    public TypeMirror asType() {
+        return type;
+    }
+
+    @Override
+    public ElementKind getKind() {
+        if (getEnclosingElement() instanceof ExecutableElement) {
+            return ElementKind.PARAMETER;
+        } else if (getEnclosingElement() instanceof TypeElement) {
+            return ElementKind.FIELD;
+        } else {
+            return ElementKind.PARAMETER;
+        }
+    }
+
+    public void setConstantValue(Object constantValue) {
+        this.constantValue = constantValue;
+    }
+
+    @Override
+    public Object getConstantValue() {
+        return constantValue;
+    }
+
+    public String getName() {
+        return getSimpleName().toString();
+    }
+
+    public void setSimpleName(Name name) {
+        this.name = name;
+    }
+
+    public void setName(String name) {
+        this.name = CodeNames.of(name);
+    }
+
+    public void setType(TypeMirror type) {
+        this.type = type;
+    }
+
+    @Override
+    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+        return v.visitVariable(this, p);
+    }
+
+    public static CodeVariableElement clone(VariableElement var) {
+        CodeVariableElement copy = new CodeVariableElement(var.getModifiers(), var.asType(), var.getSimpleName().toString());
+        copy.setConstantValue(var.getConstantValue());
+        for (AnnotationMirror mirror : var.getAnnotationMirrors()) {
+            copy.addAnnotationMirror(mirror);
+        }
+        for (Element element : var.getEnclosedElements()) {
+            copy.add(element);
+        }
+        return copy;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedElement.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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.truffle.dsl.processor.java.model;
+
+import javax.lang.model.element.*;
+
+public interface GeneratedElement {
+
+    AnnotationMirror getGeneratorAnnotationMirror();
+
+    void setGeneratorAnnotationMirror(AnnotationMirror mirror);
+
+    Element getGeneratorElement();
+
+    void setGeneratorElement(Element element);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedPackageElement.java	Mon Aug 25 21:15:59 2014 -0700
@@ -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.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public final class GeneratedPackageElement extends CodeElement<Element> implements PackageElement {
+
+    private final Name qualifiedName;
+    private final Name simpleName;
+
+    public GeneratedPackageElement(String qualifiedName) {
+        super(Collections.<Modifier> emptySet());
+        this.qualifiedName = CodeNames.of(qualifiedName);
+        int lastIndex = qualifiedName.lastIndexOf('.');
+        if (lastIndex == -1) {
+            simpleName = CodeNames.of("");
+        } else {
+            simpleName = CodeNames.of(qualifiedName.substring(lastIndex, qualifiedName.length()));
+        }
+    }
+
+    public TypeMirror asType() {
+        throw new UnsupportedOperationException();
+    }
+
+    public ElementKind getKind() {
+        return ElementKind.PACKAGE;
+    }
+
+    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+        return v.visitPackage(this, p);
+    }
+
+    public Name getQualifiedName() {
+        return qualifiedName;
+    }
+
+    public Name getSimpleName() {
+        return simpleName;
+    }
+
+    public boolean isUnnamed() {
+        return simpleName.toString().equals("");
+    }
+
+    @Override
+    public int hashCode() {
+        return qualifiedName.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof PackageElement) {
+            return qualifiedName.equals(((PackageElement) obj).getQualifiedName());
+        }
+        return super.equals(obj);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedTypeElement.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+public final class GeneratedTypeElement extends CodeTypeElement {
+
+    public GeneratedTypeElement(Set<Modifier> modifiers, ElementKind kind, PackageElement packageElement, String simpleName) {
+        super(modifiers, kind, packageElement, simpleName);
+        setEnclosingElement(packageElement);
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedTypeMirror.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror;
+
+public final class GeneratedTypeMirror extends DeclaredCodeTypeMirror {
+
+    public GeneratedTypeMirror(String packageName, String name) {
+        super(new GeneratedTypeElement(Collections.<Modifier> emptySet(), ElementKind.CLASS, new GeneratedPackageElement(packageName), name));
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/AbstractCodeWriter.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,760 @@
+/*
+ * 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.truffle.dsl.processor.java.transform;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+
+import java.io.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public abstract class AbstractCodeWriter extends CodeElementScanner<Void, Void> {
+
+    private static final int MAX_LINE_LENGTH = 200;
+    private static final int LINE_WRAP_INDENTS = 3;
+    private static final String IDENT_STRING = "    ";
+    private static final String LN = "\n"; /* unix style */
+
+    protected Writer writer;
+    private int indent;
+    private boolean newLine;
+    private int lineLength;
+    private boolean lineWrapping = false;
+
+    private OrganizedImports imports;
+
+    protected abstract Writer createWriter(CodeTypeElement clazz) throws IOException;
+
+    @Override
+    public Void visitType(CodeTypeElement e, Void p) {
+        if (e.isTopLevelClass()) {
+            Writer w = null;
+            try {
+                imports = OrganizedImports.organize(e);
+                w = new TrimTrailingSpaceWriter(createWriter(e));
+                writer = w;
+                writeRootClass(e);
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            } finally {
+                if (w != null) {
+                    try {
+                        w.close();
+                    } catch (Throwable e1) {
+                        // see eclipse bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=361378
+                        // TODO temporary suppress errors on close.
+                    }
+                }
+                writer = null;
+            }
+        } else {
+            writeClassImpl(e);
+        }
+        return null;
+    }
+
+    private void writeRootClass(CodeTypeElement e) {
+        writeHeader();
+        write("package ").write(e.getPackageName()).write(";").writeLn();
+        writeEmptyLn();
+
+        Set<CodeImport> generateImports = imports.generateImports();
+        List<CodeImport> typeImports = new ArrayList<>();
+        List<CodeImport> staticImports = new ArrayList<>();
+
+        for (CodeImport codeImport : generateImports) {
+            if (codeImport.isStaticImport()) {
+                staticImports.add(codeImport);
+            } else {
+                typeImports.add(codeImport);
+            }
+        }
+        Collections.sort(typeImports);
+        Collections.sort(staticImports);
+
+        for (CodeImport imp : staticImports) {
+            imp.accept(this, null);
+            writeLn();
+        }
+        if (!staticImports.isEmpty()) {
+            writeEmptyLn();
+        }
+
+        for (CodeImport imp : typeImports) {
+            imp.accept(this, null);
+            writeLn();
+        }
+        if (!typeImports.isEmpty()) {
+            writeEmptyLn();
+        }
+
+        writeClassImpl(e);
+    }
+
+    private String useImport(Element enclosedType, TypeMirror type) {
+        if (imports != null) {
+            return imports.createTypeReference(enclosedType, type);
+        } else {
+            return ElementUtils.getSimpleName(type);
+        }
+    }
+
+    private void writeClassImpl(CodeTypeElement e) {
+        for (AnnotationMirror annotation : e.getAnnotationMirrors()) {
+            visitAnnotation(e, annotation);
+            writeLn();
+        }
+
+        writeModifiers(e.getModifiers());
+        if (e.getKind() == ElementKind.ENUM) {
+            write("enum ");
+        } else {
+            write("class ");
+        }
+        write(e.getSimpleName());
+        if (e.getSuperclass() != null && !getQualifiedName(e.getSuperclass()).equals("java.lang.Object")) {
+            write(" extends ").write(useImport(e, e.getSuperclass()));
+        }
+        if (e.getImplements().size() > 0) {
+            write(" implements ");
+            for (int i = 0; i < e.getImplements().size(); i++) {
+                write(useImport(e, e.getImplements().get(i)));
+                if (i < e.getImplements().size() - 1) {
+                    write(", ");
+                }
+            }
+        }
+
+        write(" {").writeLn();
+        writeEmptyLn();
+        indent(1);
+
+        List<VariableElement> staticFields = getStaticFields(e);
+        List<VariableElement> instanceFields = getInstanceFields(e);
+
+        for (int i = 0; i < staticFields.size(); i++) {
+            VariableElement field = staticFields.get(i);
+            field.accept(this, null);
+            if (e.getKind() == ElementKind.ENUM && i < staticFields.size() - 1) {
+                write(",");
+                writeLn();
+            } else {
+                write(";");
+                writeLn();
+            }
+        }
+
+        if (staticFields.size() > 0) {
+            writeEmptyLn();
+        }
+
+        for (VariableElement field : instanceFields) {
+            field.accept(this, null);
+            write(";");
+            writeLn();
+        }
+        if (instanceFields.size() > 0) {
+            writeEmptyLn();
+        }
+
+        for (ExecutableElement method : ElementFilter.constructorsIn(e.getEnclosedElements())) {
+            method.accept(this, null);
+        }
+
+        for (ExecutableElement method : getInstanceMethods(e)) {
+            method.accept(this, null);
+        }
+
+        for (ExecutableElement method : getStaticMethods(e)) {
+            method.accept(this, null);
+        }
+
+        for (TypeElement clazz : e.getInnerClasses()) {
+            clazz.accept(this, null);
+        }
+
+        dedent(1);
+        write("}");
+        writeEmptyLn();
+    }
+
+    private static List<VariableElement> getStaticFields(CodeTypeElement clazz) {
+        List<VariableElement> staticFields = new ArrayList<>();
+        for (VariableElement field : clazz.getFields()) {
+            if (field.getModifiers().contains(Modifier.STATIC)) {
+                staticFields.add(field);
+            }
+        }
+        return staticFields;
+    }
+
+    private static List<VariableElement> getInstanceFields(CodeTypeElement clazz) {
+        List<VariableElement> instanceFields = new ArrayList<>();
+        for (VariableElement field : clazz.getFields()) {
+            if (!field.getModifiers().contains(Modifier.STATIC)) {
+                instanceFields.add(field);
+            }
+        }
+        return instanceFields;
+    }
+
+    private static List<ExecutableElement> getStaticMethods(CodeTypeElement clazz) {
+        List<ExecutableElement> staticMethods = new ArrayList<>();
+        for (ExecutableElement method : clazz.getMethods()) {
+            if (method.getModifiers().contains(Modifier.STATIC)) {
+                staticMethods.add(method);
+            }
+        }
+        return staticMethods;
+    }
+
+    private static List<ExecutableElement> getInstanceMethods(CodeTypeElement clazz) {
+        List<ExecutableElement> instanceMethods = new ArrayList<>();
+        for (ExecutableElement method : clazz.getMethods()) {
+            if (!method.getModifiers().contains(Modifier.STATIC)) {
+                instanceMethods.add(method);
+            }
+        }
+        return instanceMethods;
+    }
+
+    @Override
+    public Void visitVariable(VariableElement f, Void p) {
+        Element parent = f.getEnclosingElement();
+
+        for (AnnotationMirror annotation : f.getAnnotationMirrors()) {
+            visitAnnotation(f, annotation);
+            write(" ");
+        }
+
+        CodeTree init = null;
+        if (f instanceof CodeVariableElement) {
+            init = ((CodeVariableElement) f).getInit();
+        }
+
+        if (parent.getKind() == ElementKind.ENUM && f.getModifiers().contains(Modifier.STATIC)) {
+            write(f.getSimpleName());
+            if (init != null) {
+                write("(");
+                visitTree(init, p, f);
+                write(")");
+            }
+        } else {
+            Element enclosing = f.getEnclosingElement();
+            writeModifiers(f.getModifiers());
+
+            boolean varArgs = false;
+            if (enclosing.getKind() == ElementKind.METHOD) {
+                ExecutableElement method = (ExecutableElement) enclosing;
+                if (method.isVarArgs() && method.getParameters().indexOf(f) == method.getParameters().size() - 1) {
+                    varArgs = true;
+                }
+            }
+
+            TypeMirror varType = f.asType();
+            if (varArgs) {
+                if (varType.getKind() == TypeKind.ARRAY) {
+                    varType = ((ArrayType) varType).getComponentType();
+                }
+                write(useImport(f, varType));
+                write("...");
+            } else {
+                write(useImport(f, varType));
+            }
+
+            write(" ");
+            write(f.getSimpleName());
+            if (init != null) {
+                write(" = ");
+                visitTree(init, p, f);
+            }
+        }
+        return null;
+    }
+
+    private void visitAnnotation(Element enclosedElement, AnnotationMirror e) {
+        write("@").write(useImport(enclosedElement, e.getAnnotationType()));
+
+        if (!e.getElementValues().isEmpty()) {
+            write("(");
+            final ExecutableElement defaultElement = findExecutableElement(e.getAnnotationType(), "value");
+
+            Map<? extends ExecutableElement, ? extends AnnotationValue> values = e.getElementValues();
+            if (defaultElement != null && values.size() == 1 && values.get(defaultElement) != null) {
+                visitAnnotationValue(enclosedElement, values.get(defaultElement));
+            } else {
+                Set<? extends ExecutableElement> methodsSet = values.keySet();
+                List<ExecutableElement> methodsList = new ArrayList<>();
+                for (ExecutableElement method : methodsSet) {
+                    if (values.get(method) == null) {
+                        continue;
+                    }
+                    methodsList.add(method);
+                }
+
+                Collections.sort(methodsList, new Comparator<ExecutableElement>() {
+
+                    @Override
+                    public int compare(ExecutableElement o1, ExecutableElement o2) {
+                        return o1.getSimpleName().toString().compareTo(o2.getSimpleName().toString());
+                    }
+                });
+
+                for (int i = 0; i < methodsList.size(); i++) {
+                    ExecutableElement method = methodsList.get(i);
+                    AnnotationValue value = values.get(method);
+                    write(method.getSimpleName().toString());
+                    write(" = ");
+                    visitAnnotationValue(enclosedElement, value);
+
+                    if (i < methodsList.size() - 1) {
+                        write(", ");
+                    }
+                }
+            }
+
+            write(")");
+        }
+    }
+
+    private void visitAnnotationValue(Element enclosedElement, AnnotationValue e) {
+        e.accept(new AnnotationValueWriterVisitor(enclosedElement), null);
+    }
+
+    private class AnnotationValueWriterVisitor extends AbstractAnnotationValueVisitor7<Void, Void> {
+
+        private final Element enclosedElement;
+
+        public AnnotationValueWriterVisitor(Element enclosedElement) {
+            this.enclosedElement = enclosedElement;
+        }
+
+        @Override
+        public Void visitBoolean(boolean b, Void p) {
+            write(Boolean.toString(b));
+            return null;
+        }
+
+        @Override
+        public Void visitByte(byte b, Void p) {
+            write(Byte.toString(b));
+            return null;
+        }
+
+        @Override
+        public Void visitChar(char c, Void p) {
+            write(Character.toString(c));
+            return null;
+        }
+
+        @Override
+        public Void visitDouble(double d, Void p) {
+            write(Double.toString(d));
+            return null;
+        }
+
+        @Override
+        public Void visitFloat(float f, Void p) {
+            write(Float.toString(f));
+            return null;
+        }
+
+        @Override
+        public Void visitInt(int i, Void p) {
+            write(Integer.toString(i));
+            return null;
+        }
+
+        @Override
+        public Void visitLong(long i, Void p) {
+            write(Long.toString(i));
+            return null;
+        }
+
+        @Override
+        public Void visitShort(short s, Void p) {
+            write(Short.toString(s));
+            return null;
+        }
+
+        @Override
+        public Void visitString(String s, Void p) {
+            write("\"");
+            write(s);
+            write("\"");
+            return null;
+        }
+
+        @Override
+        public Void visitType(TypeMirror t, Void p) {
+            write(useImport(enclosedElement, t));
+            write(".class");
+            return null;
+        }
+
+        @Override
+        public Void visitEnumConstant(VariableElement c, Void p) {
+            write(useImport(enclosedElement, c.asType()));
+            write(".");
+            write(c.getSimpleName().toString());
+            return null;
+        }
+
+        @Override
+        public Void visitAnnotation(AnnotationMirror a, Void p) {
+            AbstractCodeWriter.this.visitAnnotation(enclosedElement, a);
+            return null;
+        }
+
+        @Override
+        public Void visitArray(List<? extends AnnotationValue> vals, Void p) {
+            write("{");
+            for (int i = 0; i < vals.size(); i++) {
+                AnnotationValue value = vals.get(i);
+                AbstractCodeWriter.this.visitAnnotationValue(enclosedElement, value);
+                if (i < vals.size() - 1) {
+                    write(", ");
+                }
+            }
+            write("}");
+            return null;
+        }
+    }
+
+    private static ExecutableElement findExecutableElement(DeclaredType type, String name) {
+        List<? extends ExecutableElement> elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements());
+        for (ExecutableElement executableElement : elements) {
+            if (executableElement.getSimpleName().toString().equals(name)) {
+                return executableElement;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public void visitImport(CodeImport e, Void p) {
+        write("import ");
+        if (e.isStaticImport()) {
+            write("static ");
+        }
+        write(e.getPackageName());
+        write(".");
+        write(e.getSymbolName());
+        write(";");
+    }
+
+    @Override
+    public Void visitExecutable(CodeExecutableElement e, Void p) {
+        for (AnnotationMirror annotation : e.getAnnotationMirrors()) {
+            visitAnnotation(e, annotation);
+            writeLn();
+        }
+
+        writeModifiers(e.getModifiers());
+
+        if (e.getReturnType() != null) {
+            write(useImport(e, e.getReturnType()));
+            write(" ");
+        }
+        write(e.getSimpleName());
+        write("(");
+
+        for (int i = 0; i < e.getParameters().size(); i++) {
+            VariableElement param = e.getParameters().get(i);
+            param.accept(this, p);
+            if (i < e.getParameters().size() - 1) {
+                write(", ");
+            }
+        }
+        write(")");
+
+        List<TypeMirror> throwables = e.getThrownTypes();
+        if (throwables.size() > 0) {
+            write(" throws ");
+            for (int i = 0; i < throwables.size(); i++) {
+                write(useImport(e, throwables.get(i)));
+                if (i < throwables.size() - 1) {
+                    write(", ");
+                }
+            }
+        }
+
+        if (e.getModifiers().contains(Modifier.ABSTRACT)) {
+            writeLn(";");
+        } else if (e.getBodyTree() != null) {
+            writeLn(" {");
+            indent(1);
+            visitTree(e.getBodyTree(), p, e);
+            dedent(1);
+            writeLn("}");
+        } else if (e.getBody() != null) {
+            write(" {");
+            write(e.getBody());
+            writeLn("}");
+        } else {
+            writeLn("{ }");
+        }
+        writeEmptyLn();
+        return null;
+    }
+
+    @Override
+    public void visitTree(CodeTree e, Void p, Element enclosingElement) {
+        CodeTreeKind kind = e.getCodeKind();
+
+        switch (kind) {
+            case COMMA_GROUP:
+                List<CodeTree> children = e.getEnclosedElements();
+                if (children != null) {
+                    for (int i = 0; i < children.size(); i++) {
+                        visitTree(children.get(i), p, enclosingElement);
+                        if (i < e.getEnclosedElements().size() - 1) {
+                            write(", ");
+                        }
+                    }
+                }
+                break;
+            case GROUP:
+                super.visitTree(e, p, enclosingElement);
+                break;
+            case INDENT:
+                indent(1);
+                super.visitTree(e, p, enclosingElement);
+                dedent(1);
+                break;
+            case NEW_LINE:
+                writeLn();
+                break;
+            case STRING:
+                if (e.getString() != null) {
+                    write(e.getString());
+                } else {
+                    write("null");
+                }
+                break;
+            case STATIC_FIELD_REFERENCE:
+                if (e.getString() != null) {
+                    write(imports.createStaticFieldReference(enclosingElement, e.getType(), e.getString()));
+                } else {
+                    write("null");
+                }
+                break;
+            case STATIC_METHOD_REFERENCE:
+                if (e.getString() != null) {
+                    write(imports.createStaticMethodReference(enclosingElement, e.getType(), e.getString()));
+                } else {
+                    write("null");
+                }
+                break;
+            case TYPE:
+                write(useImport(enclosingElement, e.getType()));
+                break;
+            default:
+                assert false;
+                return;
+        }
+    }
+
+    protected void writeHeader() {
+        // default implementation does nothing
+    }
+
+    private void writeModifiers(Set<Modifier> modifiers) {
+        if (modifiers != null) {
+            for (Modifier modifier : modifiers) {
+                write(modifier.toString());
+                write(" ");
+            }
+        }
+    }
+
+    private void indent(int count) {
+        indent += count;
+    }
+
+    private void dedent(int count) {
+        indent -= count;
+    }
+
+    private void writeLn() {
+        writeLn("");
+    }
+
+    protected void writeLn(String text) {
+        write(text);
+        write(LN);
+        lineLength = 0;
+        newLine = true;
+        if (lineWrapping) {
+            dedent(LINE_WRAP_INDENTS);
+            lineWrapping = false;
+        }
+        lineWrapping = false;
+    }
+
+    private void writeEmptyLn() {
+        writeLn();
+    }
+
+    private AbstractCodeWriter write(Name name) {
+        return write(name.toString());
+    }
+
+    private AbstractCodeWriter write(String m) {
+        if (m.isEmpty()) {
+            return this;
+        }
+        try {
+            String s = m;
+            lineLength += s.length();
+            if (newLine && s != LN) {
+                writeIndent();
+                newLine = false;
+            }
+            if (lineLength > MAX_LINE_LENGTH) {
+                s = wrapLine(s);
+            }
+            writer.write(s);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        return this;
+    }
+
+    private String wrapLine(String m) throws IOException {
+        assert !m.isEmpty();
+
+        char firstCharacter = m.charAt(0);
+        char lastCharacter = m.charAt(m.length() - 1);
+        if (firstCharacter == '\"' && lastCharacter == '\"') {
+            // string line wrapping
+            String string = m.substring(1, m.length() - 1);
+            if (string.isEmpty()) {
+                return m;
+            }
+
+            // restore original line length
+            lineLength = lineLength - m.length();
+            int size = 0;
+            for (int i = 0; i < string.length(); i += size) {
+                if (i != 0) {
+                    write("+ ");
+                }
+
+                int nextSize = MAX_LINE_LENGTH - lineLength - 2;
+                if (nextSize <= 0) {
+                    writeLn();
+                    nextSize = MAX_LINE_LENGTH - lineLength - 2;
+                }
+
+                int end = Math.min(i + nextSize, string.length());
+
+                // TODO(CH): fails in normal usage - output ok though
+                // assert lineLength + (end - i) + 2 < MAX_LINE_LENGTH;
+                write("\"");
+                write(string.substring(i, end));
+                write("\"");
+                size = nextSize;
+            }
+
+            return "";
+        } else if (!Character.isAlphabetic(firstCharacter) && firstCharacter != '+') {
+            return m;
+        }
+
+        if (!lineWrapping) {
+            indent(LINE_WRAP_INDENTS);
+        }
+        lineWrapping = true;
+        lineLength = 0;
+        write(LN);
+        writeIndent();
+        return m;
+    }
+
+    private void writeIndent() throws IOException {
+        lineLength += indentSize();
+        for (int i = 0; i < indent; i++) {
+            writer.write(IDENT_STRING);
+        }
+    }
+
+    private int indentSize() {
+        return IDENT_STRING.length() * indent;
+    }
+
+    private static class TrimTrailingSpaceWriter extends Writer {
+
+        private final Writer delegate;
+        private final StringBuilder buffer = new StringBuilder();
+
+        public TrimTrailingSpaceWriter(Writer delegate) {
+            this.delegate = delegate;
+        }
+
+        @Override
+        public void close() throws IOException {
+            this.delegate.close();
+        }
+
+        @Override
+        public void flush() throws IOException {
+            this.delegate.flush();
+        }
+
+        @Override
+        public void write(char[] cbuf, int off, int len) throws IOException {
+            buffer.append(cbuf, off, len);
+            int newLinePoint = buffer.indexOf(LN);
+
+            if (newLinePoint != -1) {
+                String lhs = trimTrailing(buffer.substring(0, newLinePoint));
+                delegate.write(lhs);
+                delegate.write(LN);
+                buffer.delete(0, newLinePoint + 1);
+            }
+        }
+
+        private static String trimTrailing(String s) {
+            int cut = 0;
+            for (int i = s.length() - 1; i >= 0; i--) {
+                if (Character.isWhitespace(s.charAt(i))) {
+                    cut++;
+                } else {
+                    break;
+                }
+            }
+            if (cut > 0) {
+                return s.substring(0, s.length() - cut);
+            }
+            return s;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/FixWarningsVisitor.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,126 @@
+/*
+ * 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.truffle.dsl.processor.java.transform;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+import static javax.lang.model.element.Modifier.*;
+
+import java.io.*;
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public class FixWarningsVisitor extends CodeElementScanner<Void, Void> {
+
+    private final Set<String> symbolsUsed = new HashSet<>();
+
+    private final ProcessingEnvironment processingEnv;
+    private final DeclaredType unusedAnnotation;
+    private final DeclaredType overrideType;
+
+    public FixWarningsVisitor(ProcessingEnvironment processingEnv, DeclaredType unusedAnnotation, DeclaredType overrideType) {
+        this.processingEnv = processingEnv;
+        this.unusedAnnotation = unusedAnnotation;
+        this.overrideType = overrideType;
+    }
+
+    @Override
+    public Void visitType(CodeTypeElement e, Void p) {
+        List<TypeElement> superTypes = ElementUtils.getSuperTypes(e);
+        for (TypeElement type : superTypes) {
+            String qualifiedName = ElementUtils.getQualifiedName(type);
+            if (qualifiedName.equals(Serializable.class.getCanonicalName())) {
+                if (!e.containsField("serialVersionUID")) {
+                    e.add(new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), ElementUtils.getType(processingEnv, long.class), "serialVersionUID", "1L"));
+                }
+                break;
+            }
+        }
+
+        return super.visitType(e, p);
+    }
+
+    @Override
+    public Void visitExecutable(CodeExecutableElement e, Void p) {
+        if (e.getParameters().isEmpty()) {
+            return null;
+        } else if (e.getModifiers().contains(Modifier.ABSTRACT)) {
+            return null;
+        } else if (containsOverride(e)) {
+            return null;
+        }
+
+        symbolsUsed.clear();
+        super.visitExecutable(e, p);
+
+        for (VariableElement parameter : e.getParameters()) {
+            if (!symbolsUsed.contains(parameter.getSimpleName().toString())) {
+                e.getAnnotationMirrors().add(createUnusedAnnotationMirror());
+                break;
+            }
+        }
+        return null;
+    }
+
+    private boolean containsOverride(CodeExecutableElement e) {
+        for (AnnotationMirror mirror : e.getAnnotationMirrors()) {
+            if (ElementUtils.typeEquals(overrideType, mirror.getAnnotationType())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private CodeAnnotationMirror createUnusedAnnotationMirror() {
+        CodeAnnotationMirror mirror = new CodeAnnotationMirror(unusedAnnotation);
+        mirror.setElementValue(mirror.findExecutableElement("value"), new CodeAnnotationValue("unused"));
+        return mirror;
+    }
+
+    @Override
+    public void visitTree(CodeTree e, Void p, Element enclosingElement) {
+        if (e.getString() != null) {
+            computeSymbols(e.getString());
+        }
+        super.visitTree(e, p, enclosingElement);
+    }
+
+    private void computeSymbols(String s) {
+        // TODO there should not be any need for a StringTokenizer if we have a real AST for
+        // method bodies. Also the current solution is not perfect. What if one token
+        // is spread across multiple CodeTree instances? But for now that works.
+        StringTokenizer tokenizer = new StringTokenizer(s, ".= :,()[];{}\"\"'' ", false);
+        while (tokenizer.hasMoreElements()) {
+            String token = tokenizer.nextToken().trim();
+            if (token.length() > 0) {
+                symbolsUsed.add(token);
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/GenerateOverrideVisitor.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,61 @@
+/*
+ * 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.truffle.dsl.processor.java.transform;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public class GenerateOverrideVisitor extends CodeElementScanner<Void, Void> {
+
+    private final DeclaredType overrideType;
+
+    public GenerateOverrideVisitor(DeclaredType overrideType) {
+        this.overrideType = overrideType;
+    }
+
+    @Override
+    public Void visitExecutable(CodeExecutableElement e, Void p) {
+        if (!e.getModifiers().contains(Modifier.STATIC) && !e.getModifiers().contains(Modifier.PRIVATE)) {
+            String name = e.getSimpleName().toString();
+            TypeMirror[] params = e.getParameterTypes();
+
+            for (AnnotationMirror mirror : e.getAnnotationMirrors()) {
+                if (ElementUtils.typeEquals(overrideType, mirror.getAnnotationType())) {
+                    // already declared (may happen if method copied from super class)
+                    return super.visitExecutable(e, p);
+                }
+            }
+
+            if (isDeclaredMethodInSuperType(e.getEnclosingClass(), name, params)) {
+                e.addAnnotationMirror(new CodeAnnotationMirror(overrideType));
+            }
+        }
+        return super.visitExecutable(e, p);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/OrganizedImports.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,484 @@
+/*
+ * 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.truffle.dsl.processor.java.transform;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public final class OrganizedImports {
+
+    private final Map<String, String> classImportUsage = new HashMap<>();
+    private final Map<String, String> staticImportUsage = new HashMap<>();
+    private final Map<String, Set<String>> autoImportCache = new HashMap<>();
+
+    private final CodeTypeElement topLevelClass;
+
+    private OrganizedImports(CodeTypeElement topLevelClass) {
+        this.topLevelClass = topLevelClass;
+    }
+
+    public static OrganizedImports organize(CodeTypeElement topLevelClass) {
+        OrganizedImports organized = new OrganizedImports(topLevelClass);
+        organized.organizeImpl();
+        return organized;
+    }
+
+    private void organizeImpl() {
+        ImportTypeReferenceVisitor reference = new ImportTypeReferenceVisitor();
+        topLevelClass.accept(reference, null);
+
+    }
+
+    public String createTypeReference(Element enclosedElement, TypeMirror type) {
+        switch (type.getKind()) {
+            case BOOLEAN:
+            case BYTE:
+            case CHAR:
+            case DOUBLE:
+            case FLOAT:
+            case SHORT:
+            case INT:
+            case LONG:
+            case VOID:
+                return ElementUtils.getSimpleName(type);
+            case DECLARED:
+                return createDeclaredTypeName(enclosedElement, (DeclaredType) type);
+            case ARRAY:
+                return createTypeReference(enclosedElement, ((ArrayType) type).getComponentType()) + "[]";
+            case WILDCARD:
+                return createWildcardName(enclosedElement, (WildcardType) type);
+            case TYPEVAR:
+                return "?";
+            default:
+                throw new RuntimeException("Unknown type specified " + type.getKind() + " mirror: " + type);
+        }
+    }
+
+    public String createStaticFieldReference(Element enclosedElement, TypeMirror type, String fieldName) {
+        return createStaticReference(enclosedElement, type, fieldName);
+    }
+
+    public String createStaticMethodReference(Element enclosedElement, TypeMirror type, String methodName) {
+        return createStaticReference(enclosedElement, type, methodName);
+    }
+
+    private String createStaticReference(Element enclosedElement, TypeMirror type, String name) {
+        String qualifiedName = staticImportUsage.get(name);
+        if (qualifiedName == null) {
+            // ambiguous import
+            return createTypeReference(enclosedElement, type) + "." + name;
+        } else {
+            // import declared and not ambiguous
+            return name;
+        }
+    }
+
+    private String createWildcardName(Element enclosedElement, WildcardType type) {
+        StringBuilder b = new StringBuilder();
+        if (type.getExtendsBound() != null) {
+            b.append("? extends ").append(createTypeReference(enclosedElement, type.getExtendsBound()));
+        } else if (type.getSuperBound() != null) {
+            b.append("? super ").append(createTypeReference(enclosedElement, type.getExtendsBound()));
+        } else {
+            b.append("?");
+        }
+        return b.toString();
+    }
+
+    private String createDeclaredTypeName(Element enclosedElement, DeclaredType type) {
+        String name = ElementUtils.fixECJBinaryNameIssue(type.asElement().getSimpleName().toString());
+        if (classImportUsage.containsKey(name)) {
+            String qualifiedImport = classImportUsage.get(name);
+            String qualifiedName = ElementUtils.getEnclosedQualifiedName(type);
+
+            if (!qualifiedName.equals(qualifiedImport)) {
+                name = qualifiedName;
+            }
+        }
+
+        List<? extends TypeMirror> genericTypes = type.getTypeArguments();
+        if (genericTypes.size() == 0) {
+            return name;
+        }
+
+        StringBuilder b = new StringBuilder(name);
+        b.append("<");
+        for (int i = 0; i < genericTypes.size(); i++) {
+            TypeMirror genericType = i < genericTypes.size() ? genericTypes.get(i) : null;
+            if (genericType != null) {
+                b.append(createTypeReference(enclosedElement, genericType));
+            } else {
+                b.append("?");
+            }
+
+            if (i < genericTypes.size() - 1) {
+                b.append(", ");
+            }
+        }
+        b.append(">");
+        return b.toString();
+    }
+
+    public Set<CodeImport> generateImports() {
+        Set<CodeImport> imports = new HashSet<>();
+
+        imports.addAll(generateImports(classImportUsage));
+        imports.addAll(generateStaticImports(staticImportUsage));
+
+        return imports;
+    }
+
+    private boolean needsImport(Element enclosed, TypeMirror importType) {
+        String importPackagName = getPackageName(importType);
+        TypeElement enclosedElement = findNearestEnclosingType(enclosed);
+        if (importPackagName == null) {
+            return false;
+        } else if (importPackagName.equals("java.lang")) {
+            return false;
+        } else if (importPackagName.equals(getPackageName(topLevelClass)) && ElementUtils.isTopLevelClass(importType)) {
+            return false; // same package name -> no import
+        }
+
+        String enclosedElementId = ElementUtils.getUniqueIdentifier(enclosedElement.asType());
+        Set<String> autoImportedTypes = autoImportCache.get(enclosedElementId);
+        if (autoImportedTypes == null) {
+            List<Element> elements = ElementUtils.getElementHierarchy(enclosedElement);
+            autoImportedTypes = new HashSet<>();
+            for (Element element : elements) {
+                if (element.getKind().isClass()) {
+                    collectSuperTypeImports((TypeElement) element, autoImportedTypes);
+                    collectInnerTypeImports((TypeElement) element, autoImportedTypes);
+                }
+            }
+            autoImportCache.put(enclosedElementId, autoImportedTypes);
+        }
+
+        String qualifiedName = getQualifiedName(importType);
+        if (autoImportedTypes.contains(qualifiedName)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    private static Set<CodeImport> generateImports(Map<String, String> symbols) {
+        TreeSet<CodeImport> importObjects = new TreeSet<>();
+        for (String symbol : symbols.keySet()) {
+            String packageName = symbols.get(symbol);
+            if (packageName != null) {
+                importObjects.add(new CodeImport(packageName, symbol, false));
+            }
+        }
+        return importObjects;
+    }
+
+    private static void collectInnerTypeImports(TypeElement e, Set<String> autoImportedTypes) {
+        autoImportedTypes.add(getQualifiedName(e));
+        for (TypeElement innerClass : ElementFilter.typesIn(e.getEnclosedElements())) {
+            collectInnerTypeImports(innerClass, autoImportedTypes);
+        }
+    }
+
+    private static void collectSuperTypeImports(TypeElement e, Set<String> autoImportedTypes) {
+        List<TypeElement> superTypes = getSuperTypes(e);
+        for (TypeElement superType : superTypes) {
+            List<TypeElement> declaredTypes = getDeclaredTypes(superType);
+            for (TypeElement declaredType : declaredTypes) {
+                autoImportedTypes.add(getQualifiedName(declaredType));
+            }
+        }
+    }
+
+    private Set<CodeImport> generateStaticImports(Map<String, String> toGenerate) {
+        Set<String> autoImportedStaticTypes = new HashSet<>();
+
+        // if type is declared inside a super type of this class -> no import
+        autoImportedStaticTypes.add(getQualifiedName(topLevelClass));
+        autoImportedStaticTypes.addAll(getQualifiedSuperTypeNames(topLevelClass));
+
+        TreeSet<CodeImport> importObjects = new TreeSet<>();
+        for (String symbol : toGenerate.keySet()) {
+            String qualifiedName = toGenerate.get(symbol);
+            if (qualifiedName == null) {
+                // ambiguous
+                continue;
+            }
+            // not not import
+            if (autoImportedStaticTypes.contains(qualifiedName)) {
+                continue;
+            }
+
+            importObjects.add(new CodeImport(qualifiedName, symbol, true));
+        }
+
+        return importObjects;
+    }
+
+    private abstract static class TypeReferenceVisitor extends CodeElementScanner<Void, Void> {
+
+        @Override
+        public void visitTree(CodeTree e, Void p, Element enclosing) {
+            if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) {
+                visitStaticFieldReference(enclosing, e.getType(), e.getString());
+            } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) {
+                visitStaticMethodReference(enclosing, e.getType(), e.getString());
+            } else if (e.getType() != null) {
+                visitTypeReference(enclosing, e.getType());
+            }
+            super.visitTree(e, p, enclosing);
+        }
+
+        @Override
+        public Void visitExecutable(CodeExecutableElement e, Void p) {
+            visitAnnotations(e, e.getAnnotationMirrors());
+            if (e.getReturnType() != null) {
+                visitTypeReference(e, e.getReturnType());
+            }
+            for (TypeMirror type : e.getThrownTypes()) {
+                visitTypeReference(e, type);
+            }
+            return super.visitExecutable(e, p);
+        }
+
+        @Override
+        public Void visitType(CodeTypeElement e, Void p) {
+            visitAnnotations(e, e.getAnnotationMirrors());
+
+            visitTypeReference(e, e.getSuperclass());
+            for (TypeMirror type : e.getImplements()) {
+                visitTypeReference(e, type);
+            }
+
+            return super.visitType(e, p);
+        }
+
+        private void visitAnnotations(Element enclosingElement, List<? extends AnnotationMirror> mirrors) {
+            for (AnnotationMirror mirror : mirrors) {
+                visitAnnotation(enclosingElement, mirror);
+            }
+        }
+
+        public void visitAnnotation(Element enclosingElement, AnnotationMirror e) {
+            visitTypeReference(enclosingElement, e.getAnnotationType());
+            if (!e.getElementValues().isEmpty()) {
+                Map<? extends ExecutableElement, ? extends AnnotationValue> values = e.getElementValues();
+                Set<? extends ExecutableElement> methodsSet = values.keySet();
+                List<ExecutableElement> methodsList = new ArrayList<>();
+                for (ExecutableElement method : methodsSet) {
+                    if (values.get(method) == null) {
+                        continue;
+                    }
+                    methodsList.add(method);
+                }
+
+                for (int i = 0; i < methodsList.size(); i++) {
+                    AnnotationValue value = values.get(methodsList.get(i));
+                    visitAnnotationValue(enclosingElement, value);
+                }
+            }
+        }
+
+        public void visitAnnotationValue(Element enclosingElement, AnnotationValue e) {
+            e.accept(new AnnotationValueReferenceVisitor(enclosingElement), null);
+        }
+
+        private class AnnotationValueReferenceVisitor extends AbstractAnnotationValueVisitor7<Void, Void> {
+
+            private final Element enclosingElement;
+
+            public AnnotationValueReferenceVisitor(Element enclosedElement) {
+                this.enclosingElement = enclosedElement;
+            }
+
+            @Override
+            public Void visitBoolean(boolean b, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitByte(byte b, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitChar(char c, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitDouble(double d, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitFloat(float f, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitInt(int i, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitLong(long i, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitShort(short s, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitString(String s, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitType(TypeMirror t, Void p) {
+                visitTypeReference(enclosingElement, t);
+                return null;
+            }
+
+            @Override
+            public Void visitEnumConstant(VariableElement c, Void p) {
+                visitTypeReference(enclosingElement, c.asType());
+                return null;
+            }
+
+            @Override
+            public Void visitAnnotation(AnnotationMirror a, Void p) {
+                TypeReferenceVisitor.this.visitAnnotation(enclosingElement, a);
+                return null;
+            }
+
+            @Override
+            public Void visitArray(List<? extends AnnotationValue> vals, Void p) {
+                for (int i = 0; i < vals.size(); i++) {
+                    TypeReferenceVisitor.this.visitAnnotationValue(enclosingElement, vals.get(i));
+                }
+                return null;
+            }
+        }
+
+        @Override
+        public Void visitVariable(VariableElement f, Void p) {
+            visitAnnotations(f, f.getAnnotationMirrors());
+            visitTypeReference(f, f.asType());
+            return super.visitVariable(f, p);
+        }
+
+        @Override
+        public void visitImport(CodeImport e, Void p) {
+        }
+
+        public abstract void visitTypeReference(Element enclosedType, TypeMirror type);
+
+        public abstract void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName);
+
+        public abstract void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName);
+
+    }
+
+    private class ImportTypeReferenceVisitor extends TypeReferenceVisitor {
+
+        @Override
+        public void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName) {
+            registerSymbol(staticImportUsage, ElementUtils.getQualifiedName(type), elementName);
+        }
+
+        @Override
+        public void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName) {
+            registerSymbol(staticImportUsage, ElementUtils.getQualifiedName(type), elementName);
+        }
+
+        @Override
+        public void visitTypeReference(Element enclosedType, TypeMirror type) {
+            if (type != null) {
+                switch (type.getKind()) {
+                    case BOOLEAN:
+                    case BYTE:
+                    case CHAR:
+                    case DOUBLE:
+                    case FLOAT:
+                    case SHORT:
+                    case INT:
+                    case LONG:
+                    case VOID:
+                        return;
+                    case DECLARED:
+                        if (needsImport(enclosedType, type)) {
+                            DeclaredType declard = (DeclaredType) type;
+                            registerSymbol(classImportUsage, ElementUtils.getEnclosedQualifiedName(declard), ElementUtils.getDeclaredName(declard, false));
+                        }
+                        for (TypeMirror argument : ((DeclaredType) type).getTypeArguments()) {
+                            visitTypeReference(enclosedType, argument);
+                        }
+                        return;
+                    case ARRAY:
+                        visitTypeReference(enclosedType, ((ArrayType) type).getComponentType());
+                        return;
+                    case WILDCARD:
+                        WildcardType wildcard = (WildcardType) type;
+                        if (wildcard.getExtendsBound() != null) {
+                            visitTypeReference(enclosedType, wildcard.getExtendsBound());
+                        } else if (wildcard.getSuperBound() != null) {
+                            visitTypeReference(enclosedType, wildcard.getSuperBound());
+                        }
+                        return;
+                    case TYPEVAR:
+                        return;
+                    default:
+                        throw new RuntimeException("Unknown type specified " + type.getKind() + " mirror: " + type);
+                }
+
+            }
+        }
+
+        private void registerSymbol(Map<String, String> symbolUsage, String elementQualifiedName, String elementName) {
+            if (symbolUsage.containsKey(elementName)) {
+                String otherQualifiedName = symbolUsage.get(elementName);
+                if (otherQualifiedName == null) {
+                    // already registered ambiguous
+                    return;
+                }
+                if (!otherQualifiedName.equals(elementQualifiedName)) {
+                    symbolUsage.put(elementName, null);
+                }
+            } else {
+                symbolUsage.put(elementName, elementQualifiedName);
+            }
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/CreateCastData.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+public class CreateCastData extends TemplateMethod {
+
+    private final List<String> childNames;
+
+    public CreateCastData(TemplateMethod method, List<String> childNames) {
+        super(method);
+        this.childNames = childNames;
+    }
+
+    public List<String> getChildNames() {
+        return childNames;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class ExecutableTypeData extends TemplateMethod {
+
+    private final TypeSystemData typeSystem;
+    private final TypeData type;
+
+    public ExecutableTypeData(TemplateMethod method, ExecutableElement executable, TypeSystemData typeSystem, TypeData type) {
+        super(method, executable);
+        this.typeSystem = typeSystem;
+        this.type = type;
+        if (executable.getParameters().size() < method.getMethod().getParameters().size()) {
+            throw new IllegalArgumentException(String.format("Method parameter count mismatch %s != %s.", executable.getParameters(), method.getMethod().getParameters()));
+        }
+    }
+
+    public TypeData getType() {
+        return type;
+    }
+
+    public TypeSystemData getTypeSystem() {
+        return typeSystem;
+    }
+
+    public boolean hasUnexpectedValue(ProcessorContext context) {
+        return ElementUtils.canThrowType(getMethod().getThrownTypes(), context.getTruffleTypes().getUnexpectedValueException());
+    }
+
+    public boolean isFinal() {
+        return getMethod().getModifiers().contains(Modifier.FINAL);
+    }
+
+    public boolean isAbstract() {
+        return getMethod().getModifiers().contains(Modifier.ABSTRACT);
+    }
+
+    public int getEvaluatedCount() {
+        int count = 0;
+        for (Parameter parameter : getParameters()) {
+            if (parameter.getSpecification().isSignature()) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    @Override
+    public int hashCode() {
+        return type.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof ExecutableTypeData) {
+            return type.equals(((ExecutableTypeData) obj).type);
+        }
+        return super.equals(obj);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardData.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+public class GuardData extends TemplateMethod {
+
+    private List<GuardExpression> impliesExpressions;
+
+    public GuardData(TemplateMethod method, List<GuardExpression> impliesExpressions) {
+        super(method);
+        this.impliesExpressions = impliesExpressions;
+    }
+
+    public List<GuardExpression> getImpliesExpressions() {
+        return impliesExpressions;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof GuardData) {
+            GuardData other = (GuardData) obj;
+            return getMethod().equals(other.getMethod());
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return getMethod().hashCode();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+public final class GuardExpression {
+
+    private GuardData resolvedGuard;
+    private NodeExecutionData[] resolvedChildren;
+
+    private final String guardName;
+    private final boolean negated;
+    private final String[] childNames;
+
+    public GuardExpression(String expression, boolean allowArguments) {
+        String exp = expression;
+        if (exp.startsWith("!")) {
+            exp = exp.substring(1, exp.length());
+            negated = true;
+        } else {
+            negated = false;
+        }
+
+        int argumentStart = exp.indexOf('(');
+        int endIndex = exp.lastIndexOf(')');
+        if (allowArguments && argumentStart != -1 && endIndex != -1) {
+            guardName = exp.substring(0, argumentStart).trim();
+            String arguments = exp.substring(argumentStart + 1, endIndex);
+            String[] children = arguments.split(",");
+            for (int i = 0; i < children.length; i++) {
+                children[i] = children[i].trim();
+            }
+            if (children.length == 1 && children[0].isEmpty()) {
+                childNames = new String[0];
+            } else {
+                childNames = children;
+            }
+        } else {
+            guardName = exp;
+            childNames = null;
+        }
+    }
+
+    public String[] getChildNames() {
+        return childNames;
+    }
+
+    public boolean isResolved() {
+        return resolvedGuard != null;
+    }
+
+    public String getGuardName() {
+        return guardName;
+    }
+
+    public NodeExecutionData[] getResolvedChildren() {
+        return resolvedChildren;
+    }
+
+    public void setResolvedChildren(NodeExecutionData[] resolvedChildren) {
+        this.resolvedChildren = resolvedChildren;
+    }
+
+    public void setResolvedGuard(GuardData guard) {
+        this.resolvedGuard = guard;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        } else if (obj instanceof GuardExpression) {
+            GuardExpression other = (GuardExpression) obj;
+            if (isResolved() && other.isResolved()) {
+                return resolvedGuard.equals(other.resolvedGuard) && negated == other.negated && Arrays.equals(resolvedChildren, other.resolvedChildren);
+            } else {
+                boolean equal = guardName.equals(other.guardName) && negated == other.negated;
+                if (childNames != null && other.childNames != null) {
+                    equal &= Arrays.equals(childNames, other.childNames);
+                }
+                return equal;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(guardName, negated, resolvedGuard, resolvedChildren);
+    }
+
+    public final boolean implies(GuardExpression other) {
+        if (equals(other)) {
+            return true;
+        }
+
+        if (isResolved() && other.isResolved()) {
+            for (GuardExpression implies : getResolvedGuard().getImpliesExpressions()) {
+                if (implies.getGuardName().equals(other.getGuardName())) {
+                    if (implies.isNegated() == other.isNegated()) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return (negated ? "!" : "") + guardName;
+    }
+
+    public boolean isNegated() {
+        return negated;
+    }
+
+    public GuardData getResolvedGuard() {
+        return resolvedGuard;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ImplicitCastData.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+public class ImplicitCastData extends TemplateMethod {
+
+    private final TypeData sourceType;
+    private final TypeData targetType;
+
+    public ImplicitCastData(TemplateMethod method, TypeData sourceType, TypeData targetType) {
+        super(method);
+        this.sourceType = sourceType;
+        this.targetType = targetType;
+    }
+
+    public TypeData getSourceType() {
+        return sourceType;
+    }
+
+    public TypeData getTargetType() {
+        return targetType;
+    }
+
+    @Override
+    public int compareTo(TemplateMethod o) {
+        if (o instanceof ImplicitCastData && sourceType != null) {
+            // implicit casts are ordered by source type since
+            // its also the order in which they are checked.
+            TypeData otherSourceType = ((ImplicitCastData) o).getSourceType();
+            if (otherSourceType != null) {
+                return this.sourceType.compareTo(otherSourceType);
+            }
+        }
+        return super.compareTo(o);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MessageContainer.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,274 @@
+/*
+ * 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.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.tools.Diagnostic.Kind;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+
+public abstract class MessageContainer implements Iterable<MessageContainer> {
+
+    private final List<Message> messages = new ArrayList<>();
+
+    public final void addWarning(String text, Object... params) {
+        getMessages().add(new Message(null, null, this, String.format(text, params), Kind.WARNING));
+    }
+
+    public final void addWarning(AnnotationValue value, String text, Object... params) {
+        getMessages().add(new Message(null, value, this, String.format(text, params), Kind.WARNING));
+    }
+
+    public final void addError(String text, Object... params) {
+        addError(null, text, params);
+    }
+
+    public final void addError(AnnotationValue value, String text, Object... params) {
+        getMessages().add(new Message(null, value, this, String.format(text, params), Kind.ERROR));
+    }
+
+    public final void addError(AnnotationMirror mirror, AnnotationValue value, String text, Object... params) {
+        getMessages().add(new Message(mirror, value, this, String.format(text, params), Kind.ERROR));
+    }
+
+    protected List<MessageContainer> findChildContainers() {
+        return Collections.emptyList();
+    }
+
+    public abstract Element getMessageElement();
+
+    public MessageContainer getBaseContainer() {
+        return null;
+    }
+
+    public Iterator<MessageContainer> iterator() {
+        return findChildContainers().iterator();
+    }
+
+    public final void emitMessages(ProcessorContext context, Log log) {
+        emitMessagesImpl(context, log, new HashSet<MessageContainer>(), null);
+    }
+
+    private void emitMessagesImpl(ProcessorContext context, Log log, Set<MessageContainer> visitedSinks, List<Message> verifiedMessages) {
+        List<Message> childMessages;
+        if (verifiedMessages == null) {
+            childMessages = collectMessagesWithElementChildren(new HashSet<MessageContainer>(), getMessageElement());
+        } else {
+            childMessages = verifiedMessages;
+        }
+        verifyExpectedMessages(context, log, childMessages);
+
+        for (int i = getMessages().size() - 1; i >= 0; i--) {
+            emitDefault(context, log, getMessages().get(i));
+        }
+
+        for (MessageContainer sink : findChildContainers()) {
+            if (visitedSinks.contains(sink)) {
+                continue;
+            }
+
+            visitedSinks.add(sink);
+            if (sink.getMessageElement() == this.getMessageElement()) {
+                sink.emitMessagesImpl(context, log, visitedSinks, childMessages);
+            } else {
+                sink.emitMessagesImpl(context, log, visitedSinks, null);
+            }
+        }
+    }
+
+    private List<Message> collectMessagesWithElementChildren(Set<MessageContainer> visitedSinks, Element e) {
+        if (visitedSinks.contains(this)) {
+            return Collections.emptyList();
+        }
+        visitedSinks.add(this);
+
+        List<Message> foundMessages = new ArrayList<>();
+        if (ElementUtils.typeEquals(getMessageElement().asType(), e.asType())) {
+            foundMessages.addAll(getMessages());
+        }
+        for (MessageContainer sink : findChildContainers()) {
+            foundMessages.addAll(sink.collectMessagesWithElementChildren(visitedSinks, e));
+        }
+        return foundMessages;
+    }
+
+    private void verifyExpectedMessages(ProcessorContext context, Log log, List<Message> msgs) {
+        TypeElement expectError = context.getTruffleTypes().getExpectError();
+        if (expectError != null) {
+            Element element = getMessageElement();
+            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(element.getAnnotationMirrors(), expectError);
+            if (mirror != null) {
+                List<String> values = ElementUtils.getAnnotationValueList(String.class, mirror, "value");
+                if (values == null) {
+                    values = Collections.emptyList();
+                }
+                if (values.size() != msgs.size()) {
+                    log.message(Kind.ERROR, element, mirror, ElementUtils.getAnnotationValue(mirror, "value"), String.format("Error count expected %s but was %s.", values.size(), msgs.size()));
+                }
+            }
+        }
+    }
+
+    private void emitDefault(ProcessorContext context, Log log, Message message) {
+        Kind kind = message.getKind();
+
+        Element messageElement = getMessageElement();
+        AnnotationMirror messageAnnotation = getMessageAnnotation();
+        AnnotationValue messageValue = getMessageAnnotationValue();
+        if (message.getAnnotationValue() != null) {
+            messageValue = message.getAnnotationValue();
+        }
+        if (message.getAnnotationMirror() != null) {
+            messageAnnotation = message.getAnnotationMirror();
+        }
+
+        String text = message.getText();
+
+        TypeElement expectError = context.getTruffleTypes().getExpectError();
+        if (expectError != null) {
+            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(messageElement.getAnnotationMirrors(), expectError);
+            if (mirror != null) {
+                List<String> expectedTexts = ElementUtils.getAnnotationValueList(String.class, mirror, "value");
+                boolean found = false;
+                for (String expectedText : expectedTexts) {
+                    if (expectedText.endsWith("%") && text.startsWith(expectedText.substring(0, expectedText.length() - 1))) {
+                        found = true;
+                        break;
+                    } else if (text.equals(expectedText)) {
+                        found = true;
+                        break;
+                    }
+                }
+                if (!found) {
+                    log.message(kind, messageElement, mirror, ElementUtils.getAnnotationValue(mirror, "value"), "Message expected one of '%s' but was '%s'.", expectedTexts, text);
+                } else {
+                    return;
+                }
+
+            }
+        }
+
+        log.message(kind, messageElement, messageAnnotation, messageValue, text);
+    }
+
+    public AnnotationMirror getMessageAnnotation() {
+        return null;
+    }
+
+    public AnnotationValue getMessageAnnotationValue() {
+        return null;
+    }
+
+    public final boolean hasErrors() {
+        return hasErrorsImpl(new HashSet<MessageContainer>());
+    }
+
+    public final List<Message> collectMessages() {
+        List<Message> collectedMessages = new ArrayList<>();
+        collectMessagesImpl(collectedMessages, new HashSet<MessageContainer>());
+        return collectedMessages;
+    }
+
+    private void collectMessagesImpl(List<Message> collectedMessages, Set<MessageContainer> visitedSinks) {
+        collectedMessages.addAll(getMessages());
+        for (MessageContainer sink : findChildContainers()) {
+            if (visitedSinks.contains(sink)) {
+                return;
+            }
+
+            visitedSinks.add(sink);
+            sink.collectMessagesImpl(collectedMessages, visitedSinks);
+        }
+    }
+
+    private boolean hasErrorsImpl(Set<MessageContainer> visitedSinks) {
+        for (Message msg : getMessages()) {
+            if (msg.getKind() == Kind.ERROR) {
+                return true;
+            }
+        }
+        for (MessageContainer sink : findChildContainers()) {
+            if (visitedSinks.contains(sink)) {
+                return false;
+            }
+
+            visitedSinks.add(sink);
+
+            if (sink.hasErrorsImpl(visitedSinks)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public List<Message> getMessages() {
+        return messages;
+    }
+
+    public static final class Message {
+
+        private final MessageContainer originalContainer;
+        private final AnnotationMirror annotationMirror;
+        private final AnnotationValue annotationValue;
+        private final String text;
+        private final Kind kind;
+
+        public Message(AnnotationMirror annotationMirror, AnnotationValue annotationValue, MessageContainer originalContainer, String text, Kind kind) {
+            this.annotationMirror = annotationMirror;
+            this.annotationValue = annotationValue;
+            this.originalContainer = originalContainer;
+            this.text = text;
+            this.kind = kind;
+        }
+
+        public AnnotationMirror getAnnotationMirror() {
+            return annotationMirror;
+        }
+
+        public AnnotationValue getAnnotationValue() {
+            return annotationValue;
+        }
+
+        public MessageContainer getOriginalContainer() {
+            return originalContainer;
+        }
+
+        public String getText() {
+            return text;
+        }
+
+        public Kind getKind() {
+            return kind;
+        }
+
+        @Override
+        public String toString() {
+            return kind + ": " + text;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MethodSpec.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,239 @@
+/*
+ * 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.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class MethodSpec {
+
+    private final ParameterSpec returnType;
+    private final List<ParameterSpec> optional = new ArrayList<>();
+    private final List<ParameterSpec> required = new ArrayList<>();
+
+    private boolean ignoreAdditionalParameters;
+    private boolean ignoreAdditionalSpecifications;
+    private boolean variableRequiredParameters;
+
+    private List<TypeDef> typeDefinitions;
+
+    public MethodSpec(ParameterSpec returnType) {
+        this.returnType = returnType;
+    }
+
+    public void setVariableRequiredParameters(boolean variableRequiredParameters) {
+        this.variableRequiredParameters = variableRequiredParameters;
+    }
+
+    public boolean isVariableRequiredParameters() {
+        return variableRequiredParameters;
+    }
+
+    public void setIgnoreAdditionalParameters(boolean ignoreAdditionalParameter) {
+        this.ignoreAdditionalParameters = ignoreAdditionalParameter;
+    }
+
+    public boolean isIgnoreAdditionalParameters() {
+        return ignoreAdditionalParameters;
+    }
+
+    public void addOptional(ParameterSpec spec) {
+        optional.add(spec);
+    }
+
+    public ParameterSpec addRequired(ParameterSpec spec) {
+        required.add(spec);
+        return spec;
+    }
+
+    public ParameterSpec getReturnType() {
+        return returnType;
+    }
+
+    public List<ParameterSpec> getRequired() {
+        return required;
+    }
+
+    public List<ParameterSpec> getOptional() {
+        return optional;
+    }
+
+    public List<ParameterSpec> getAll() {
+        List<ParameterSpec> specs = new ArrayList<>();
+        specs.add(getReturnType());
+        specs.addAll(getOptional());
+        specs.addAll(getRequired());
+        return specs;
+    }
+
+    public ParameterSpec findParameterSpec(String name) {
+        for (ParameterSpec spec : getAll()) {
+            if (spec.getName().equals(name)) {
+                return spec;
+            }
+        }
+        return null;
+    }
+
+    public void applyTypeDefinitions(String prefix) {
+        this.typeDefinitions = createTypeDefinitions(prefix);
+    }
+
+    private List<TypeDef> createTypeDefinitions(String prefix) {
+        List<TypeDef> typeDefs = new ArrayList<>();
+
+        int defIndex = 0;
+        for (ParameterSpec spec : getAll()) {
+            List<TypeMirror> allowedTypes = spec.getAllowedTypes();
+            List<TypeMirror> types = spec.getAllowedTypes();
+            if (types != null && allowedTypes.size() > 1) {
+                TypeDef foundDef = null;
+                for (TypeDef def : typeDefs) {
+                    if (allowedTypes.equals(def.getTypes())) {
+                        foundDef = def;
+                        break;
+                    }
+                }
+                if (foundDef == null) {
+                    foundDef = new TypeDef(types, prefix + defIndex);
+                    typeDefs.add(foundDef);
+                    defIndex++;
+                }
+
+                spec.setTypeDefinition(foundDef);
+            }
+        }
+
+        return typeDefs;
+    }
+
+    public String toSignatureString(String methodName) {
+        StringBuilder b = new StringBuilder();
+        b.append("    ");
+        b.append(createTypeSignature(returnType, true));
+
+        b.append(" ");
+        b.append(methodName);
+        b.append("(");
+
+        String sep = "";
+
+        for (ParameterSpec optionalSpec : getOptional()) {
+            b.append(sep);
+            b.append("[");
+            b.append(createTypeSignature(optionalSpec, false));
+            b.append("]");
+            sep = ", ";
+        }
+
+        for (int i = 0; i < getRequired().size(); i++) {
+            ParameterSpec requiredSpec = getRequired().get(i);
+            b.append(sep);
+
+            if (isVariableRequiredParameters() && i == getRequired().size() - 1) {
+                b.append(("{"));
+            }
+            b.append(createTypeSignature(requiredSpec, false));
+            if (isVariableRequiredParameters() && i == getRequired().size() - 1) {
+                b.append(("}"));
+            }
+
+            sep = ", ";
+        }
+
+        b.append(")");
+
+        if (typeDefinitions != null && !typeDefinitions.isEmpty()) {
+            b.append("\n\n");
+
+            String lineSep = "";
+            for (TypeDef def : typeDefinitions) {
+                b.append(lineSep);
+                b.append("    <").append(def.getName()).append(">");
+                b.append(" = {");
+                String separator = "";
+                for (TypeMirror type : def.getTypes()) {
+                    b.append(separator).append(ElementUtils.getSimpleName(type));
+                    separator = ", ";
+                }
+                b.append("}");
+                lineSep = "\n";
+
+            }
+        }
+        return b.toString();
+    }
+
+    private static String createTypeSignature(ParameterSpec spec, boolean typeOnly) {
+        StringBuilder builder = new StringBuilder();
+        TypeDef foundTypeDef = spec.getTypeDefinition();
+        if (foundTypeDef != null) {
+            builder.append("<" + foundTypeDef.getName() + ">");
+        } else if (spec.getAllowedTypes().size() >= 1) {
+            builder.append(ElementUtils.getSimpleName(spec.getAllowedTypes().get(0)));
+        } else {
+            builder.append("void");
+        }
+        if (!typeOnly) {
+            builder.append(" ");
+            builder.append(spec.getName());
+        }
+        return builder.toString();
+    }
+
+    @Override
+    public String toString() {
+        return toSignatureString("methodName");
+    }
+
+    static class TypeDef {
+
+        private final List<TypeMirror> types;
+        private final String name;
+
+        private TypeDef(List<TypeMirror> types, String name) {
+            this.types = types;
+            this.name = name;
+        }
+
+        public List<TypeMirror> getTypes() {
+            return types;
+        }
+
+        public String getName() {
+            return name;
+        }
+    }
+
+    public void setIgnoreAdditionalSpecifications(boolean ignoreAdditoinalSpecifications) {
+        this.ignoreAdditionalSpecifications = ignoreAdditoinalSpecifications;
+    }
+
+    public boolean isIgnoreAdditionalSpecifications() {
+        return ignoreAdditionalSpecifications;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeChildData.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,139 @@
+/*
+ * 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.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.*;
+
+public class NodeChildData extends MessageContainer {
+
+    public enum Cardinality {
+        ONE,
+        MANY;
+
+        public boolean isMany() {
+            return this == MANY;
+        }
+
+        public boolean isOne() {
+            return this == ONE;
+        }
+    }
+
+    private final Element sourceElement;
+    private final AnnotationMirror sourceAnnotationMirror;
+    private final String name;
+    private final TypeMirror type;
+    private final TypeMirror originalType;
+    private final Element accessElement;
+    private final Cardinality cardinality;
+
+    private List<NodeChildData> executeWith = Collections.emptyList();
+
+    private NodeData childNode;
+
+    public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, TypeMirror originalNodeType, Element accessElement, Cardinality cardinality) {
+        this.sourceElement = sourceElement;
+        this.sourceAnnotationMirror = sourceMirror;
+        this.name = name;
+        this.type = nodeType;
+        this.originalType = originalNodeType;
+        this.accessElement = accessElement;
+        this.cardinality = cardinality;
+    }
+
+    public List<NodeChildData> getExecuteWith() {
+        return executeWith;
+    }
+
+    public void setExecuteWith(List<NodeChildData> executeWith) {
+        this.executeWith = executeWith;
+    }
+
+    public ExecutableTypeData findExecutableType(ProcessorContext context, TypeData targetType) {
+        ExecutableTypeData executableType = childNode.findExecutableType(targetType, getExecuteWith().size());
+        if (executableType == null) {
+            executableType = findAnyGenericExecutableType(context);
+        }
+        return executableType;
+    }
+
+    public List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context) {
+        return childNode.findGenericExecutableTypes(context, getExecuteWith().size());
+    }
+
+    public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context) {
+        return childNode.findAnyGenericExecutableType(context, getExecuteWith().size());
+    }
+
+    public TypeMirror getOriginalType() {
+        return originalType;
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return sourceElement;
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return sourceAnnotationMirror;
+    }
+
+    public void setNode(NodeData nodeData) {
+        this.childNode = nodeData;
+        if (nodeData != null) {
+            getMessages().addAll(nodeData.collectMessages());
+        }
+    }
+
+    public Element getAccessElement() {
+        return accessElement;
+    }
+
+    public TypeMirror getNodeType() {
+        return type;
+    }
+
+    public Cardinality getCardinality() {
+        return cardinality;
+    }
+
+    public NodeData getNodeData() {
+        return childNode;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String toString() {
+        return "NodeFieldData[name=" + getName() + ", kind=" + cardinality + ", node=" + getNodeData() + "]";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,489 @@
+/*
+ * 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.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality;
+
+public class NodeData extends Template implements Comparable<NodeData> {
+
+    private final String nodeId;
+    private final String shortName;
+    private final List<NodeData> enclosingNodes = new ArrayList<>();
+    private NodeData declaringNode;
+
+    private final TypeSystemData typeSystem;
+    private final List<NodeChildData> children;
+    private final List<NodeExecutionData> childExecutions;
+    private final List<NodeFieldData> fields;
+    private final List<String> assumptions;
+
+    private ParameterSpec instanceParameterSpec;
+
+    private final List<SpecializationData> specializations = new ArrayList<>();
+    private final List<ShortCircuitData> shortCircuits = new ArrayList<>();
+    private final List<CreateCastData> casts = new ArrayList<>();
+    private Map<Integer, List<ExecutableTypeData>> executableTypes;
+
+    private final NodeExecutionData thisExecution;
+
+    public NodeData(ProcessorContext context, TypeElement type, String shortName, TypeSystemData typeSystem, List<NodeChildData> children, List<NodeExecutionData> executions,
+                    List<NodeFieldData> fields, List<String> assumptions) {
+        super(context, type, null, null);
+        this.nodeId = type.getSimpleName().toString();
+        this.shortName = shortName;
+        this.typeSystem = typeSystem;
+        this.fields = fields;
+        this.children = children;
+        this.childExecutions = executions;
+        this.assumptions = assumptions;
+        this.thisExecution = new NodeExecutionData(new NodeChildData(null, null, "this", getNodeType(), getNodeType(), null, Cardinality.ONE), -1, false);
+        this.thisExecution.getChild().setNode(this);
+    }
+
+    public NodeData(ProcessorContext context, TypeElement type) {
+        this(context, type, null, null, null, null, null, null);
+    }
+
+    public NodeExecutionData getThisExecution() {
+        return thisExecution;
+    }
+
+    public boolean isFallbackReachable() {
+        SpecializationData generic = getGenericSpecialization();
+        if (generic != null) {
+            return generic.isReachable();
+        }
+        return false;
+    }
+
+    public void addEnclosedNode(NodeData node) {
+        this.enclosingNodes.add(node);
+        node.declaringNode = this;
+    }
+
+    public List<NodeExecutionData> getChildExecutions() {
+        return childExecutions;
+    }
+
+    public int getSignatureSize() {
+        if (getSpecializations() != null && !getSpecializations().isEmpty()) {
+            return getSpecializations().get(0).getSignatureSize();
+        }
+        return 0;
+    }
+
+    public boolean needsFrame(ProcessorContext context) {
+        for (SpecializationData specialization : specializations) {
+            if (!specialization.isReachable()) {
+                continue;
+            }
+            if (specialization.hasFrame(context)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean isPolymorphic(ProcessorContext context) {
+        return needsRewrites(context);
+    }
+
+    public List<CreateCastData> getCasts() {
+        return casts;
+    }
+
+    public String getShortName() {
+        return shortName;
+    }
+
+    public List<NodeFieldData> getFields() {
+        return fields;
+    }
+
+    @Override
+    protected List<MessageContainer> findChildContainers() {
+        List<MessageContainer> containerChildren = new ArrayList<>();
+        if (enclosingNodes != null) {
+            containerChildren.addAll(enclosingNodes);
+        }
+        if (typeSystem != null) {
+            containerChildren.add(typeSystem);
+        }
+        if (specializations != null) {
+            for (MessageContainer specialization : specializations) {
+                if (specialization.getMessageElement() != null) {
+                    containerChildren.add(specialization);
+                }
+            }
+        }
+        if (executableTypes != null) {
+            containerChildren.addAll(getExecutableTypes());
+        }
+        if (shortCircuits != null) {
+            containerChildren.addAll(shortCircuits);
+        }
+        if (children != null) {
+            containerChildren.addAll(children);
+        }
+        if (fields != null) {
+            containerChildren.addAll(fields);
+        }
+        if (casts != null) {
+            containerChildren.addAll(casts);
+        }
+        return containerChildren;
+    }
+
+    public ParameterSpec getInstanceParameterSpec() {
+        return instanceParameterSpec;
+    }
+
+    public void setInstanceParameterSpec(ParameterSpec instanceParameter) {
+        this.instanceParameterSpec = instanceParameter;
+    }
+
+    public String getNodeId() {
+        return nodeId;
+    }
+
+    public TypeMirror getNodeType() {
+        return getTemplateType().asType();
+    }
+
+    public List<String> getAssumptions() {
+        return assumptions;
+    }
+
+    public boolean needsFactory() {
+        if (specializations == null) {
+            return false;
+        }
+        if (getTemplateType().getModifiers().contains(Modifier.PRIVATE)) {
+            return false;
+        }
+
+        boolean noSpecialization = true;
+        for (SpecializationData specialization : specializations) {
+            noSpecialization = noSpecialization && !specialization.isSpecialized();
+        }
+        return !noSpecialization;
+    }
+
+    public boolean supportsFrame() {
+        if (executableTypes != null) {
+            for (ExecutableTypeData execType : getExecutableTypes(-1)) {
+                if (execType.findParameter("frameValue") == null) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    public NodeExecutionData findExecutionByExpression(String childNameExpression) {
+        String childName = childNameExpression;
+        int index = -1;
+
+        int start = childName.indexOf('[');
+        int end = childName.lastIndexOf(']');
+        if (start != -1 && end != -1 && start < end) {
+            try {
+                index = Integer.parseInt(childName.substring(start + 1, end));
+                childName = childName.substring(0, start);
+                childName = NodeExecutionData.createName(childName, index);
+            } catch (NumberFormatException e) {
+                // ignore
+            }
+        }
+
+        for (NodeExecutionData execution : childExecutions) {
+            if (execution.getName().equals(childName) && (execution.getIndex() == -1 || execution.getIndex() == index)) {
+                return execution;
+            }
+        }
+        return null;
+    }
+
+    public List<NodeData> getNodeDeclaringChildren() {
+        List<NodeData> nodeChildren = new ArrayList<>();
+        for (NodeData child : getEnclosingNodes()) {
+            if (child.needsFactory()) {
+                nodeChildren.add(child);
+            }
+            nodeChildren.addAll(child.getNodeDeclaringChildren());
+        }
+        return nodeChildren;
+    }
+
+    public NodeData getDeclaringNode() {
+        return declaringNode;
+    }
+
+    public List<NodeData> getEnclosingNodes() {
+        return enclosingNodes;
+    }
+
+    public List<TemplateMethod> getAllTemplateMethods() {
+        List<TemplateMethod> methods = new ArrayList<>();
+
+        for (SpecializationData specialization : getSpecializations()) {
+            methods.add(specialization);
+        }
+
+        methods.addAll(getExecutableTypes());
+        methods.addAll(getShortCircuits());
+        if (getCasts() != null) {
+            methods.addAll(getCasts());
+        }
+
+        return methods;
+    }
+
+    public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context, int evaluatedCount) {
+        List<ExecutableTypeData> types = findGenericExecutableTypes(context, evaluatedCount);
+        for (ExecutableTypeData type : types) {
+            if (type.getType().isGeneric()) {
+                return type;
+            }
+        }
+
+        for (ExecutableTypeData type : types) {
+            if (!type.getType().isVoid()) {
+                return type;
+            }
+        }
+
+        for (ExecutableTypeData type : types) {
+            return type;
+        }
+        return null;
+    }
+
+    public List<ExecutableTypeData> getExecutableTypes(int evaluatedCount) {
+        if (executableTypes == null) {
+            return Collections.emptyList();
+        }
+        if (evaluatedCount == -1) {
+            List<ExecutableTypeData> typeData = new ArrayList<>();
+            for (int currentEvaluationCount : executableTypes.keySet()) {
+                typeData.addAll(executableTypes.get(currentEvaluationCount));
+            }
+            return typeData;
+        } else {
+            List<ExecutableTypeData> types = executableTypes.get(evaluatedCount);
+            if (types == null) {
+                return Collections.emptyList();
+            }
+            return types;
+        }
+    }
+
+    public List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context, int evaluatedCount) {
+        List<ExecutableTypeData> types = new ArrayList<>();
+        for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) {
+            if (!type.hasUnexpectedValue(context)) {
+                types.add(type);
+            }
+        }
+        return types;
+    }
+
+    public ExecutableTypeData findExecutableType(TypeData prmitiveType, int evaluatedCount) {
+        for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) {
+            if (ElementUtils.typeEquals(type.getType().getPrimitiveType(), prmitiveType.getPrimitiveType())) {
+                return type;
+            }
+        }
+        return null;
+    }
+
+    public boolean needsRewrites(ProcessorContext context) {
+        boolean needsRewrites = false;
+
+        for (SpecializationData specialization : getSpecializations()) {
+            if (specialization.hasRewrite(context)) {
+                needsRewrites = true;
+                break;
+            }
+        }
+        return needsRewrites || getSpecializations().size() > 1;
+    }
+
+    public SpecializationData getPolymorphicSpecialization() {
+        for (SpecializationData specialization : specializations) {
+            if (specialization.isPolymorphic()) {
+                return specialization;
+            }
+        }
+        return null;
+    }
+
+    public SpecializationData getGenericSpecialization() {
+        for (SpecializationData specialization : specializations) {
+            if (specialization.isGeneric()) {
+                return specialization;
+            }
+        }
+        return null;
+    }
+
+    public SpecializationData getUninitializedSpecialization() {
+        for (SpecializationData specialization : specializations) {
+            if (specialization.isUninitialized()) {
+                return specialization;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public TypeSystemData getTypeSystem() {
+        return typeSystem;
+    }
+
+    public String dump() {
+        return dump(0);
+    }
+
+    private String dump(int level) {
+        String indent = "";
+        for (int i = 0; i < level; i++) {
+            indent += "    ";
+        }
+        StringBuilder builder = new StringBuilder();
+
+        builder.append(String.format("%s%s {", indent, toString()));
+
+        dumpProperty(builder, indent, "templateClass", ElementUtils.getQualifiedName(getTemplateType()));
+        dumpProperty(builder, indent, "typeSystem", getTypeSystem());
+        dumpProperty(builder, indent, "fields", getChildren());
+        dumpProperty(builder, indent, "executableTypes", getExecutableTypes());
+        dumpProperty(builder, indent, "specializations", getSpecializations());
+        dumpProperty(builder, indent, "assumptions", getAssumptions());
+        dumpProperty(builder, indent, "casts", getCasts());
+        dumpProperty(builder, indent, "messages", collectMessages());
+        if (getEnclosingNodes().size() > 0) {
+            builder.append(String.format("\n%s  children = [", indent));
+            for (NodeData node : getEnclosingNodes()) {
+                builder.append("\n");
+                builder.append(node.dump(level + 1));
+            }
+            builder.append(String.format("\n%s  ]", indent));
+        }
+        builder.append(String.format("%s}", indent));
+        return builder.toString();
+    }
+
+    private static void dumpProperty(StringBuilder b, String indent, String propertyName, Object value) {
+        if (value instanceof List) {
+            List<?> list = (List<?>) value;
+            if (!list.isEmpty()) {
+                b.append(String.format("\n%s  %s = %s", indent, propertyName, dumpList(indent, (List<?>) value)));
+            }
+        } else {
+            if (value != null) {
+                b.append(String.format("\n%s  %s = %s", indent, propertyName, value));
+            }
+        }
+    }
+
+    private static String dumpList(String indent, List<?> array) {
+        if (array == null) {
+            return "null";
+        }
+
+        if (array.isEmpty()) {
+            return "[]";
+        } else if (array.size() == 1) {
+            return "[" + array.get(0).toString() + "]";
+        }
+
+        StringBuilder b = new StringBuilder();
+        b.append("[");
+        for (Object object : array) {
+            b.append("\n        ");
+            b.append(indent);
+            b.append(object);
+            b.append(", ");
+        }
+        b.append("\n    ").append(indent).append("]");
+        return b.toString();
+    }
+
+    public NodeChildData findChild(String name) {
+        for (NodeChildData field : getChildren()) {
+            if (field.getName().equals(name)) {
+                return field;
+            }
+        }
+        return null;
+    }
+
+    public List<NodeChildData> getChildren() {
+        return children;
+    }
+
+    public List<SpecializationData> getSpecializations() {
+        return specializations;
+    }
+
+    public List<ExecutableTypeData> getExecutableTypes() {
+        return getExecutableTypes(-1);
+    }
+
+    public List<ShortCircuitData> getShortCircuits() {
+        return shortCircuits;
+    }
+
+    public void setExecutableTypes(Map<Integer, List<ExecutableTypeData>> executableTypes) {
+        this.executableTypes = executableTypes;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[" + getNodeId() + "]";
+    }
+
+    public CreateCastData findCast(String name) {
+        if (getCasts() != null) {
+            for (CreateCastData cast : getCasts()) {
+                if (cast.getChildNames().contains(name)) {
+                    return cast;
+                }
+            }
+        }
+        return null;
+    }
+
+    public int compareTo(NodeData o) {
+        return getNodeId().compareTo(o.getNodeId());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeExecutionData.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,96 @@
+/*
+ * 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.truffle.dsl.processor.model;
+
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality;
+
+public class NodeExecutionData {
+
+    private final NodeChildData child;
+    private final String name;
+    private final int index;
+    private final boolean shortCircuit;
+
+    public NodeExecutionData(NodeChildData child, int index, boolean shortCircuit) {
+        this.child = child;
+        this.index = index;
+        this.shortCircuit = shortCircuit;
+        this.name = createName();
+    }
+
+    private String createName() {
+        return createName(child.getName(), index);
+    }
+
+    public TypeMirror getNodeType() {
+        TypeMirror type;
+        if (child.getCardinality() == Cardinality.MANY && child.getNodeType().getKind() == TypeKind.ARRAY) {
+            type = ((ArrayType) child.getNodeType()).getComponentType();
+        } else {
+            type = child.getNodeType();
+        }
+        return type;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public NodeChildData getChild() {
+        return child;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public boolean isIndexed() {
+        return index > -1;
+    }
+
+    public boolean isShortCircuit() {
+        return shortCircuit;
+    }
+
+    public String getShortCircuitId() {
+        return createShortCircuitId(child, index);
+    }
+
+    public static String createShortCircuitId(NodeChildData child, int varArgsIndex) {
+        String shortCircuitName = child.getName();
+        if (child.getCardinality().isMany()) {
+            shortCircuitName = shortCircuitName + "[" + varArgsIndex + "]";
+        }
+        return shortCircuitName;
+    }
+
+    public static String createName(String childName, int index) {
+        if (index > -1) {
+            return childName + index;
+        }
+        return childName;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeFieldData.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,75 @@
+/*
+ * 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.truffle.dsl.processor.model;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public class NodeFieldData extends MessageContainer {
+
+    private final Element messageElement;
+    private final AnnotationMirror messageAnnotation;
+    private final String name;
+    private final TypeMirror type;
+    private final boolean generated;
+    private ExecutableElement getter;
+
+    public NodeFieldData(Element messageElement, AnnotationMirror messageAnnotation, TypeMirror type, String name, boolean generated) {
+        this.messageElement = messageElement;
+        this.messageAnnotation = messageAnnotation;
+        this.name = name;
+        this.type = type;
+        this.generated = generated;
+    }
+
+    public void setGetter(ExecutableElement getter) {
+        this.getter = getter;
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return messageElement;
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return messageAnnotation;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public TypeMirror getType() {
+        return type;
+    }
+
+    public boolean isGenerated() {
+        return generated;
+    }
+
+    public ExecutableElement getGetter() {
+        return getter;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,116 @@
+/*
+ * 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.truffle.dsl.processor.model;
+
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public final class Parameter {
+
+    private final ParameterSpec specification;
+    private TypeData typeSystemType;
+    private TemplateMethod method;
+    private final String localName;
+    private final int specificationVarArgsIndex;
+    private final int typeVarArgsIndex;
+    private final TypeMirror actualType;
+
+    public Parameter(ParameterSpec specification, TypeMirror actualType, int specificationVarArgsIndex, int typeVarArgsIndex) {
+        this.specification = specification;
+        this.actualType = actualType;
+        this.typeSystemType = null;
+
+        this.specificationVarArgsIndex = specificationVarArgsIndex;
+
+        String valueName = specification.getName() + "Value";
+        if (specificationVarArgsIndex > -1) {
+            valueName += specificationVarArgsIndex;
+        }
+        this.typeVarArgsIndex = typeVarArgsIndex;
+        this.localName = valueName;
+    }
+
+    public Parameter(ParameterSpec specification, TypeData actualType, int specificationIndex, int varArgsIndex) {
+        this(specification, actualType.getPrimitiveType(), specificationIndex, varArgsIndex);
+        this.typeSystemType = actualType;
+    }
+
+    public Parameter(Parameter parameter, TypeData otherType) {
+        this(parameter.specification, otherType, parameter.specificationVarArgsIndex, parameter.typeVarArgsIndex);
+    }
+
+    public Parameter(Parameter parameter) {
+        this.specification = parameter.specification;
+        this.actualType = parameter.actualType;
+        this.typeSystemType = parameter.typeSystemType;
+        this.specificationVarArgsIndex = parameter.specificationVarArgsIndex;
+        this.localName = parameter.localName;
+        this.typeVarArgsIndex = parameter.typeVarArgsIndex;
+    }
+
+    public int getTypeVarArgsIndex() {
+        return typeVarArgsIndex;
+    }
+
+    public int getSpecificationVarArgsIndex() {
+        return specificationVarArgsIndex;
+    }
+
+    public String getLocalName() {
+        return localName;
+    }
+
+    void setMethod(TemplateMethod method) {
+        this.method = method;
+    }
+
+    public ParameterSpec getSpecification() {
+        return specification;
+    }
+
+    public TemplateMethod getMethod() {
+        return method;
+    }
+
+    public TypeMirror getType() {
+        return actualType;
+    }
+
+    public TypeData getTypeSystemType() {
+        return typeSystemType;
+    }
+
+    public boolean isTypeVarArgs() {
+        return typeVarArgsIndex >= 0;
+    }
+
+    public Parameter getPreviousParameter() {
+        return method.getPreviousParam(this);
+    }
+
+    @Override
+    public String toString() {
+        return ElementUtils.getSimpleName(actualType);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,132 @@
+/*
+ * 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.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.MethodSpec.TypeDef;
+
+public class ParameterSpec {
+
+    private final String name;
+    private final List<TypeMirror> allowedTypes;
+    private final Set<String> allowedTypesIdentifier;
+
+    /** Type is bound to local final variable. */
+    private boolean local;
+    private boolean signature;
+
+    /** Optional bound execution of node. */
+    private NodeExecutionData execution;
+    private TypeDef typeDefinition;
+
+    public ParameterSpec(String name, List<TypeMirror> allowedTypes, Set<String> typeIdentifiers) {
+        this.name = name;
+        this.allowedTypes = allowedTypes;
+        this.allowedTypesIdentifier = typeIdentifiers;
+    }
+
+    public ParameterSpec(String name, TypeMirror type) {
+        this(name, Arrays.asList(type), new HashSet<>(Arrays.asList(ElementUtils.getUniqueIdentifier(type))));
+    }
+
+    public ParameterSpec(ParameterSpec o, List<TypeMirror> allowedTypes, Set<String> typeIdentifiers) {
+        this.name = o.name;
+        this.local = o.local;
+        this.typeDefinition = o.typeDefinition;
+        this.execution = o.execution;
+        this.signature = o.signature;
+        this.allowedTypes = allowedTypes;
+        this.allowedTypesIdentifier = typeIdentifiers;
+    }
+
+    public NodeExecutionData getExecution() {
+        return execution;
+    }
+
+    public void setExecution(NodeExecutionData executionData) {
+        this.execution = executionData;
+        this.signature = execution != null;
+    }
+
+    public void setSignature(boolean signature) {
+        this.signature = signature;
+    }
+
+    void setTypeDefinition(TypeDef typeDefinition) {
+        this.typeDefinition = typeDefinition;
+    }
+
+    TypeDef getTypeDefinition() {
+        return typeDefinition;
+    }
+
+    public void setLocal(boolean local) {
+        this.local = local;
+    }
+
+    public boolean isSignature() {
+        return signature;
+    }
+
+    public boolean isLocal() {
+        return local;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public List<TypeMirror> getAllowedTypes() {
+        return allowedTypes;
+    }
+
+    public boolean matches(TypeMirror actualType) {
+        return allowedTypesIdentifier.contains(ElementUtils.getUniqueIdentifier(actualType));
+    }
+
+    @Override
+    public String toString() {
+        return toSignatureString(false);
+    }
+
+    public String toSignatureString(boolean typeOnly) {
+        StringBuilder builder = new StringBuilder();
+        if (typeDefinition != null) {
+            builder.append("<" + typeDefinition.getName() + ">");
+        } else if (getAllowedTypes().size() >= 1) {
+            builder.append(ElementUtils.getSimpleName(getAllowedTypes().get(0)));
+        } else {
+            builder.append("void");
+        }
+        if (!typeOnly) {
+            builder.append(" ");
+            builder.append(getName());
+        }
+        return builder.toString();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ShortCircuitData.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class ShortCircuitData extends TemplateMethod {
+
+    private ShortCircuitData genericShortCircuitMethod;
+    private final String valueName;
+
+    public ShortCircuitData(TemplateMethod template, String valueName) {
+        super(template);
+        this.valueName = valueName;
+    }
+
+    public String getValueName() {
+        return valueName;
+    }
+
+    public void setGenericShortCircuitMethod(ShortCircuitData genericShortCircuitMethod) {
+        this.genericShortCircuitMethod = genericShortCircuitMethod;
+    }
+
+    public boolean isGeneric() {
+        return genericShortCircuitMethod == null;
+    }
+
+    public ShortCircuitData getGeneric() {
+        if (isGeneric()) {
+            return this;
+        } else {
+            return genericShortCircuitMethod;
+        }
+    }
+
+    public boolean isCompatibleTo(SpecializationData specialization) {
+        if (isGeneric() && specialization.isGeneric()) {
+            return true;
+        }
+
+        for (Parameter param : getParameters()) {
+            Parameter specializationParam = specialization.findParameter(param.getLocalName());
+            if (!ElementUtils.typeEquals(param.getType(), specializationParam.getType())) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+
+public final class SpecializationData extends TemplateMethod {
+
+    public enum SpecializationKind {
+        UNINITIALIZED,
+        SPECIALIZED,
+        POLYMORPHIC,
+        GENERIC
+    }
+
+    private final NodeData node;
+    private final SpecializationKind kind;
+    private final List<SpecializationThrowsData> exceptions;
+    private List<GuardExpression> guards = Collections.emptyList();
+    private List<ShortCircuitData> shortCircuits;
+    private List<String> assumptions = Collections.emptyList();
+    private final Set<SpecializationData> contains = new TreeSet<>();
+    private final Set<String> containsNames = new TreeSet<>();
+    private final Set<SpecializationData> excludedBy = new TreeSet<>();
+    private String insertBeforeName;
+    private SpecializationData insertBefore;
+    private boolean reachable;
+    private int index;
+
+    public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind, List<SpecializationThrowsData> exceptions) {
+        super(template);
+        this.node = node;
+        this.kind = kind;
+        this.exceptions = exceptions;
+        this.index = template.getNaturalOrder();
+
+        for (SpecializationThrowsData exception : exceptions) {
+            exception.setSpecialization(this);
+        }
+    }
+
+    public void setInsertBefore(SpecializationData insertBefore) {
+        this.insertBefore = insertBefore;
+    }
+
+    public void setInsertBeforeName(String insertBeforeName) {
+        this.insertBeforeName = insertBeforeName;
+    }
+
+    public SpecializationData getInsertBefore() {
+        return insertBefore;
+    }
+
+    public String getInsertBeforeName() {
+        return insertBeforeName;
+    }
+
+    public Set<String> getContainsNames() {
+        return containsNames;
+    }
+
+    public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind) {
+        this(node, template, kind, new ArrayList<SpecializationThrowsData>());
+    }
+
+    public Set<SpecializationData> getContains() {
+        return contains;
+    }
+
+    public Set<SpecializationData> getExcludedBy() {
+        return excludedBy;
+    }
+
+    public void setReachable(boolean reachable) {
+        this.reachable = reachable;
+    }
+
+    public boolean isReachable() {
+        return reachable;
+    }
+
+    public boolean isPolymorphic() {
+        return kind == SpecializationKind.POLYMORPHIC;
+    }
+
+    @Override
+    protected List<MessageContainer> findChildContainers() {
+        List<MessageContainer> sinks = new ArrayList<>();
+        if (exceptions != null) {
+            sinks.addAll(exceptions);
+        }
+        if (guards != null) {
+            for (GuardExpression guard : guards) {
+                if (guard.isResolved()) {
+                    sinks.add(guard.getResolvedGuard());
+                }
+            }
+        }
+        return sinks;
+    }
+
+    public boolean hasRewrite(ProcessorContext context) {
+        if (!getExceptions().isEmpty()) {
+            return true;
+        }
+        if (!getGuards().isEmpty()) {
+            return true;
+        }
+        if (!getAssumptions().isEmpty()) {
+            return true;
+        }
+        for (Parameter parameter : getSignatureParameters()) {
+            ExecutableTypeData type = parameter.getSpecification().getExecution().getChild().findExecutableType(context, parameter.getTypeSystemType());
+            if (type.hasUnexpectedValue(context)) {
+                return true;
+            }
+            if (type.getReturnType().getTypeSystemType().needsCastTo(parameter.getTypeSystemType())) {
+                return true;
+            }
+
+        }
+        return false;
+    }
+
+    @Override
+    public int compareTo(TemplateMethod other) {
+        if (this == other) {
+            return 0;
+        } else if (!(other instanceof SpecializationData)) {
+            return super.compareTo(other);
+        }
+        SpecializationData m2 = (SpecializationData) other;
+        int kindOrder = kind.compareTo(m2.kind);
+        if (kindOrder != 0) {
+            return kindOrder;
+        }
+
+        int compare = 0;
+        int order1 = index;
+        int order2 = m2.index;
+        if (order1 != NO_NATURAL_ORDER && order2 != NO_NATURAL_ORDER) {
+            compare = Integer.compare(order1, order2);
+            if (compare != 0) {
+                return compare;
+            }
+        }
+
+        return super.compareTo(other);
+    }
+
+    public void setIndex(int order) {
+        this.index = order;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public boolean isContainedBy(SpecializationData next) {
+        if (compareTo(next) > 0) {
+            // must be declared after the current specialization
+            return false;
+        }
+
+        Iterator<Parameter> currentSignature = getSignatureParameters().iterator();
+        Iterator<Parameter> nextSignature = next.getSignatureParameters().iterator();
+
+        while (currentSignature.hasNext() && nextSignature.hasNext()) {
+            TypeData currentType = currentSignature.next().getTypeSystemType();
+            TypeData prevType = nextSignature.next().getTypeSystemType();
+
+            if (!currentType.isImplicitSubtypeOf(prevType)) {
+                return false;
+            }
+        }
+
+        for (String nextAssumption : next.getAssumptions()) {
+            if (!getAssumptions().contains(nextAssumption)) {
+                return false;
+            }
+        }
+
+        Iterator<GuardExpression> nextGuards = next.getGuards().iterator();
+        while (nextGuards.hasNext()) {
+            GuardExpression nextGuard = nextGuards.next();
+            boolean implied = false;
+            for (GuardExpression currentGuard : getGuards()) {
+                if (currentGuard.implies(nextGuard)) {
+                    implied = true;
+                    break;
+                }
+            }
+            if (!implied) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public String createReferenceName() {
+        if (getMethod() == null) {
+            return "-";
+        }
+        return ElementUtils.createReferenceName(getMethod());
+    }
+
+    public NodeData getNode() {
+        return node;
+    }
+
+    public void setGuards(List<GuardExpression> guards) {
+        this.guards = guards;
+    }
+
+    public boolean isSpecialized() {
+        return kind == SpecializationKind.SPECIALIZED;
+    }
+
+    public boolean isGeneric() {
+        return kind == SpecializationKind.GENERIC;
+    }
+
+    public boolean isUninitialized() {
+        return kind == SpecializationKind.UNINITIALIZED;
+    }
+
+    public List<SpecializationThrowsData> getExceptions() {
+        return exceptions;
+    }
+
+    public List<GuardExpression> getGuards() {
+        return guards;
+    }
+
+    public void setShortCircuits(List<ShortCircuitData> shortCircuits) {
+        this.shortCircuits = shortCircuits;
+    }
+
+    public List<ShortCircuitData> getShortCircuits() {
+        return shortCircuits;
+    }
+
+    public List<String> getAssumptions() {
+        return assumptions;
+    }
+
+    public void setAssumptions(List<String> assumptions) {
+        this.assumptions = assumptions;
+    }
+
+    public SpecializationData findNextSpecialization() {
+        List<SpecializationData> specializations = node.getSpecializations();
+        for (int i = 0; i < specializations.size() - 1; i++) {
+            if (specializations.get(i) == this) {
+                return specializations.get(i + 1);
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getTypeSignature());
+    }
+
+    public boolean hasFrame(ProcessorContext context) {
+        for (Parameter param : getParameters()) {
+            if (ElementUtils.typeEquals(param.getType(), context.getTruffleTypes().getFrame())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean isReachableAfter(SpecializationData prev) {
+        if (!prev.isSpecialized()) {
+            return true;
+        }
+
+        if (!prev.getExceptions().isEmpty()) {
+            return true;
+        }
+
+        Iterator<Parameter> currentSignature = getSignatureParameters().iterator();
+        Iterator<Parameter> prevSignature = prev.getSignatureParameters().iterator();
+
+        while (currentSignature.hasNext() && prevSignature.hasNext()) {
+            TypeData currentType = currentSignature.next().getTypeSystemType();
+            TypeData prevType = prevSignature.next().getTypeSystemType();
+
+            if (!currentType.isImplicitSubtypeOf(prevType)) {
+                return true;
+            }
+        }
+
+        for (String prevAssumption : prev.getAssumptions()) {
+            if (!getAssumptions().contains(prevAssumption)) {
+                return true;
+            }
+        }
+
+        Iterator<GuardExpression> prevGuards = prev.getGuards().iterator();
+        Iterator<GuardExpression> currentGuards = getGuards().iterator();
+        while (prevGuards.hasNext()) {
+            GuardExpression prevGuard = prevGuards.next();
+            GuardExpression currentGuard = currentGuards.hasNext() ? currentGuards.next() : null;
+            if (currentGuard == null || !currentGuard.implies(prevGuard)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationThrowsData.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public class SpecializationThrowsData extends MessageContainer {
+
+    private final AnnotationValue annotationValue;
+    private final AnnotationMirror annotationMirror;
+    private final TypeMirror javaClass;
+    private SpecializationData specialization;
+
+    public SpecializationThrowsData(AnnotationMirror annotationMirror, AnnotationValue value, TypeMirror javaClass) {
+        this.annotationMirror = annotationMirror;
+        this.annotationValue = value;
+        this.javaClass = javaClass;
+    }
+
+    void setSpecialization(SpecializationData specialization) {
+        this.specialization = specialization;
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return specialization.getMessageElement();
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return annotationMirror;
+    }
+
+    @Override
+    public AnnotationValue getMessageAnnotationValue() {
+        return annotationValue;
+    }
+
+    public TypeMirror getJavaClass() {
+        return javaClass;
+    }
+
+    public SpecializationData getSpecialization() {
+        return specialization;
+    }
+
+    public AnnotationMirror getAnnotationMirror() {
+        return annotationMirror;
+    }
+
+    public SpecializationData getTransitionTo() {
+        return specialization.findNextSpecialization();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Template.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,84 @@
+/*
+ * 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.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+
+public abstract class Template extends MessageContainer {
+
+    private final ProcessorContext context;
+    private final TypeElement templateType;
+    private final String templateMethodName;
+    private final AnnotationMirror annotation;
+
+    public Template(ProcessorContext context, TypeElement templateType, String templateMethodName, AnnotationMirror annotation) {
+        this.context = context;
+        this.templateType = templateType;
+        this.templateMethodName = templateMethodName;
+        this.annotation = annotation;
+    }
+
+    public ProcessorContext getContext() {
+        return context;
+    }
+
+    @Override
+    public MessageContainer getBaseContainer() {
+        return this;
+    }
+
+    public abstract TypeSystemData getTypeSystem();
+
+    @Override
+    public Element getMessageElement() {
+        return templateType;
+    }
+
+    @Override
+    protected List<MessageContainer> findChildContainers() {
+        return Collections.emptyList();
+    }
+
+    public String getTemplateMethodName() {
+        return templateMethodName;
+    }
+
+    public TypeElement getTemplateType() {
+        return templateType;
+    }
+
+    public AnnotationMirror getTemplateTypeAnnotation() {
+        return annotation;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[" + ElementUtils.getSimpleName(getTemplateType()) + "]";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,437 @@
+/*
+ * 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.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.util.*;
+
+/**
+ * Note: this class has a natural ordering that is inconsistent with equals.
+ */
+public class TemplateMethod extends MessageContainer implements Comparable<TemplateMethod> {
+
+    public static final int NO_NATURAL_ORDER = -1;
+
+    private String id;
+    private final Template template;
+    private final int naturalOrder;
+    private final MethodSpec specification;
+    private final ExecutableElement method;
+    private final AnnotationMirror markerAnnotation;
+    private Parameter returnType;
+    private final List<Parameter> parameters;
+    private final Map<String, Parameter> parameterCache = new HashMap<>();
+
+    public TemplateMethod(String id, int naturalOrder, Template template, MethodSpec specification, ExecutableElement method, AnnotationMirror markerAnnotation, Parameter returnType,
+                    List<Parameter> parameters) {
+        this.template = template;
+        this.specification = specification;
+        this.naturalOrder = naturalOrder;
+        this.method = method;
+        this.markerAnnotation = markerAnnotation;
+        this.returnType = returnType;
+        this.parameters = new ArrayList<>();
+        for (Parameter param : parameters) {
+            Parameter newParam = new Parameter(param);
+            this.parameters.add(newParam);
+            newParam.setMethod(this);
+            parameterCache.put(param.getLocalName(), param);
+        }
+        if (returnType != null) {
+            parameterCache.put(returnType.getLocalName(), returnType);
+        }
+        this.id = id;
+    }
+
+    public int getNaturalOrder() {
+        return naturalOrder;
+    }
+
+    public TemplateMethod(TemplateMethod method) {
+        this(method.id, method.naturalOrder, method.template, method.specification, method.method, method.markerAnnotation, method.returnType, method.parameters);
+        getMessages().addAll(method.getMessages());
+    }
+
+    public TemplateMethod(TemplateMethod method, ExecutableElement executable) {
+        this(method.id, method.naturalOrder, method.template, method.specification, executable, method.markerAnnotation, method.returnType, method.parameters);
+        getMessages().addAll(method.getMessages());
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return method;
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return markerAnnotation;
+    }
+
+    @Override
+    protected List<MessageContainer> findChildContainers() {
+        return Collections.emptyList();
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public Template getTemplate() {
+        return template;
+    }
+
+    public MethodSpec getSpecification() {
+        return specification;
+    }
+
+    public Parameter getReturnType() {
+        return returnType;
+    }
+
+    public void replaceParameter(String localName, Parameter newParameter) {
+        if (returnType.getLocalName().equals(localName)) {
+            returnType = newParameter;
+            returnType.setMethod(this);
+        } else {
+            Parameter local = findParameter(localName);
+            int index = parameters.indexOf(local);
+            parameters.set(index, newParameter);
+        }
+    }
+
+    public List<Parameter> getRequiredParameters() {
+        List<Parameter> requiredParameters = new ArrayList<>();
+        for (Parameter parameter : getParameters()) {
+            if (getSpecification().getRequired().contains(parameter.getSpecification())) {
+                requiredParameters.add(parameter);
+            }
+        }
+        return requiredParameters;
+    }
+
+    public Iterable<Parameter> getSignatureParameters() {
+        return new FilteredIterable<>(getParameters(), new Predicate<Parameter>() {
+            public boolean evaluate(Parameter value) {
+                return value.getSpecification().isSignature();
+            }
+        });
+    }
+
+    public List<Parameter> getParameters() {
+        return parameters;
+    }
+
+    public List<Parameter> findParameters(ParameterSpec spec) {
+        List<Parameter> foundParameters = new ArrayList<>();
+        for (Parameter param : getReturnTypeAndParameters()) {
+            if (param.getSpecification().getName().equals(spec.getName())) {
+                foundParameters.add(param);
+            }
+        }
+        return foundParameters;
+    }
+
+    public List<Parameter> findByExecutionData(NodeExecutionData execution) {
+        List<Parameter> foundParameters = new ArrayList<>();
+        for (Parameter parameter : getParameters()) {
+            ParameterSpec spec = parameter.getSpecification();
+            if (spec != null && spec.getExecution() != null && spec.getExecution().equals(execution) && parameter.getSpecification().isSignature()) {
+                foundParameters.add(parameter);
+            }
+        }
+        return foundParameters;
+    }
+
+    public Parameter findParameter(String valueName) {
+        return parameterCache.get(valueName);
+    }
+
+    public List<Parameter> getReturnTypeAndParameters() {
+        List<Parameter> allParameters = new ArrayList<>(getParameters().size() + 1);
+        if (getReturnType() != null) {
+            allParameters.add(getReturnType());
+        }
+        allParameters.addAll(getParameters());
+        return Collections.unmodifiableList(allParameters);
+    }
+
+    public boolean canBeAccessedByInstanceOf(TypeMirror type) {
+        TypeMirror methodType = ElementUtils.findNearestEnclosingType(getMethod()).asType();
+        return ElementUtils.isAssignable(type, methodType) || ElementUtils.isAssignable(methodType, type);
+    }
+
+    public ExecutableElement getMethod() {
+        return method;
+    }
+
+    public String getMethodName() {
+        if (getMethod() != null) {
+            return getMethod().getSimpleName().toString();
+        } else {
+            return "$synthetic";
+        }
+    }
+
+    public AnnotationMirror getMarkerAnnotation() {
+        return markerAnnotation;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s [id = %s, method = %s]", getClass().getSimpleName(), getId(), getMethod());
+    }
+
+    public Parameter getPreviousParam(Parameter searchParam) {
+        Parameter prev = null;
+        for (Parameter param : getParameters()) {
+            if (param == searchParam) {
+                return prev;
+            }
+            prev = param;
+        }
+        return prev;
+    }
+
+    @SuppressWarnings("unused")
+    public int getSignatureSize() {
+        int signatureSize = 0;
+        for (Parameter parameter : getSignatureParameters()) {
+            signatureSize++;
+        }
+        return signatureSize;
+    }
+
+    public TypeSignature getTypeSignature() {
+        TypeSignature signature = new TypeSignature();
+        signature.types.add(getReturnType().getTypeSystemType());
+        for (Parameter parameter : getSignatureParameters()) {
+            TypeData typeData = parameter.getTypeSystemType();
+            if (typeData != null) {
+                signature.types.add(typeData);
+            }
+        }
+        return signature;
+    }
+
+    public Parameter getSignatureParameter(int searchIndex) {
+        int index = 0;
+        for (Parameter parameter : getParameters()) {
+            if (!parameter.getSpecification().isSignature()) {
+                continue;
+            }
+            if (index == searchIndex) {
+                return parameter;
+            }
+            index++;
+        }
+        return null;
+    }
+
+    public void updateSignature(TypeSignature signature) {
+        // TODO(CH): fails in normal usage - output ok though
+        // assert signature.size() >= 1;
+
+        int signatureIndex = 0;
+        for (Parameter parameter : getReturnTypeAndParameters()) {
+            if (!parameter.getSpecification().isSignature()) {
+                continue;
+            }
+            if (signatureIndex >= signature.size()) {
+                break;
+            }
+            TypeData newType = signature.get(signatureIndex++);
+            if (!parameter.getTypeSystemType().equals(newType)) {
+                replaceParameter(parameter.getLocalName(), new Parameter(parameter, newType));
+            }
+        }
+    }
+
+    @Override
+    public int compareTo(TemplateMethod o) {
+        if (this == o) {
+            return 0;
+        }
+
+        int compare = compareBySignature(o);
+        if (compare == 0) {
+            // if signature sorting failed sort by id
+            compare = getId().compareTo(o.getId());
+        }
+        if (compare == 0) {
+            // if still no difference sort by enclosing type name
+            TypeElement enclosingType1 = ElementUtils.findNearestEnclosingType(getMethod());
+            TypeElement enclosingType2 = ElementUtils.findNearestEnclosingType(o.getMethod());
+            compare = enclosingType1.getQualifiedName().toString().compareTo(enclosingType2.getQualifiedName().toString());
+        }
+        return compare;
+    }
+
+    public List<Parameter> getParametersAfter(Parameter genericParameter) {
+        boolean found = false;
+        List<Parameter> foundParameters = new ArrayList<>();
+        for (Parameter param : getParameters()) {
+            if (param.getLocalName().equals(genericParameter.getLocalName())) {
+                found = true;
+            } else if (found) {
+                foundParameters.add(param);
+            }
+        }
+        return foundParameters;
+    }
+
+    public int compareBySignature(TemplateMethod compareMethod) {
+        final TypeSystemData typeSystem = getTemplate().getTypeSystem();
+        if (typeSystem != compareMethod.getTemplate().getTypeSystem()) {
+            throw new IllegalStateException("Cannot compare two methods with different type systems.");
+        }
+
+        List<TypeMirror> signature1 = getSignatureTypes(this);
+        List<TypeMirror> signature2 = getSignatureTypes(compareMethod);
+
+        int result = 0;
+        for (int i = 0; i < Math.max(signature1.size(), signature2.size()); i++) {
+            TypeMirror t1 = i < signature1.size() ? signature1.get(i) : null;
+            TypeMirror t2 = i < signature2.size() ? signature2.get(i) : null;
+            result = compareParameter(typeSystem, t1, t2);
+            if (result != 0) {
+                break;
+            }
+        }
+
+        return result;
+    }
+
+    protected static int compareParameter(TypeSystemData data, TypeMirror signature1, TypeMirror signature2) {
+        if (signature1 == null) {
+            return 1;
+        } else if (signature2 == null) {
+            return -1;
+        }
+
+        if (ElementUtils.typeEquals(signature1, signature2)) {
+            return 0;
+        }
+
+        int index1 = data.findType(signature1);
+        int index2 = data.findType(signature2);
+        if (index1 != -1 && index2 != -1) {
+            return index1 - index2;
+        }
+
+        // TODO this version if subclass of should be improved.
+        if (signature1.getKind() == TypeKind.DECLARED && signature2.getKind() == TypeKind.DECLARED) {
+            TypeElement element1 = ElementUtils.fromTypeMirror(signature1);
+            TypeElement element2 = ElementUtils.fromTypeMirror(signature2);
+
+            if (ElementUtils.getDirectSuperTypes(element1).contains(element2)) {
+                return -1;
+            } else if (ElementUtils.getDirectSuperTypes(element2).contains(element1)) {
+                return 1;
+            }
+        }
+        return ElementUtils.getSimpleName(signature1).compareTo(ElementUtils.getSimpleName(signature2));
+    }
+
+    public static List<TypeMirror> getSignatureTypes(TemplateMethod method) {
+        List<TypeMirror> types = new ArrayList<>();
+        for (Parameter param : method.getSignatureParameters()) {
+            types.add(param.getType());
+        }
+        return types;
+    }
+
+    public static class TypeSignature implements Iterable<TypeData>, Comparable<TypeSignature> {
+
+        private final List<TypeData> types;
+
+        public TypeSignature() {
+            this.types = new ArrayList<>();
+        }
+
+        public TypeSignature(List<TypeData> signature) {
+            this.types = signature;
+        }
+
+        @Override
+        public int hashCode() {
+            return types.hashCode();
+        }
+
+        public int size() {
+            return types.size();
+        }
+
+        public TypeData get(int index) {
+            return types.get(index);
+        }
+
+        public int compareTo(TypeSignature other) {
+            if (this == other) {
+                return 0;
+            } else if (types.size() != other.types.size()) {
+                return types.size() - other.types.size();
+            } else if (types.isEmpty()) {
+                return 0;
+            }
+
+            for (int i = 0; i < types.size(); i++) {
+                TypeData type1 = types.get(i);
+                TypeData type2 = other.types.get(i);
+
+                int comparison = type1.compareTo(type2);
+                if (comparison != 0) {
+                    return comparison;
+                }
+            }
+
+            return 0;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof TypeSignature) {
+                return ((TypeSignature) obj).types.equals(types);
+            }
+            return super.equals(obj);
+        }
+
+        public Iterator<TypeData> iterator() {
+            return types.iterator();
+        }
+
+        @Override
+        public String toString() {
+            return types.toString();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCastData.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+public class TypeCastData extends TemplateMethod {
+
+    private final TypeData targetType;
+    private final TypeData sourceType;
+
+    public TypeCastData(TemplateMethod method, TypeData sourceType, TypeData targetType) {
+        super(method);
+        this.sourceType = sourceType;
+        this.targetType = targetType;
+    }
+
+    public boolean isGeneric() {
+        return sourceType.isGeneric();
+    }
+
+    public TypeData getSourceType() {
+        return sourceType;
+    }
+
+    public TypeData getTargetType() {
+        return targetType;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCheckData.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+public class TypeCheckData extends TemplateMethod {
+
+    private final TypeData checkedType;
+    private final TypeData valueType;
+
+    public TypeCheckData(TemplateMethod method, TypeData checkedType, TypeData valueType) {
+        super(method);
+        this.checkedType = checkedType;
+        this.valueType = valueType;
+    }
+
+    public boolean isGeneric() {
+        return valueType.isGeneric();
+    }
+
+    public TypeData getCheckedType() {
+        return checkedType;
+    }
+
+    public TypeData getValueType() {
+        return valueType;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeData.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class TypeData extends MessageContainer implements Comparable<TypeData> {
+
+    private final TypeSystemData typeSystem;
+    private final AnnotationValue annotationValue;
+    private final TypeMirror primitiveType;
+    private final TypeMirror boxedType;
+
+    private final int index;
+    private final List<TypeCastData> typeCasts = new ArrayList<>();
+    private final List<TypeCheckData> typeChecks = new ArrayList<>();
+
+    public TypeData(TypeSystemData typeSystem, int index, AnnotationValue value, TypeMirror primitiveType, TypeMirror boxedType) {
+        this.index = index;
+        this.typeSystem = typeSystem;
+        this.annotationValue = value;
+        this.primitiveType = primitiveType;
+        this.boxedType = boxedType;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return typeSystem.getMessageElement();
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return typeSystem.getMessageAnnotation();
+    }
+
+    @Override
+    public AnnotationValue getMessageAnnotationValue() {
+        return annotationValue;
+    }
+
+    public void addTypeCast(TypeCastData typeCast) {
+        this.typeCasts.add(typeCast);
+    }
+
+    public void addTypeCheck(TypeCheckData typeCheck) {
+        this.typeChecks.add(typeCheck);
+    }
+
+    public List<TypeCastData> getTypeCasts() {
+        return typeCasts;
+    }
+
+    public List<TypeCheckData> getTypeChecks() {
+        return typeChecks;
+    }
+
+    public TypeSystemData getTypeSystem() {
+        return typeSystem;
+    }
+
+    public TypeMirror getPrimitiveType() {
+        return primitiveType;
+    }
+
+    public TypeMirror getBoxedType() {
+        return boxedType;
+    }
+
+    public boolean isGeneric() {
+        return ElementUtils.typeEquals(boxedType, getTypeSystem().getGenericType());
+    }
+
+    public boolean isVoid() {
+        if (getTypeSystem().getVoidType() == null) {
+            return false;
+        }
+        return ElementUtils.typeEquals(boxedType, getTypeSystem().getVoidType().getBoxedType());
+    }
+
+    public int compareTo(TypeData o) {
+        if (this.equals(o)) {
+            return 0;
+        }
+        return index - o.index;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(index, primitiveType);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof TypeData)) {
+            return false;
+        }
+        TypeData otherType = (TypeData) obj;
+        return index == otherType.index && ElementUtils.typeEquals(primitiveType, otherType.primitiveType);
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[" + ElementUtils.getSimpleName(primitiveType) + "]";
+    }
+
+    public boolean equalsType(TypeData actualTypeData) {
+        return ElementUtils.typeEquals(boxedType, actualTypeData.boxedType);
+    }
+
+    public boolean needsCastTo(TypeData targetType) {
+        return ElementUtils.needsCastTo(getPrimitiveType(), targetType.getPrimitiveType());
+    }
+
+    public boolean needsCastTo(TypeMirror targetType) {
+        return ElementUtils.needsCastTo(getPrimitiveType(), targetType);
+    }
+
+    public boolean isPrimitive() {
+        return ElementUtils.isPrimitive(getPrimitiveType());
+    }
+
+    public boolean isImplicitSubtypeOf(TypeData other) {
+        List<ImplicitCastData> casts = other.getTypeSystem().lookupByTargetType(other);
+        for (ImplicitCastData cast : casts) {
+            if (isSubtypeOf(cast.getSourceType())) {
+                return true;
+            }
+        }
+        return isSubtypeOf(other);
+    }
+
+    public boolean isSubtypeOf(TypeData other) {
+        return ElementUtils.isSubtype(boxedType, other.boxedType);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class TypeSystemData extends Template {
+
+    private List<TypeData> types;
+    private List<TypeMirror> primitiveTypeMirrors = new ArrayList<>();
+    private List<TypeMirror> boxedTypeMirrors = new ArrayList<>();
+    private Map<String, TypeData> cachedTypes = new HashMap<>();
+
+    private List<ImplicitCastData> implicitCasts;
+    private List<TypeCastData> casts;
+    private List<TypeCheckData> checks;
+
+    private TypeMirror genericType;
+    private TypeData voidType;
+
+    public TypeSystemData(ProcessorContext context, TypeElement templateType, AnnotationMirror annotation) {
+        super(context, templateType, null, annotation);
+    }
+
+    @Override
+    public TypeSystemData getTypeSystem() {
+        return this;
+    }
+
+    public void setTypes(List<TypeData> types) {
+        this.types = types;
+        if (types != null) {
+            for (TypeData typeData : types) {
+                primitiveTypeMirrors.add(typeData.getPrimitiveType());
+                boxedTypeMirrors.add(typeData.getBoxedType());
+                cachedTypes.put(ElementUtils.getUniqueIdentifier(typeData.getPrimitiveType()), typeData);
+                cachedTypes.put(ElementUtils.getUniqueIdentifier(typeData.getBoxedType()), typeData);
+            }
+        }
+    }
+
+    public void setImplicitCasts(List<ImplicitCastData> implicitCasts) {
+        this.implicitCasts = implicitCasts;
+    }
+
+    public List<ImplicitCastData> getImplicitCasts() {
+        return implicitCasts;
+    }
+
+    public void setCasts(List<TypeCastData> casts) {
+        this.casts = casts;
+    }
+
+    public void setChecks(List<TypeCheckData> checks) {
+        this.checks = checks;
+    }
+
+    public void setGenericType(TypeMirror genericType) {
+        this.genericType = genericType;
+    }
+
+    public void setVoidType(TypeData voidType) {
+        this.voidType = voidType;
+    }
+
+    @Override
+    protected List<MessageContainer> findChildContainers() {
+        List<MessageContainer> sinks = new ArrayList<>();
+        if (types != null) {
+            sinks.addAll(types);
+        }
+        if (checks != null) {
+            sinks.addAll(checks);
+        }
+        if (casts != null) {
+            sinks.addAll(casts);
+        }
+        if (implicitCasts != null) {
+            sinks.addAll(implicitCasts);
+        }
+        return sinks;
+    }
+
+    public TypeData getVoidType() {
+        return voidType;
+    }
+
+    public List<TypeMirror> getBoxedTypeMirrors() {
+        return boxedTypeMirrors;
+    }
+
+    public List<TypeMirror> getPrimitiveTypeMirrors() {
+        return primitiveTypeMirrors;
+    }
+
+    public Set<String> getTypeIdentifiers() {
+        return cachedTypes.keySet();
+    }
+
+    public List<TypeData> getTypes() {
+        return types;
+    }
+
+    public TypeMirror getGenericType() {
+        return genericType;
+    }
+
+    public TypeData getGenericTypeData() {
+        TypeData result = types.get(types.size() - 2);
+        assert result.getBoxedType() == genericType;
+        return result;
+    }
+
+    public TypeData findType(String simpleName) {
+        for (TypeData type : types) {
+            if (ElementUtils.getSimpleName(type.getBoxedType()).equals(simpleName)) {
+                return type;
+            }
+        }
+        return null;
+    }
+
+    public TypeData findTypeData(TypeMirror type) {
+        if (ElementUtils.typeEquals(voidType.getPrimitiveType(), type)) {
+            return voidType;
+        }
+
+        int index = findType(type);
+        if (index == -1) {
+            return null;
+        }
+        return types.get(index);
+    }
+
+    public int findType(TypeMirror type) {
+        TypeData data = cachedTypes.get(ElementUtils.getUniqueIdentifier(type));
+        if (data != null) {
+            return data.getIndex();
+        }
+        return -1;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[template = " + ElementUtils.getSimpleName(getTemplateType()) + ", types = " + types + "]";
+    }
+
+    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/node/CreateCastData.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.util.*;
-
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class CreateCastData extends TemplateMethod {
-
-    private final List<String> childNames;
-
-    public CreateCastData(TemplateMethod method, List<String> childNames) {
-        super(method);
-        this.childNames = childNames;
-    }
-
-    public List<String> getChildNames() {
-        return childNames;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class CreateCastParser extends NodeMethodParser<CreateCastData> {
-
-    public CreateCastParser(ProcessorContext context, NodeData operation) {
-        super(context, operation);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return CreateCast.class;
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        List<String> childNames = Utils.getAnnotationValueList(String.class, mirror, "value");
-        NodeChildData foundChild = null;
-        for (String childName : childNames) {
-            foundChild = getNode().findChild(childName);
-            if (foundChild != null) {
-                break;
-            }
-        }
-        TypeMirror baseType = getContext().getTruffleTypes().getNode();
-        if (foundChild != null) {
-            baseType = foundChild.getOriginalType();
-        }
-
-        MethodSpec spec = new MethodSpec(new InheritsParameterSpec(getContext(), "child", baseType));
-        addDefaultFieldMethodSpec(spec);
-        ParameterSpec childSpec = new ParameterSpec("castedChild", baseType);
-        childSpec.setSignature(true);
-        spec.addRequired(childSpec);
-        return spec;
-    }
-
-    @Override
-    public CreateCastData create(TemplateMethod method, boolean invalid) {
-        AnnotationMirror mirror = method.getMarkerAnnotation();
-        List<String> childNames = Utils.getAnnotationValueList(String.class, mirror, "value");
-        CreateCastData cast = new CreateCastData(method, childNames);
-        AnnotationValue value = Utils.getAnnotationValue(mirror, "value");
-        TypeMirror type = null;
-        if (childNames == null || childNames.isEmpty()) {
-            cast.addError(value, "No value specified but required.");
-            return cast;
-        }
-
-        for (String childName : childNames) {
-            NodeChildData child = getNode().findChild(childName);
-            if (child == null) {
-                // error
-                cast.addError(value, "Specified child '%s' not found.", childName);
-                continue;
-            }
-            if (type == null) {
-                type = child.getNodeType();
-            } else if (!Utils.typeEquals(type, child.getNodeType())) {
-                cast.addError(value, "All child nodes for a cast must have the same node type.");
-                continue;
-            }
-        }
-        return cast;
-    }
-
-    private static class InheritsParameterSpec extends ParameterSpec {
-
-        private final ProcessorContext context;
-
-        public InheritsParameterSpec(ProcessorContext context, String name, TypeMirror... allowedTypes) {
-            super(name, Arrays.asList(allowedTypes));
-            this.context = context;
-        }
-
-        @Override
-        public boolean matches(TypeMirror actualType) {
-            boolean found = false;
-            for (TypeMirror specType : getAllowedTypes()) {
-                if (Utils.isAssignable(context, actualType, specType)) {
-                    found = true;
-                    break;
-                }
-            }
-            return found;
-        }
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeData.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public class ExecutableTypeData extends TemplateMethod {
-
-    private final TypeSystemData typeSystem;
-    private final TypeData type;
-
-    public ExecutableTypeData(TemplateMethod method, ExecutableElement executable, TypeSystemData typeSystem, TypeData type) {
-        super(method, executable);
-        this.typeSystem = typeSystem;
-        this.type = type;
-        if (executable.getParameters().size() < method.getMethod().getParameters().size()) {
-            throw new IllegalArgumentException(String.format("Method parameter count mismatch %s != %s.", executable.getParameters(), method.getMethod().getParameters()));
-        }
-    }
-
-    public TypeData getType() {
-        return type;
-    }
-
-    public TypeSystemData getTypeSystem() {
-        return typeSystem;
-    }
-
-    public boolean hasFrame() {
-        return getMethod().getParameters().size() > 0;
-    }
-
-    public boolean hasUnexpectedValue(ProcessorContext context) {
-        return Utils.canThrowType(getMethod().getThrownTypes(), context.getTruffleTypes().getUnexpectedValueException());
-    }
-
-    public boolean isFinal() {
-        return getMethod().getModifiers().contains(Modifier.FINAL);
-    }
-
-    public boolean isAbstract() {
-        return getMethod().getModifiers().contains(Modifier.ABSTRACT);
-    }
-
-    public int getEvaluatedCount() {
-        int count = 0;
-        for (ActualParameter parameter : getParameters()) {
-            if (parameter.getSpecification().isSignature()) {
-                count++;
-            }
-        }
-        return count;
-    }
-
-    @Override
-    public int hashCode() {
-        return type.hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof ExecutableTypeData) {
-            return type.equals(((ExecutableTypeData) obj).type);
-        }
-        return super.equals(obj);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public class ExecutableTypeMethodParser extends NodeMethodParser<ExecutableTypeData> {
-
-    public ExecutableTypeMethodParser(ProcessorContext context, NodeData node) {
-        super(context, node);
-        setEmitErrors(false);
-        setParseNullOnError(false);
-        setUseVarArgs(true);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        MethodSpec spec = createDefaultMethodSpec(method, mirror, false, null);
-        List<ParameterSpec> requiredSpecs = new ArrayList<>(spec.getRequired());
-        spec.getRequired().clear();
-
-        List<TypeMirror> allowedTypes = getNode().getTypeSystem().getPrimitiveTypeMirrors();
-        for (ParameterSpec originalSpec : requiredSpecs) {
-            spec.addRequired(new ParameterSpec(originalSpec, allowedTypes));
-        }
-        spec.setIgnoreAdditionalSpecifications(true);
-        spec.setIgnoreAdditionalParameters(true);
-        spec.setVariableRequiredParameters(true);
-        // varargs
-        ParameterSpec otherParameters = new ParameterSpec("other", allowedTypes);
-        otherParameters.setSignature(true);
-        spec.addRequired(otherParameters);
-        return spec;
-    }
-
-    @Override
-    public final boolean isParsable(ExecutableElement method) {
-        if (method.getModifiers().contains(Modifier.STATIC)) {
-            return false;
-        } else if (method.getModifiers().contains(Modifier.NATIVE)) {
-            return false;
-        }
-        return method.getSimpleName().toString().startsWith("execute");
-    }
-
-    @Override
-    protected List<TypeMirror> nodeTypeMirrors(NodeData nodeData) {
-        List<TypeMirror> types = new ArrayList<>(getNode().getTypeSystem().getPrimitiveTypeMirrors());
-        types.add(getNode().getTypeSystem().getVoidType().getPrimitiveType());
-        return types;
-    }
-
-    @Override
-    public ExecutableTypeData create(TemplateMethod method, boolean invalid) {
-        TypeData resolvedType = method.getReturnType().getTypeSystemType();
-        return new ExecutableTypeData(method, method.getMethod(), getNode().getTypeSystem(), resolvedType);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return null;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.SpecializationData.SpecializationKind;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class GenericParser extends NodeMethodParser<SpecializationData> {
-
-    public GenericParser(ProcessorContext context, NodeData node) {
-        super(context, node);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        return createDefaultMethodSpec(method, mirror, true, null);
-    }
-
-    @Override
-    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
-        List<ExecutableTypeData> execTypes = execution.getChild().findGenericExecutableTypes(getContext());
-        List<TypeMirror> types = new ArrayList<>();
-        for (ExecutableTypeData type : execTypes) {
-            types.add(type.getType().getPrimitiveType());
-        }
-        ParameterSpec spec = new ParameterSpec(execution.getName(), types);
-        spec.setExecution(execution);
-        return spec;
-    }
-
-    @Override
-    public SpecializationData create(TemplateMethod method, boolean invalid) {
-        return new SpecializationData(getNode(), method, SpecializationKind.GENERIC);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return Generic.class;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeChildData.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,169 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public class NodeChildData extends MessageContainer {
-
-    public enum Cardinality {
-        ONE,
-        MANY;
-
-        public boolean isMany() {
-            return this == MANY;
-        }
-
-        public boolean isOne() {
-            return this == ONE;
-        }
-    }
-
-    private NodeData parentNode;
-    private final Element sourceElement;
-    private final AnnotationMirror sourceAnnotationMirror;
-    private final String name;
-    private final TypeMirror type;
-    private final TypeMirror originalType;
-    private final Element accessElement;
-    private final Cardinality cardinality;
-
-    private List<NodeChildData> executeWith = Collections.emptyList();
-
-    private NodeData childNode;
-
-    public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, TypeMirror originalNodeType, Element accessElement, Cardinality cardinality) {
-        this.sourceElement = sourceElement;
-        this.sourceAnnotationMirror = sourceMirror;
-        this.name = name;
-        this.type = nodeType;
-        this.originalType = originalNodeType;
-        this.accessElement = accessElement;
-        this.cardinality = cardinality;
-    }
-
-    void setParentNode(NodeData parentNode) {
-        this.parentNode = parentNode;
-    }
-
-    public List<NodeChildData> getExecuteWith() {
-        return executeWith;
-    }
-
-    void setExecuteWith(List<NodeChildData> executeWith) {
-        this.executeWith = executeWith;
-    }
-
-    public boolean needsImplicitCast(ProcessorContext context) {
-        if (!parentNode.needsRewrites(context)) {
-            return false;
-        }
-
-        boolean used = false;
-        for (NodeExecutionData execution : parentNode.getChildExecutions()) {
-            if (execution.getChild() == 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 = childNode.findExecutableType(targetType, getExecuteWith().size());
-        if (executableType == null) {
-            executableType = findAnyGenericExecutableType(context);
-        }
-        return executableType;
-    }
-
-    public List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context) {
-        return childNode.findGenericExecutableTypes(context, getExecuteWith().size());
-    }
-
-    public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context) {
-        return childNode.findAnyGenericExecutableType(context, getExecuteWith().size());
-    }
-
-    public List<ExecutableTypeData> findExecutableTypes() {
-        return childNode.getExecutableTypes(getExecuteWith().size());
-    }
-
-    public TypeMirror getOriginalType() {
-        return originalType;
-    }
-
-    @Override
-    public Element getMessageElement() {
-        return sourceElement;
-    }
-
-    @Override
-    public AnnotationMirror getMessageAnnotation() {
-        return sourceAnnotationMirror;
-    }
-
-    void setNode(NodeData nodeData) {
-        this.childNode = nodeData;
-        if (nodeData != null) {
-            getMessages().addAll(nodeData.collectMessages());
-        }
-    }
-
-    public Element getAccessElement() {
-        return accessElement;
-    }
-
-    public TypeMirror getNodeType() {
-        return type;
-    }
-
-    public Cardinality getCardinality() {
-        return cardinality;
-    }
-
-    public NodeData getNodeData() {
-        return childNode;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    @Override
-    public String toString() {
-        return "NodeFieldData[name=" + getName() + ", kind=" + cardinality + ", node=" + getNodeData() + "]";
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2968 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import static com.oracle.truffle.dsl.processor.Utils.*;
-import static javax.lang.model.element.Modifier.*;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.ast.*;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality;
-import com.oracle.truffle.dsl.processor.node.SpecializationGroup.TypeGuard;
-import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public class NodeCodeGenerator extends CompilationUnitFactory<NodeData> {
-
-    private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode";
-
-    private static final String EXECUTE_GENERIC_NAME = "executeGeneric0";
-    private static final String EXECUTE_SPECIALIZE_NAME = "executeAndSpecialize0";
-    private static final String EXECUTE_POLYMORPHIC_NAME = "executePolymorphic0";
-
-    private static final String UPDATE_TYPES_NAME = "updateTypes";
-    private static final String COPY_WITH_CONSTRUCTOR_NAME = "copyWithConstructor";
-    private static final String CREATE_SPECIALIZATION_NAME = "createSpecialization";
-
-    public NodeCodeGenerator(ProcessorContext context) {
-        super(context);
-    }
-
-    private TypeMirror getUnexpectedValueException() {
-        return getContext().getTruffleTypes().getUnexpectedValueException();
-    }
-
-    private static String factoryClassName(NodeData node) {
-        return node.getNodeId() + "Factory";
-    }
-
-    private static String nodeSpecializationClassName(SpecializationData specialization) {
-        String nodeid = resolveNodeId(specialization.getNode());
-        String name = Utils.firstLetterUpperCase(nodeid);
-        name += Utils.firstLetterUpperCase(specialization.getId());
-        name += "Node";
-        return name;
-    }
-
-    private static String nodePolymorphicClassName(NodeData node) {
-        return Utils.firstLetterUpperCase(resolveNodeId(node)) + "PolymorphicNode";
-    }
-
-    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 implicitTypeName(ActualParameter param) {
-        return param.getLocalName() + "ImplicitType";
-    }
-
-    private static String polymorphicTypeName(ActualParameter param) {
-        return param.getLocalName() + "PolymorphicType";
-    }
-
-    private static String valueName(ActualParameter param) {
-        return param.getLocalName();
-    }
-
-    private static CodeTree createAccessChild(NodeExecutionData targetExecution, String thisReference) {
-        String reference = thisReference;
-        if (reference == null) {
-            reference = "this";
-        }
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        Element accessElement = targetExecution.getChild().getAccessElement();
-        if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) {
-            builder.string(reference).string(".").string(targetExecution.getChild().getName());
-        } else if (accessElement.getKind() == ElementKind.FIELD) {
-            builder.string(reference).string(".").string(accessElement.getSimpleName().toString());
-        } else {
-            throw new AssertionError();
-        }
-        if (targetExecution.isIndexed()) {
-            builder.string("[" + targetExecution.getIndex() + "]");
-        }
-        return builder.getRoot();
-    }
-
-    private static String castValueName(ActualParameter parameter) {
-        return valueName(parameter) + "Cast";
-    }
-
-    private void addInternalValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame, boolean evaluated) {
-        if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
-            method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue"));
-        }
-        for (ActualParameter parameter : specialization.getParameters()) {
-            ParameterSpec spec = parameter.getSpecification();
-            if (forceFrame && spec.getName().equals("frame")) {
-                continue;
-            }
-            if (spec.isLocal()) {
-                continue;
-            }
-
-            String name = valueName(parameter);
-            if (evaluated && spec.isSignature()) {
-                name = valueNameEvaluated(parameter);
-            }
-
-            method.addParameter(new CodeVariableElement(parameter.getType(), name));
-        }
-    }
-
-    private void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame,
-                    Map<String, String> customNames) {
-        if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
-            builder.string("frameValue");
-        }
-        for (ActualParameter parameter : specialization.getParameters()) {
-            ParameterSpec spec = parameter.getSpecification();
-            if (forceFrame && spec.getName().equals("frame")) {
-                continue;
-            }
-
-            if (parameter.getSpecification().isLocal()) {
-                continue;
-            }
-
-            ActualParameter sourceParameter = source.findParameter(parameter.getLocalName());
-
-            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));
-            } else {
-                builder.string(valueName(parameter));
-            }
-        }
-    }
-
-    private String valueName(ActualParameter sourceParameter, ActualParameter targetParameter) {
-        if (!sourceParameter.getSpecification().isSignature()) {
-            return valueName(targetParameter);
-        } else if (sourceParameter.getTypeSystemType() != null && targetParameter.getTypeSystemType() != null) {
-            if (sourceParameter.getTypeSystemType().needsCastTo(getContext(), targetParameter.getTypeSystemType())) {
-                return castValueName(targetParameter);
-            }
-        }
-        return valueName(targetParameter);
-    }
-
-    private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName,
-                    String... customSignatureValueNames) {
-        CodeTreeBuilder builder = parent.create();
-
-        boolean castedValues = sourceMethod != targetMethod;
-
-        builder.startGroup();
-        ExecutableElement method = targetMethod.getMethod();
-        if (method == null) {
-            throw new UnsupportedOperationException();
-        }
-        TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement());
-        NodeData node = (NodeData) targetMethod.getTemplate();
-
-        if (target == null) {
-            boolean accessible = targetMethod.canBeAccessedByInstanceOf(getContext(), node.getNodeType());
-            if (accessible) {
-                if (builder.findMethod().getModifiers().contains(STATIC)) {
-                    if (method.getModifiers().contains(STATIC)) {
-                        builder.type(targetClass.asType());
-                    } else {
-                        builder.string(THIS_NODE_LOCAL_VAR_NAME);
-                    }
-                } else {
-                    if (targetMethod instanceof ExecutableTypeData) {
-                        builder.string("this");
-                    } else {
-                        builder.string("super");
-                    }
-                }
-            } else {
-                if (method.getModifiers().contains(STATIC)) {
-                    builder.type(targetClass.asType());
-                } else {
-                    ActualParameter firstParameter = null;
-                    for (ActualParameter searchParameter : targetMethod.getParameters()) {
-                        if (searchParameter.getSpecification().isSignature()) {
-                            firstParameter = searchParameter;
-                            break;
-                        }
-                    }
-                    if (firstParameter == null) {
-                        throw new AssertionError();
-                    }
-
-                    ActualParameter sourceParameter = sourceMethod.findParameter(firstParameter.getLocalName());
-
-                    if (castedValues && sourceParameter != null) {
-                        builder.string(valueName(sourceParameter, firstParameter));
-                    } else {
-                        builder.string(valueName(firstParameter));
-                    }
-                }
-            }
-            builder.string(".");
-        } else {
-            builder.tree(target);
-        }
-        builder.startCall(method.getSimpleName().toString());
-
-        int signatureIndex = 0;
-
-        for (ActualParameter targetParameter : targetMethod.getParameters()) {
-            ActualParameter valueParameter = null;
-            if (sourceMethod != null) {
-                valueParameter = sourceMethod.findParameter(targetParameter.getLocalName());
-            }
-            if (valueParameter == null) {
-                valueParameter = targetParameter;
-            }
-            TypeMirror targetType = targetParameter.getType();
-            TypeMirror valueType = null;
-            if (valueParameter != null) {
-                valueType = valueParameter.getType();
-            }
-
-            if (signatureIndex < customSignatureValueNames.length && targetParameter.getSpecification().isSignature()) {
-                builder.string(customSignatureValueNames[signatureIndex]);
-                signatureIndex++;
-            } else if (targetParameter.getSpecification().isLocal()) {
-                builder.startGroup();
-                if (builder.findMethod().getModifiers().contains(Modifier.STATIC)) {
-                    builder.string(THIS_NODE_LOCAL_VAR_NAME).string(".");
-                } else {
-                    builder.string("this.");
-                }
-                builder.string(targetParameter.getSpecification().getName());
-                builder.end();
-            } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) {
-                builder.cast(targetParameter.getType(), CodeTreeBuilder.singleString("ex.getResult()"));
-            } else if (!Utils.needsCastTo(getContext(), valueType, targetType)) {
-                builder.startGroup();
-                builder.string(valueName(targetParameter));
-                builder.end();
-            } else {
-                builder.string(castValueName(targetParameter));
-            }
-        }
-
-        builder.end().end();
-
-        return builder.getRoot();
-    }
-
-    private static String baseClassName(NodeData node) {
-        String nodeid = resolveNodeId(node);
-        String name = Utils.firstLetterUpperCase(nodeid);
-        name += "BaseNode";
-        return name;
-    }
-
-    private static CodeTree createCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder parent, NodeData node, String methodName, CodeTree... args) {
-        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-        startCallTypeSystemMethod(context, builder, node.getTypeSystem(), methodName);
-        for (CodeTree arg : args) {
-            builder.tree(arg);
-        }
-        builder.end().end();
-        return builder.getRoot();
-    }
-
-    private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body, TypeSystemData typeSystem, String methodName) {
-        VariableElement singleton = TypeSystemCodeGenerator.findSingleton(context, typeSystem);
-        assert singleton != null;
-
-        body.startGroup();
-        body.staticReference(singleton.getEnclosingElement().asType(), singleton.getSimpleName().toString());
-        body.string(".").startCall(methodName);
-    }
-
-    /**
-     * <pre>
-     * variant1 $condition != null
-     *
-     * $type $name = defaultValue($type);
-     * if ($condition) {
-     *     $name = $value;
-     * }
-     *
-     * variant2 $condition != null
-     * $type $name = $value;
-     * </pre>
-     *
-     * .
-     */
-    private static CodeTree createLazyAssignment(CodeTreeBuilder parent, String name, TypeMirror type, CodeTree condition, CodeTree value) {
-        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-        if (condition == null) {
-            builder.declaration(type, name, value);
-        } else {
-            builder.declaration(type, name, new CodeTreeBuilder(parent).defaultValue(type).getRoot());
-
-            builder.startIf().tree(condition).end();
-            builder.startBlock();
-            builder.startStatement();
-            builder.string(name);
-            builder.string(" = ");
-            builder.tree(value);
-            builder.end(); // statement
-            builder.end(); // block
-        }
-        return builder.getRoot();
-    }
-
-    protected void emitEncounteredSynthetic(CodeTreeBuilder builder, TemplateMethod current) {
-        CodeTreeBuilder nodes = builder.create();
-        CodeTreeBuilder arguments = builder.create();
-        nodes.startCommaGroup();
-        arguments.startCommaGroup();
-        boolean empty = true;
-        for (ActualParameter parameter : current.getParameters()) {
-            NodeExecutionData executionData = parameter.getSpecification().getExecution();
-            if (executionData != null) {
-                if (executionData.isShortCircuit()) {
-                    nodes.nullLiteral();
-                    arguments.string(valueName(parameter.getPreviousParameter()));
-                }
-                nodes.tree(createAccessChild(executionData, null));
-                arguments.string(valueName(parameter));
-                empty = false;
-            }
-        }
-        nodes.end();
-        arguments.end();
-
-        builder.startThrow().startNew(getContext().getType(UnsupportedSpecializationException.class));
-        builder.string("this");
-        builder.startNewArray(getContext().getTruffleTypes().getNodeArray(), null);
-
-        builder.tree(nodes.getRoot());
-        builder.end();
-        if (!empty) {
-            builder.tree(arguments.getRoot());
-        }
-        builder.end().end();
-    }
-
-    private static List<ExecutableElement> findUserConstructors(TypeMirror nodeType) {
-        List<ExecutableElement> constructors = new ArrayList<>();
-        for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(nodeType).getEnclosedElements())) {
-            if (constructor.getModifiers().contains(PRIVATE)) {
-                continue;
-            }
-            if (isCopyConstructor(constructor)) {
-                continue;
-            }
-            constructors.add(constructor);
-        }
-
-        if (constructors.isEmpty()) {
-            constructors.add(new CodeExecutableElement(null, Utils.getSimpleName(nodeType)));
-        }
-
-        return constructors;
-    }
-
-    private static ExecutableElement findCopyConstructor(TypeMirror type) {
-        for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(type).getEnclosedElements())) {
-            if (constructor.getModifiers().contains(PRIVATE)) {
-                continue;
-            }
-            if (isCopyConstructor(constructor)) {
-                return constructor;
-            }
-        }
-
-        return null;
-    }
-
-    private static boolean isCopyConstructor(ExecutableElement element) {
-        if (element.getParameters().size() != 1) {
-            return false;
-        }
-        VariableElement var = element.getParameters().get(0);
-        TypeElement enclosingType = Utils.findNearestEnclosingType(var);
-        if (Utils.typeEquals(var.asType(), enclosingType.asType())) {
-            return true;
-        }
-        List<TypeElement> types = Utils.getDirectSuperTypes(enclosingType);
-        for (TypeElement type : types) {
-            if (!(type instanceof CodeTypeElement)) {
-                // no copy constructors which are not generated types
-                return false;
-            }
-
-            if (Utils.typeEquals(var.asType(), type.asType())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @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<>();
-        for (NodeData nodeChild : node.getEnclosingNodes()) {
-            NodeCodeGenerator generator = new NodeCodeGenerator(getContext());
-            childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements());
-        }
-
-        if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) {
-            NodeFactoryFactory factory = new NodeFactoryFactory(context, childTypes);
-            add(factory, node);
-            factory.getElement().getEnclosedElements().addAll(casts);
-        }
-    }
-
-    protected CodeTree createCastType(TypeSystemData typeSystem, 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, typeSystem, targetMethodName);
-        builder.tree(value);
-        builder.end().end();
-        return builder.getRoot();
-    }
-
-    protected CodeTree createExpectType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, CodeTree expression) {
-        return createCastType(typeSystem, sourceType, targetType, true, expression);
-    }
-
-    public CodeTree createDeoptimize(CodeTreeBuilder parent) {
-        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-        builder.startStatement();
-        builder.startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end();
-        builder.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) {
-            super(context);
-            this.childTypes = childElements;
-        }
-
-        @Override
-        protected CodeTypeElement create(NodeData node) {
-            Modifier visibility = Utils.getVisibility(node.getTemplateType().getModifiers());
-            CodeTypeElement clazz = createClass(node, modifiers(), factoryClassName(node), null, false);
-            if (visibility != null) {
-                clazz.getModifiers().add(visibility);
-            }
-            clazz.getModifiers().add(Modifier.FINAL);
-            clazz.add(createConstructorUsingFields(modifiers(PRIVATE), clazz));
-            return clazz;
-        }
-
-        @Override
-        protected void createChildren(NodeData node) {
-            CodeTypeElement clazz = getElement();
-
-            Modifier createVisibility = Utils.getVisibility(clazz.getModifiers());
-
-            CodeTypeElement polymorphicNode = null;
-            if (node.needsFactory()) {
-                NodeBaseFactory factory = new NodeBaseFactory(context);
-                add(factory, node.getGenericSpecialization() == null ? node.getSpecializations().get(0) : node.getGenericSpecialization());
-                generatedNode = factory.getElement();
-
-                if (node.needsRewrites(context)) {
-                    clazz.add(createCreateGenericMethod(node, createVisibility));
-                }
-
-                createFactoryMethods(node, clazz, createVisibility);
-
-                for (SpecializationData specialization : node.getSpecializations()) {
-                    if (!specialization.isReachable()) {
-                        continue;
-                    }
-
-                    if (specialization.isPolymorphic() && node.isPolymorphic()) {
-                        PolymorphicNodeFactory polymorphicFactory = new PolymorphicNodeFactory(getContext(), generatedNode);
-                        add(polymorphicFactory, specialization);
-                        polymorphicNode = polymorphicFactory.getElement();
-                        continue;
-                    }
-
-                    add(new SpecializedNodeFactory(context, generatedNode), specialization);
-                }
-
-                TypeMirror nodeFactory = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(NodeFactory.class)), node.getNodeType());
-                clazz.getImplements().add(nodeFactory);
-                clazz.add(createCreateNodeMethod(node));
-                clazz.add(createGetNodeClassMethod(node));
-                clazz.add(createGetNodeSignaturesMethod());
-                clazz.add(createGetChildrenSignatureMethod(node));
-                clazz.add(createGetInstanceMethod(node, createVisibility));
-                clazz.add(createInstanceConstant(node, clazz.asType()));
-            }
-
-            if (polymorphicNode != null) {
-                patchParameterType(clazz, UPDATE_TYPES_NAME, generatedNode.asType(), polymorphicNode.asType());
-            }
-
-            for (NodeData childNode : childTypes.keySet()) {
-                if (childNode.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) {
-                    continue;
-                }
-
-                for (TypeElement type : childTypes.get(childNode)) {
-                    Set<Modifier> typeModifiers = ((CodeTypeElement) type).getModifiers();
-                    Modifier visibility = Utils.getVisibility(type.getModifiers());
-                    typeModifiers.clear();
-                    if (visibility != null) {
-                        typeModifiers.add(visibility);
-                    }
-
-                    typeModifiers.add(Modifier.STATIC);
-                    typeModifiers.add(Modifier.FINAL);
-                    clazz.add(type);
-                }
-            }
-
-            List<NodeData> children = node.getNodeDeclaringChildren();
-            if (node.getDeclaringNode() == null && children.size() > 0) {
-                clazz.add(createGetFactories(node));
-            }
-
-        }
-
-        private void patchParameterType(CodeTypeElement enclosingClass, String methodName, TypeMirror originalType, TypeMirror newType) {
-            for (TypeElement enclosedType : ElementFilter.typesIn(enclosingClass.getEnclosedElements())) {
-                CodeTypeElement type = (CodeTypeElement) enclosedType;
-                ExecutableElement method = type.getMethod(methodName);
-                for (VariableElement v : method.getParameters()) {
-                    CodeVariableElement var = (CodeVariableElement) v;
-                    if (Utils.typeEquals(var.getType(), originalType)) {
-                        var.setType(newType);
-                    }
-                }
-            }
-        }
-
-        private CodeExecutableElement createGetNodeClassMethod(NodeData node) {
-            TypeMirror returnType = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(Class.class)), node.getNodeType());
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeClass");
-            CodeTreeBuilder builder = method.createBuilder();
-            builder.startReturn().typeLiteral(node.getNodeType()).end();
-            return method;
-        }
-
-        private CodeExecutableElement createGetNodeSignaturesMethod() {
-            TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class));
-            TypeMirror classType = getContext().getType(Class.class);
-            TypeMirror returnType = Utils.getDeclaredType(listType, Utils.getDeclaredType(listType, classType));
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeSignatures");
-            CodeTreeBuilder builder = method.createBuilder();
-            builder.startReturn();
-            builder.startStaticCall(getContext().getType(Arrays.class), "asList");
-            List<ExecutableElement> constructors = findUserConstructors(generatedNode.asType());
-            for (ExecutableElement constructor : constructors) {
-                builder.tree(createAsList(builder, Utils.asTypeMirrors(constructor.getParameters()), classType));
-            }
-            builder.end();
-            builder.end();
-            return method;
-        }
-
-        private CodeExecutableElement createGetChildrenSignatureMethod(NodeData node) {
-            Types types = getContext().getEnvironment().getTypeUtils();
-            TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class));
-            TypeMirror classType = getContext().getType(Class.class);
-            TypeMirror nodeType = getContext().getTruffleTypes().getNode();
-            TypeMirror wildcardNodeType = types.getWildcardType(nodeType, null);
-            classType = Utils.getDeclaredType(Utils.fromTypeMirror(classType), wildcardNodeType);
-            TypeMirror returnType = Utils.getDeclaredType(listType, classType);
-
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getExecutionSignature");
-            CodeTreeBuilder builder = method.createBuilder();
-
-            List<TypeMirror> signatureTypes = new ArrayList<>();
-            assert !node.getSpecializations().isEmpty();
-            SpecializationData data = node.getSpecializations().get(0);
-
-            for (ActualParameter parameter : data.getSignatureParameters()) {
-                signatureTypes.add(parameter.getSpecification().getExecution().getNodeType());
-            }
-
-            builder.startReturn().tree(createAsList(builder, signatureTypes, classType)).end();
-            return method;
-        }
-
-        private CodeTree createAsList(CodeTreeBuilder parent, List<TypeMirror> types, TypeMirror elementClass) {
-            CodeTreeBuilder builder = parent.create();
-            builder.startGroup();
-            builder.type(getContext().getType(Arrays.class));
-            builder.string(".<").type(elementClass).string(">");
-            builder.startCall("asList");
-            for (TypeMirror typeMirror : types) {
-                builder.typeLiteral(typeMirror);
-            }
-            builder.end().end();
-            return builder.getRoot();
-        }
-
-        private CodeExecutableElement createCreateNodeMethod(NodeData node) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNode");
-            CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Object.class), "arguments");
-            method.setVarArgs(true);
-            method.addParameter(arguments);
-
-            CodeTreeBuilder builder = method.createBuilder();
-            List<ExecutableElement> signatures = findUserConstructors(generatedNode.asType());
-            boolean ifStarted = false;
-
-            for (ExecutableElement element : signatures) {
-                ifStarted = builder.startIf(ifStarted);
-                builder.string("arguments.length == " + element.getParameters().size());
-
-                int index = 0;
-                for (VariableElement param : element.getParameters()) {
-                    if (Utils.isObject(param.asType())) {
-                        continue;
-                    }
-                    builder.string(" && ");
-                    if (!param.asType().getKind().isPrimitive()) {
-                        builder.string("(arguments[" + index + "] == null || ");
-                    }
-                    builder.string("arguments[" + index + "] instanceof ");
-                    builder.type(Utils.boxType(getContext(), param.asType()));
-                    if (!param.asType().getKind().isPrimitive()) {
-                        builder.string(")");
-                    }
-                    index++;
-                }
-                builder.end();
-                builder.startBlock();
-
-                builder.startReturn().startCall("create");
-                index = 0;
-                for (VariableElement param : element.getParameters()) {
-                    builder.startGroup();
-                    if (!Utils.isObject(param.asType())) {
-                        builder.string("(").type(param.asType()).string(") ");
-                    }
-                    builder.string("arguments[").string(String.valueOf(index)).string("]");
-                    builder.end();
-                    index++;
-                }
-                builder.end().end();
-
-                builder.end(); // block
-            }
-
-            builder.startElseBlock();
-            builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class));
-            builder.doubleQuote("Invalid create signature.");
-            builder.end().end();
-            builder.end(); // else block
-            return method;
-        }
-
-        private ExecutableElement createGetInstanceMethod(NodeData node, Modifier visibility) {
-            TypeElement nodeFactoryType = Utils.fromTypeMirror(getContext().getType(NodeFactory.class));
-            TypeMirror returnType = Utils.getDeclaredType(nodeFactoryType, node.getNodeType());
-
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(), returnType, "getInstance");
-            if (visibility != null) {
-                method.getModifiers().add(visibility);
-            }
-            method.getModifiers().add(Modifier.STATIC);
-
-            String varName = instanceVarName(node);
-
-            CodeTreeBuilder builder = method.createBuilder();
-            builder.startIf();
-            builder.string(varName).string(" == null");
-            builder.end().startBlock();
-
-            builder.startStatement();
-            builder.string(varName);
-            builder.string(" = ");
-            builder.startNew(factoryClassName(node)).end();
-            builder.end();
-
-            builder.end();
-            builder.startReturn().string(varName).end();
-            return method;
-        }
-
-        private String instanceVarName(NodeData node) {
-            if (node.getDeclaringNode() != null) {
-                return Utils.firstLetterLowerCase(factoryClassName(node)) + "Instance";
-            } else {
-                return "instance";
-            }
-        }
-
-        private CodeVariableElement createInstanceConstant(NodeData node, TypeMirror factoryType) {
-            String varName = instanceVarName(node);
-            CodeVariableElement var = new CodeVariableElement(modifiers(), factoryType, varName);
-            var.getModifiers().add(Modifier.PRIVATE);
-            var.getModifiers().add(Modifier.STATIC);
-            return var;
-        }
-
-        private ExecutableElement createGetFactories(NodeData node) {
-            List<NodeData> children = node.getNodeDeclaringChildren();
-            if (node.needsFactory()) {
-                children.add(node);
-            }
-
-            List<TypeMirror> nodeTypesList = new ArrayList<>();
-            TypeMirror prev = null;
-            boolean allSame = true;
-            for (NodeData child : children) {
-                nodeTypesList.add(child.getNodeType());
-                if (prev != null && !Utils.typeEquals(child.getNodeType(), prev)) {
-                    allSame = false;
-                }
-                prev = child.getNodeType();
-            }
-            TypeMirror commonNodeSuperType = Utils.getCommonSuperType(getContext(), nodeTypesList.toArray(new TypeMirror[nodeTypesList.size()]));
-
-            Types types = getContext().getEnvironment().getTypeUtils();
-            TypeMirror factoryType = getContext().getType(NodeFactory.class);
-            TypeMirror baseType;
-            if (allSame) {
-                baseType = Utils.getDeclaredType(Utils.fromTypeMirror(factoryType), commonNodeSuperType);
-            } else {
-                baseType = Utils.getDeclaredType(Utils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null));
-            }
-            TypeMirror listType = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(List.class)), baseType);
-
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), listType, "getFactories");
-
-            CodeTreeBuilder builder = method.createBuilder();
-            builder.startReturn();
-            builder.startStaticCall(getContext().getType(Arrays.class), "asList");
-
-            for (NodeData child : children) {
-                builder.startGroup();
-                NodeData childNode = child;
-                List<NodeData> factories = new ArrayList<>();
-                while (childNode.getDeclaringNode() != null) {
-                    factories.add(childNode);
-                    childNode = childNode.getDeclaringNode();
-                }
-                Collections.reverse(factories);
-                for (NodeData nodeData : factories) {
-                    builder.string(factoryClassName(nodeData)).string(".");
-                }
-                builder.string("getInstance()");
-                builder.end();
-            }
-            builder.end();
-            builder.end();
-            return method;
-        }
-
-        private void createFactoryMethods(NodeData node, CodeTypeElement clazz, Modifier createVisibility) {
-            List<ExecutableElement> constructors = findUserConstructors(generatedNode.asType());
-            for (ExecutableElement constructor : constructors) {
-                clazz.add(createCreateMethod(node, createVisibility, constructor));
-            }
-        }
-
-        private CodeExecutableElement createCreateMethod(NodeData node, Modifier visibility, ExecutableElement constructor) {
-            CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), constructor);
-            method.setSimpleName(CodeNames.of("create"));
-            method.getModifiers().clear();
-            if (visibility != null) {
-                method.getModifiers().add(visibility);
-            }
-            method.getModifiers().add(Modifier.STATIC);
-            method.setReturnType(node.getNodeType());
-
-            CodeTreeBuilder body = method.createBuilder();
-            body.startReturn();
-            if (node.getSpecializations().isEmpty()) {
-                body.nullLiteral();
-            } else {
-                body.startCall(nodeSpecializationClassName(node.getSpecializations().get(0)), CREATE_SPECIALIZATION_NAME);
-                for (VariableElement var : method.getParameters()) {
-                    body.string(var.getSimpleName().toString());
-                }
-                body.end();
-            }
-            body.end();
-            return method;
-        }
-
-        private CodeExecutableElement createCreateGenericMethod(NodeData node, Modifier visibility) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(), node.getNodeType(), "createGeneric");
-            if (visibility != null) {
-                method.getModifiers().add(visibility);
-            }
-            method.getModifiers().add(Modifier.STATIC);
-            method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME));
-
-            CodeTreeBuilder body = method.createBuilder();
-
-            SpecializationData found = null;
-            List<SpecializationData> specializations = node.getSpecializations();
-            for (int i = 0; i < specializations.size(); i++) {
-                if (specializations.get(i).isReachable()) {
-                    found = specializations.get(i);
-                }
-            }
-
-            if (found == null) {
-                body.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end();
-            } else {
-                body.startReturn().startCall(nodeSpecializationClassName(found), CREATE_SPECIALIZATION_NAME).startGroup().string(THIS_NODE_LOCAL_VAR_NAME).end().end().end();
-            }
-            return method;
-        }
-    }
-
-    private class NodeBaseFactory extends ClassElementFactory<SpecializationData> {
-
-        public NodeBaseFactory(ProcessorContext context) {
-            super(context);
-        }
-
-        @Override
-        protected CodeTypeElement create(SpecializationData specialization) {
-            NodeData node = specialization.getNode();
-            CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, ABSTRACT, STATIC), baseClassName(node), node.getNodeType(), false);
-
-            for (NodeChildData child : node.getChildren()) {
-                clazz.add(createChildField(child));
-
-                if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) {
-                    ExecutableElement getter = (ExecutableElement) child.getAccessElement();
-                    CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), getter);
-                    method.getModifiers().remove(Modifier.ABSTRACT);
-                    CodeTreeBuilder builder = method.createBuilder();
-                    builder.startReturn().string("this.").string(child.getName()).end();
-                    clazz.add(method);
-                }
-            }
-
-            for (NodeFieldData field : node.getFields()) {
-                if (!field.isGenerated()) {
-                    continue;
-                }
-
-                clazz.add(new CodeVariableElement(modifiers(PROTECTED, FINAL), field.getType(), field.getName()));
-                if (field.getGetter() != null && field.getGetter().getModifiers().contains(Modifier.ABSTRACT)) {
-                    CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), field.getGetter());
-                    method.getModifiers().remove(Modifier.ABSTRACT);
-                    method.createBuilder().startReturn().string("this.").string(field.getName()).end();
-                    clazz.add(method);
-                }
-            }
-
-            for (String assumption : node.getAssumptions()) {
-                clazz.add(createAssumptionField(assumption));
-            }
-
-            createConstructors(node, clazz);
-
-            return clazz;
-        }
-
-        @Override
-        protected void createChildren(SpecializationData specialization) {
-            NodeData node = specialization.getNode();
-            CodeTypeElement clazz = getElement();
-
-            SpecializationGroup rootGroup = createSpecializationGroups(node);
-
-            if (node.needsRewrites(context)) {
-                if (node.isPolymorphic()) {
-
-                    CodeVariableElement var = new CodeVariableElement(modifiers(PROTECTED), clazz.asType(), "next0");
-                    var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation()));
-                    clazz.add(var);
-
-                    CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getPolymorphicSpecialization());
-                    clazz.add(genericCachedExecute);
-
-                    getElement().add(createUpdateTypes(clazz.asType()));
-                }
-
-                for (CodeExecutableElement method : createImplicitChildrenAccessors()) {
-                    clazz.add(method);
-                }
-                clazz.add(createGenericExecuteAndSpecialize(node, rootGroup));
-                clazz.add(createInfoMessage(node));
-            }
-
-            if (needsInvokeCopyConstructorMethod()) {
-                clazz.add(createCopy(clazz.asType(), null));
-            }
-
-            if (node.getGenericSpecialization() != null && node.getGenericSpecialization().isReachable()) {
-                clazz.add(createGenericExecute(node, rootGroup));
-            }
-        }
-
-        protected boolean needsInvokeCopyConstructorMethod() {
-            return getModel().getNode().isPolymorphic();
-        }
-
-        protected CodeExecutableElement createCopy(TypeMirror baseType, SpecializationData specialization) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), baseType, COPY_WITH_CONSTRUCTOR_NAME);
-            if (specialization == null) {
-                method.getModifiers().add(ABSTRACT);
-            } else {
-                CodeTreeBuilder builder = method.createBuilder();
-                builder.startReturn();
-                builder.startNew(getElement().asType());
-                builder.string("this");
-                for (ActualParameter param : getImplicitTypeParameters(specialization)) {
-                    builder.string(implicitTypeName(param));
-                }
-                builder.end().end();
-            }
-            return method;
-        }
-
-        private List<CodeExecutableElement> createImplicitChildrenAccessors() {
-            NodeData node = getModel().getNode();
-            List<Set<TypeData>> prototype = Collections.nCopies(node.getGenericSpecialization().getParameters().size(), null);
-            List<Set<TypeData>> expectTypes = new ArrayList<>(prototype);
-
-            for (ExecutableTypeData executableType : node.getExecutableTypes()) {
-                for (int i = 0; i < executableType.getEvaluatedCount(); i++) {
-                    ActualParameter parameter = executableType.getSignatureParameter(i);
-                    if (i >= expectTypes.size()) {
-                        break;
-                    }
-                    Set<TypeData> types = expectTypes.get(i);
-                    if (types == null) {
-                        types = new TreeSet<>();
-                        expectTypes.set(i, types);
-                    }
-                    types.add(parameter.getTypeSystemType());
-                }
-            }
-
-            List<CodeExecutableElement> methods = new ArrayList<>();
-            List<Set<TypeData>> visitedList = new ArrayList<>(prototype);
-            for (SpecializationData spec : node.getSpecializations()) {
-                int signatureIndex = -1;
-                for (ActualParameter param : spec.getParameters()) {
-                    if (!param.getSpecification().isSignature()) {
-                        continue;
-                    }
-                    signatureIndex++;
-                    Set<TypeData> visitedTypeData = visitedList.get(signatureIndex);
-                    if (visitedTypeData == null) {
-                        visitedTypeData = new TreeSet<>();
-                        visitedList.set(signatureIndex, visitedTypeData);
-                    }
-
-                    if (visitedTypeData.contains(param.getTypeSystemType())) {
-                        continue;
-                    }
-                    visitedTypeData.add(param.getTypeSystemType());
-
-                    Set<TypeData> expect = expectTypes.get(signatureIndex);
-                    if (expect == null) {
-                        expect = Collections.emptySet();
-                    }
-
-                    methods.addAll(createExecuteChilds(param, expect));
-                }
-            }
-            return methods;
-        }
-
-        private CodeTree truffleBooleanOption(CodeTreeBuilder parent, String name) {
-            CodeTreeBuilder builder = parent.create();
-            builder.staticReference(getContext().getTruffleTypes().getTruffleOptions(), name);
-            return builder.getRoot();
-        }
-
-        private Element createInfoMessage(NodeData node) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), getContext().getType(String.class), "createInfo0");
-            method.addParameter(new CodeVariableElement(getContext().getType(String.class), "message"));
-            addInternalValueParameters(method, node.getGenericSpecialization(), false, false);
-
-            CodeTreeBuilder builder = method.createBuilder();
-
-            builder.startIf().tree(truffleBooleanOption(builder, TruffleTypes.OPTION_DETAILED_REWRITE_REASONS)).end();
-            builder.startBlock();
-
-            builder.startStatement().string("StringBuilder builder = new StringBuilder(message)").end();
-            builder.startStatement().startCall("builder", "append").doubleQuote(" (").end().end();
-
-            String sep = null;
-            for (ActualParameter parameter : node.getGenericSpecialization().getSignatureParameters()) {
-                builder.startStatement();
-                builder.string("builder");
-                if (sep != null) {
-                    builder.startCall(".append").doubleQuote(sep).end();
-                }
-                builder.startCall(".append").doubleQuote(parameter.getLocalName()).end();
-                builder.startCall(".append").doubleQuote(" = ").end();
-                builder.startCall(".append").string(parameter.getLocalName()).end();
-                builder.end();
-
-                if (!Utils.isPrimitive(parameter.getType())) {
-                    builder.startIf().string(parameter.getLocalName() + " != null").end();
-                    builder.startBlock();
-                }
-                builder.startStatement();
-                if (Utils.isPrimitive(parameter.getType())) {
-                    builder.startCall("builder.append").doubleQuote(" (" + Utils.getSimpleName(parameter.getType()) + ")").end();
-                } else {
-                    builder.startCall("builder.append").doubleQuote(" (").end();
-                    builder.startCall(".append").string(parameter.getLocalName() + ".getClass().getSimpleName()").end();
-                    builder.startCall(".append").doubleQuote(")").end();
-                }
-                builder.end();
-                if (!Utils.isPrimitive(parameter.getType())) {
-                    builder.end();
-                }
-
-                sep = ", ";
-            }
-
-            builder.startStatement().startCall("builder", "append").doubleQuote(")").end().end();
-            builder.startReturn().string("builder.toString()").end();
-
-            builder.end();
-            builder.startElseBlock();
-            builder.startReturn().string("message").end();
-            builder.end();
-
-            return method;
-        }
-
-        private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph) {
-            CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), EXECUTE_POLYMORPHIC_NAME);
-            addInternalValueParameters(cachedExecute, polymorph, true, false);
-
-            ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0);
-            boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext());
-            if (sourceThrowsUnexpected && sourceExecutableType.getType().equals(node.getGenericSpecialization().getReturnType().getTypeSystemType())) {
-                sourceThrowsUnexpected = false;
-            }
-            if (sourceThrowsUnexpected) {
-                cachedExecute.getThrownTypes().add(getContext().getType(UnexpectedResultException.class));
-            }
-            return cachedExecute;
-
-        }
-
-        private void createConstructors(NodeData node, CodeTypeElement clazz) {
-            List<ExecutableElement> constructors = findUserConstructors(node.getNodeType());
-            ExecutableElement sourceSectionConstructor = null;
-            if (constructors.isEmpty()) {
-                clazz.add(createUserConstructor(clazz, null));
-            } else {
-                for (ExecutableElement constructor : constructors) {
-                    clazz.add(createUserConstructor(clazz, constructor));
-                    if (NodeParser.isSourceSectionConstructor(context, constructor)) {
-                        sourceSectionConstructor = constructor;
-                    }
-                }
-            }
-            if (node.needsRewrites(getContext())) {
-                clazz.add(createCopyConstructor(clazz, findCopyConstructor(node.getNodeType()), sourceSectionConstructor));
-            }
-        }
-
-        private CodeExecutableElement createUserConstructor(CodeTypeElement type, ExecutableElement superConstructor) {
-            CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
-            CodeTreeBuilder builder = method.createBuilder();
-
-            NodeData node = getModel().getNode();
-
-            if (superConstructor != null) {
-                for (VariableElement param : superConstructor.getParameters()) {
-                    method.getParameters().add(CodeVariableElement.clone(param));
-                }
-            }
-
-            if (superConstructor != null) {
-                builder.startStatement().startSuperCall();
-                for (VariableElement param : superConstructor.getParameters()) {
-                    builder.string(param.getSimpleName().toString());
-                }
-                builder.end().end();
-            }
-
-            for (VariableElement var : type.getFields()) {
-                NodeChildData child = node.findChild(var.getSimpleName().toString());
-
-                if (child != null) {
-                    method.getParameters().add(new CodeVariableElement(child.getOriginalType(), child.getName()));
-                } else {
-                    method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString()));
-                }
-
-                builder.startStatement();
-                String fieldName = var.getSimpleName().toString();
-
-                CodeTree init = createStaticCast(builder, child, fieldName);
-
-                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 CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor, ExecutableElement sourceSectionConstructor) {
-            CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
-            CodeTreeBuilder builder = method.createBuilder();
-            method.getParameters().add(new CodeVariableElement(type.asType(), "copy"));
-
-            if (superConstructor != null) {
-                builder.startStatement().startSuperCall().string("copy").end().end();
-            } else if (sourceSectionConstructor != null) {
-                builder.startStatement().startSuperCall().string("copy.getSourceSection()").end().end();
-            }
-
-            for (VariableElement var : type.getFields()) {
-                builder.startStatement();
-                final String varName = var.getSimpleName().toString();
-                final TypeMirror varType = var.asType();
-
-                String copyAccess = "copy." + varName;
-                if (Utils.isAssignable(getContext(), varType, getContext().getTruffleTypes().getNodeArray())) {
-                    copyAccess += ".clone()";
-                }
-                CodeTree init = CodeTreeBuilder.singleString(copyAccess);
-                builder.startStatement().string("this.").string(varName).string(" = ").tree(init).end();
-            }
-
-            return method;
-        }
-
-        private CodeVariableElement createAssumptionField(String assumption) {
-            CodeVariableElement var = new CodeVariableElement(getContext().getTruffleTypes().getAssumption(), assumption);
-            var.getModifiers().add(Modifier.FINAL);
-            return var;
-        }
-
-        private CodeVariableElement createChildField(NodeChildData child) {
-            TypeMirror type = child.getNodeType();
-            CodeVariableElement var = new CodeVariableElement(type, child.getName());
-            var.getModifiers().add(Modifier.PROTECTED);
-
-            DeclaredType annotationType;
-            if (child.getCardinality() == Cardinality.MANY) {
-                var.getModifiers().add(Modifier.FINAL);
-                annotationType = getContext().getTruffleTypes().getChildrenAnnotation();
-            } else {
-                annotationType = getContext().getTruffleTypes().getChildAnnotation();
-            }
-
-            var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType));
-            return var;
-        }
-
-        private CodeExecutableElement createGenericExecuteAndSpecialize(final NodeData node, SpecializationGroup rootGroup) {
-            TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType();
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), genericReturnType, EXECUTE_SPECIALIZE_NAME);
-            method.addParameter(new CodeVariableElement(getContext().getType(int.class), "minimumState"));
-            addInternalValueParameters(method, node.getGenericSpecialization(), true, false);
-            method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason"));
-
-            CodeTreeBuilder builder = method.createBuilder();
-            builder.startStatement();
-            builder.startStaticCall(getContext().getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end();
-            builder.end();
-
-            String currentNode = "this";
-            for (SpecializationData specialization : node.getSpecializations()) {
-                if (!specialization.getExceptions().isEmpty()) {
-                    currentNode = "current";
-                    builder.declaration(baseClassName(node), currentNode, "this");
-                    break;
-                }
-            }
-
-            builder.startStatement().string("String message = ").startCall("createInfo0").string("reason");
-            addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, false, null);
-            builder.end().end();
-
-            final String currentNodeVar = currentNode;
-            builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), rootGroup, true, new CodeBlock<SpecializationData>() {
-
-                public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
-                    return createGenericInvokeAndSpecialize(b, node.getGenericSpecialization(), current, currentNodeVar);
-                }
-            }, null, false, true, false));
-
-            boolean firstUnreachable = true;
-            for (SpecializationData current : node.getSpecializations()) {
-                if (current.isReachable()) {
-                    continue;
-                }
-                if (firstUnreachable) {
-                    emitEncounteredSynthetic(builder, current);
-                    firstUnreachable = false;
-                }
-            }
-            emitUnreachableSpecializations(builder, node);
-
-            return method;
-        }
-
-        private SpecializationGroup createSpecializationGroups(final NodeData node) {
-            List<SpecializationData> specializations = node.getSpecializations();
-            List<SpecializationData> filteredSpecializations = new ArrayList<>();
-            for (SpecializationData current : specializations) {
-                if (current.isUninitialized() || current.isPolymorphic() || !current.isReachable()) {
-                    continue;
-                }
-                filteredSpecializations.add(current);
-            }
-
-            return SpecializationGroup.create(filteredSpecializations);
-        }
-
-        private CodeExecutableElement createGenericExecute(NodeData node, SpecializationGroup group) {
-            TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType();
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), genericReturnType, EXECUTE_GENERIC_NAME);
-
-            if (!node.needsFrame(getContext())) {
-                method.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getSlowPath()));
-            }
-            addInternalValueParameters(method, node.getGenericSpecialization(), node.needsFrame(getContext()), false);
-            final CodeTreeBuilder builder = method.createBuilder();
-
-            builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), group, false, new CodeBlock<SpecializationData>() {
-
-                public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
-                    return createGenericInvoke(builder, current.getNode().getGenericSpecialization(), current);
-                }
-            }, null, false, true, false));
-
-            emitUnreachableSpecializations(builder, node);
-
-            return method;
-        }
-
-        private void emitUnreachableSpecializations(final CodeTreeBuilder builder, NodeData node) {
-            for (SpecializationData current : node.getSpecializations()) {
-                if (current.isReachable()) {
-                    continue;
-                }
-                builder.string("// unreachable ").string(current.getId()).newLine();
-            }
-        }
-
-        protected CodeTree createExecuteTree(CodeTreeBuilder outerParent, final SpecializationData source, final SpecializationGroup group, final boolean checkMinimumState,
-                        final CodeBlock<SpecializationData> guardedblock, final CodeTree elseBlock, boolean forceElse, final boolean emitAssumptions, final boolean typedCasts) {
-            return guard(outerParent, source, group, checkMinimumState, new CodeBlock<Integer>() {
-
-                public CodeTree create(CodeTreeBuilder parent, Integer ifCount) {
-                    CodeTreeBuilder builder = parent.create();
-
-                    if (group.getSpecialization() != null) {
-                        builder.tree(guardedblock.create(builder, group.getSpecialization()));
-
-                        assert group.getChildren().isEmpty() : "missed a specialization";
-
-                    } else {
-                        for (SpecializationGroup childGroup : group.getChildren()) {
-                            builder.tree(createExecuteTree(builder, source, childGroup, checkMinimumState, guardedblock, null, false, emitAssumptions, typedCasts));
-                        }
-                    }
-
-                    return builder.getRoot();
-                }
-            }, elseBlock, forceElse, emitAssumptions, typedCasts);
-        }
-
-        private CodeTree guard(CodeTreeBuilder parent, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, CodeBlock<Integer> bodyBlock, CodeTree elseBlock,
-                        boolean forceElse, boolean emitAssumptions, boolean typedCasts) {
-            CodeTreeBuilder builder = parent.create();
-
-            int ifCount = emitGuards(builder, source, group, checkMinimumState, emitAssumptions, typedCasts);
-
-            if (isReachableGroup(group, ifCount, checkMinimumState)) {
-                builder.tree(bodyBlock.create(builder, ifCount));
-            }
-
-            builder.end(ifCount);
-
-            if (elseBlock != null) {
-                if (ifCount > 0 || forceElse) {
-                    builder.tree(elseBlock);
-                }
-            }
-
-            return builder.getRoot();
-        }
-
-        private boolean isReachableGroup(SpecializationGroup group, int ifCount, boolean checkMinimumState) {
-            if (ifCount != 0) {
-                return true;
-            }
-            SpecializationGroup previous = group.getPreviousGroup();
-            if (previous == null || previous.findElseConnectableGuards(checkMinimumState).isEmpty()) {
-                return true;
-            }
-
-            /*
-             * Hacky else case. In this case the specialization is not reachable due to previous
-             * else branch. This is only true if the minimum state is not checked.
-             */
-            if (previous.getGuards().size() == 1 && previous.getTypeGuards().isEmpty() && previous.getAssumptions().isEmpty() && !checkMinimumState &&
-                            (previous.getParent() == null || previous.getMaxSpecializationIndex() != previous.getParent().getMaxSpecializationIndex())) {
-                return false;
-            }
-
-            return true;
-        }
-
-        private int emitGuards(CodeTreeBuilder builder, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, boolean emitAssumptions, boolean typedCasts) {
-            NodeData node = source.getNode();
-
-            CodeTreeBuilder guardsBuilder = builder.create();
-            CodeTreeBuilder castBuilder = builder.create();
-            CodeTreeBuilder guardsCastBuilder = builder.create();
-
-            String guardsAnd = "";
-            String guardsCastAnd = "";
-
-            boolean minimumState = checkMinimumState;
-            if (minimumState) {
-                int groupMaxIndex = group.getUncheckedSpecializationIndex();
-
-                if (groupMaxIndex > -1) {
-                    guardsBuilder.string(guardsAnd);
-                    guardsBuilder.string("minimumState < " + groupMaxIndex);
-                    guardsAnd = " && ";
-                }
-            }
-
-            if (emitAssumptions) {
-                for (String assumption : group.getAssumptions()) {
-                    guardsBuilder.string(guardsAnd);
-                    guardsBuilder.string("this");
-                    guardsBuilder.string(".").string(assumption).string(".isValid()");
-                    guardsAnd = " && ";
-                }
-            }
-
-            for (TypeGuard typeGuard : group.getTypeGuards()) {
-                ActualParameter valueParam = source.getSignatureParameter(typeGuard.getSignatureIndex());
-
-                if (valueParam == null) {
-                    /*
-                     * If used inside a execute evaluated method then the value param may not exist.
-                     * In that case we assume that the value is executed generic or of the current
-                     * specialization.
-                     */
-                    if (group.getSpecialization() != null) {
-                        valueParam = group.getSpecialization().getSignatureParameter(typeGuard.getSignatureIndex());
-                    } else {
-                        valueParam = node.getGenericSpecialization().getSignatureParameter(typeGuard.getSignatureIndex());
-                    }
-                }
-
-                NodeExecutionData execution = valueParam.getSpecification().getExecution();
-                CodeTree implicitGuard = createTypeGuard(guardsBuilder, execution, valueParam, typeGuard.getType(), typedCasts);
-                if (implicitGuard != null) {
-                    guardsBuilder.string(guardsAnd);
-                    guardsBuilder.tree(implicitGuard);
-                    guardsAnd = " && ";
-                }
-
-                CodeTree cast = createCast(castBuilder, execution, valueParam, typeGuard.getType(), checkMinimumState, typedCasts);
-                if (cast != null) {
-                    castBuilder.tree(cast);
-                }
-            }
-            List<GuardData> elseGuards = group.findElseConnectableGuards(checkMinimumState);
-
-            for (GuardData guard : group.getGuards()) {
-                if (elseGuards.contains(guard)) {
-                    continue;
-                }
-
-                if (needsTypeGuard(source, group, guard)) {
-                    guardsCastBuilder.tree(createMethodGuard(builder, guardsCastAnd, source, guard));
-                    guardsCastAnd = " && ";
-                } else {
-                    guardsBuilder.tree(createMethodGuard(builder, guardsAnd, source, guard));
-                    guardsAnd = " && ";
-                }
-            }
-
-            int ifCount = startGuardIf(builder, guardsBuilder, 0, elseGuards);
-            builder.tree(castBuilder.getRoot());
-            ifCount = startGuardIf(builder, guardsCastBuilder, ifCount, elseGuards);
-            return ifCount;
-        }
-
-        private int startGuardIf(CodeTreeBuilder builder, CodeTreeBuilder conditionBuilder, int ifCount, List<GuardData> elseGuard) {
-            int newIfCount = ifCount;
-
-            if (!conditionBuilder.isEmpty()) {
-                if (ifCount == 0 && !elseGuard.isEmpty()) {
-                    builder.startElseIf();
-                } else {
-                    builder.startIf();
-                }
-                builder.tree(conditionBuilder.getRoot());
-                builder.end().startBlock();
-                newIfCount++;
-            } else if (ifCount == 0 && !elseGuard.isEmpty()) {
-                builder.startElseBlock();
-                newIfCount++;
-            }
-            return newIfCount;
-        }
-
-        private boolean needsTypeGuard(SpecializationData source, SpecializationGroup group, GuardData guard) {
-            int signatureIndex = 0;
-            for (ActualParameter parameter : guard.getParameters()) {
-                if (!parameter.getSpecification().isSignature()) {
-                    continue;
-                }
-
-                TypeGuard typeGuard = group.findTypeGuard(signatureIndex);
-                if (typeGuard != null) {
-                    TypeData requiredType = typeGuard.getType();
-
-                    ActualParameter sourceParameter = source.findParameter(parameter.getLocalName());
-                    if (sourceParameter == null) {
-                        sourceParameter = source.getNode().getGenericSpecialization().findParameter(parameter.getLocalName());
-                    }
-
-                    if (Utils.needsCastTo(getContext(), sourceParameter.getType(), requiredType.getPrimitiveType())) {
-                        return true;
-                    }
-                }
-
-                signatureIndex++;
-            }
-            return false;
-        }
-
-        private CodeTree createTypeGuard(CodeTreeBuilder parent, NodeExecutionData execution, ActualParameter source, TypeData targetType, boolean typedCasts) {
-            NodeData node = execution.getChild().getNodeData();
-
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-
-            TypeData sourceType = source.getTypeSystemType();
-
-            if (!sourceType.needsCastTo(getContext(), targetType)) {
-                return null;
-            }
-
-            builder.startGroup();
-
-            if (execution.isShortCircuit()) {
-                ActualParameter shortCircuit = source.getPreviousParameter();
-                assert shortCircuit != null;
-                builder.string("(");
-                builder.string("!").string(valueName(shortCircuit));
-                builder.string(" || ");
-            }
-
-            String castMethodName;
-            String castTypeName = null;
-            List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
-            if (types.size() > 1) {
-                castMethodName = TypeSystemCodeGenerator.isImplicitTypeMethodName(targetType);
-                if (typedCasts) {
-                    castTypeName = implicitTypeName(source);
-                }
-            } else {
-                castMethodName = TypeSystemCodeGenerator.isTypeMethodName(targetType);
-            }
-
-            startCallTypeSystemMethod(getContext(), builder, node.getTypeSystem(), castMethodName);
-            builder.string(valueName(source));
-            if (castTypeName != null) {
-                builder.string(castTypeName);
-            }
-            builder.end().end(); // call
-
-            if (execution.isShortCircuit()) {
-                builder.string(")");
-            }
-
-            builder.end(); // group
-
-            return builder.getRoot();
-        }
-
-        // TODO merge redundancies with #createTypeGuard
-        private CodeTree createCast(CodeTreeBuilder parent, NodeExecutionData execution, ActualParameter source, TypeData targetType, boolean checkMinimumState, boolean typedCasts) {
-            NodeData node = execution.getChild().getNodeData();
-            TypeData sourceType = source.getTypeSystemType();
-
-            if (!sourceType.needsCastTo(getContext(), targetType)) {
-                return null;
-            }
-
-            CodeTree condition = null;
-            if (execution.isShortCircuit()) {
-                ActualParameter shortCircuit = source.getPreviousParameter();
-                assert shortCircuit != null;
-                condition = CodeTreeBuilder.singleString(valueName(shortCircuit));
-            }
-
-            String castMethodName;
-            String castTypeName = null;
-            List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
-            if (types.size() > 1) {
-                castMethodName = TypeSystemCodeGenerator.asImplicitTypeMethodName(targetType);
-                if (typedCasts) {
-                    castTypeName = implicitTypeName(source);
-                }
-            } else {
-                castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType);
-            }
-
-            List<CodeTree> args = new ArrayList<>();
-            args.add(CodeTreeBuilder.singleString(valueName(source)));
-            if (castTypeName != null) {
-                args.add(CodeTreeBuilder.singleString(castTypeName));
-            }
-
-            CodeTree value = createCallTypeSystemMethod(context, parent, node, castMethodName, args.toArray(new CodeTree[0]));
-
-            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, implicitTypeName(source), getContext().getType(Class.class), condition, castType));
-            }
-
-            return builder.getRoot();
-        }
-
-        private CodeTree createMethodGuard(CodeTreeBuilder parent, String prefix, SpecializationData source, GuardData guard) {
-            CodeTreeBuilder builder = parent.create();
-            builder.string(prefix);
-            if (guard.isNegated()) {
-                builder.string("!");
-            }
-            builder.tree(createTemplateMethodCall(builder, null, source, guard, null));
-            return builder.getRoot();
-        }
-
-        protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) {
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-
-            if (current.getMethod() == null) {
-                emitEncounteredSynthetic(builder, current);
-            } else {
-                builder.startReturn().tree(createTemplateMethodCall(builder, null, source, current, null)).end();
-            }
-
-            return encloseThrowsWithFallThrough(current, builder.getRoot());
-        }
-
-        protected CodeTree createGenericInvokeAndSpecialize(CodeTreeBuilder parent, SpecializationData source, SpecializationData current, String currentNodeVar) {
-            CodeTreeBuilder builder = parent.create();
-            CodeTreeBuilder prefix = parent.create();
-
-            NodeData node = current.getNode();
-
-            if (current.isGeneric() && node.isPolymorphic()) {
-                builder.startIf().string(currentNodeVar).string(".next0 == null && minimumState > 0").end().startBlock();
-                builder.tree(createRewritePolymorphic(builder, node, currentNodeVar));
-                builder.end();
-                builder.startElseBlock();
-                builder.tree(createRewriteGeneric(builder, source, current, currentNodeVar));
-                builder.end();
-            } else {
-                if (current.getExceptions().isEmpty()) {
-                    builder.tree(createGenericInvoke(builder, source, current, createReplaceCall(builder, current, currentNodeVar, currentNodeVar, null), null));
-                } else {
-                    builder.startStatement().string(currentNodeVar).string(" = ").tree(createReplaceCall(builder, current, currentNodeVar, currentNodeVar, null)).end();
-                    builder.tree(createGenericInvoke(builder, source, current, null, CodeTreeBuilder.singleString(currentNodeVar)));
-                }
-            }
-            CodeTreeBuilder root = parent.create();
-            root.tree(prefix.getRoot());
-            root.tree(encloseThrowsWithFallThrough(current, builder.getRoot()));
-            return root.getRoot();
-        }
-
-        private CodeTree createRewriteGeneric(CodeTreeBuilder parent, SpecializationData source, SpecializationData current, String currentNode) {
-            NodeData node = current.getNode();
-
-            CodeTreeBuilder builder = parent.create();
-            builder.declaration(getContext().getTruffleTypes().getNode(), "root", currentNode);
-            builder.startIf().string(currentNode).string(".next0 != null").end().startBlock();
-            /*
-             * Communicates to the caller of executeAndSpecialize that it was rewritten to generic.
-             * Its important that this is used instead of the currentNode since the caller is this.
-             * CurrentNode may not be this anymore at this place.
-             */
-            builder.statement("this.next0 = null");
-            builder.tree(createFindRoot(builder, node, false));
-            builder.end();
-            builder.end();
-            builder.tree(createGenericInvoke(builder, source, current, createReplaceCall(builder, current, "root", "(" + baseClassName(node) + ") root", null), null));
-            return builder.getRoot();
-        }
-
-        protected CodeTree createFindRoot(CodeTreeBuilder parent, NodeData node, boolean countDepth) {
-            CodeTreeBuilder builder = parent.create();
-            builder.startDoBlock();
-            builder.startAssert().string("root != null").string(" : ").doubleQuote("No polymorphic parent node.").end();
-            builder.startStatement().string("root = ").string("root.getParent()").end();
-            if (countDepth) {
-                builder.statement("depth++");
-            }
-            builder.end();
-            builder.startDoWhile();
-            builder.string("!").startParantheses().instanceOf("root", nodePolymorphicClassName(node)).end();
-            builder.end();
-            return builder.getRoot();
-        }
-
-        private CodeTree encloseThrowsWithFallThrough(SpecializationData current, CodeTree tree) {
-            if (current.getExceptions().isEmpty()) {
-                return tree;
-            }
-            CodeTreeBuilder builder = new CodeTreeBuilder(null);
-
-            builder.startTryBlock();
-            builder.tree(tree);
-            for (SpecializationThrowsData exception : current.getExceptions()) {
-                builder.end().startCatchBlock(exception.getJavaClass(), "rewriteEx");
-                builder.string("// fall through").newLine();
-            }
-            builder.end();
-
-            return builder.getRoot();
-        }
-
-        protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current, CodeTree replaceCall, CodeTree replaceVar) {
-            assert replaceCall == null || replaceVar == null;
-            CodeTreeBuilder builder = parent.create();
-            CodeTree replace = replaceVar;
-            if (replace == null) {
-                replace = replaceCall;
-            }
-            if (current.isGeneric()) {
-                builder.startReturn().tree(replace).string(".").startCall(EXECUTE_GENERIC_NAME);
-                addInternalValueParameterNames(builder, source, current, null, current.getNode().needsFrame(getContext()), null);
-                builder.end().end();
-            } else if (current.getMethod() == null) {
-                if (replaceCall != null) {
-                    builder.statement(replaceCall);
-                }
-                emitEncounteredSynthetic(builder, current);
-            } else if (!current.canBeAccessedByInstanceOf(getContext(), source.getNode().getNodeType())) {
-                if (replaceCall != null) {
-                    builder.statement(replaceCall);
-                }
-                builder.startReturn().tree(createTemplateMethodCall(parent, null, source, current, null)).end();
-            } else {
-                replace.add(new CodeTree(CodeTreeKind.STRING, null, "."));
-                builder.startReturn().tree(createTemplateMethodCall(parent, replace, source, current, null)).end();
-            }
-            return builder.getRoot();
-        }
-
-        protected CodeTree createReplaceCall(CodeTreeBuilder builder, SpecializationData current, String target, String source, String message) {
-            String className = nodeSpecializationClassName(current);
-            CodeTreeBuilder replaceCall = builder.create();
-            if (target != null) {
-                replaceCall.startCall(target, "replace");
-            } else {
-                replaceCall.startCall("replace");
-            }
-            replaceCall.startGroup().cast(baseClassName(current.getNode())).startCall(className, CREATE_SPECIALIZATION_NAME).string(source);
-            for (ActualParameter param : current.getSignatureParameters()) {
-                NodeChildData child = param.getSpecification().getExecution().getChild();
-                List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
-                if (types.size() > 1) {
-                    replaceCall.string(implicitTypeName(param));
-                }
-            }
-            replaceCall.end().end();
-
-            if (message == null) {
-                replaceCall.string("message");
-            } else {
-                replaceCall.doubleQuote(message);
-            }
-            replaceCall.end();
-            return replaceCall.getRoot();
-        }
-
-        private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node, String currentNode) {
-            String polyClassName = nodePolymorphicClassName(node);
-            String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization());
-            CodeTreeBuilder builder = parent.create();
-
-            builder.declaration(getElement().asType(), "currentCopy", currentNode + "." + COPY_WITH_CONSTRUCTOR_NAME + "()");
-            for (ActualParameter param : getModel().getSignatureParameters()) {
-                NodeExecutionData execution = param.getSpecification().getExecution();
-                builder.startStatement().tree(createAccessChild(execution, "currentCopy")).string(" = ").nullLiteral().end();
-            }
-            builder.startStatement().string("currentCopy.next0 = ").startNew(uninitializedName).string("currentCopy").end().end();
-
-            builder.declaration(polyClassName, "polymorphic", builder.create().startNew(polyClassName).string(currentNode).end());
-            builder.startStatement().string("polymorphic.next0 = ").string("currentCopy").end();
-            builder.startStatement().startCall(currentNode, "replace").string("polymorphic").string("message").end().end();
-
-            builder.startReturn();
-            builder.startCall("currentCopy.next0", EXECUTE_POLYMORPHIC_NAME);
-            addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, null);
-            builder.end();
-            builder.end();
-
-            return builder.getRoot();
-        }
-
-        protected CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) {
-            TypeData type = executable.getType();
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            NodeData node = specialization.getNode();
-
-            ExecutableTypeData castedType = node.findExecutableType(type, 0);
-            TypeData primaryType = castExecutable.getType();
-
-            boolean needsTry = castExecutable.hasUnexpectedValue(getContext());
-            boolean returnVoid = type.isVoid();
-
-            List<ActualParameter> executeParameters = new ArrayList<>();
-            for (ActualParameter sourceParameter : executable.getSignatureParameters()) {
-                ActualParameter targetParameter = castExecutable.findParameter(sourceParameter.getLocalName());
-                if (targetParameter != null) {
-                    executeParameters.add(targetParameter);
-                }
-            }
-
-            // execute names are enforced no cast
-            String[] executeParameterNames = new String[executeParameters.size()];
-            for (int i = 0; i < executeParameterNames.length; i++) {
-                executeParameterNames[i] = valueName(executeParameters.get(i));
-            }
-
-            builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null));
-
-            CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null, executeParameterNames);
-            if (needsTry) {
-                if (!returnVoid) {
-                    builder.declaration(primaryType.getPrimitiveType(), "value");
-                }
-                builder.startTryBlock();
-
-                if (returnVoid) {
-                    builder.statement(primaryExecuteCall);
-                } else {
-                    builder.startStatement();
-                    builder.string("value = ");
-                    builder.tree(primaryExecuteCall);
-                    builder.end();
-                }
-
-                builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
-                if (returnVoid) {
-                    builder.string("// ignore").newLine();
-                } else {
-                    builder.startReturn();
-                    builder.tree(createExpectExecutableType(node, specialization.getNode().getTypeSystem().getGenericTypeData(), castedType, CodeTreeBuilder.singleString("ex.getResult()")));
-                    builder.end();
-                }
-                builder.end();
-
-                if (!returnVoid) {
-                    builder.startReturn();
-                    builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), executable, CodeTreeBuilder.singleString("value")));
-                    builder.end();
-                }
-            } else {
-                if (returnVoid) {
-                    builder.statement(primaryExecuteCall);
-                } else {
-                    builder.startReturn();
-                    builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), executable, primaryExecuteCall));
-                    builder.end();
-                }
-            }
-
-            return builder.getRoot();
-        }
-
-        protected CodeTree createExpectExecutableType(NodeData node, TypeData sourceType, ExecutableTypeData castedType, CodeTree value) {
-            boolean hasUnexpected = castedType.hasUnexpectedValue(getContext());
-            return createCastType(node.getTypeSystem(), sourceType, castedType.getType(), hasUnexpected, value);
-        }
-
-        protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List<ActualParameter> targetParameters,
-                        ActualParameter unexpectedParameter) {
-            CodeTreeBuilder builder = parent.create();
-            for (ActualParameter targetParameter : targetParameters) {
-                if (!targetParameter.getSpecification().isSignature()) {
-                    continue;
-                }
-                NodeExecutionData execution = targetParameter.getSpecification().getExecution();
-                CodeTree executionExpressions = createExecuteChild(builder, execution, sourceExecutable, targetParameter, unexpectedParameter);
-                CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpressions, specialization, sourceExecutable, targetParameter, execution.isShortCircuit(), unexpectedParameter);
-                CodeTree shortCircuitTree = createShortCircuitTree(builder, unexpectedTree, specialization, targetParameter, unexpectedParameter);
-
-                if (shortCircuitTree == executionExpressions) {
-                    if (containsNewLine(executionExpressions)) {
-                        builder.declaration(targetParameter.getType(), valueName(targetParameter));
-                        builder.tree(shortCircuitTree);
-                    } else {
-                        builder.startStatement().type(targetParameter.getType()).string(" ").tree(shortCircuitTree).end();
-                    }
-                } else {
-                    builder.tree(shortCircuitTree);
-                }
-
-            }
-            return builder.getRoot();
-        }
-
-        private ExecutableTypeData resolveExecutableType(NodeExecutionData execution, TypeData type) {
-            ExecutableTypeData targetExecutable = execution.getChild().findExecutableType(getContext(), type);
-            if (targetExecutable == null) {
-                targetExecutable = execution.getChild().findAnyGenericExecutableType(getContext());
-            }
-            return targetExecutable;
-        }
-
-        private CodeTree createExecuteChild(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData sourceExecutable, ActualParameter targetParameter,
-                        ActualParameter unexpectedParameter) {
-            SpecializationData specialization = getModel();
-            TreeSet<TypeData> possiblePolymorphicTypes = lookupPolymorphicTargetTypes(targetParameter);
-            if (specialization.isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null && possiblePolymorphicTypes.size() > 1) {
-
-                CodeTreeBuilder builder = parent.create();
-
-                boolean elseIf = false;
-                for (TypeData possiblePolymoprhicType : possiblePolymorphicTypes) {
-                    if (possiblePolymoprhicType.isGeneric()) {
-                        continue;
-                    }
-                    elseIf = builder.startIf(elseIf);
-
-                    ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName());
-                    TypeData sourceType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null;
-                    builder.string(polymorphicTypeName(targetParameter)).string(" == ").typeLiteral(possiblePolymoprhicType.getPrimitiveType());
-                    builder.end().startBlock();
-                    builder.startStatement();
-                    builder.tree(createExecuteChildExpression(parent, execution, sourceType, new ActualParameter(targetParameter, possiblePolymoprhicType), unexpectedParameter, null));
-                    builder.end();
-                    builder.end();
-                }
-
-                builder.startElseBlock();
-                builder.startStatement().tree(createExecuteChildImplicit(parent, execution, sourceExecutable, targetParameter, unexpectedParameter)).end();
-                builder.end();
-
-                return builder.getRoot();
-            } else {
-                return createExecuteChildImplicit(parent, execution, sourceExecutable, targetParameter, unexpectedParameter);
-            }
-        }
-
-        protected final List<ActualParameter> getImplicitTypeParameters(SpecializationData model) {
-            List<ActualParameter> parameter = new ArrayList<>();
-            for (ActualParameter param : model.getSignatureParameters()) {
-                NodeChildData child = param.getSpecification().getExecution().getChild();
-                List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
-                if (types.size() > 1) {
-                    parameter.add(param);
-                }
-            }
-            return parameter;
-        }
-
-        protected final TreeSet<TypeData> lookupPolymorphicTargetTypes(ActualParameter param) {
-            SpecializationData specialization = getModel();
-            TreeSet<TypeData> possiblePolymorphicTypes = new TreeSet<>();
-            for (SpecializationData otherSpecialization : specialization.getNode().getSpecializations()) {
-                if (!otherSpecialization.isSpecialized()) {
-                    continue;
-                }
-                ActualParameter otherParameter = otherSpecialization.findParameter(param.getLocalName());
-                if (otherParameter != null) {
-                    possiblePolymorphicTypes.add(otherParameter.getTypeSystemType());
-                }
-            }
-            return possiblePolymorphicTypes;
-        }
-
-        private CodeTree createExecuteChildImplicit(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData sourceExecutable, ActualParameter param, ActualParameter unexpectedParameter) {
-            CodeTreeBuilder builder = parent.create();
-            ActualParameter sourceParameter = sourceExecutable.findParameter(param.getLocalName());
-            String childExecuteName = createExecuteChildMethodName(param, sourceParameter != null);
-            if (childExecuteName != null) {
-                builder.string(valueName(param));
-                builder.string(" = ");
-                builder.startCall(childExecuteName);
-
-                for (ActualParameter parameters : sourceExecutable.getParameters()) {
-                    if (parameters.getSpecification().isSignature()) {
-                        continue;
-                    }
-                    builder.string(parameters.getLocalName());
-                }
-
-                if (sourceParameter != null) {
-                    builder.string(valueNameEvaluated(sourceParameter));
-                }
-
-                builder.string(implicitTypeName(param));
-
-                builder.end();
-            } else {
-                List<TypeData> sourceTypes = execution.getChild().getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
-                TypeData expectType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null;
-                if (sourceTypes.size() > 1) {
-                    builder.tree(createExecuteChildImplicitExpressions(parent, param, expectType));
-                } else {
-                    builder.tree(createExecuteChildExpression(parent, execution, expectType, param, unexpectedParameter, null));
-                }
-            }
-            return builder.getRoot();
-        }
-
-        private String createExecuteChildMethodName(ActualParameter param, boolean expect) {
-            NodeExecutionData execution = param.getSpecification().getExecution();
-            NodeChildData child = execution.getChild();
-            if (child.getExecuteWith().size() > 0) {
-                return null;
-            }
-            List<TypeData> sourceTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
-            if (sourceTypes.size() <= 1) {
-                return null;
-            }
-            String prefix = expect ? "expect" : "execute";
-            String suffix = execution.getIndex() > -1 ? String.valueOf(execution.getIndex()) : "";
-            return prefix + Utils.firstLetterUpperCase(child.getName()) + Utils.firstLetterUpperCase(Utils.getSimpleName(param.getType())) + suffix;
-        }
-
-        private List<CodeExecutableElement> createExecuteChilds(ActualParameter param, Set<TypeData> expectTypes) {
-            CodeExecutableElement executeMethod = createExecuteChild(param, null);
-            if (executeMethod == null) {
-                return Collections.emptyList();
-            }
-            List<CodeExecutableElement> childs = new ArrayList<>();
-            childs.add(executeMethod);
-
-            for (TypeData expectType : expectTypes) {
-                CodeExecutableElement method = createExecuteChild(param, expectType);
-                if (method != null) {
-                    childs.add(method);
-                }
-            }
-            return childs;
-        }
-
-        private CodeExecutableElement createExecuteChild(ActualParameter param, TypeData expectType) {
-            String childExecuteName = createExecuteChildMethodName(param, expectType != null);
-            if (childExecuteName == null) {
-                return null;
-            }
-
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, expectType != null ? STATIC : FINAL), param.getType(), childExecuteName);
-            method.getThrownTypes().add(getContext().getTruffleTypes().getUnexpectedValueException());
-            method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue"));
-            if (expectType != null) {
-                method.addParameter(new CodeVariableElement(expectType.getPrimitiveType(), valueNameEvaluated(param)));
-            }
-            method.addParameter(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param)));
-
-            CodeTreeBuilder builder = method.createBuilder();
-            builder.declaration(param.getType(), valueName(param));
-            builder.tree(createExecuteChildImplicitExpressions(builder, param, expectType));
-            builder.startReturn().string(valueName(param)).end();
-
-            return method;
-        }
-
-        private CodeTree createExecuteChildImplicitExpressions(CodeTreeBuilder parent, ActualParameter targetParameter, TypeData expectType) {
-            CodeTreeBuilder builder = parent.create();
-            NodeData node = getModel().getNode();
-            NodeExecutionData execution = targetParameter.getSpecification().getExecution();
-            List<TypeData> sourceTypes = node.getTypeSystem().lookupSourceTypes(targetParameter.getTypeSystemType());
-            boolean elseIf = false;
-            int index = 0;
-            for (TypeData sourceType : sourceTypes) {
-                if (index < sourceTypes.size() - 1) {
-                    elseIf = builder.startIf(elseIf);
-                    builder.string(implicitTypeName(targetParameter)).string(" == ").typeLiteral(sourceType.getPrimitiveType());
-                    builder.end();
-                    builder.startBlock();
-                } else {
-                    builder.startElseBlock();
-                }
-
-                ExecutableTypeData implictExecutableTypeData = execution.getChild().findExecutableType(getContext(), sourceType);
-                if (implictExecutableTypeData == null) {
-                    /*
-                     * For children with executeWith.size() > 0 an executable type may not exist so
-                     * use the generic executable type which is guaranteed to exist. An expect call
-                     * is inserted automatically by #createExecuteExpression.
-                     */
-                    implictExecutableTypeData = execution.getChild().getNodeData().findExecutableType(node.getTypeSystem().getGenericTypeData(), execution.getChild().getExecuteWith().size());
-                }
-
-                ImplicitCastData cast = execution.getChild().getNodeData().getTypeSystem().lookupCast(sourceType, targetParameter.getTypeSystemType());
-                CodeTree execute = createExecuteChildExpression(builder, execution, expectType, targetParameter, null, cast);
-                builder.statement(execute);
-                builder.end();
-                index++;
-            }
-            return builder.getRoot();
-        }
-
-        private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData execution, TypeData sourceParameterType, ActualParameter targetParameter,
-                        ActualParameter unexpectedParameter, ImplicitCastData cast) {
-            // assignments: targetType <- castTargetType <- castSourceType <- sourceType
-            TypeData sourceType = sourceParameterType;
-            TypeData targetType = targetParameter.getTypeSystemType();
-            TypeData castSourceType = targetType;
-            TypeData castTargetType = targetType;
-
-            if (cast != null) {
-                castSourceType = cast.getSourceType();
-                castTargetType = cast.getTargetType();
-            }
-
-            CodeTree expression;
-            if (sourceType == null) {
-                ExecutableTypeData targetExecutable = resolveExecutableType(execution, castSourceType);
-                expression = createExecuteChildExpression(parent, execution, targetExecutable, unexpectedParameter);
-                sourceType = targetExecutable.getType();
-            } else {
-                expression = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter));
-            }
-
-            // target = expectTargetType(implicitCast(expectCastSourceType(source)))
-            TypeSystemData typeSystem = execution.getChild().getNodeData().getTypeSystem();
-            expression = createExpectType(typeSystem, sourceType, castSourceType, expression);
-            expression = createImplicitCast(parent, typeSystem, cast, expression);
-            expression = createExpectType(typeSystem, castTargetType, targetType, expression);
-
-            CodeTreeBuilder builder = parent.create();
-            builder.string(valueName(targetParameter));
-            builder.string(" = ");
-            builder.tree(expression);
-            return builder.getRoot();
-        }
-
-        private CodeTree createImplicitCast(CodeTreeBuilder parent, TypeSystemData typeSystem, ImplicitCastData cast, CodeTree expression) {
-            if (cast == null) {
-                return expression;
-            }
-            CodeTreeBuilder builder = parent.create();
-            startCallTypeSystemMethod(getContext(), builder, typeSystem, cast.getMethodName());
-            builder.tree(expression);
-            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(ActualParameter sourceParameter, ActualParameter targetParameter, ActualParameter unexpectedParameter) {
-            NodeExecutionData execution = targetParameter.getSpecification().getExecution();
-
-            if (getModel().isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null) {
-                // check for other polymorphic types
-                TreeSet<TypeData> polymorphicTargetTypes = lookupPolymorphicTargetTypes(targetParameter);
-                if (polymorphicTargetTypes.size() > 1) {
-                    for (TypeData polymorphicTargetType : polymorphicTargetTypes) {
-                        if (hasUnexpectedType(execution, sourceParameter, polymorphicTargetType)) {
-                            return true;
-                        }
-                    }
-                }
-            }
-
-            if (hasUnexpectedType(execution, sourceParameter, targetParameter.getTypeSystemType())) {
-                return true;
-            }
-            return false;
-        }
-
-        private boolean hasUnexpectedType(NodeExecutionData execution, ActualParameter sourceParameter, TypeData targetType) {
-            List<TypeData> implicitSourceTypes = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
-
-            for (TypeData implicitSourceType : implicitSourceTypes) {
-                TypeData sourceType;
-                ExecutableTypeData targetExecutable = resolveExecutableType(execution, implicitSourceType);
-                if (sourceParameter != null) {
-                    sourceType = sourceParameter.getTypeSystemType();
-                } else {
-                    if (targetExecutable.hasUnexpectedValue(getContext())) {
-                        return true;
-                    }
-                    sourceType = targetExecutable.getType();
-                }
-
-                ImplicitCastData cast = getModel().getNode().getTypeSystem().lookupCast(implicitSourceType, targetType);
-                if (cast != null) {
-                    if (cast.getSourceType().needsCastTo(getContext(), targetType)) {
-                        return true;
-                    }
-                }
-
-                if (sourceType.needsCastTo(getContext(), targetType)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, ExecutableTypeData currentExecutable, ActualParameter param,
-                        boolean shortCircuit, ActualParameter unexpectedParameter) {
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            ActualParameter sourceParameter = currentExecutable.findParameter(param.getLocalName());
-            boolean unexpected = hasUnexpected(sourceParameter, param, unexpectedParameter);
-            if (!unexpected) {
-                return body;
-            }
-
-            if (!shortCircuit) {
-                builder.declaration(param.getType(), valueName(param));
-            }
-            builder.startTryBlock();
-
-            if (containsNewLine(body)) {
-                builder.tree(body);
-            } else {
-                builder.statement(body);
-            }
-
-            builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
-            SpecializationData generic = specialization.getNode().getGenericSpecialization();
-            ActualParameter genericParameter = generic.findParameter(param.getLocalName());
-
-            List<ActualParameter> genericParameters = generic.getParametersAfter(genericParameter);
-            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();
-        }
-
-        private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, ActualParameter param) {
-            NodeData node = specialization.getNode();
-            SpecializationData polymorphic = node.getPolymorphicSpecialization();
-
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            builder.startStatement().string(polymorphicTypeName(param)).string(" = ").typeLiteral(getContext().getType(Object.class)).end();
-
-            builder.startReturn();
-
-            CodeTreeBuilder execute = new CodeTreeBuilder(builder);
-            execute.startCall("next0", EXECUTE_POLYMORPHIC_NAME);
-            addInternalValueParameterNames(execute, specialization, polymorphic, param.getLocalName(), true, null);
-            execute.end();
-
-            TypeData sourceType = polymorphic.getReturnType().getTypeSystemType();
-
-            builder.tree(createExpectExecutableType(node, sourceType, currentExecutable, execute.getRoot()));
-
-            builder.end();
-            return builder.getRoot();
-        }
-
-        private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData targetExecution, ExecutableTypeData targetExecutable, ActualParameter unexpectedParameter) {
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            if (targetExecution != null) {
-                builder.tree(createAccessChild(targetExecution, null));
-                builder.string(".");
-            }
-
-            builder.startCall(targetExecutable.getMethodName());
-
-            // TODO this should be merged with #createTemplateMethodCall
-            int index = 0;
-            for (ActualParameter parameter : targetExecutable.getParameters()) {
-
-                if (!parameter.getSpecification().isSignature()) {
-                    builder.string(parameter.getLocalName());
-                } else {
-
-                    if (index < targetExecution.getChild().getExecuteWith().size()) {
-                        NodeChildData child = targetExecution.getChild().getExecuteWith().get(index);
-
-                        ParameterSpec spec = getModel().getSpecification().findParameterSpec(child.getName());
-                        List<ActualParameter> specializationParams = getModel().findParameters(spec);
-
-                        if (specializationParams.isEmpty()) {
-                            builder.defaultValue(parameter.getType());
-                            continue;
-                        }
-
-                        ActualParameter specializationParam = specializationParams.get(0);
-
-                        TypeData targetType = parameter.getTypeSystemType();
-                        TypeData sourceType = specializationParam.getTypeSystemType();
-                        String localName = specializationParam.getLocalName();
-
-                        if (unexpectedParameter != null && unexpectedParameter.getLocalName().equals(specializationParam.getLocalName())) {
-                            localName = "ex.getResult()";
-                            sourceType = getModel().getNode().getTypeSystem().getGenericTypeData();
-                        }
-
-                        CodeTree value = CodeTreeBuilder.singleString(localName);
-
-                        if (sourceType.needsCastTo(getContext(), targetType)) {
-                            value = createCallTypeSystemMethod(getContext(), builder, getModel().getNode(), TypeSystemCodeGenerator.asTypeMethodName(targetType), value);
-                        }
-                        builder.tree(value);
-                    } else {
-                        builder.defaultValue(parameter.getType());
-                    }
-                    index++;
-                }
-            }
-
-            builder.end();
-
-            return builder.getRoot();
-        }
-
-        private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, ActualParameter parameter, ActualParameter exceptionParam) {
-            NodeExecutionData execution = parameter.getSpecification().getExecution();
-            if (execution == null || !execution.isShortCircuit()) {
-                return body;
-            }
-
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter);
-            builder.tree(createShortCircuitValue(builder, specialization, execution, shortCircuitParam, exceptionParam));
-            builder.declaration(parameter.getType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getType()));
-            builder.startIf().string(shortCircuitParam.getLocalName()).end();
-            builder.startBlock();
-
-            if (containsNewLine(body)) {
-                builder.tree(body);
-            } else {
-                builder.statement(body);
-            }
-            builder.end();
-
-            return builder.getRoot();
-        }
-
-        private CodeTree createShortCircuitValue(CodeTreeBuilder parent, SpecializationData specialization, NodeExecutionData execution, ActualParameter shortCircuitParam,
-                        ActualParameter exceptionParam) {
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            int shortCircuitIndex = 0;
-            for (NodeExecutionData otherExectuion : specialization.getNode().getChildExecutions()) {
-                if (otherExectuion.isShortCircuit()) {
-                    if (otherExectuion == execution) {
-                        break;
-                    }
-                    shortCircuitIndex++;
-                }
-            }
-
-            builder.startStatement().type(shortCircuitParam.getType()).string(" ").string(valueName(shortCircuitParam)).string(" = ");
-            ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex);
-            builder.tree(createTemplateMethodCall(builder, null, specialization, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null));
-            builder.end(); // statement
-
-            return builder.getRoot();
-        }
-
-        protected CodeTree createReturnExecuteAndSpecialize(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData current, ActualParameter exceptionParam, String reason) {
-            NodeData node = current.getNode();
-            SpecializationData generic = node.getGenericSpecialization();
-            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, null);
-            specializeCall.doubleQuote(reason);
-            specializeCall.end().end();
-
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-
-            builder.startReturn();
-            builder.tree(createExpectExecutableType(node, generic.getReturnType().getTypeSystemType(), executable, specializeCall.getRoot()));
-            builder.end();
-
-            return builder.getRoot();
-        }
-
-        protected final CodeExecutableElement createUpdateTypes(TypeMirror polymorphicType) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), getContext().getType(void.class), UPDATE_TYPES_NAME);
-            method.getParameters().add(new CodeVariableElement(polymorphicType, "polymorphic"));
-            CodeTreeBuilder builder = method.createBuilder();
-
-            if (getModel().isPolymorphic()) {
-                builder.startStatement();
-                builder.startCall("next0", "updateTypes").string("polymorphic").end();
-                builder.end();
-            } else if (getModel().isSpecialized()) {
-                for (ActualParameter parameter : getModel().getParameters()) {
-                    if (!parameter.getSpecification().isSignature()) {
-                        continue;
-                    }
-                    if (lookupPolymorphicTargetTypes(parameter).size() <= 1) {
-                        continue;
-                    }
-                    builder.startStatement();
-                    builder.startCall("polymorphic", createUpdateTypeName(parameter));
-                    builder.typeLiteral(parameter.getType());
-                    builder.end().end();
-                }
-
-                builder.startStatement().startCall("super", UPDATE_TYPES_NAME).string("polymorphic").end().end();
-            }
-            return method;
-        }
-
-        protected String createUpdateTypeName(ActualParameter parameter) {
-            return "update" + Utils.firstLetterUpperCase(parameter.getLocalName()) + "Type";
-        }
-    }
-
-    private class PolymorphicNodeFactory extends SpecializedNodeFactory {
-
-        public PolymorphicNodeFactory(ProcessorContext context, CodeTypeElement nodeGen) {
-            super(context, nodeGen);
-        }
-
-        @Override
-        public CodeTypeElement create(SpecializationData polymorph) {
-            NodeData node = polymorph.getNode();
-            TypeMirror baseType = node.getNodeType();
-            if (nodeGen != null) {
-                baseType = nodeGen.asType();
-            }
-            CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodePolymorphicClassName(node), baseType, false);
-
-            clazz.getAnnotationMirrors().add(createNodeInfo(node, NodeCost.POLYMORPHIC));
-
-            for (ActualParameter polymorphParameter : polymorph.getSignatureParameters()) {
-                if (!polymorphParameter.getTypeSystemType().isGeneric()) {
-                    continue;
-                }
-                Set<TypeData> types = new HashSet<>();
-                for (SpecializationData specialization : node.getSpecializations()) {
-                    if (!specialization.isSpecialized()) {
-                        continue;
-                    }
-                    ActualParameter parameter = specialization.findParameter(polymorphParameter.getLocalName());
-                    assert parameter != null;
-                    types.add(parameter.getTypeSystemType());
-                }
-                CodeVariableElement var = new CodeVariableElement(modifiers(PRIVATE), getContext().getType(Class.class), polymorphicTypeName(polymorphParameter));
-                var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getCompilationFinal()));
-                clazz.add(var);
-            }
-
-            return clazz;
-        }
-
-        @Override
-        protected void createChildren(SpecializationData specialization) {
-            CodeTypeElement clazz = getElement();
-
-            createConstructors(clazz);
-            createExecuteMethods(specialization);
-
-            getElement().add(createUpdateTypes(nodeGen.asType()));
-
-            for (ActualParameter parameter : specialization.getParameters()) {
-                if (!parameter.getSpecification().isSignature()) {
-                    continue;
-                }
-                if (lookupPolymorphicTargetTypes(parameter).size() <= 1) {
-                    continue;
-                }
-                getElement().add(createUpdateType(parameter));
-            }
-
-            if (needsInvokeCopyConstructorMethod()) {
-                clazz.add(createCopy(nodeGen.asType(), specialization));
-            }
-
-            createCachedExecuteMethods(specialization);
-        }
-
-        private ExecutableElement createUpdateType(ActualParameter parameter) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), getContext().getType(void.class), createUpdateTypeName(parameter));
-            method.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), "type"));
-            CodeTreeBuilder builder = method.createBuilder();
-
-            String fieldName = polymorphicTypeName(parameter);
-            builder.startIf().string(fieldName).isNull().end().startBlock();
-            builder.startStatement().string(fieldName).string(" = ").string("type").end();
-            builder.end();
-            builder.startElseIf().string(fieldName).string(" != ").string("type").end();
-            builder.startBlock();
-            builder.startStatement().string(fieldName).string(" = ").typeLiteral(getContext().getType(Object.class)).end();
-            builder.end();
-
-            return method;
-        }
-
-    }
-
-    private class SpecializedNodeFactory extends NodeBaseFactory {
-
-        protected final CodeTypeElement nodeGen;
-
-        public SpecializedNodeFactory(ProcessorContext context, CodeTypeElement nodeGen) {
-            super(context);
-            this.nodeGen = nodeGen;
-        }
-
-        @Override
-        public CodeTypeElement create(SpecializationData specialization) {
-            NodeData node = specialization.getNode();
-            TypeMirror baseType = node.getNodeType();
-            if (nodeGen != null) {
-                baseType = nodeGen.asType();
-            }
-            CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false);
-
-            NodeCost cost;
-            if (specialization.isGeneric()) {
-                cost = NodeCost.MEGAMORPHIC;
-            } else if (specialization.isUninitialized()) {
-                cost = NodeCost.UNINITIALIZED;
-            } else if (specialization.isPolymorphic()) {
-                cost = NodeCost.POLYMORPHIC;
-            } else if (specialization.isSpecialized()) {
-                cost = NodeCost.MONOMORPHIC;
-            } else {
-                throw new AssertionError();
-            }
-            clazz.getAnnotationMirrors().add(createNodeInfo(node, cost));
-
-            return clazz;
-        }
-
-        protected CodeAnnotationMirror createNodeInfo(NodeData node, NodeCost cost) {
-            String shortName = node.getShortName();
-            CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(getContext().getTruffleTypes().getNodeInfoAnnotation());
-            if (shortName != null) {
-                nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("shortName"), new CodeAnnotationValue(shortName));
-            }
-
-            DeclaredType nodeinfoCost = getContext().getTruffleTypes().getNodeCost();
-            VariableElement varKind = Utils.findVariableElement(nodeinfoCost, cost.name());
-
-            nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("cost"), new CodeAnnotationValue(varKind));
-            return nodeInfoMirror;
-        }
-
-        @Override
-        protected void createChildren(SpecializationData specialization) {
-            CodeTypeElement clazz = getElement();
-            createConstructors(clazz);
-
-            createExecuteMethods(specialization);
-            createCachedExecuteMethods(specialization);
-            if (specialization.getNode().isPolymorphic()) {
-                getElement().add(createUpdateTypes(nodeGen.asType()));
-            }
-            if (needsInvokeCopyConstructorMethod()) {
-                clazz.add(createCopy(nodeGen.asType(), specialization));
-            }
-
-            if (!specialization.isUninitialized() && specialization.getNode().needsRewrites(context)) {
-                clazz.add(createCopyConstructorFactoryMethod(nodeGen.asType(), specialization));
-            } else {
-                for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) {
-                    if (constructor.getParameters().size() == 1 && ((CodeVariableElement) constructor.getParameters().get(0)).getType().equals(nodeGen.asType())) {
-                        // skip copy constructor - not used
-                        continue;
-                    }
-                    clazz.add(createConstructorFactoryMethod(specialization, constructor));
-                }
-            }
-        }
-
-        protected void createConstructors(CodeTypeElement clazz) {
-            TypeElement superTypeElement = Utils.fromTypeMirror(clazz.getSuperclass());
-            SpecializationData specialization = getModel();
-            NodeData node = specialization.getNode();
-            for (ExecutableElement constructor : ElementFilter.constructorsIn(superTypeElement.getEnclosedElements())) {
-                if (specialization.isUninitialized()) {
-                    // ignore copy constructors for uninitialized if not polymorphic
-                    if (isCopyConstructor(constructor) && !node.isPolymorphic()) {
-                        continue;
-                    }
-                } else if (node.getUninitializedSpecialization() != null) {
-                    // ignore others than copy constructors for specialized nodes
-                    if (!isCopyConstructor(constructor)) {
-                        continue;
-                    }
-                }
-
-                CodeExecutableElement superConstructor = createSuperConstructor(clazz, constructor);
-                if (superConstructor == null) {
-                    continue;
-                }
-                CodeTree body = superConstructor.getBodyTree();
-                CodeTreeBuilder builder = superConstructor.createBuilder();
-                builder.tree(body);
-
-                if (node.isPolymorphic()) {
-                    if (specialization.isSpecialized() || specialization.isPolymorphic()) {
-                        builder.statement("this.next0 = copy.next0");
-                    }
-                }
-                if (superConstructor != null) {
-                    for (ActualParameter param : getImplicitTypeParameters(getModel())) {
-                        clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), implicitTypeName(param)));
-                        superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param)));
-
-                        builder.startStatement();
-                        builder.string("this.").string(implicitTypeName(param)).string(" = ").string(implicitTypeName(param));
-                        builder.end();
-                    }
-
-                    clazz.add(superConstructor);
-                }
-            }
-        }
-
-        protected void createExecuteMethods(SpecializationData specialization) {
-            NodeData node = specialization.getNode();
-            CodeTypeElement clazz = getElement();
-
-            for (ExecutableTypeData execType : node.getExecutableTypes()) {
-                if (execType.isFinal()) {
-                    continue;
-                }
-                CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, true);
-                clazz.add(executeMethod);
-                CodeTreeBuilder builder = executeMethod.getBuilder();
-                CodeTree result = createExecuteBody(builder, specialization, execType);
-                if (result != null) {
-                    builder.tree(result);
-                } else {
-                    clazz.remove(executeMethod);
-                }
-            }
-        }
-
-        protected void createCachedExecuteMethods(SpecializationData specialization) {
-            NodeData node = specialization.getNode();
-            if (!node.isPolymorphic()) {
-                return;
-            }
-
-            CodeTypeElement clazz = getElement();
-
-            final SpecializationData polymorphic = node.getPolymorphicSpecialization();
-            ExecutableElement executeCached = nodeGen.getMethod(EXECUTE_POLYMORPHIC_NAME);
-            CodeExecutableElement executeMethod = CodeExecutableElement.clone(getContext().getEnvironment(), executeCached);
-            executeMethod.getModifiers().remove(Modifier.ABSTRACT);
-            CodeTreeBuilder builder = executeMethod.createBuilder();
-
-            if (specialization.isGeneric() || specialization.isPolymorphic()) {
-                builder.startThrow().startNew(getContext().getType(AssertionError.class));
-                builder.doubleQuote("Should not be reached.");
-                builder.end().end();
-            } else if (specialization.isUninitialized()) {
-                builder.tree(createAppendPolymorphic(builder, specialization));
-            } else {
-                CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder);
-                elseBuilder.startReturn().startCall("this.next0", EXECUTE_POLYMORPHIC_NAME);
-                addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, null);
-                elseBuilder.end().end();
-
-                boolean forceElse = specialization.getExceptions().size() > 0;
-                builder.tree(createExecuteTree(builder, polymorphic, SpecializationGroup.create(specialization), false, new CodeBlock<SpecializationData>() {
-
-                    public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
-                        return createGenericInvoke(b, polymorphic, current);
-                    }
-                }, elseBuilder.getRoot(), forceElse, true, true));
-            }
-            clazz.add(executeMethod);
-        }
-
-        private CodeTree createAppendPolymorphic(CodeTreeBuilder parent, SpecializationData specialization) {
-            NodeData node = specialization.getNode();
-
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            builder.tree(createDeoptimize(builder));
-
-            builder.declaration(getContext().getTruffleTypes().getNode(), "root", "this");
-            builder.declaration(getContext().getType(int.class), "depth", "0");
-            builder.tree(createFindRoot(builder, node, true));
-            builder.newLine();
-
-            builder.startIf().string("depth > ").string(String.valueOf(node.getPolymorphicDepth())).end();
-            builder.startBlock();
-            String message = "Polymorphic limit reached (" + node.getPolymorphicDepth() + ")";
-            String castRoot = "(" + baseClassName(node) + ") root";
-            builder.tree(createGenericInvoke(builder, node.getPolymorphicSpecialization(), node.getGenericSpecialization(),
-                            createReplaceCall(builder, node.getGenericSpecialization(), "root", castRoot, message), null));
-            builder.end();
-
-            builder.startElseBlock();
-            builder.startStatement().string("next0 = ");
-            builder.startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string("this").end();
-            builder.end();
-
-            CodeTreeBuilder specializeCall = new CodeTreeBuilder(builder);
-            specializeCall.startCall(EXECUTE_SPECIALIZE_NAME);
-            specializeCall.string("0");
-            addInternalValueParameterNames(specializeCall, specialization, node.getGenericSpecialization(), null, true, null);
-            specializeCall.startGroup().doubleQuote("Uninitialized polymorphic (").string(" + depth + ").doubleQuote("/" + node.getPolymorphicDepth() + ")").end();
-            specializeCall.end().end();
-
-            builder.declaration(node.getGenericSpecialization().getReturnType().getType(), "result", specializeCall.getRoot());
-
-            CodeTree root = builder.create().cast(nodePolymorphicClassName(node)).string("root").getRoot();
-            builder.startIf().string("this.next0 != null").end().startBlock();
-            builder.startStatement().string("(").tree(root).string(").").startCall(UPDATE_TYPES_NAME).tree(root).end().end();
-            builder.end();
-
-            if (Utils.isVoid(builder.findMethod().getReturnType())) {
-                builder.returnStatement();
-            } else {
-                builder.startReturn().string("result").end();
-            }
-
-            builder.end();
-
-            return builder.getRoot();
-        }
-
-        private CodeTree createExecuteBody(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData execType) {
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-
-            List<ExecutableTypeData> primaryExecutes = findFunctionalExecutableType(specialization, execType.getEvaluatedCount());
-
-            if (primaryExecutes.contains(execType) || primaryExecutes.isEmpty()) {
-                builder.tree(createFunctionalExecute(builder, specialization, execType));
-            } else if (needsCastingExecuteMethod(execType)) {
-                assert !primaryExecutes.isEmpty();
-                builder.tree(createCastingExecute(builder, specialization, execType, primaryExecutes.get(0)));
-            } else {
-                return null;
-            }
-
-            return builder.getRoot();
-        }
-
-        private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType, boolean evaluated) {
-            CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod());
-
-            CodeTreeBuilder builder = method.createBuilder();
-            int i = 0;
-            int signatureIndex = -1;
-            for (VariableElement param : method.getParameters()) {
-                CodeVariableElement var = CodeVariableElement.clone(param);
-                ActualParameter actualParameter = i < execType.getParameters().size() ? execType.getParameters().get(i) : null;
-                String name;
-                if (actualParameter != null) {
-                    if (actualParameter.getSpecification().isSignature()) {
-                        signatureIndex++;
-                    }
-
-                    if (evaluated && actualParameter.getSpecification().isSignature()) {
-                        name = valueNameEvaluated(actualParameter);
-                    } else {
-                        name = valueName(actualParameter);
-                    }
-
-                    int varArgCount = getModel().getSignatureSize() - signatureIndex;
-                    if (evaluated && actualParameter.isTypeVarArgs()) {
-                        ActualParameter baseVarArgs = actualParameter;
-                        name = valueName(baseVarArgs) + "Args";
-
-                        builder.startAssert().string(name).string(" != null").end();
-                        builder.startAssert().string(name).string(".length == ").string(String.valueOf(varArgCount)).end();
-                        if (varArgCount > 0) {
-                            List<ActualParameter> varArgsParameter = execType.getParameters().subList(i, execType.getParameters().size());
-                            for (ActualParameter varArg : varArgsParameter) {
-                                if (varArgCount <= 0) {
-                                    break;
-                                }
-                                TypeMirror type = baseVarArgs.getType();
-                                if (type.getKind() == TypeKind.ARRAY) {
-                                    type = ((ArrayType) type).getComponentType();
-                                }
-                                builder.declaration(type, valueNameEvaluated(varArg), name + "[" + varArg.getTypeVarArgsIndex() + "]");
-                                varArgCount--;
-                            }
-                        }
-                    }
-                } else {
-                    name = "arg" + i;
-                }
-                var.setName(name);
-                method.getParameters().set(i, var);
-                i++;
-            }
-
-            method.getAnnotationMirrors().clear();
-            method.getModifiers().remove(Modifier.ABSTRACT);
-            return method;
-        }
-
-        private boolean needsCastingExecuteMethod(ExecutableTypeData execType) {
-            if (execType.isAbstract()) {
-                return true;
-            }
-            if (execType.getType().isGeneric()) {
-                return true;
-            }
-            return false;
-        }
-
-        private List<ExecutableTypeData> findFunctionalExecutableType(SpecializationData specialization, int evaluatedCount) {
-            TypeData primaryType = specialization.getReturnType().getTypeSystemType();
-            List<ExecutableTypeData> otherTypes = specialization.getNode().getExecutableTypes(evaluatedCount);
-
-            List<ExecutableTypeData> filteredTypes = new ArrayList<>();
-            for (ExecutableTypeData compareType : otherTypes) {
-                if (!Utils.typeEquals(compareType.getType().getPrimitiveType(), primaryType.getPrimitiveType())) {
-                    continue;
-                }
-                filteredTypes.add(compareType);
-            }
-
-            // no direct matches found use generic where the type is Object
-            if (filteredTypes.isEmpty()) {
-                for (ExecutableTypeData compareType : otherTypes) {
-                    if (compareType.getType().isGeneric() && !compareType.hasUnexpectedValue(getContext())) {
-                        filteredTypes.add(compareType);
-                    }
-                }
-            }
-
-            if (filteredTypes.isEmpty()) {
-                for (ExecutableTypeData compareType : otherTypes) {
-                    if (compareType.getType().isGeneric()) {
-                        filteredTypes.add(compareType);
-                    }
-                }
-            }
-
-            return filteredTypes;
-        }
-
-        private CodeTree createFunctionalExecute(CodeTreeBuilder parent, final SpecializationData specialization, final ExecutableTypeData executable) {
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            if (specialization.isUninitialized()) {
-                builder.tree(createDeoptimize(builder));
-            }
-
-            builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null));
-
-            CodeTree returnSpecialized = null;
-
-            if (specialization.findNextSpecialization() != null) {
-                CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder);
-                returnBuilder.tree(createDeoptimize(builder));
-                returnBuilder.tree(createReturnExecuteAndSpecialize(builder, executable, specialization, null, "One of guards " + specialization.getGuardDefinitions() + " failed"));
-                returnSpecialized = returnBuilder.getRoot();
-            }
-
-            builder.tree(createExecuteTree(builder, specialization, SpecializationGroup.create(specialization), false, new CodeBlock<SpecializationData>() {
-
-                public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
-                    return createExecute(b, executable, specialization);
-                }
-            }, returnSpecialized, false, false, false));
-
-            return builder.getRoot();
-        }
-
-        private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) {
-            NodeData node = specialization.getNode();
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            if (!specialization.getExceptions().isEmpty() || !specialization.getAssumptions().isEmpty()) {
-                builder.startTryBlock();
-            }
-
-            for (String assumption : specialization.getAssumptions()) {
-                builder.startStatement();
-                builder.string("this.").string(assumption).string(".check()");
-                builder.end();
-            }
-
-            CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent);
-            if (specialization.isPolymorphic()) {
-                returnBuilder.startCall("next0", EXECUTE_POLYMORPHIC_NAME);
-                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, null);
-                returnBuilder.end();
-            } else if (specialization.isUninitialized()) {
-                returnBuilder.startCall("super", EXECUTE_SPECIALIZE_NAME);
-                returnBuilder.string("0");
-                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, 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(getContext()), null);
-                returnBuilder.end();
-            } else {
-                returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null));
-            }
-
-            if (!returnBuilder.isEmpty()) {
-                TypeData targetType = node.getTypeSystem().findTypeData(builder.findMethod().getReturnType());
-                TypeData sourceType = specialization.getReturnType().getTypeSystemType();
-
-                builder.startReturn();
-                if (targetType == null || sourceType == null) {
-                    builder.tree(returnBuilder.getRoot());
-                } else if (sourceType.needsCastTo(getContext(), targetType)) {
-                    String castMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType);
-                    if (!executable.hasUnexpectedValue(context)) {
-                        castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType);
-                    }
-                    builder.tree(createCallTypeSystemMethod(context, parent, node, castMethodName, returnBuilder.getRoot()));
-                } else {
-                    builder.tree(returnBuilder.getRoot());
-                }
-                builder.end();
-            }
-
-            if (!specialization.getExceptions().isEmpty()) {
-                for (SpecializationThrowsData exception : specialization.getExceptions()) {
-                    builder.end().startCatchBlock(exception.getJavaClass(), "ex");
-                    builder.tree(createDeoptimize(builder));
-                    builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization, null, "Thrown " + Utils.getSimpleName(exception.getJavaClass())));
-                }
-                builder.end();
-            }
-            if (!specialization.getAssumptions().isEmpty()) {
-                builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex");
-                builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization, null, "Assumption failed"));
-                builder.end();
-            }
-
-            return builder.getRoot();
-        }
-
-        protected CodeExecutableElement createCopyConstructorFactoryMethod(TypeMirror baseType, SpecializationData specialization) {
-            List<ActualParameter> implicitTypeParams = getImplicitTypeParameters(specialization);
-            CodeVariableElement[] parameters = new CodeVariableElement[implicitTypeParams.size() + 1];
-            int i = 0;
-            String baseName = "current";
-            parameters[i++] = new CodeVariableElement(specialization.getNode().getNodeType(), baseName);
-            for (ActualParameter implicitTypeParam : implicitTypeParams) {
-                parameters[i++] = new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(implicitTypeParam));
-            }
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), CREATE_SPECIALIZATION_NAME, parameters);
-            CodeTreeBuilder builder = method.createBuilder();
-            builder.startReturn();
-            builder.startNew(getElement().asType());
-            builder.startGroup().cast(baseType, CodeTreeBuilder.singleString(baseName)).end();
-            for (ActualParameter param : implicitTypeParams) {
-                builder.string(implicitTypeName(param));
-            }
-            builder.end().end();
-            return method;
-        }
-
-        protected CodeExecutableElement createConstructorFactoryMethod(SpecializationData specialization, ExecutableElement constructor) {
-            List<? extends VariableElement> parameters = constructor.getParameters();
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), CREATE_SPECIALIZATION_NAME,
-                            parameters.toArray(new CodeVariableElement[parameters.size()]));
-            CodeTreeBuilder builder = method.createBuilder();
-            builder.startReturn();
-            builder.startNew(getElement().asType());
-            for (VariableElement param : parameters) {
-                builder.string(((CodeVariableElement) param).getName());
-            }
-            builder.end().end();
-            return method;
-        }
-    }
-
-    private interface CodeBlock<T> {
-
-        CodeTree create(CodeTreeBuilder parent, T value);
-
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,520 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality;
-import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public class NodeData extends Template implements Comparable<NodeData> {
-
-    private final String nodeId;
-    private final String shortName;
-    private final List<NodeData> enclosingNodes = new ArrayList<>();
-    private NodeData declaringNode;
-
-    private final TypeSystemData typeSystem;
-    private final List<NodeChildData> children;
-    private final List<NodeExecutionData> childExecutions;
-    private final List<NodeFieldData> fields;
-    private final List<String> assumptions;
-
-    private ParameterSpec instanceParameterSpec;
-
-    private final List<SpecializationData> specializations = new ArrayList<>();
-    private final List<ShortCircuitData> shortCircuits = new ArrayList<>();
-    private final List<CreateCastData> casts = new ArrayList<>();
-    private Map<Integer, List<ExecutableTypeData>> executableTypes;
-
-    private final NodeExecutionData thisExecution;
-
-    private int polymorphicDepth = -1;
-
-    public NodeData(TypeElement type, String shortName, TypeSystemData typeSystem, List<NodeChildData> children, List<NodeExecutionData> executions, List<NodeFieldData> fields,
-                    List<String> assumptions, int polymorphicDepth) {
-        super(type, null, null);
-        this.nodeId = type.getSimpleName().toString();
-        this.shortName = shortName;
-        this.typeSystem = typeSystem;
-        this.fields = fields;
-        this.children = children;
-        this.childExecutions = executions;
-        this.assumptions = assumptions;
-        this.polymorphicDepth = polymorphicDepth;
-        this.thisExecution = new NodeExecutionData(new NodeChildData(null, null, "this", getNodeType(), getNodeType(), null, Cardinality.ONE), -1, false);
-        this.thisExecution.getChild().setNode(this);
-        if (children != null) {
-            for (NodeChildData child : children) {
-                child.setParentNode(this);
-            }
-        }
-    }
-
-    public NodeData(TypeElement type) {
-        this(type, null, null, null, null, null, null, -1);
-    }
-
-    public NodeExecutionData getThisExecution() {
-        return thisExecution;
-    }
-
-    public void addEnclosedNode(NodeData node) {
-        this.enclosingNodes.add(node);
-        node.declaringNode = this;
-    }
-
-    public List<NodeExecutionData> getChildExecutions() {
-        return childExecutions;
-    }
-
-    public int getSignatureSize() {
-        if (getSpecializations() != null && !getSpecializations().isEmpty()) {
-            return getSpecializations().get(0).getSignatureSize();
-        }
-        return 0;
-    }
-
-    public boolean needsFrame(ProcessorContext context) {
-        for (SpecializationData specialization : specializations) {
-            if (!specialization.isReachable()) {
-                continue;
-            }
-            if (specialization.hasFrame(context)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public boolean needsImplicitCast(ProcessorContext context) {
-        for (NodeChildData child : getChildren()) {
-            if (child.needsImplicitCast(context)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public int getPolymorphicDepth() {
-        return polymorphicDepth;
-    }
-
-    public boolean isPolymorphic() {
-        return polymorphicDepth > 1;
-    }
-
-    public void setPolymorphicDepth(int polymorphicDepth) {
-        this.polymorphicDepth = polymorphicDepth;
-    }
-
-    public List<CreateCastData> getCasts() {
-        return casts;
-    }
-
-    public String getShortName() {
-        return shortName;
-    }
-
-    public List<NodeFieldData> getFields() {
-        return fields;
-    }
-
-    @Override
-    protected List<MessageContainer> findChildContainers() {
-        List<MessageContainer> containerChildren = new ArrayList<>();
-        if (enclosingNodes != null) {
-            containerChildren.addAll(enclosingNodes);
-        }
-        if (typeSystem != null) {
-            containerChildren.add(typeSystem);
-        }
-        if (specializations != null) {
-            for (MessageContainer specialization : specializations) {
-                if (specialization.getMessageElement() != null) {
-                    containerChildren.add(specialization);
-                }
-            }
-        }
-        if (executableTypes != null) {
-            containerChildren.addAll(getExecutableTypes());
-        }
-        if (shortCircuits != null) {
-            containerChildren.addAll(shortCircuits);
-        }
-        if (children != null) {
-            containerChildren.addAll(children);
-        }
-        if (fields != null) {
-            containerChildren.addAll(fields);
-        }
-        if (casts != null) {
-            containerChildren.addAll(casts);
-        }
-        return containerChildren;
-    }
-
-    public ParameterSpec getInstanceParameterSpec() {
-        return instanceParameterSpec;
-    }
-
-    public void setInstanceParameterSpec(ParameterSpec instanceParameter) {
-        this.instanceParameterSpec = instanceParameter;
-    }
-
-    public String getNodeId() {
-        return nodeId;
-    }
-
-    public TypeMirror getNodeType() {
-        return getTemplateType().asType();
-    }
-
-    public List<String> getAssumptions() {
-        return assumptions;
-    }
-
-    public boolean needsFactory() {
-        if (specializations == null) {
-            return false;
-        }
-        if (getTemplateType().getModifiers().contains(Modifier.PRIVATE)) {
-            return false;
-        }
-
-        boolean noSpecialization = true;
-        for (SpecializationData specialization : specializations) {
-            noSpecialization = noSpecialization && !specialization.isSpecialized();
-        }
-        return !noSpecialization;
-    }
-
-    public boolean supportsFrame() {
-        if (executableTypes != null) {
-            for (ExecutableTypeData execType : getExecutableTypes(-1)) {
-                if (execType.findParameter("frameValue") == null) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    public List<NodeData> getNodeDeclaringChildren() {
-        List<NodeData> nodeChildren = new ArrayList<>();
-        for (NodeData child : getEnclosingNodes()) {
-            if (child.needsFactory()) {
-                nodeChildren.add(child);
-            }
-            nodeChildren.addAll(child.getNodeDeclaringChildren());
-        }
-        return nodeChildren;
-    }
-
-    public NodeData getDeclaringNode() {
-        return declaringNode;
-    }
-
-    public List<NodeData> getEnclosingNodes() {
-        return enclosingNodes;
-    }
-
-    public List<TemplateMethod> getAllTemplateMethods() {
-        List<TemplateMethod> methods = new ArrayList<>();
-
-        for (SpecializationData specialization : getSpecializations()) {
-            methods.add(specialization);
-        }
-
-        methods.addAll(getExecutableTypes());
-        methods.addAll(getShortCircuits());
-        if (getCasts() != null) {
-            methods.addAll(getCasts());
-        }
-
-        return methods;
-    }
-
-    public ExecutableTypeData findGenericExecutableType(ProcessorContext context, TypeData type, int evaluatedCount) {
-        List<ExecutableTypeData> types = findGenericExecutableTypes(context, evaluatedCount);
-        for (ExecutableTypeData availableType : types) {
-            if (Utils.typeEquals(availableType.getType().getBoxedType(), type.getBoxedType())) {
-                return availableType;
-            }
-        }
-        return null;
-    }
-
-    public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context, int evaluatedCount) {
-        List<ExecutableTypeData> types = findGenericExecutableTypes(context, evaluatedCount);
-        for (ExecutableTypeData type : types) {
-            if (type.getType().isGeneric()) {
-                return type;
-            }
-        }
-
-        for (ExecutableTypeData type : types) {
-            if (!type.getType().isVoid()) {
-                return type;
-            }
-        }
-
-        for (ExecutableTypeData type : types) {
-            return type;
-        }
-        return null;
-    }
-
-    public List<ExecutableTypeData> getExecutableTypes(int evaluatedCount) {
-        if (executableTypes == null) {
-            return Collections.emptyList();
-        }
-        if (evaluatedCount == -1) {
-            List<ExecutableTypeData> typeData = new ArrayList<>();
-            for (int currentEvaluationCount : executableTypes.keySet()) {
-                typeData.addAll(executableTypes.get(currentEvaluationCount));
-            }
-            return typeData;
-        } else {
-            List<ExecutableTypeData> types = executableTypes.get(evaluatedCount);
-            if (types == null) {
-                return Collections.emptyList();
-            }
-            return types;
-        }
-    }
-
-    public List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context, int evaluatedCount) {
-        List<ExecutableTypeData> types = new ArrayList<>();
-        for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) {
-            if (!type.hasUnexpectedValue(context)) {
-                types.add(type);
-            }
-        }
-        return types;
-    }
-
-    public ExecutableTypeData findExecutableType(TypeData prmitiveType, int evaluatedCount) {
-        for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) {
-            if (Utils.typeEquals(type.getType().getPrimitiveType(), prmitiveType.getPrimitiveType())) {
-                return type;
-            }
-        }
-        return null;
-    }
-
-    public SpecializationData findUniqueSpecialization(TypeData type) {
-        SpecializationData result = null;
-        for (SpecializationData specialization : specializations) {
-            if (specialization.getReturnType().getTypeSystemType() == type) {
-                if (result != null) {
-                    // Result not unique;
-                    return null;
-                }
-                result = specialization;
-            }
-        }
-        return result;
-    }
-
-    public boolean needsRewrites(ProcessorContext context) {
-        boolean needsRewrites = false;
-
-        for (SpecializationData specialization : getSpecializations()) {
-            if (specialization.hasRewrite(context)) {
-                needsRewrites = true;
-                break;
-            }
-        }
-        return needsRewrites || getSpecializations().size() > 1;
-    }
-
-    public SpecializationData getPolymorphicSpecialization() {
-        for (SpecializationData specialization : specializations) {
-            if (specialization.isPolymorphic()) {
-                return specialization;
-            }
-        }
-        return null;
-    }
-
-    public SpecializationData getGenericSpecialization() {
-        for (SpecializationData specialization : specializations) {
-            if (specialization.isGeneric()) {
-                return specialization;
-            }
-        }
-        return null;
-    }
-
-    public SpecializationData getUninitializedSpecialization() {
-        for (SpecializationData specialization : specializations) {
-            if (specialization.isUninitialized()) {
-                return specialization;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public TypeSystemData getTypeSystem() {
-        return typeSystem;
-    }
-
-    public String dump() {
-        return dump(0);
-    }
-
-    private String dump(int level) {
-        String indent = "";
-        for (int i = 0; i < level; i++) {
-            indent += "    ";
-        }
-        StringBuilder builder = new StringBuilder();
-
-        builder.append(String.format("%s%s {", indent, toString()));
-
-        dumpProperty(builder, indent, "templateClass", Utils.getQualifiedName(getTemplateType()));
-        dumpProperty(builder, indent, "typeSystem", getTypeSystem());
-        dumpProperty(builder, indent, "fields", getChildren());
-        dumpProperty(builder, indent, "executableTypes", getExecutableTypes());
-        dumpProperty(builder, indent, "specializations", getSpecializations());
-        dumpProperty(builder, indent, "polymorphicDepth", getPolymorphicDepth());
-        dumpProperty(builder, indent, "assumptions", getAssumptions());
-        dumpProperty(builder, indent, "casts", getCasts());
-        dumpProperty(builder, indent, "messages", collectMessages());
-        if (getEnclosingNodes().size() > 0) {
-            builder.append(String.format("\n%s  children = [", indent));
-            for (NodeData node : getEnclosingNodes()) {
-                builder.append("\n");
-                builder.append(node.dump(level + 1));
-            }
-            builder.append(String.format("\n%s  ]", indent));
-        }
-        builder.append(String.format("%s}", indent));
-        return builder.toString();
-    }
-
-    private static void dumpProperty(StringBuilder b, String indent, String propertyName, Object value) {
-        if (value instanceof List) {
-            List<?> list = (List<?>) value;
-            if (!list.isEmpty()) {
-                b.append(String.format("\n%s  %s = %s", indent, propertyName, dumpList(indent, (List<?>) value)));
-            }
-        } else {
-            if (value != null) {
-                b.append(String.format("\n%s  %s = %s", indent, propertyName, value));
-            }
-        }
-    }
-
-    private static String dumpList(String indent, List<?> array) {
-        if (array == null) {
-            return "null";
-        }
-
-        if (array.isEmpty()) {
-            return "[]";
-        } else if (array.size() == 1) {
-            return "[" + array.get(0).toString() + "]";
-        }
-
-        StringBuilder b = new StringBuilder();
-        b.append("[");
-        for (Object object : array) {
-            b.append("\n        ");
-            b.append(indent);
-            b.append(object);
-            b.append(", ");
-        }
-        b.append("\n    ").append(indent).append("]");
-        return b.toString();
-    }
-
-    public NodeExecutionData findExecution(String name) {
-        if (getChildExecutions() == null) {
-            return null;
-        }
-        for (NodeExecutionData execution : getChildExecutions()) {
-            if (execution.getName().equals(name)) {
-                return execution;
-            }
-        }
-        return null;
-    }
-
-    public NodeChildData findChild(String name) {
-        for (NodeChildData field : getChildren()) {
-            if (field.getName().equals(name)) {
-                return field;
-            }
-        }
-        return null;
-    }
-
-    public List<NodeChildData> getChildren() {
-        return children;
-    }
-
-    public List<SpecializationData> getSpecializations() {
-        return specializations;
-    }
-
-    public List<ExecutableTypeData> getExecutableTypes() {
-        return getExecutableTypes(-1);
-    }
-
-    public List<ShortCircuitData> getShortCircuits() {
-        return shortCircuits;
-    }
-
-    public void setExecutableTypes(Map<Integer, List<ExecutableTypeData>> executableTypes) {
-        this.executableTypes = executableTypes;
-    }
-
-    @Override
-    public String toString() {
-        return getClass().getSimpleName() + "[" + getNodeId() + "]";
-    }
-
-    public CreateCastData findCast(String name) {
-        if (getCasts() != null) {
-            for (CreateCastData cast : getCasts()) {
-                if (cast.getChildNames().contains(name)) {
-                    return cast;
-                }
-            }
-        }
-        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/NodeExecutionData.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality;
-
-public class NodeExecutionData {
-
-    private final NodeChildData child;
-    private final String name;
-    private final int index;
-    private final boolean shortCircuit;
-
-    public NodeExecutionData(NodeChildData child, int index, boolean shortCircuit) {
-        this.child = child;
-        this.index = index;
-        this.shortCircuit = shortCircuit;
-        this.name = createName();
-    }
-
-    private String createName() {
-        if (isIndexed()) {
-            return child.getName() + index;
-        }
-        return child.getName();
-    }
-
-    public TypeMirror getNodeType() {
-        TypeMirror type;
-        if (child.getCardinality() == Cardinality.MANY && child.getNodeType().getKind() == TypeKind.ARRAY) {
-            type = ((ArrayType) child.getNodeType()).getComponentType();
-        } else {
-            type = child.getNodeType();
-        }
-        return type;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public NodeChildData getChild() {
-        return child;
-    }
-
-    public int getIndex() {
-        return index;
-    }
-
-    public boolean isIndexed() {
-        return index > -1;
-    }
-
-    public boolean isShortCircuit() {
-        return shortCircuit;
-    }
-
-    public String getShortCircuitId() {
-        return createShortCircuitId(child, index);
-    }
-
-    public static String createShortCircuitId(NodeChildData child, int varArgsIndex) {
-        String shortCircuitName = child.getName();
-        if (child.getCardinality().isMany()) {
-            shortCircuitName = shortCircuitName + "[" + varArgsIndex + "]";
-        }
-        return shortCircuitName;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeFieldData.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class NodeFieldData extends MessageContainer {
-
-    private final Element messageElement;
-    private final AnnotationMirror messageAnnotation;
-    private final String name;
-    private final TypeMirror type;
-    private final boolean generated;
-    private ExecutableElement getter;
-
-    public NodeFieldData(Element messageElement, AnnotationMirror messageAnnotation, TypeMirror type, String name, boolean generated) {
-        this.messageElement = messageElement;
-        this.messageAnnotation = messageAnnotation;
-        this.name = name;
-        this.type = type;
-        this.generated = generated;
-    }
-
-    void setGetter(ExecutableElement getter) {
-        this.getter = getter;
-    }
-
-    @Override
-    public Element getMessageElement() {
-        return messageElement;
-    }
-
-    @Override
-    public AnnotationMirror getMessageAnnotation() {
-        return messageAnnotation;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public TypeMirror getType() {
-        return type;
-    }
-
-    public boolean isGenerated() {
-        return generated;
-    }
-
-    public ExecutableElement getGetter() {
-        return getter;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public abstract class NodeMethodParser<E extends TemplateMethod> extends TemplateMethodParser<NodeData, E> {
-
-    public NodeMethodParser(ProcessorContext context, NodeData node) {
-        super(context, node);
-    }
-
-    public NodeData getNode() {
-        return template;
-    }
-
-    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
-        ParameterSpec spec = new ParameterSpec(execution.getName(), nodeTypeMirrors(execution.getChild().getNodeData()));
-        spec.setExecution(execution);
-        return spec;
-    }
-
-    protected List<TypeMirror> nodeTypeMirrors(NodeData nodeData) {
-        Set<TypeMirror> typeMirrors = new LinkedHashSet<>();
-
-        for (ExecutableTypeData typeData : nodeData.getExecutableTypes()) {
-            typeMirrors.add(typeData.getType().getPrimitiveType());
-        }
-
-        typeMirrors.add(nodeData.getTypeSystem().getGenericType());
-
-        return new ArrayList<>(typeMirrors);
-    }
-
-    protected ParameterSpec createReturnParameterSpec() {
-        ParameterSpec returnValue = new ParameterSpec("returnValue", nodeTypeMirrors(getNode()));
-        returnValue.setExecution(getNode().getThisExecution());
-        return returnValue;
-    }
-
-    @Override
-    public boolean isParsable(ExecutableElement method) {
-        if (getAnnotationType() != null) {
-            return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null;
-        }
-
-        return true;
-    }
-
-    @SuppressWarnings("unused")
-    protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, boolean shortCircuitsEnabled, String shortCircuitName) {
-        MethodSpec methodSpec = new MethodSpec(createReturnParameterSpec());
-
-        addDefaultFrame(methodSpec);
-        addDefaultFieldMethodSpec(methodSpec);
-        addDefaultChildren(shortCircuitsEnabled, shortCircuitName, methodSpec);
-
-        return methodSpec;
-    }
-
-    public void addDefaultChildren(boolean shortCircuitsEnabled, String breakName, MethodSpec spec) {
-        if (getNode().getChildren() == null) {
-            // children are null when parsing executable types
-            return;
-        }
-
-        for (NodeExecutionData execution : getNode().getChildExecutions()) {
-            if (breakName != null && execution.getShortCircuitId().equals(breakName)) {
-                break;
-            }
-
-            if (execution.isShortCircuit() && shortCircuitsEnabled) {
-                spec.addRequired(new ParameterSpec(shortCircuitValueName(execution.getName()), getContext().getType(boolean.class)));
-            }
-            spec.addRequired(createValueParameterSpec(execution));
-        }
-    }
-
-    private void addDefaultFrame(MethodSpec methodSpec) {
-        if (getNode().supportsFrame()) {
-            methodSpec.addOptional(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame()));
-        }
-    }
-
-    protected void addDefaultFieldMethodSpec(MethodSpec methodSpec) {
-        for (NodeFieldData field : getNode().getFields()) {
-            if (field.getGetter() == null) {
-                ParameterSpec spec = new ParameterSpec(field.getName(), field.getType());
-                spec.setLocal(true);
-                methodSpec.addOptional(spec);
-            }
-        }
-    }
-
-    private static String shortCircuitValueName(String valueName) {
-        return "has" + Utils.firstLetterUpperCase(valueName);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1225 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-import javax.tools.Diagnostic.Kind;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality;
-import com.oracle.truffle.dsl.processor.node.SpecializationData.SpecializationKind;
-import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.template.TemplateMethod.TypeSignature;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public class NodeParser extends AbstractParser<NodeData> {
-
-    public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, NodeChild.class,
-                    NodeChildren.class);
-
-    private Map<String, NodeData> parsedNodes;
-
-    public NodeParser(ProcessorContext c) {
-        super(c);
-    }
-
-    @Override
-    protected NodeData parse(Element element, AnnotationMirror mirror) {
-        NodeData node = null;
-        try {
-            parsedNodes = new HashMap<>();
-            node = resolveNode((TypeElement) element);
-            if (Log.DEBUG) {
-                NodeData parsed = parsedNodes.get(Utils.getQualifiedName((TypeElement) element));
-                if (node != null) {
-                    String dump = parsed.dump();
-                    log.message(Kind.ERROR, null, null, null, dump);
-                }
-            }
-        } finally {
-            parsedNodes = null;
-        }
-
-        return node;
-    }
-
-    @Override
-    protected NodeData filterErrorElements(NodeData model) {
-        for (Iterator<NodeData> iterator = model.getEnclosingNodes().iterator(); iterator.hasNext();) {
-            NodeData node = filterErrorElements(iterator.next());
-            if (node == null) {
-                iterator.remove();
-            }
-        }
-        if (model.hasErrors()) {
-            return null;
-        }
-        return model;
-    }
-
-    @Override
-    public boolean isDelegateToRootDeclaredType() {
-        return true;
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return null;
-    }
-
-    @Override
-    public List<Class<? extends Annotation>> getTypeDelegatedAnnotationTypes() {
-        return ANNOTATIONS;
-    }
-
-    private NodeData resolveNode(TypeElement rootType) {
-        String typeName = Utils.getQualifiedName(rootType);
-        if (parsedNodes.containsKey(typeName)) {
-            return parsedNodes.get(typeName);
-        }
-
-        List<NodeData> enclosedNodes = new ArrayList<>();
-        for (TypeElement enclosedType : ElementFilter.typesIn(rootType.getEnclosedElements())) {
-            NodeData enclosedChild = resolveNode(enclosedType);
-            if (enclosedChild != null) {
-                enclosedNodes.add(enclosedChild);
-            }
-        }
-
-        NodeData node = parseNode(rootType);
-        if (node == null && !enclosedNodes.isEmpty()) {
-            node = new NodeData(rootType);
-        }
-
-        if (node != null) {
-            for (NodeData enclosedNode : enclosedNodes) {
-                node.addEnclosedNode(enclosedNode);
-            }
-        }
-
-        parsedNodes.put(typeName, node);
-        return node;
-    }
-
-    private NodeData parseNode(TypeElement originalTemplateType) {
-        // reloading the type elements is needed for ecj
-        TypeElement templateType = Utils.fromTypeMirror(context.reloadTypeElement(originalTemplateType));
-
-        if (Utils.findAnnotationMirror(processingEnv, originalTemplateType, GeneratedBy.class) != null) {
-            // generated nodes should not get called again.
-            return null;
-        }
-
-        List<TypeElement> lookupTypes = collectSuperClasses(new ArrayList<TypeElement>(), templateType);
-        if (!Utils.isAssignable(context, templateType.asType(), context.getTruffleTypes().getNode())) {
-            return null;
-        }
-
-        List<? extends Element> elements = context.getEnvironment().getElementUtils().getAllMembers(templateType);
-
-        NodeData node = parseNodeData(templateType, elements, lookupTypes);
-        if (node.hasErrors()) {
-            return node; // error sync point
-        }
-
-        initializeChildren(node);
-
-        node.getSpecializations().addAll(new SpecializationMethodParser(context, node).parse(elements));
-        node.getSpecializations().addAll(new GenericParser(context, node).parse(elements));
-        node.getCasts().addAll(new CreateCastParser(context, node).parse(elements));
-        node.getShortCircuits().addAll(new ShortCircuitParser(context, node).parse(elements));
-
-        if (node.hasErrors()) {
-            return node;  // error sync point
-        }
-
-        verifySpecializationSameLength(node);
-        initializeSpecializations(elements, node);
-        initializeShortCircuits(node); // requires specializations and polymorphic specializations
-
-        verifyVisibilities(node);
-        verifySpecializationOrder(node);
-        verifyMissingAbstractMethods(node, elements);
-        verifyConstructors(node);
-        verifyNamingConvention(node.getShortCircuits(), "needs");
-        verifySpecializationThrows(node);
-        return node;
-    }
-
-    private NodeData parseNodeData(TypeElement templateType, List<? extends Element> elements, List<TypeElement> typeHierarchy) {
-        AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class);
-        if (typeSystemMirror == null) {
-            NodeData nodeData = new NodeData(templateType);
-            nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), Utils.getQualifiedName(templateType));
-            return nodeData;
-        }
-
-        TypeMirror typeSystemType = Utils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value");
-        final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSystemType, true);
-        if (typeSystem == null) {
-            NodeData nodeData = new NodeData(templateType);
-            nodeData.addError("The used type system '%s' is invalid or not a Node.", Utils.getQualifiedName(typeSystemType));
-            return nodeData;
-        }
-
-        AnnotationMirror polymorphicMirror = findFirstAnnotation(typeHierarchy, PolymorphicLimit.class);
-        int polymorphicLimit = -1;
-        if (polymorphicMirror != null) {
-            AnnotationValue limitValue = Utils.getAnnotationValue(polymorphicMirror, "value");
-            int customPolymorphicLimit = Utils.getAnnotationValue(Integer.class, polymorphicMirror, "value");
-            if (customPolymorphicLimit < 1) {
-                NodeData nodeData = new NodeData(templateType);
-                nodeData.addError(limitValue, "Invalid polymorphic limit %s.", polymorphicLimit);
-                return nodeData;
-            }
-            polymorphicLimit = customPolymorphicLimit;
-        }
-
-        List<String> assumptionsList = new ArrayList<>();
-        for (int i = typeHierarchy.size() - 1; i >= 0; i--) {
-            TypeElement type = typeHierarchy.get(i);
-            AnnotationMirror assumptions = Utils.findAnnotationMirror(context.getEnvironment(), type, NodeAssumptions.class);
-            if (assumptions != null) {
-                List<String> assumptionStrings = Utils.getAnnotationValueList(String.class, assumptions, "value");
-                for (String string : assumptionStrings) {
-                    if (assumptionsList.contains(string)) {
-                        assumptionsList.remove(string);
-                    }
-                    assumptionsList.add(string);
-                }
-            }
-        }
-        AnnotationMirror nodeInfoMirror = findFirstAnnotation(typeHierarchy, NodeInfo.class);
-        String shortName = null;
-        if (nodeInfoMirror != null) {
-            shortName = Utils.getAnnotationValue(String.class, nodeInfoMirror, "shortName");
-        }
-
-        List<NodeFieldData> fields = parseFields(typeHierarchy, elements);
-        List<NodeChildData> children = parseChildren(elements, typeHierarchy);
-        List<NodeExecutionData> executions = parseExecutions(children, elements);
-
-        NodeData nodeData = new NodeData(templateType, shortName, typeSystem, children, executions, fields, assumptionsList, polymorphicLimit);
-        nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)));
-
-        parsedNodes.put(Utils.getQualifiedName(templateType), nodeData);
-
-        return nodeData;
-    }
-
-    private List<NodeFieldData> parseFields(List<TypeElement> typeHierarchy, List<? extends Element> elements) {
-        Set<String> names = new HashSet<>();
-
-        List<NodeFieldData> fields = new ArrayList<>();
-        for (VariableElement field : ElementFilter.fieldsIn(elements)) {
-            if (field.getModifiers().contains(Modifier.STATIC)) {
-                continue;
-            }
-            if (field.getModifiers().contains(Modifier.PUBLIC) || field.getModifiers().contains(Modifier.PROTECTED)) {
-                String name = field.getSimpleName().toString();
-                fields.add(new NodeFieldData(field, null, field.asType(), name, false));
-                names.add(name);
-            }
-        }
-
-        List<TypeElement> reversedTypeHierarchy = new ArrayList<>(typeHierarchy);
-        Collections.reverse(reversedTypeHierarchy);
-        for (TypeElement typeElement : reversedTypeHierarchy) {
-            AnnotationMirror nodeChildrenMirror = Utils.findAnnotationMirror(processingEnv, typeElement, NodeFields.class);
-            List<AnnotationMirror> children = Utils.collectAnnotations(context, nodeChildrenMirror, "value", typeElement, NodeField.class);
-
-            for (AnnotationMirror mirror : children) {
-                String name = Utils.firstLetterLowerCase(Utils.getAnnotationValue(String.class, mirror, "name"));
-                TypeMirror type = Utils.getAnnotationValue(TypeMirror.class, mirror, "type");
-
-                NodeFieldData field = new NodeFieldData(typeElement, mirror, type, name, true);
-                if (name.isEmpty()) {
-                    field.addError(Utils.getAnnotationValue(mirror, "name"), "Field name cannot be empty.");
-                } else if (names.contains(name)) {
-                    field.addError(Utils.getAnnotationValue(mirror, "name"), "Duplicate field name '%s'.", name);
-                }
-                names.add(name);
-
-                fields.add(field);
-            }
-        }
-
-        for (NodeFieldData nodeFieldData : fields) {
-            nodeFieldData.setGetter(findGetter(elements, nodeFieldData.getName(), nodeFieldData.getType()));
-        }
-
-        return fields;
-    }
-
-    private List<NodeChildData> parseChildren(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);
-            if (mirror != null) {
-                shortCircuits.add(Utils.getAnnotationValue(String.class, mirror, "value"));
-            }
-        }
-        Map<String, TypeMirror> castNodeTypes = new HashMap<>();
-        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
-            AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, CreateCast.class);
-            if (mirror != null) {
-                List<String> children = (Utils.getAnnotationValueList(String.class, mirror, "value"));
-                if (children != null) {
-                    for (String child : children) {
-                        castNodeTypes.put(child, method.getReturnType());
-                    }
-                }
-            }
-        }
-
-        List<NodeChildData> parsedChildren = new ArrayList<>();
-        List<TypeElement> typeHierarchyReversed = new ArrayList<>(typeHierarchy);
-        Collections.reverse(typeHierarchyReversed);
-        for (TypeElement type : typeHierarchyReversed) {
-            AnnotationMirror nodeChildrenMirror = Utils.findAnnotationMirror(processingEnv, type, NodeChildren.class);
-
-            TypeMirror nodeClassType = type.getSuperclass();
-            if (!Utils.isAssignable(context, nodeClassType, context.getTruffleTypes().getNode())) {
-                nodeClassType = null;
-            }
-
-            List<AnnotationMirror> children = Utils.collectAnnotations(context, nodeChildrenMirror, "value", type, NodeChild.class);
-            int index = 0;
-            for (AnnotationMirror childMirror : children) {
-                String name = Utils.getAnnotationValue(String.class, childMirror, "value");
-                if (name.equals("")) {
-                    name = "child" + index;
-                }
-
-                Cardinality cardinality = Cardinality.ONE;
-
-                TypeMirror childType = inheritType(childMirror, "type", nodeClassType);
-                if (childType.getKind() == TypeKind.ARRAY) {
-                    cardinality = Cardinality.MANY;
-                }
-
-                TypeMirror originalChildType = childType;
-                TypeMirror castNodeType = castNodeTypes.get(name);
-                if (castNodeType != null) {
-                    childType = castNodeType;
-                }
-
-                Element getter = findGetter(elements, name, childType);
-
-                NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality);
-
-                parsedChildren.add(nodeChild);
-
-                if (nodeChild.getNodeType() == null) {
-                    nodeChild.addError("No valid node type could be resoleved.");
-                }
-                if (nodeChild.hasErrors()) {
-                    continue;
-                }
-
-                index++;
-            }
-        }
-
-        List<NodeChildData> filteredChildren = new ArrayList<>();
-        Set<String> encounteredNames = new HashSet<>();
-        for (int i = parsedChildren.size() - 1; i >= 0; i--) {
-            NodeChildData child = parsedChildren.get(i);
-            if (!encounteredNames.contains(child.getName())) {
-                filteredChildren.add(0, child);
-                encounteredNames.add(child.getName());
-            }
-        }
-
-        for (NodeChildData child : filteredChildren) {
-            List<String> executeWithStrings = Utils.getAnnotationValueList(String.class, child.getMessageAnnotation(), "executeWith");
-            AnnotationValue executeWithValue = Utils.getAnnotationValue(child.getMessageAnnotation(), "executeWith");
-            List<NodeChildData> executeWith = new ArrayList<>();
-            for (String executeWithString : executeWithStrings) {
-
-                if (child.getName().equals(executeWithString)) {
-                    child.addError(executeWithValue, "The child node '%s' cannot be executed with itself.", executeWithString);
-                    continue;
-                }
-
-                NodeChildData found = null;
-                boolean before = true;
-                for (NodeChildData resolveChild : filteredChildren) {
-                    if (resolveChild == child) {
-                        before = false;
-                        continue;
-                    }
-                    if (resolveChild.getName().equals(executeWithString)) {
-                        found = resolveChild;
-                        break;
-                    }
-                }
-
-                if (found == null) {
-                    child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The child node was not found.", child.getName(), executeWithString);
-                    continue;
-                } else if (!before) {
-                    child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The node %s is executed after the current node.", child.getName(), executeWithString,
-                                    executeWithString);
-                    continue;
-                }
-                executeWith.add(found);
-            }
-            child.setExecuteWith(executeWith);
-            if (child.getNodeData() == null) {
-                continue;
-            }
-        }
-
-        return filteredChildren;
-    }
-
-    private List<NodeExecutionData> parseExecutions(List<NodeChildData> children, List<? extends Element> elements) {
-        if (children == null) {
-            return null;
-        }
-
-        // pre-parse short circuits
-        Set<String> shortCircuits = new HashSet<>();
-        List<ExecutableElement> methods = ElementFilter.methodsIn(elements);
-        for (ExecutableElement method : methods) {
-            AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
-            if (mirror != null) {
-                shortCircuits.add(Utils.getAnnotationValue(String.class, mirror, "value"));
-            }
-        }
-
-        boolean hasVarArgs = false;
-        int maxSignatureSize = 0;
-        if (!children.isEmpty()) {
-            int lastIndex = children.size() - 1;
-            hasVarArgs = children.get(lastIndex).getCardinality() == Cardinality.MANY;
-            if (hasVarArgs) {
-                maxSignatureSize = lastIndex;
-            } else {
-                maxSignatureSize = children.size();
-            }
-        }
-
-        // pre-parse specializations
-        for (ExecutableElement method : methods) {
-            AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, Specialization.class);
-            if (mirror == null) {
-                continue;
-            }
-
-            int currentArgumentCount = 0;
-            boolean skipShortCircuit = false;
-            for (VariableElement var : method.getParameters()) {
-                TypeMirror type = var.asType();
-                if (currentArgumentCount == 0) {
-                    // skip optionals
-                    if (Utils.typeEquals(type, context.getTruffleTypes().getFrame())) {
-                        continue;
-                    }
-                    // TODO skip optional fields?
-                }
-                int childIndex = currentArgumentCount < children.size() ? currentArgumentCount : children.size() - 1;
-                if (childIndex == -1) {
-                    continue;
-                }
-                if (!skipShortCircuit) {
-                    NodeChildData child = children.get(childIndex);
-                    if (shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, currentArgumentCount - childIndex))) {
-                        skipShortCircuit = true;
-                        continue;
-                    }
-                } else {
-                    skipShortCircuit = false;
-                }
-
-                currentArgumentCount++;
-            }
-            maxSignatureSize = Math.max(maxSignatureSize, currentArgumentCount);
-        }
-
-        List<NodeExecutionData> executions = new ArrayList<>();
-        for (int i = 0; i < maxSignatureSize; i++) {
-            int childIndex = i;
-            boolean varArg = false;
-            if (childIndex >= children.size() - 1) {
-                if (hasVarArgs) {
-                    childIndex = children.size() - 1;
-                    varArg = hasVarArgs;
-                } else if (childIndex >= children.size()) {
-                    break;
-                }
-            }
-            int varArgsIndex = varArg ? Math.abs(childIndex - i) : -1;
-            NodeChildData child = children.get(childIndex);
-            boolean shortCircuit = shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, varArgsIndex));
-            executions.add(new NodeExecutionData(child, varArgsIndex, shortCircuit));
-        }
-        return executions;
-    }
-
-    private static Map<Integer, List<ExecutableTypeData>> groupExecutableTypes(List<ExecutableTypeData> executableTypes) {
-        Map<Integer, List<ExecutableTypeData>> groupedTypes = new TreeMap<>();
-        for (ExecutableTypeData type : executableTypes) {
-            int evaluatedCount = type.getEvaluatedCount();
-
-            List<ExecutableTypeData> types = groupedTypes.get(evaluatedCount);
-            if (types == null) {
-                types = new ArrayList<>();
-                groupedTypes.put(evaluatedCount, types);
-            }
-            types.add(type);
-        }
-
-        for (List<ExecutableTypeData> types : groupedTypes.values()) {
-            Collections.sort(types);
-        }
-        return groupedTypes;
-    }
-
-    private void initializeChildren(NodeData node) {
-        for (NodeChildData nodeChild : node.getChildren()) {
-            NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(nodeChild.getNodeType()));
-            nodeChild.setNode(fieldNodeData);
-            if (fieldNodeData == null) {
-                nodeChild.addError("Node type '%s' is invalid or not a valid Node.", Utils.getQualifiedName(nodeChild.getNodeType()));
-            } else if (!Utils.typeEquals(fieldNodeData.getTypeSystem().getTemplateType().asType(), (node.getTypeSystem().getTemplateType().asType()))) {
-                nodeChild.addError("The @%s of the node and the @%s of the @%s does not match. %s != %s. ", TypeSystem.class.getSimpleName(), TypeSystem.class.getSimpleName(),
-                                NodeChild.class.getSimpleName(), Utils.getSimpleName(node.getTypeSystem().getTemplateType()), Utils.getSimpleName(fieldNodeData.getTypeSystem().getTemplateType()));
-            }
-            if (fieldNodeData != null) {
-                List<ExecutableTypeData> types = nodeChild.findGenericExecutableTypes(context);
-                if (types.isEmpty()) {
-                    AnnotationValue executeWithValue = Utils.getAnnotationValue(nodeChild.getMessageAnnotation(), "executeWith");
-                    nodeChild.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", nodeChild.getExecuteWith().size(),
-                                    Utils.getSimpleName(nodeChild.getNodeType()));
-                }
-            }
-        }
-    }
-
-    private void initializeSpecializations(List<? extends Element> elements, final NodeData node) {
-        if (node.getSpecializations().isEmpty()) {
-            return;
-        }
-
-        for (SpecializationData specialization : node.getSpecializations()) {
-            if (!specialization.isSpecialized()) {
-                continue;
-            }
-            initializeGuards(elements, specialization);
-        }
-
-        initializeGeneric(node);
-        initializeUninitialized(node);
-        initializePolymorphism(node); // requires specializations
-        Collections.sort(node.getSpecializations());
-        initializeReachability(node);
-
-        // reduce polymorphicness if generic is not reachable
-        if (node.getGenericSpecialization() != null && !node.getGenericSpecialization().isReachable()) {
-            node.setPolymorphicDepth(1);
-            node.getSpecializations().remove(node.getPolymorphicSpecialization());
-        }
-
-        List<SpecializationData> needsId = new ArrayList<>();
-        for (SpecializationData specialization : node.getSpecializations()) {
-            if (specialization.isGeneric()) {
-                specialization.setId("Generic");
-            } else if (specialization.isUninitialized()) {
-                specialization.setId("Uninitialized");
-            } else if (specialization.isPolymorphic()) {
-                specialization.setId("Polymorphic");
-            } else if (specialization.isSpecialized()) {
-                needsId.add(specialization);
-            } else {
-                throw new AssertionError();
-            }
-        }
-
-        // verify specialization parameter length
-        List<String> ids = initializeSpecializationIds(needsId);
-        for (int i = 0; i < ids.size(); i++) {
-            needsId.get(i).setId(ids.get(i));
-        }
-
-    }
-
-    private void initializeReachability(final NodeData node) {
-        SpecializationData prev = null;
-        boolean reachable = true;
-        for (SpecializationData specialization : node.getSpecializations()) {
-            if (specialization.isUninitialized() || specialization.isPolymorphic()) {
-                specialization.setReachable(true);
-                continue;
-            }
-            if (prev != null && prev.equalsGuards(specialization) && prev.getExceptions().isEmpty()) {
-                specialization.addError("%s is not reachable.", specialization.isGeneric() ? "Generic" : "Specialization");
-            } else if (!reachable && specialization.getMethod() != null) {
-                specialization.addError("%s is not reachable.", specialization.isGeneric() ? "Generic" : "Specialization");
-            }
-            specialization.setReachable(reachable);
-            if (!specialization.hasRewrite(context)) {
-                reachable = false;
-            }
-            prev = specialization;
-        }
-    }
-
-    private static List<String> initializeSpecializationIds(List<SpecializationData> specializations) {
-        int lastSize = -1;
-        List<List<String>> signatureChunks = new ArrayList<>();
-        for (SpecializationData other : specializations) {
-            if (!other.isSpecialized()) {
-                continue;
-            }
-            List<String> paramIds = new LinkedList<>();
-            paramIds.add(Utils.getTypeId(other.getReturnType().getType()));
-            for (ActualParameter param : other.getParameters()) {
-                if (param.getSpecification().getExecution() == null) {
-                    continue;
-                }
-                paramIds.add(Utils.getTypeId(param.getType()));
-            }
-            assert lastSize == -1 || lastSize == paramIds.size();
-            if (lastSize != -1 && lastSize != paramIds.size()) {
-                throw new AssertionError();
-            }
-            signatureChunks.add(paramIds);
-            lastSize = paramIds.size();
-        }
-
-        // reduce id vertically
-        for (int i = 0; i < lastSize; i++) {
-            String prev = null;
-            boolean allSame = true;
-            for (List<String> signature : signatureChunks) {
-                String arg = signature.get(i);
-                if (prev == null) {
-                    prev = arg;
-                    continue;
-                } else if (!prev.equals(arg)) {
-                    allSame = false;
-                    break;
-                }
-                prev = arg;
-            }
-
-            if (allSame) {
-                for (List<String> signature : signatureChunks) {
-                    signature.remove(i);
-                }
-                lastSize--;
-            }
-        }
-
-        // reduce id horizontally
-        for (List<String> signature : signatureChunks) {
-            if (signature.isEmpty()) {
-                continue;
-            }
-            String prev = null;
-            boolean allSame = true;
-            for (String arg : signature) {
-                if (prev == null) {
-                    prev = arg;
-                    continue;
-                } else if (!prev.equals(arg)) {
-                    allSame = false;
-                    break;
-                }
-                prev = arg;
-            }
-
-            if (allSame) {
-                signature.clear();
-                signature.add(prev);
-            }
-        }
-
-        // create signatures
-        List<String> signatures = new ArrayList<>();
-        for (List<String> signatureChunk : signatureChunks) {
-            StringBuilder b = new StringBuilder();
-            if (signatureChunk.isEmpty()) {
-                b.append("Default");
-            } else {
-                for (String s : signatureChunk) {
-                    b.append(s);
-                }
-            }
-            signatures.add(b.toString());
-        }
-
-        Map<String, Integer> counts = new HashMap<>();
-        for (String s1 : signatures) {
-            Integer count = counts.get(s1);
-            if (count == null) {
-                count = 0;
-            }
-            count++;
-            counts.put(s1, count);
-        }
-
-        for (String s : counts.keySet()) {
-            int count = counts.get(s);
-            if (count > 1) {
-                int number = 0;
-                for (ListIterator<String> iterator = signatures.listIterator(); iterator.hasNext();) {
-                    String s2 = iterator.next();
-                    if (s.equals(s2)) {
-                        iterator.set(s2 + number);
-                        number++;
-                    }
-                }
-            }
-        }
-
-        return signatures;
-    }
-
-    private void initializeGuards(List<? extends Element> elements, SpecializationData specialization) {
-        if (specialization.getGuardDefinitions().isEmpty()) {
-            specialization.setGuards(Collections.<GuardData> emptyList());
-            return;
-        }
-
-        List<GuardData> foundGuards = new ArrayList<>();
-        List<ExecutableElement> methods = ElementFilter.methodsIn(elements);
-        for (String guardDefinition : specialization.getGuardDefinitions()) {
-            GuardParser parser = new GuardParser(context, specialization, guardDefinition);
-            List<GuardData> guards = parser.parse(methods);
-            if (!guards.isEmpty()) {
-                foundGuards.add(guards.get(0));
-            } else {
-                // error no guard found
-                MethodSpec spec = parser.createSpecification(specialization.getMethod(), null);
-                spec.applyTypeDefinitions("types");
-                specialization.addError("Guard with method name '%s' not found. Expected signature: %n%s", guardDefinition, spec.toSignatureString("guard"));
-            }
-        }
-
-        specialization.setGuards(foundGuards);
-
-    }
-
-    private void initializeGeneric(final NodeData node) {
-        if (!node.needsRewrites(context)) {
-            return;
-        }
-
-        List<SpecializationData> generics = new ArrayList<>();
-        for (SpecializationData spec : node.getSpecializations()) {
-            if (spec.isGeneric()) {
-                generics.add(spec);
-            }
-        }
-
-        if (generics.size() == 1 && node.getSpecializations().size() == 1) {
-            // TODO this limitation should be lifted
-            for (SpecializationData generic : generics) {
-                generic.addError("@%s defined but no @%s.", Generic.class.getSimpleName(), Specialization.class.getSimpleName());
-            }
-        }
-
-        if (generics.isEmpty()) {
-            node.getSpecializations().add(createGenericSpecialization(node));
-        } else {
-            if (generics.size() > 1) {
-                for (SpecializationData generic : generics) {
-                    generic.addError("Only @%s is allowed per operation.", Generic.class.getSimpleName());
-                }
-            }
-        }
-    }
-
-    private SpecializationData createGenericSpecialization(final NodeData node) {
-        GenericParser parser = new GenericParser(context, node);
-        MethodSpec specification = parser.createDefaultMethodSpec(node.getSpecializations().iterator().next().getMethod(), null, true, null);
-
-        List<TypeMirror> parameterTypes = new ArrayList<>();
-        int signatureIndex = 1;
-        for (ParameterSpec spec : specification.getRequired()) {
-            parameterTypes.add(createGenericType(spec, node.getSpecializations(), signatureIndex));
-            if (spec.isSignature()) {
-                signatureIndex++;
-            }
-        }
-
-        TypeMirror returnType = createGenericType(specification.getReturnType(), node.getSpecializations(), 0);
-        SpecializationData generic = parser.create("Generic", null, null, returnType, parameterTypes);
-        if (generic == null) {
-            throw new RuntimeException("Unable to create generic signature for node " + node.getNodeId() + " with " + parameterTypes + ". Specification " + specification + ".");
-        }
-
-        return generic;
-    }
-
-    private TypeMirror createGenericType(ParameterSpec spec, List<SpecializationData> specializations, int signatureIndex) {
-        NodeExecutionData execution = spec.getExecution();
-        if (execution == null) {
-            if (spec.getAllowedTypes().size() == 1) {
-                return spec.getAllowedTypes().get(0);
-            } else {
-                return Utils.getCommonSuperType(context, spec.getAllowedTypes().toArray(new TypeMirror[0]));
-            }
-        } else {
-            Set<TypeData> types = new HashSet<>();
-            for (SpecializationData specialization : specializations) {
-                types.add(specialization.getTypeSignature().get(signatureIndex));
-            }
-
-            NodeChildData child = execution.getChild();
-            TypeData genericType = null;
-            if (types.size() == 1) {
-                ExecutableTypeData executable = child.findExecutableType(context, types.iterator().next());
-                if (executable != null && (signatureIndex == 0 || !executable.hasUnexpectedValue(context))) {
-                    genericType = types.iterator().next();
-                }
-            }
-            if (genericType == null) {
-                genericType = child.findAnyGenericExecutableType(context).getType();
-            }
-            return genericType.getPrimitiveType();
-        }
-    }
-
-    private static void initializeUninitialized(final NodeData node) {
-        SpecializationData generic = node.getGenericSpecialization();
-        if (generic == null) {
-            return;
-        }
-        for (ActualParameter parameter : generic.getReturnTypeAndParameters()) {
-            if (Utils.isObject(parameter.getType())) {
-                continue;
-            }
-            Set<String> types = new HashSet<>();
-            for (SpecializationData specialization : node.getSpecializations()) {
-                ActualParameter actualParameter = specialization.findParameter(parameter.getLocalName());
-                if (actualParameter != null) {
-                    types.add(Utils.getQualifiedName(actualParameter.getType()));
-                }
-            }
-            if (types.size() > 1) {
-                generic.replaceParameter(parameter.getLocalName(), new ActualParameter(parameter, node.getTypeSystem().getGenericTypeData()));
-            }
-        }
-        TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", node, generic.getSpecification(), null, null, generic.getReturnType(), generic.getParameters());
-        // should not use messages from generic specialization
-        uninializedMethod.getMessages().clear();
-        node.getSpecializations().add(new SpecializationData(node, uninializedMethod, SpecializationKind.UNINITIALIZED));
-    }
-
-    private void initializePolymorphism(NodeData node) {
-        initializePolymorphicDepth(node);
-
-        if (!node.needsRewrites(context) || !node.isPolymorphic()) {
-            return;
-        }
-
-        SpecializationData generic = node.getGenericSpecialization();
-
-        List<TypeData> polymorphicSignature = new ArrayList<>();
-        List<ActualParameter> updatePolymorphic = Arrays.asList();
-        for (ActualParameter genericParameter : updatePolymorphic) {
-            if (!genericParameter.getSpecification().isSignature()) {
-                continue;
-            }
-
-            Set<TypeData> usedTypes = new HashSet<>();
-            for (SpecializationData specialization : node.getSpecializations()) {
-                if (!specialization.isSpecialized()) {
-                    continue;
-                }
-                ActualParameter parameter = specialization.findParameter(genericParameter.getLocalName());
-                if (parameter == null) {
-                    throw new AssertionError("Parameter existed in generic specialization but not in specialized. param = " + genericParameter.getLocalName());
-                }
-                usedTypes.add(parameter.getTypeSystemType());
-            }
-
-            TypeData polymorphicType;
-            if (usedTypes.size() == 1) {
-                polymorphicType = usedTypes.iterator().next();
-            } else {
-                polymorphicType = node.getTypeSystem().getGenericTypeData();
-            }
-            polymorphicSignature.add(polymorphicType);
-        }
-
-        SpecializationData polymorphic = new SpecializationData(node, generic, SpecializationKind.POLYMORPHIC);
-        polymorphic.updateSignature(new TypeSignature(polymorphicSignature));
-        node.getSpecializations().add(polymorphic);
-    }
-
-    private static void initializePolymorphicDepth(final NodeData node) {
-        int polymorphicCombinations = 0;
-        for (SpecializationData specialization : node.getSpecializations()) {
-            if (specialization.isGeneric()) {
-                continue;
-            }
-
-            int combinations = 1;
-            for (ActualParameter parameter : specialization.getSignatureParameters()) {
-                combinations *= node.getTypeSystem().lookupSourceTypes(parameter.getTypeSystemType()).size();
-            }
-            polymorphicCombinations += combinations;
-        }
-
-        // initialize polymorphic depth
-        if (node.getPolymorphicDepth() < 0) {
-            node.setPolymorphicDepth(polymorphicCombinations - 1);
-        }
-
-    }
-
-    private void initializeShortCircuits(NodeData node) {
-        Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(node.getShortCircuits());
-
-        boolean valid = true;
-        List<NodeExecutionData> shortCircuitExecutions = new ArrayList<>();
-        for (NodeExecutionData execution : node.getChildExecutions()) {
-            if (!execution.isShortCircuit()) {
-                continue;
-            }
-            shortCircuitExecutions.add(execution);
-            String valueName = execution.getShortCircuitId();
-            List<ShortCircuitData> availableCircuits = groupedShortCircuits.get(valueName);
-
-            if (availableCircuits == null || availableCircuits.isEmpty()) {
-                node.addError("@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName);
-                valid = false;
-                continue;
-            }
-
-            boolean sameMethodName = true;
-            String methodName = availableCircuits.get(0).getMethodName();
-            for (ShortCircuitData circuit : availableCircuits) {
-                if (!circuit.getMethodName().equals(methodName)) {
-                    sameMethodName = false;
-                }
-            }
-
-            if (!sameMethodName) {
-                for (ShortCircuitData circuit : availableCircuits) {
-                    circuit.addError("All short circuits for short cut value '%s' must have the same method name.", valueName);
-                }
-                valid = false;
-                continue;
-            }
-
-            ShortCircuitData genericCircuit = null;
-            for (ShortCircuitData circuit : availableCircuits) {
-                if (isGenericShortCutMethod(circuit)) {
-                    genericCircuit = circuit;
-                    break;
-                }
-            }
-
-            if (genericCircuit == null) {
-                node.addError("No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName);
-                valid = false;
-                continue;
-            }
-
-            for (ShortCircuitData circuit : availableCircuits) {
-                if (circuit != genericCircuit) {
-                    circuit.setGenericShortCircuitMethod(genericCircuit);
-                }
-            }
-        }
-
-        if (!valid) {
-            return;
-        }
-
-        List<SpecializationData> specializations = new ArrayList<>();
-        specializations.addAll(node.getSpecializations());
-        for (SpecializationData specialization : specializations) {
-            List<ShortCircuitData> assignedShortCuts = new ArrayList<>(shortCircuitExecutions.size());
-
-            for (NodeExecutionData shortCircuit : shortCircuitExecutions) {
-                List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(shortCircuit.getShortCircuitId());
-
-                ShortCircuitData genericShortCircuit = null;
-                ShortCircuitData compatibleShortCircuit = null;
-                for (ShortCircuitData circuit : availableShortCuts) {
-                    if (circuit.isGeneric()) {
-                        genericShortCircuit = circuit;
-                    } else if (circuit.isCompatibleTo(specialization)) {
-                        compatibleShortCircuit = circuit;
-                    }
-                }
-
-                if (compatibleShortCircuit == null) {
-                    compatibleShortCircuit = genericShortCircuit;
-                }
-                assignedShortCuts.add(compatibleShortCircuit);
-            }
-            specialization.setShortCircuits(assignedShortCuts);
-        }
-    }
-
-    private boolean isGenericShortCutMethod(ShortCircuitData method) {
-        for (ActualParameter parameter : method.getParameters()) {
-            NodeExecutionData execution = parameter.getSpecification().getExecution();
-            if (execution == null) {
-                continue;
-            }
-            ExecutableTypeData found = null;
-            List<ExecutableTypeData> executableElements = execution.getChild().findGenericExecutableTypes(context);
-            for (ExecutableTypeData executable : executableElements) {
-                if (executable.getType().equalsType(parameter.getTypeSystemType())) {
-                    found = executable;
-                    break;
-                }
-            }
-            if (found == null) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    private static Map<String, List<ShortCircuitData>> groupShortCircuits(List<ShortCircuitData> shortCircuits) {
-        Map<String, List<ShortCircuitData>> group = new HashMap<>();
-        for (ShortCircuitData shortCircuit : shortCircuits) {
-            List<ShortCircuitData> circuits = group.get(shortCircuit.getValueName());
-            if (circuits == null) {
-                circuits = new ArrayList<>();
-                group.put(shortCircuit.getValueName(), circuits);
-            }
-            circuits.add(shortCircuit);
-        }
-        return group;
-    }
-
-    private static boolean verifySpecializationSameLength(NodeData nodeData) {
-        int lastArgs = -1;
-        for (SpecializationData specializationData : nodeData.getSpecializations()) {
-            int signatureArgs = specializationData.getSignatureSize();
-            if (lastArgs == signatureArgs) {
-                continue;
-            }
-            if (lastArgs != -1) {
-                for (SpecializationData specialization : nodeData.getSpecializations()) {
-                    specialization.addError("All specializations must have the same number of arguments.");
-                }
-                return false;
-            } else {
-                lastArgs = signatureArgs;
-            }
-        }
-        return true;
-    }
-
-    private static void verifyVisibilities(NodeData node) {
-        if (node.getTemplateType().getModifiers().contains(Modifier.PRIVATE) && node.getSpecializations().size() > 0) {
-            node.addError("Classes containing a @%s annotation must not be private.", Specialization.class.getSimpleName());
-        }
-    }
-
-    private static void verifySpecializationOrder(NodeData node) {
-        List<SpecializationData> specializations = node.getSpecializations();
-        for (int i = 0; i < specializations.size(); i++) {
-            SpecializationData m1 = specializations.get(i);
-            for (int j = i + 1; j < specializations.size(); j++) {
-                SpecializationData m2 = specializations.get(j);
-                int inferredOrder = m1.compareBySignature(m2);
-
-                if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) {
-                    int specOrder = m1.getOrder() - m2.getOrder();
-                    if (specOrder == 0) {
-                        m1.addError("Order value %d used multiple times", m1.getOrder());
-                        m2.addError("Order value %d used multiple times", m1.getOrder());
-                        return;
-                    } else if ((specOrder < 0 && inferredOrder > 0) || (specOrder > 0 && inferredOrder < 0)) {
-                        m1.addError("Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder());
-                        m2.addError("Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder());
-                        return;
-                    }
-                } else if (inferredOrder == 0) {
-                    SpecializationData m = (m1.getOrder() == Specialization.DEFAULT_ORDER ? m1 : m2);
-                    m.addError("Cannot calculate a consistent order for this specialization. Define the order attribute to resolve this.");
-                    return;
-                }
-            }
-        }
-    }
-
-    private static void verifyMissingAbstractMethods(NodeData nodeData, List<? extends Element> originalElements) {
-        if (!nodeData.needsFactory()) {
-            // missing abstract methods only needs to be implemented
-            // if we need go generate factory for it.
-            return;
-        }
-
-        List<Element> elements = new ArrayList<>(originalElements);
-        Set<Element> unusedElements = new HashSet<>(elements);
-        for (TemplateMethod method : nodeData.getAllTemplateMethods()) {
-            unusedElements.remove(method.getMethod());
-        }
-
-        for (NodeFieldData field : nodeData.getFields()) {
-            if (field.getGetter() != null) {
-                unusedElements.remove(field.getGetter());
-            }
-        }
-
-        for (NodeChildData child : nodeData.getChildren()) {
-            if (child.getAccessElement() != null) {
-                unusedElements.remove(child.getAccessElement());
-            }
-        }
-
-        for (ExecutableElement unusedMethod : ElementFilter.methodsIn(unusedElements)) {
-            if (unusedMethod.getModifiers().contains(Modifier.ABSTRACT)) {
-                nodeData.addError("The type %s must implement the inherited abstract method %s.", Utils.getSimpleName(nodeData.getTemplateType()), Utils.getReadableSignature(unusedMethod));
-            }
-        }
-    }
-
-    private static void verifyNamingConvention(List<? extends TemplateMethod> methods, String prefix) {
-        for (int i = 0; i < methods.size(); i++) {
-            TemplateMethod m1 = methods.get(i);
-            if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) {
-                m1.addError("Naming convention: method name must start with '%s'.", prefix);
-            }
-        }
-    }
-
-    private static void verifySpecializationThrows(NodeData node) {
-        Map<String, SpecializationData> specializationMap = new HashMap<>();
-        for (SpecializationData spec : node.getSpecializations()) {
-            specializationMap.put(spec.getMethodName(), spec);
-        }
-        for (SpecializationData sourceSpecialization : node.getSpecializations()) {
-            if (sourceSpecialization.getExceptions() != null) {
-                for (SpecializationThrowsData throwsData : sourceSpecialization.getExceptions()) {
-                    for (SpecializationThrowsData otherThrowsData : sourceSpecialization.getExceptions()) {
-                        if (otherThrowsData != throwsData && Utils.typeEquals(otherThrowsData.getJavaClass(), throwsData.getJavaClass())) {
-                            throwsData.addError("Duplicate exception type.");
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    private void verifyConstructors(NodeData nodeData) {
-        if (!nodeData.needsRewrites(context)) {
-            // no specialization constructor is needed if the node never rewrites.
-            return;
-        }
-
-        TypeElement type = Utils.fromTypeMirror(nodeData.getNodeType());
-        List<ExecutableElement> constructors = ElementFilter.constructorsIn(type.getEnclosedElements());
-
-        boolean parametersFound = false;
-        for (ExecutableElement constructor : constructors) {
-            if (!constructor.getParameters().isEmpty() && !isSourceSectionConstructor(context, constructor)) {
-                parametersFound = true;
-            }
-        }
-        if (!parametersFound) {
-            return;
-        }
-        for (ExecutableElement e : constructors) {
-            if (e.getParameters().size() == 1) {
-                TypeMirror firstArg = e.getParameters().get(0).asType();
-                if (Utils.typeEquals(firstArg, nodeData.getNodeType())) {
-                    if (e.getModifiers().contains(Modifier.PRIVATE)) {
-                        nodeData.addError("The specialization constructor must not be private.");
-                    } else if (constructors.size() <= 1) {
-                        nodeData.addError("The specialization constructor must not be the only constructor. The definition of an alternative constructor is required.");
-                    }
-                    return;
-                }
-            }
-        }
-
-        // not found
-        nodeData.addError("Specialization constructor '%s(%s previousNode) { this(...); }' is required.", Utils.getSimpleName(type), Utils.getSimpleName(type));
-    }
-
-    static boolean isSourceSectionConstructor(ProcessorContext context, ExecutableElement constructor) {
-        return constructor.getParameters().size() == 1 && Utils.typeEquals(constructor.getParameters().get(0).asType(), context.getTruffleTypes().getSourceSection());
-    }
-
-    private AnnotationMirror findFirstAnnotation(List<? extends Element> elements, Class<? extends Annotation> annotation) {
-        for (Element element : elements) {
-            AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, element, annotation);
-            if (mirror != null) {
-                return mirror;
-            }
-        }
-        return null;
-    }
-
-    private TypeMirror inheritType(AnnotationMirror annotation, String valueName, TypeMirror parentType) {
-        TypeMirror inhertNodeType = context.getTruffleTypes().getNode();
-        TypeMirror value = Utils.getAnnotationValue(TypeMirror.class, annotation, valueName);
-        if (Utils.typeEquals(inhertNodeType, value)) {
-            return parentType;
-        } else {
-            return value;
-        }
-    }
-
-    private ExecutableElement findGetter(List<? extends Element> elements, String variableName, TypeMirror type) {
-        if (type == null) {
-            return null;
-        }
-        String methodName;
-        if (Utils.typeEquals(type, context.getType(boolean.class))) {
-            methodName = "is" + Utils.firstLetterUpperCase(variableName);
-        } else {
-            methodName = "get" + Utils.firstLetterUpperCase(variableName);
-        }
-
-        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
-            if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && Utils.isAssignable(context, type, method.getReturnType())) {
-                return method;
-            }
-        }
-        return null;
-    }
-
-    private static List<TypeElement> collectSuperClasses(List<TypeElement> collection, TypeElement element) {
-        if (element != null) {
-            collection.add(element);
-            if (element.getSuperclass() != null) {
-                collectSuperClasses(collection, Utils.fromTypeMirror(element.getSuperclass()));
-            }
-        }
-        return collection;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitData.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class ShortCircuitData extends TemplateMethod {
-
-    private ShortCircuitData genericShortCircuitMethod;
-    private final String valueName;
-
-    public ShortCircuitData(TemplateMethod template, String valueName) {
-        super(template);
-        this.valueName = valueName;
-    }
-
-    public String getValueName() {
-        return valueName;
-    }
-
-    public void setGenericShortCircuitMethod(ShortCircuitData genericShortCircuitMethod) {
-        this.genericShortCircuitMethod = genericShortCircuitMethod;
-    }
-
-    public boolean isGeneric() {
-        return genericShortCircuitMethod == null;
-    }
-
-    public ShortCircuitData getGeneric() {
-        if (isGeneric()) {
-            return this;
-        } else {
-            return genericShortCircuitMethod;
-        }
-    }
-
-    public boolean isCompatibleTo(SpecializationData specialization) {
-        if (isGeneric() && specialization.isGeneric()) {
-            return true;
-        }
-
-        for (ActualParameter param : getParameters()) {
-            ActualParameter specializationParam = specialization.findParameter(param.getLocalName());
-            if (!Utils.typeEquals(param.getType(), specializationParam.getType())) {
-                return false;
-            }
-        }
-        return true;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class ShortCircuitParser extends NodeMethodParser<ShortCircuitData> {
-
-    private final Set<String> shortCircuitValues;
-
-    public ShortCircuitParser(ProcessorContext context, NodeData node) {
-        super(context, node);
-
-        shortCircuitValues = new HashSet<>();
-        for (NodeExecutionData execution : node.getChildExecutions()) {
-            if (execution.isShortCircuit()) {
-                shortCircuitValues.add(execution.getShortCircuitId());
-            }
-        }
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        String shortCircuitValue = Utils.getAnnotationValue(String.class, mirror, "value");
-
-        return createDefaultMethodSpec(method, mirror, true, shortCircuitValue);
-    }
-
-    @Override
-    protected ParameterSpec createReturnParameterSpec() {
-        return new ParameterSpec("has", getContext().getType(boolean.class));
-    }
-
-    @Override
-    public ShortCircuitData create(TemplateMethod method, boolean invalid) {
-        String shortCircuitValue = Utils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "value");
-
-        if (!shortCircuitValues.contains(shortCircuitValue)) {
-            method.addError("Invalid short circuit value %s.", shortCircuitValue);
-        }
-
-        return new ShortCircuitData(method, shortCircuitValue);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return ShortCircuit.class;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,268 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.util.*;
-
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public class SpecializationData extends TemplateMethod {
-
-    public enum SpecializationKind {
-        UNINITIALIZED,
-        SPECIALIZED,
-        POLYMORPHIC,
-        GENERIC
-    }
-
-    private final NodeData node;
-    private final int order;
-    private final SpecializationKind kind;
-    private final List<SpecializationThrowsData> exceptions;
-    private List<String> guardDefinitions = Collections.emptyList();
-    private List<GuardData> guards = Collections.emptyList();
-    private List<ShortCircuitData> shortCircuits;
-    private List<String> assumptions = Collections.emptyList();
-    private boolean reachable;
-
-    public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind, int order, List<SpecializationThrowsData> exceptions) {
-        super(template);
-        this.node = node;
-        this.order = order;
-        this.kind = kind;
-        this.exceptions = exceptions;
-
-        for (SpecializationThrowsData exception : exceptions) {
-            exception.setSpecialization(this);
-        }
-    }
-
-    public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind) {
-        this(node, template, kind, Specialization.DEFAULT_ORDER, new ArrayList<SpecializationThrowsData>());
-    }
-
-    public void setReachable(boolean reachable) {
-        this.reachable = reachable;
-    }
-
-    public boolean isReachable() {
-        return reachable;
-    }
-
-    public boolean isPolymorphic() {
-        return kind == SpecializationKind.POLYMORPHIC;
-    }
-
-    @Override
-    protected List<MessageContainer> findChildContainers() {
-        List<MessageContainer> sinks = new ArrayList<>();
-        if (exceptions != null) {
-            sinks.addAll(exceptions);
-        }
-        if (guards != null) {
-            sinks.addAll(guards);
-        }
-        return sinks;
-    }
-
-    public boolean isGenericSpecialization(ProcessorContext context) {
-        if (isGeneric()) {
-            return true;
-        }
-        if (hasRewrite(context)) {
-            return false;
-        }
-
-        for (ActualParameter parameter : getSignatureParameters()) {
-            ActualParameter genericParameter = getNode().getGenericSpecialization().findParameter(parameter.getLocalName());
-            if (!parameter.getTypeSystemType().equals(genericParameter.getTypeSystemType())) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    public boolean hasRewrite(ProcessorContext context) {
-        if (!getExceptions().isEmpty()) {
-            return true;
-        }
-        if (!getGuards().isEmpty()) {
-            return true;
-        }
-        if (!getAssumptions().isEmpty()) {
-            return true;
-        }
-        for (ActualParameter parameter : getSignatureParameters()) {
-            ExecutableTypeData type = parameter.getSpecification().getExecution().getChild().findExecutableType(context, parameter.getTypeSystemType());
-            if (type.hasUnexpectedValue(context)) {
-                return true;
-            }
-            if (type.getReturnType().getTypeSystemType().needsCastTo(context, parameter.getTypeSystemType())) {
-                return true;
-            }
-
-        }
-        return false;
-    }
-
-    @Override
-    public int compareBySignature(TemplateMethod other) {
-        if (this == other) {
-            return 0;
-        } else if (!(other instanceof SpecializationData)) {
-            return super.compareBySignature(other);
-        }
-
-        SpecializationData m2 = (SpecializationData) other;
-
-        int kindOrder = kind.compareTo(m2.kind);
-        if (kindOrder != 0) {
-            return kindOrder;
-        }
-        if (getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) {
-            return getOrder() - m2.getOrder();
-        }
-
-        if (getTemplate() != m2.getTemplate()) {
-            throw new UnsupportedOperationException("Cannot compare two specializations with different templates.");
-        }
-
-        return super.compareBySignature(m2);
-    }
-
-    public NodeData getNode() {
-        return node;
-    }
-
-    public void setGuards(List<GuardData> guards) {
-        this.guards = guards;
-    }
-
-    public void setGuardDefinitions(List<String> guardDefinitions) {
-        this.guardDefinitions = guardDefinitions;
-    }
-
-    public int getOrder() {
-        return order;
-    }
-
-    public boolean isSpecialized() {
-        return kind == SpecializationKind.SPECIALIZED;
-    }
-
-    public boolean isGeneric() {
-        return kind == SpecializationKind.GENERIC;
-    }
-
-    public boolean isUninitialized() {
-        return kind == SpecializationKind.UNINITIALIZED;
-    }
-
-    public List<SpecializationThrowsData> getExceptions() {
-        return exceptions;
-    }
-
-    public List<String> getGuardDefinitions() {
-        return guardDefinitions;
-    }
-
-    public List<GuardData> getGuards() {
-        return guards;
-    }
-
-    public void setShortCircuits(List<ShortCircuitData> shortCircuits) {
-        this.shortCircuits = shortCircuits;
-    }
-
-    public List<ShortCircuitData> getShortCircuits() {
-        return shortCircuits;
-    }
-
-    public List<String> getAssumptions() {
-        return assumptions;
-    }
-
-    void setAssumptions(List<String> assumptions) {
-        this.assumptions = assumptions;
-    }
-
-    public SpecializationData findPreviousSpecialization() {
-        List<SpecializationData> specializations = node.getSpecializations();
-        for (int i = 0; i < specializations.size() - 1; i++) {
-            if (specializations.get(i) == this && i > 0) {
-                return specializations.get(i - 1);
-            }
-        }
-        return null;
-    }
-
-    public SpecializationData findNextSpecialization() {
-        List<SpecializationData> specializations = node.getSpecializations();
-        for (int i = 0; i < specializations.size() - 1; i++) {
-            if (specializations.get(i) == this) {
-                return specializations.get(i + 1);
-            }
-        }
-        return null;
-    }
-
-    public boolean hasDynamicGuards() {
-        return !getGuards().isEmpty();
-    }
-
-    @Override
-    public String toString() {
-        return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getTypeSignature());
-    }
-
-    public void forceFrame(TypeMirror frameType) {
-        if (getParameters().isEmpty() || !Utils.typeEquals(getParameters().get(0).getType(), frameType)) {
-            ParameterSpec frameSpec = getSpecification().findParameterSpec("frame");
-            if (frameSpec != null) {
-                getParameters().add(0, new ActualParameter(frameSpec, frameType, -1, -1));
-            }
-        }
-    }
-
-    public boolean equalsGuards(SpecializationData specialization) {
-        if (assumptions.equals(specialization.getAssumptions()) && guards.equals(specialization.getGuards()) && getTypeSignature().equalsParameters(specialization.getTypeSignature())) {
-            return true;
-        }
-        return false;
-    }
-
-    public boolean hasFrame(ProcessorContext context) {
-        for (ActualParameter param : getParameters()) {
-            if (Utils.typeEquals(param.getType(), context.getTruffleTypes().getFrame())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,432 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.util.*;
-
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.template.TemplateMethod.TypeSignature;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-/**
- * Class creates groups of specializations to optimize the layout of generated executeAndSpecialize
- * and generic execute methods.
- */
-public final class SpecializationGroup {
-
-    private final List<String> assumptions;
-    private final List<TypeGuard> typeGuards;
-    private final List<GuardData> guards;
-
-    private final NodeData node;
-    private final SpecializationData specialization;
-    private final List<SpecializationGroup> children = new ArrayList<>();
-
-    private SpecializationGroup parent;
-
-    private SpecializationGroup(SpecializationData data) {
-        this.node = data.getNode();
-        this.assumptions = new ArrayList<>();
-        this.typeGuards = new ArrayList<>();
-        this.guards = new ArrayList<>();
-        this.specialization = data;
-
-        this.assumptions.addAll(data.getAssumptions());
-        TypeSignature sig = data.getTypeSignature();
-        for (int i = 1; i < sig.size(); i++) {
-            typeGuards.add(new TypeGuard(sig.get(i), i - 1));
-        }
-        this.guards.addAll(data.getGuards());
-    }
-
-    public SpecializationGroup(List<SpecializationGroup> children, List<String> assumptionMatches, List<TypeGuard> typeGuardsMatches, List<GuardData> guardMatches) {
-        assert !children.isEmpty() : "children must not be empty";
-        this.assumptions = assumptionMatches;
-        this.typeGuards = typeGuardsMatches;
-        this.guards = guardMatches;
-        this.node = children.get(0).node;
-        this.specialization = null;
-        updateChildren(children);
-    }
-
-    public List<TypeGuard> getAllGuards() {
-        List<TypeGuard> collectedGuards = new ArrayList<>();
-        collectedGuards.addAll(typeGuards);
-        if (parent != null) {
-            collectedGuards.addAll(parent.getAllGuards());
-        }
-        return collectedGuards;
-    }
-
-    public TypeGuard findTypeGuard(int signatureIndex) {
-        for (TypeGuard guard : typeGuards) {
-            if (guard.getSignatureIndex() == signatureIndex) {
-                return guard;
-            }
-        }
-        return null;
-    }
-
-    public List<GuardData> findElseConnectableGuards(boolean minimumStateCheck) {
-        if (minimumStateCheck) {
-            /*
-             * TODO investigate further if we really cannot else connect guards if minimum state is
-             * required
-             */
-            return Collections.emptyList();
-        }
-        if (!getTypeGuards().isEmpty() || !getAssumptions().isEmpty()) {
-            return Collections.emptyList();
-        }
-
-        if (getGuards().isEmpty()) {
-            return Collections.emptyList();
-        }
-
-        List<GuardData> elseConnectableGuards = new ArrayList<>();
-        int guardIndex = 0;
-        while (guardIndex < getGuards().size() && findNegatedGuardInPrevious(getGuards().get(guardIndex), minimumStateCheck) != null) {
-            elseConnectableGuards.add(getGuards().get(guardIndex));
-            guardIndex++;
-        }
-
-        return elseConnectableGuards;
-    }
-
-    private GuardData findNegatedGuardInPrevious(GuardData guard, boolean minimumStateCheck) {
-        SpecializationGroup previous = this.getPreviousGroup();
-        if (previous == null) {
-            return null;
-        }
-        List<GuardData> elseConnectedGuards = previous.findElseConnectableGuards(minimumStateCheck);
-
-        if (previous == null || previous.getGuards().size() != elseConnectedGuards.size() + 1) {
-            return null;
-        }
-
-        /* Guard is else branch can be connected in previous specialization. */
-        if (elseConnectedGuards.contains(guard)) {
-            return guard;
-        }
-
-        GuardData previousGuard = previous.getGuards().get(elseConnectedGuards.size());
-        if (guard.getMethod().equals(previousGuard.getMethod()) && guard.isNegated() != previousGuard.isNegated()) {
-            return guard;
-        }
-        return null;
-    }
-
-    private void updateChildren(List<SpecializationGroup> childs) {
-        if (!children.isEmpty()) {
-            children.clear();
-        }
-        this.children.addAll(childs);
-        for (SpecializationGroup child : childs) {
-            child.parent = this;
-        }
-    }
-
-    public SpecializationGroup getParent() {
-        return parent;
-    }
-
-    public List<String> getAssumptions() {
-        return assumptions;
-    }
-
-    public List<TypeGuard> getTypeGuards() {
-        return typeGuards;
-    }
-
-    public List<GuardData> getGuards() {
-        return guards;
-    }
-
-    public List<SpecializationGroup> getChildren() {
-        return children;
-    }
-
-    public SpecializationData getSpecialization() {
-        return specialization;
-    }
-
-    private static SpecializationGroup combine(List<SpecializationGroup> groups) {
-        if (groups.isEmpty()) {
-            throw new IllegalArgumentException("empty combinations");
-        }
-        if (groups.size() == 1) {
-            return null;
-        }
-
-        List<String> assumptionMatches = new ArrayList<>();
-        List<TypeGuard> typeGuardsMatches = new ArrayList<>();
-        List<GuardData> guardMatches = new ArrayList<>();
-
-        SpecializationGroup first = groups.get(0);
-        List<SpecializationGroup> others = groups.subList(1, groups.size());
-
-        outer: for (String assumption : first.assumptions) {
-            for (SpecializationGroup other : others) {
-                if (!other.assumptions.contains(assumption)) {
-                    // assumptions can be combined unordered
-                    continue outer;
-                }
-            }
-            assumptionMatches.add(assumption);
-        }
-
-        outer: for (TypeGuard typeGuard : first.typeGuards) {
-            for (SpecializationGroup other : others) {
-                if (!other.typeGuards.contains(typeGuard)) {
-                    // type guards can be combined unordered
-                    continue outer;
-                }
-            }
-            typeGuardsMatches.add(typeGuard);
-        }
-
-        outer: for (GuardData guard : first.guards) {
-            for (SpecializationGroup other : others) {
-                if (!other.guards.contains(guard)) {
-                    // we must break here. One guard may depend on the other.
-                    break outer;
-                }
-            }
-            guardMatches.add(guard);
-        }
-
-        // check for guards for required type casts
-        for (Iterator<GuardData> iterator = guardMatches.iterator(); iterator.hasNext();) {
-            GuardData guardMatch = iterator.next();
-
-            int signatureIndex = 0;
-            for (ActualParameter parameter : guardMatch.getParameters()) {
-                signatureIndex++;
-                if (!parameter.getSpecification().isSignature()) {
-                    continue;
-                }
-
-                TypeMirror guardType = parameter.getType();
-
-                // object guards can be safely moved up
-                if (Utils.isObject(guardType)) {
-                    continue;
-                }
-
-                // generic guards can be safely moved up
-                SpecializationData generic = first.node.getGenericSpecialization();
-                if (generic != null) {
-                    ActualParameter genericParameter = generic.findParameter(parameter.getLocalName());
-                    if (genericParameter != null && Utils.typeEquals(genericParameter.getType(), guardType)) {
-                        continue;
-                    }
-                }
-
-                // signature index required for moving up guards
-                if (containsIndex(typeGuardsMatches, signatureIndex) || (first.getParent() != null && first.getParent().containsTypeGuardIndex(signatureIndex))) {
-                    continue;
-                }
-
-                iterator.remove();
-                break;
-            }
-        }
-
-        if (assumptionMatches.isEmpty() && typeGuardsMatches.isEmpty() && guardMatches.isEmpty()) {
-            return null;
-        }
-
-        for (SpecializationGroup group : groups) {
-            group.assumptions.removeAll(assumptionMatches);
-            group.typeGuards.removeAll(typeGuardsMatches);
-            group.guards.removeAll(guardMatches);
-        }
-
-        List<SpecializationGroup> newChildren = new ArrayList<>(groups);
-        return new SpecializationGroup(newChildren, assumptionMatches, typeGuardsMatches, guardMatches);
-    }
-
-    private boolean containsTypeGuardIndex(int index) {
-        if (containsIndex(typeGuards, index)) {
-            return true;
-        }
-        if (parent != null) {
-            return parent.containsTypeGuardIndex(index);
-        }
-        return false;
-    }
-
-    private static boolean containsIndex(List<TypeGuard> typeGuards, int signatureIndex) {
-        for (TypeGuard guard : typeGuards) {
-            if (guard.signatureIndex == signatureIndex) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public static SpecializationGroup create(SpecializationData specialization) {
-        return new SpecializationGroup(specialization);
-    }
-
-    public static SpecializationGroup create(List<SpecializationData> specializations) {
-        List<SpecializationGroup> groups = new ArrayList<>();
-        for (SpecializationData specialization : specializations) {
-            groups.add(new SpecializationGroup(specialization));
-        }
-        return new SpecializationGroup(createCombinationalGroups(groups), Collections.<String> emptyList(), Collections.<TypeGuard> emptyList(), Collections.<GuardData> emptyList());
-    }
-
-    @Override
-    public String toString() {
-        return "SpecializationGroup [assumptions=" + assumptions + ", typeGuards=" + typeGuards + ", guards=" + guards + "]";
-    }
-
-    private static List<SpecializationGroup> createCombinationalGroups(List<SpecializationGroup> groups) {
-        if (groups.size() <= 1) {
-            return groups;
-        }
-        List<SpecializationGroup> newGroups = new ArrayList<>();
-
-        int i = 0;
-        for (i = 0; i < groups.size();) {
-            SpecializationGroup combined = null;
-            for (int j = groups.size(); j > i + 1; j--) {
-                combined = combine(groups.subList(i, j));
-                if (combined != null) {
-                    break;
-                }
-            }
-            SpecializationGroup newGroup;
-            if (combined == null) {
-                newGroup = groups.get(i);
-                i++;
-            } else {
-                newGroup = combined;
-                List<SpecializationGroup> originalGroups = new ArrayList<>(combined.children);
-                combined.updateChildren(createCombinationalGroups(originalGroups));
-                i += originalGroups.size();
-            }
-
-            newGroups.add(newGroup);
-
-        }
-
-        return newGroups;
-    }
-
-    public SpecializationGroup getPreviousGroup() {
-        if (parent == null || parent.children.isEmpty()) {
-            return null;
-        }
-        int index = parent.children.indexOf(this);
-        if (index <= 0) {
-            return null;
-        }
-        return parent.children.get(index - 1);
-    }
-
-    public int getUncheckedSpecializationIndex() {
-        int groupMaxIndex = getMaxSpecializationIndex();
-
-        int genericIndex = node.getSpecializations().indexOf(node.getGenericSpecialization());
-        if (groupMaxIndex >= genericIndex) {
-            // no minimum state check for an generic index
-            groupMaxIndex = -1;
-        }
-
-        if (groupMaxIndex > -1) {
-            // no minimum state check if already checked by parent group
-            int parentMaxIndex = -1;
-            if (getParent() != null) {
-                parentMaxIndex = getParent().getMaxSpecializationIndex();
-            }
-            if (groupMaxIndex == parentMaxIndex) {
-                groupMaxIndex = -1;
-            }
-        }
-        return groupMaxIndex;
-    }
-
-    public int getMaxSpecializationIndex() {
-        if (specialization != null) {
-            return specialization.getNode().getSpecializations().indexOf(specialization);
-        } else {
-            int max = Integer.MIN_VALUE;
-            for (SpecializationGroup childGroup : getChildren()) {
-                max = Math.max(max, childGroup.getMaxSpecializationIndex());
-            }
-            return max;
-        }
-    }
-
-    public static final class TypeGuard {
-
-        private final int signatureIndex;
-        private final TypeData type;
-
-        public TypeGuard(TypeData type, int signatureIndex) {
-            this.type = type;
-            this.signatureIndex = signatureIndex;
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + signatureIndex;
-            result = prime * result + type.hashCode();
-            return result;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            } else if (obj == null) {
-                return false;
-            } else if (getClass() != obj.getClass()) {
-                return false;
-            }
-
-            TypeGuard other = (TypeGuard) obj;
-            if (signatureIndex != other.signatureIndex) {
-                return false;
-            } else if (!type.equals(other.type)) {
-                return false;
-            }
-            return true;
-        }
-
-        public int getSignatureIndex() {
-            return signatureIndex;
-        }
-
-        public TypeData getType() {
-            return type;
-        }
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGuardData.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public class SpecializationGuardData extends MessageContainer {
-
-    private final SpecializationData specialization;
-    private final AnnotationValue value;
-    private final String guardMethod;
-    private final boolean onSpecialization;
-    private final boolean onExecution;
-
-    private GuardData guardDeclaration;
-
-    public SpecializationGuardData(SpecializationData specialization, AnnotationValue value, String guardMethod, boolean onSpecialization, boolean onExecution) {
-        this.specialization = specialization;
-        this.guardMethod = guardMethod;
-        this.onSpecialization = onSpecialization;
-        this.onExecution = onExecution;
-        this.value = value;
-    }
-
-    @Override
-    public Element getMessageElement() {
-        return specialization.getMessageElement();
-    }
-
-    @Override
-    public AnnotationMirror getMessageAnnotation() {
-        return specialization.getMessageAnnotation();
-    }
-
-    @Override
-    public AnnotationValue getMessageAnnotationValue() {
-        return value;
-    }
-
-    public String getGuardMethod() {
-        return guardMethod;
-    }
-
-    public boolean isOnExecution() {
-        return onExecution;
-    }
-
-    public boolean isOnSpecialization() {
-        return onSpecialization;
-    }
-
-    public void setGuardDeclaration(GuardData compatibleGuard) {
-        this.guardDeclaration = compatibleGuard;
-    }
-
-    public GuardData getGuardDeclaration() {
-        return guardDeclaration;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.SpecializationData.SpecializationKind;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class SpecializationMethodParser extends NodeMethodParser<SpecializationData> {
-
-    public SpecializationMethodParser(ProcessorContext context, NodeData operation) {
-        super(context, operation);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        return createDefaultMethodSpec(method, mirror, true, null);
-    }
-
-    @Override
-    public SpecializationData create(TemplateMethod method, boolean invalid) {
-        return parseSpecialization(method);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return Specialization.class;
-    }
-
-    private SpecializationData parseSpecialization(TemplateMethod method) {
-        int order = Utils.getAnnotationValue(Integer.class, method.getMarkerAnnotation(), "order");
-        if (order < 0 && order != Specialization.DEFAULT_ORDER) {
-            method.addError("Invalid order attribute %d. The value must be >= 0 or the default value.");
-        }
-
-        AnnotationValue rewriteValue = Utils.getAnnotationValue(method.getMarkerAnnotation(), "rewriteOn");
-        List<TypeMirror> exceptionTypes = Utils.getAnnotationValueList(TypeMirror.class, method.getMarkerAnnotation(), "rewriteOn");
-        List<SpecializationThrowsData> exceptionData = new ArrayList<>();
-        for (TypeMirror exceptionType : exceptionTypes) {
-            SpecializationThrowsData throwsData = new SpecializationThrowsData(method.getMarkerAnnotation(), rewriteValue, exceptionType);
-            if (!Utils.canThrowType(method.getMethod().getThrownTypes(), exceptionType)) {
-                throwsData.addError("Method must specify a throws clause with the exception type '%s'.", Utils.getQualifiedName(exceptionType));
-            }
-            exceptionData.add(throwsData);
-        }
-
-        Collections.sort(exceptionData, new Comparator<SpecializationThrowsData>() {
-
-            @Override
-            public int compare(SpecializationThrowsData o1, SpecializationThrowsData o2) {
-                return Utils.compareByTypeHierarchy(o1.getJavaClass(), o2.getJavaClass());
-            }
-        });
-        SpecializationData specialization = new SpecializationData(getNode(), method, SpecializationKind.SPECIALIZED, order, exceptionData);
-        List<String> guardDefs = Utils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards");
-        specialization.setGuardDefinitions(guardDefs);
-
-        List<String> assumptionDefs = Utils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "assumptions");
-        specialization.setAssumptions(assumptionDefs);
-
-        for (String assumption : assumptionDefs) {
-            if (!getNode().getAssumptions().contains(assumption)) {
-                specialization.addError("Undeclared assumption '%s' used. Use @NodeAssumptions to declare them.", assumption);
-            }
-        }
-
-        return specialization;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationThrowsData.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class SpecializationThrowsData extends MessageContainer {
-
-    private final AnnotationValue annotationValue;
-    private final AnnotationMirror annotationMirror;
-    private final TypeMirror javaClass;
-    private SpecializationData specialization;
-
-    public SpecializationThrowsData(AnnotationMirror annotationMirror, AnnotationValue value, TypeMirror javaClass) {
-        this.annotationMirror = annotationMirror;
-        this.annotationValue = value;
-        this.javaClass = javaClass;
-    }
-
-    void setSpecialization(SpecializationData specialization) {
-        this.specialization = specialization;
-    }
-
-    @Override
-    public Element getMessageElement() {
-        return specialization.getMessageElement();
-    }
-
-    @Override
-    public AnnotationMirror getMessageAnnotation() {
-        return annotationMirror;
-    }
-
-    @Override
-    public AnnotationValue getMessageAnnotationValue() {
-        return annotationValue;
-    }
-
-    public TypeMirror getJavaClass() {
-        return javaClass;
-    }
-
-    public SpecializationData getSpecialization() {
-        return specialization;
-    }
-
-    public AnnotationMirror getAnnotationMirror() {
-        return annotationMirror;
-    }
-
-    public SpecializationData getTransitionTo() {
-        return specialization.findNextSpecialization();
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/AbstractParser.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,152 @@
+/*
+ * 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.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.tools.Diagnostic.Kind;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.model.MessageContainer.Message;
+
+/**
+ * THIS IS NOT PUBLIC API.
+ */
+public abstract class AbstractParser<M extends MessageContainer> {
+
+    protected final ProcessorContext context;
+    protected final ProcessingEnvironment processingEnv;
+
+    protected final Log log;
+
+    public AbstractParser() {
+        this.context = ProcessorContext.getInstance();
+        this.processingEnv = context.getEnvironment();
+        this.log = context.getLog();
+    }
+
+    public final M parse(Element element) {
+        M model = null;
+        try {
+            AnnotationMirror mirror = null;
+            if (getAnnotationType() != null) {
+                mirror = ElementUtils.findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), getAnnotationType());
+            }
+
+            if (!context.getTruffleTypes().verify(context, element, mirror)) {
+                return null;
+            }
+            model = parse(element, mirror);
+            if (model == null) {
+                return null;
+            }
+
+            redirectMessages(new HashSet<MessageContainer>(), model, model);
+            model.emitMessages(context, log);
+            return filterErrorElements(model);
+        } catch (CompileErrorException e) {
+            log.message(Kind.WARNING, element, null, null, "The truffle processor could not parse class due to error: %s", e.getMessage());
+            return null;
+        }
+    }
+
+    private void redirectMessages(Set<MessageContainer> visitedSinks, MessageContainer model, MessageContainer baseContainer) {
+        List<Message> messages = model.getMessages();
+        for (int i = messages.size() - 1; i >= 0; i--) {
+            Message message = messages.get(i);
+            if (!ElementUtils.isEnclosedIn(baseContainer.getMessageElement(), message.getOriginalContainer().getMessageElement())) {
+                // redirect message
+                MessageContainer original = message.getOriginalContainer();
+                String text = wrapText(original.getMessageElement(), original.getMessageAnnotation(), message.getText());
+                Message redirectedMessage = new Message(null, null, baseContainer, text, message.getKind());
+                model.getMessages().remove(i);
+                baseContainer.getMessages().add(redirectedMessage);
+            }
+        }
+
+        for (MessageContainer childContainer : model) {
+            if (visitedSinks.contains(childContainer)) {
+                continue;
+            }
+            visitedSinks.add(childContainer);
+
+            MessageContainer newBase = baseContainer;
+            if (childContainer.getBaseContainer() != null) {
+                newBase = childContainer.getBaseContainer();
+            }
+            redirectMessages(visitedSinks, childContainer, newBase);
+        }
+    }
+
+    private static String wrapText(Element element, AnnotationMirror mirror, String text) {
+        StringBuilder b = new StringBuilder();
+        if (element != null) {
+            if (element.getKind() == ElementKind.METHOD) {
+                b.append("Method " + ElementUtils.createReferenceName((ExecutableElement) element));
+            } else {
+                b.append("Element " + element.getSimpleName());
+            }
+        }
+        if (mirror != null) {
+            b.append(" at annotation @" + ElementUtils.getSimpleName(mirror.getAnnotationType()).trim());
+        }
+
+        if (b.length() > 0) {
+            b.append(" is erroneous: ").append(text);
+            return b.toString();
+        } else {
+            return text;
+        }
+    }
+
+    protected M filterErrorElements(M model) {
+        return model.hasErrors() ? null : model;
+    }
+
+    protected abstract M parse(Element element, AnnotationMirror mirror);
+
+    public abstract Class<? extends Annotation> getAnnotationType();
+
+    public boolean isDelegateToRootDeclaredType() {
+        return false;
+    }
+
+    public List<Class<? extends Annotation>> getAllAnnotationTypes() {
+        List<Class<? extends Annotation>> list = new ArrayList<>();
+        if (getAnnotationType() != null) {
+            list.add(getAnnotationType());
+        }
+        list.addAll(getTypeDelegatedAnnotationTypes());
+        return list;
+    }
+
+    public List<Class<? extends Annotation>> getTypeDelegatedAnnotationTypes() {
+        return Collections.emptyList();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/CreateCastParser.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class CreateCastParser extends NodeMethodParser<CreateCastData> {
+
+    public CreateCastParser(ProcessorContext context, NodeData operation) {
+        super(context, operation);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return CreateCast.class;
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        List<String> childNames = ElementUtils.getAnnotationValueList(String.class, mirror, "value");
+        NodeChildData foundChild = null;
+        for (String childName : childNames) {
+            foundChild = getNode().findChild(childName);
+            if (foundChild != null) {
+                break;
+            }
+        }
+        TypeMirror baseType = getContext().getTruffleTypes().getNode();
+        if (foundChild != null) {
+            baseType = foundChild.getOriginalType();
+        }
+
+        MethodSpec spec = new MethodSpec(new InheritsParameterSpec("child", baseType));
+        addDefaultFieldMethodSpec(spec);
+        ParameterSpec childSpec = new ParameterSpec("castedChild", baseType);
+        childSpec.setSignature(true);
+        spec.addRequired(childSpec);
+        return spec;
+    }
+
+    @Override
+    public CreateCastData create(TemplateMethod method, boolean invalid) {
+        AnnotationMirror mirror = method.getMarkerAnnotation();
+        List<String> childNames = ElementUtils.getAnnotationValueList(String.class, mirror, "value");
+        CreateCastData cast = new CreateCastData(method, childNames);
+        AnnotationValue value = ElementUtils.getAnnotationValue(mirror, "value");
+        TypeMirror type = null;
+        if (childNames == null || childNames.isEmpty()) {
+            cast.addError(value, "No value specified but required.");
+            return cast;
+        }
+
+        for (String childName : childNames) {
+            NodeChildData child = getNode().findChild(childName);
+            if (child == null) {
+                // error
+                cast.addError(value, "Specified child '%s' not found.", childName);
+                continue;
+            }
+            if (type == null) {
+                type = child.getNodeType();
+            } else if (!ElementUtils.typeEquals(type, child.getNodeType())) {
+                cast.addError(value, "All child nodes for a cast must have the same node type.");
+                continue;
+            }
+        }
+        return cast;
+    }
+
+    private static class InheritsParameterSpec extends ParameterSpec {
+
+        public InheritsParameterSpec(String name, TypeMirror... allowedTypes) {
+            super(name, Arrays.asList(allowedTypes), null);
+        }
+
+        @Override
+        public boolean matches(TypeMirror actualType) {
+            boolean found = false;
+            for (TypeMirror specType : getAllowedTypes()) {
+                if (ElementUtils.isAssignable(actualType, specType)) {
+                    found = true;
+                    break;
+                }
+            }
+            return found;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class ExecutableTypeMethodParser extends NodeMethodParser<ExecutableTypeData> {
+
+    public ExecutableTypeMethodParser(ProcessorContext context, NodeData node) {
+        super(context, node);
+        setParseNullOnError(false);
+        getParser().setEmitErrors(false);
+        getParser().setUseVarArgs(true);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        MethodSpec spec = createDefaultMethodSpec(method, mirror, false, null);
+        List<ParameterSpec> requiredSpecs = new ArrayList<>(spec.getRequired());
+        spec.getRequired().clear();
+
+        List<TypeMirror> allowedTypes = getNode().getTypeSystem().getPrimitiveTypeMirrors();
+        Set<String> allowedIdentifiers = getNode().getTypeSystem().getTypeIdentifiers();
+        for (ParameterSpec originalSpec : requiredSpecs) {
+            spec.addRequired(new ParameterSpec(originalSpec, allowedTypes, allowedIdentifiers));
+        }
+        spec.setIgnoreAdditionalSpecifications(true);
+        spec.setIgnoreAdditionalParameters(true);
+        spec.setVariableRequiredParameters(true);
+        // varargs
+        ParameterSpec otherParameters = new ParameterSpec("other", allowedTypes, allowedIdentifiers);
+        otherParameters.setSignature(true);
+        spec.addRequired(otherParameters);
+        return spec;
+    }
+
+    @Override
+    protected List<TypeMirror> nodeTypeMirrors(NodeData nodeData) {
+        return getNode().getTypeSystem().getPrimitiveTypeMirrors();
+    }
+
+    @Override
+    protected Set<String> nodeTypeIdentifiers(NodeData nodeData) {
+        return getNode().getTypeSystem().getTypeIdentifiers();
+    }
+
+    @Override
+    public final boolean isParsable(ExecutableElement method) {
+        if (method.getModifiers().contains(Modifier.STATIC)) {
+            return false;
+        } else if (method.getModifiers().contains(Modifier.NATIVE)) {
+            return false;
+        }
+        return method.getSimpleName().toString().startsWith("execute");
+    }
+
+    @Override
+    public ExecutableTypeData create(TemplateMethod method, boolean invalid) {
+        TypeData resolvedType = method.getReturnType().getTypeSystemType();
+        return new ExecutableTypeData(method, method.getMethod(), getNode().getTypeSystem(), resolvedType);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GenericParser.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind;
+
+public class GenericParser extends NodeMethodParser<SpecializationData> {
+
+    public GenericParser(ProcessorContext context, NodeData node) {
+        super(context, node);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        return createDefaultMethodSpec(method, mirror, true, null);
+    }
+
+    @Override
+    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
+        List<ExecutableTypeData> execTypes = execution.getChild().findGenericExecutableTypes(getContext());
+        List<TypeMirror> types = new ArrayList<>();
+        Set<String> typeIds = new HashSet<>();
+        for (ExecutableTypeData type : execTypes) {
+            TypeMirror typeMirror = type.getType().getPrimitiveType();
+            types.add(typeMirror);
+            typeIds.add(ElementUtils.getUniqueIdentifier(typeMirror));
+        }
+        ParameterSpec spec = new ParameterSpec(execution.getName(), types, typeIds);
+        spec.setExecution(execution);
+        return spec;
+    }
+
+    @Override
+    public SpecializationData create(TemplateMethod method, boolean invalid) {
+        return new SpecializationData(getNode(), method, SpecializationKind.GENERIC);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return Fallback.class;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GuardParser.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class GuardParser extends NodeMethodParser<GuardData> {
+
+    private final GuardExpression expression;
+    private final TemplateMethod guardedMethod;
+
+    public GuardParser(ProcessorContext context, NodeData node, TemplateMethod compatibleSource, GuardExpression expression) {
+        super(context, node);
+        this.expression = expression;
+        this.guardedMethod = compatibleSource;
+        getParser().setEmitErrors(false);
+        setParseNullOnError(false);
+    }
+
+    @Override
+    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
+        return super.createValueParameterSpec(execution);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        MethodSpec spec = createDefaultMethodSpec(method, mirror, true, null);
+        spec.setIgnoreAdditionalSpecifications(true);
+        spec.getRequired().clear();
+
+        if (expression.getResolvedChildren() != null) {
+            for (NodeExecutionData execution : expression.getResolvedChildren()) {
+                List<Parameter> foundInGuardedMethod = guardedMethod.findByExecutionData(execution);
+                for (Parameter guardedParameter : foundInGuardedMethod) {
+                    spec.addRequired(createParameterSpec(guardedParameter));
+                }
+            }
+        } else {
+            for (Parameter parameter : guardedMethod.getRequiredParameters()) {
+                spec.addRequired(createParameterSpec(parameter));
+            }
+        }
+
+        return spec;
+    }
+
+    private ParameterSpec createParameterSpec(Parameter parameter) {
+        List<TypeMirror> typeMirrors = ElementUtils.getAssignableTypes(getContext(), parameter.getType());
+        Set<String> typeIds = new HashSet<>();
+        for (TypeMirror typeMirror : typeMirrors) {
+            typeIds.add(ElementUtils.getUniqueIdentifier(typeMirror));
+        }
+        if (parameter.getSpecification().isSignature()) {
+            typeIds.retainAll(getTypeSystem().getTypeIdentifiers());
+        }
+
+        return new ParameterSpec(parameter.getSpecification(), typeMirrors, typeIds);
+    }
+
+    @Override
+    protected List<TypeMirror> nodeTypeMirrors(NodeData nodeData) {
+        Set<TypeMirror> typeMirrors = new LinkedHashSet<>();
+        typeMirrors.addAll(nodeData.getTypeSystem().getPrimitiveTypeMirrors());
+        typeMirrors.addAll(nodeData.getTypeSystem().getBoxedTypeMirrors());
+        return new ArrayList<>(typeMirrors);
+    }
+
+    @Override
+    protected Set<String> nodeTypeIdentifiers(NodeData nodeData) {
+        return nodeData.getTypeSystem().getTypeIdentifiers();
+    }
+
+    @Override
+    protected ParameterSpec createReturnParameterSpec() {
+        return new ParameterSpec("returnType", getContext().getType(boolean.class));
+    }
+
+    @Override
+    public boolean isParsable(ExecutableElement method) {
+        return true;
+    }
+
+    @Override
+    public GuardData create(TemplateMethod method, boolean invalid) {
+        Implies impliesAnnotation = method.getMethod().getAnnotation(Implies.class);
+        String[] impliesExpressions = new String[0];
+        if (impliesAnnotation != null) {
+            impliesExpressions = impliesAnnotation.value();
+        }
+        List<GuardExpression> guardExpressions = new ArrayList<>();
+        for (String string : impliesExpressions) {
+            guardExpressions.add(new GuardExpression(string, false));
+        }
+        return new GuardData(method, guardExpressions);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ImplicitCastParser.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class ImplicitCastParser extends TypeSystemMethodParser<ImplicitCastData> {
+
+    public ImplicitCastParser(ProcessorContext context, TypeSystemData typeSystem) {
+        super(context, typeSystem);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return ImplicitCast.class;
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        List<TypeMirror> types = getTypeSystem().getPrimitiveTypeMirrors();
+        Set<String> identifiers = getTypeSystem().getTypeIdentifiers();
+        MethodSpec spec = new MethodSpec(new ParameterSpec("target", types, identifiers));
+        spec.addRequired(new ParameterSpec("source", types, identifiers));
+        return spec;
+    }
+
+    @Override
+    public ImplicitCastData create(TemplateMethod method, boolean invalid) {
+        if (invalid) {
+            return new ImplicitCastData(method, null, null);
+        }
+
+        Parameter target = method.findParameter("targetValue");
+        Parameter 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);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,288 @@
+/*
+ * 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.truffle.dsl.processor.parser;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public final class MethodSpecParser {
+
+    private boolean emitErrors = true;
+    private boolean useVarArgs = false;
+
+    private final Template template;
+
+    public MethodSpecParser(Template template) {
+        this.template = template;
+    }
+
+    public Template getTemplate() {
+        return template;
+    }
+
+    public TypeSystemData getTypeSystem() {
+        return template.getTypeSystem();
+    }
+
+    public boolean isEmitErrors() {
+        return emitErrors;
+    }
+
+    public boolean isUseVarArgs() {
+        return useVarArgs;
+    }
+
+    public void setEmitErrors(boolean emitErrors) {
+        this.emitErrors = emitErrors;
+    }
+
+    public void setUseVarArgs(boolean useVarArgs) {
+        this.useVarArgs = useVarArgs;
+    }
+
+    public TemplateMethod parse(MethodSpec methodSpecification, ExecutableElement method, AnnotationMirror annotation, int naturalOrder) {
+        if (methodSpecification == null) {
+            return null;
+        }
+
+        methodSpecification.applyTypeDefinitions("types");
+
+        String id = method.getSimpleName().toString();
+        TypeMirror returnType = method.getReturnType();
+        List<TypeMirror> parameterTypes = new ArrayList<>();
+        for (VariableElement var : method.getParameters()) {
+            parameterTypes.add(var.asType());
+        }
+
+        return parseImpl(methodSpecification, naturalOrder, id, method, annotation, returnType, parameterTypes);
+    }
+
+    public TemplateMethod parseImpl(MethodSpec methodSpecification, int naturalOrder, String id, ExecutableElement method, AnnotationMirror annotation, TypeMirror returnType,
+                    List<TypeMirror> parameterTypes) {
+        ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
+        Parameter returnTypeMirror = matchParameter(returnTypeSpec, returnType, -1, -1);
+        if (returnTypeMirror == null) {
+            if (emitErrors) {
+                TemplateMethod invalidMethod = new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<Parameter> emptyList());
+                String expectedReturnType = returnTypeSpec.toSignatureString(true);
+                String actualReturnType = ElementUtils.getSimpleName(returnType);
+
+                String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
+                                methodSpecification.toSignatureString(method.getSimpleName().toString()));
+                invalidMethod.addError(message);
+                return invalidMethod;
+            } else {
+                return null;
+            }
+        }
+
+        List<Parameter> parameters = parseParameters(methodSpecification, parameterTypes, isUseVarArgs() && method != null ? method.isVarArgs() : false);
+        if (parameters == null) {
+            if (isEmitErrors() && method != null) {
+                TemplateMethod invalidMethod = new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<Parameter> emptyList());
+                String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(method),
+                                methodSpecification.toSignatureString(method.getSimpleName().toString()));
+                invalidMethod.addError(message);
+                return invalidMethod;
+            } else {
+                return null;
+            }
+        }
+
+        return new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, parameters);
+    }
+
+    private static String createActualSignature(ExecutableElement method) {
+        StringBuilder b = new StringBuilder("(");
+        String sep = "";
+        if (method != null) {
+            for (VariableElement var : method.getParameters()) {
+                b.append(sep);
+                b.append(ElementUtils.getSimpleName(var.asType()));
+                sep = ", ";
+            }
+        }
+        b.append(")");
+        return b.toString();
+    }
+
+    /*
+     * Parameter parsing tries to parse required arguments starting from offset 0 with increasing
+     * offset until it finds a signature end that matches the required specification. If there is no
+     * end matching the required arguments, parsing fails. Parameters prior to the parsed required
+     * ones are cut and used to parse the optional parameters.
+     */
+    private List<Parameter> parseParameters(MethodSpec spec, List<TypeMirror> parameterTypes, boolean varArgs) {
+        List<Parameter> parsedRequired = null;
+        int offset = 0;
+        for (; offset <= parameterTypes.size(); offset++) {
+            List<TypeMirror> parameters = new ArrayList<>();
+            parameters.addAll(parameterTypes.subList(offset, parameterTypes.size()));
+            parsedRequired = parseParametersRequired(spec, parameters, varArgs);
+            if (parsedRequired != null) {
+                break;
+            }
+        }
+
+        if (parsedRequired == null) {
+            return null;
+        }
+
+        if (parsedRequired.isEmpty() && offset == 0) {
+            offset = parameterTypes.size();
+        }
+        List<TypeMirror> potentialOptionals = parameterTypes.subList(0, offset);
+        List<Parameter> parsedOptionals = parseParametersOptional(spec, potentialOptionals);
+        if (parsedOptionals == null) {
+            return null;
+        }
+
+        List<Parameter> finalParameters = new ArrayList<>();
+        finalParameters.addAll(parsedOptionals);
+        finalParameters.addAll(parsedRequired);
+        return finalParameters;
+    }
+
+    private List<Parameter> parseParametersOptional(MethodSpec spec, List<TypeMirror> types) {
+        List<Parameter> parsedParams = new ArrayList<>();
+
+        int typeStartIndex = 0;
+        List<ParameterSpec> specifications = spec.getOptional();
+        outer: for (int specIndex = 0; specIndex < specifications.size(); specIndex++) {
+            ParameterSpec specification = specifications.get(specIndex);
+            for (int typeIndex = typeStartIndex; typeIndex < types.size(); typeIndex++) {
+                TypeMirror actualType = types.get(typeIndex);
+                Parameter optionalParam = matchParameter(specification, actualType, -1, -1);
+                if (optionalParam != null) {
+                    parsedParams.add(optionalParam);
+                    typeStartIndex = typeIndex + 1;
+                    continue outer;
+                }
+            }
+        }
+
+        if (typeStartIndex < types.size()) {
+            // not enough types found
+            return null;
+        }
+        return parsedParams;
+    }
+
+    private List<Parameter> parseParametersRequired(MethodSpec spec, List<TypeMirror> types, boolean typeVarArgs) {
+        List<Parameter> parsedParams = new ArrayList<>();
+        List<ParameterSpec> specifications = spec.getRequired();
+        boolean specVarArgs = spec.isVariableRequiredParameters();
+        int typeIndex = 0;
+        int specificationIndex = 0;
+
+        ParameterSpec specification;
+        while ((specification = nextSpecification(specifications, specificationIndex, specVarArgs)) != null) {
+            TypeMirror actualType = nextActualType(types, typeIndex, typeVarArgs);
+            if (actualType == null) {
+                if (spec.isIgnoreAdditionalSpecifications()) {
+                    break;
+                }
+                return null;
+            }
+
+            int typeVarArgsIndex = typeVarArgs ? typeIndex - types.size() + 1 : -1;
+            int specVarArgsIndex = specVarArgs ? specificationIndex - specifications.size() + 1 : -1;
+
+            if (typeVarArgsIndex >= 0 && specVarArgsIndex >= 0) {
+                // both specifications and types have a variable number of arguments
+                // we would get into an endless loop if we would continue
+                break;
+            }
+
+            Parameter resolvedParameter = matchParameter(specification, actualType, specVarArgsIndex, typeVarArgsIndex);
+            if (resolvedParameter == null) {
+                return null;
+            }
+            parsedParams.add(resolvedParameter);
+            typeIndex++;
+            specificationIndex++;
+        }
+
+        if (typeIndex < types.size()) {
+            // additional types available
+            if (spec.isIgnoreAdditionalParameters()) {
+                return parsedParams;
+            } else {
+                return null;
+            }
+        }
+
+        return parsedParams;
+    }
+
+    private static ParameterSpec nextSpecification(List<ParameterSpec> specifications, int specIndex, boolean varArgs) {
+        if (varArgs && specIndex >= specifications.size() - 1 && !specifications.isEmpty()) {
+            return specifications.get(specifications.size() - 1);
+        } else if (specIndex < specifications.size()) {
+            return specifications.get(specIndex);
+        } else {
+            return null;
+        }
+    }
+
+    private static TypeMirror nextActualType(List<TypeMirror> types, int typeIndex, boolean varArgs) {
+        if (varArgs && typeIndex >= types.size() - 1 && !types.isEmpty()) {
+            // unpack varargs array argument
+            TypeMirror actualType = types.get(types.size() - 1);
+            if (actualType.getKind() == TypeKind.ARRAY) {
+                actualType = ((ArrayType) actualType).getComponentType();
+            }
+            return actualType;
+        } else if (typeIndex < types.size()) {
+            return types.get(typeIndex);
+        } else {
+            return null;
+        }
+    }
+
+    private Parameter matchParameter(ParameterSpec specification, TypeMirror mirror, int specificationIndex, int varArgsIndex) {
+        TypeMirror resolvedType = mirror;
+        if (hasError(resolvedType)) {
+            return null;
+        }
+
+        if (!specification.matches(resolvedType)) {
+            return null;
+        }
+
+        TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType);
+        if (resolvedTypeData != null) {
+            return new Parameter(specification, resolvedTypeData, specificationIndex, varArgsIndex);
+        } else {
+            return new Parameter(specification, resolvedType, specificationIndex, varArgsIndex);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public abstract class NodeMethodParser<E extends TemplateMethod> extends TemplateMethodParser<NodeData, E> {
+
+    public NodeMethodParser(ProcessorContext context, NodeData node) {
+        super(context, node);
+    }
+
+    public NodeData getNode() {
+        return template;
+    }
+
+    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
+        ParameterSpec spec = new ParameterSpec(execution.getName(), nodeTypeMirrors(execution.getChild().getNodeData()), nodeTypeIdentifiers(execution.getChild().getNodeData()));
+        spec.setExecution(execution);
+        return spec;
+    }
+
+    protected List<TypeMirror> nodeTypeMirrors(NodeData nodeData) {
+        return nodeData.getTypeSystem().getPrimitiveTypeMirrors();
+    }
+
+    protected Set<String> nodeTypeIdentifiers(NodeData nodeData) {
+        return nodeData.getTypeSystem().getTypeIdentifiers();
+    }
+
+    protected ParameterSpec createReturnParameterSpec() {
+        ParameterSpec returnValue = new ParameterSpec("returnValue", nodeTypeMirrors(getNode()), nodeTypeIdentifiers(getNode()));
+        returnValue.setExecution(getNode().getThisExecution());
+        return returnValue;
+    }
+
+    @Override
+    public boolean isParsable(ExecutableElement method) {
+        if (getAnnotationType() != null) {
+            return ElementUtils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null;
+        }
+
+        return true;
+    }
+
+    @SuppressWarnings("unused")
+    protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, boolean shortCircuitsEnabled, String shortCircuitName) {
+        MethodSpec methodSpec = new MethodSpec(createReturnParameterSpec());
+
+        addDefaultFrame(methodSpec);
+        addDefaultFieldMethodSpec(methodSpec);
+        addDefaultChildren(shortCircuitsEnabled, shortCircuitName, methodSpec);
+
+        return methodSpec;
+    }
+
+    private void addDefaultChildren(boolean shortCircuitsEnabled, String breakName, MethodSpec spec) {
+        if (getNode().getChildren() == null) {
+            // children are null when parsing executable types
+            return;
+        }
+
+        for (NodeExecutionData execution : getNode().getChildExecutions()) {
+            if (breakName != null && execution.getShortCircuitId().equals(breakName)) {
+                break;
+            }
+
+            if (execution.isShortCircuit() && shortCircuitsEnabled) {
+                spec.addRequired(new ParameterSpec(shortCircuitValueName(execution.getName()), getContext().getType(boolean.class)));
+            }
+            spec.addRequired(createValueParameterSpec(execution));
+        }
+    }
+
+    private void addDefaultFrame(MethodSpec methodSpec) {
+        if (getNode().supportsFrame()) {
+            methodSpec.addOptional(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame()));
+        }
+    }
+
+    protected void addDefaultFieldMethodSpec(MethodSpec methodSpec) {
+        for (NodeFieldData field : getNode().getFields()) {
+            if (field.getGetter() == null) {
+                ParameterSpec spec = new ParameterSpec(field.getName(), field.getType());
+                spec.setLocal(true);
+                methodSpec.addOptional(spec);
+            }
+        }
+    }
+
+    private static String shortCircuitValueName(String valueName) {
+        return "has" + ElementUtils.firstLetterUpperCase(valueName);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,1403 @@
+/*
+ * 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.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+import javax.tools.Diagnostic.Kind;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.compiler.*;
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality;
+import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind;
+import com.oracle.truffle.dsl.processor.model.TemplateMethod.TypeSignature;
+
+public class NodeParser extends AbstractParser<NodeData> {
+
+    public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Fallback.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, NodeChild.class,
+                    NodeChildren.class);
+
+    private Map<String, NodeData> parsedNodes;
+
+    @Override
+    protected NodeData parse(Element element, AnnotationMirror mirror) {
+        NodeData node = null;
+        try {
+            parsedNodes = new HashMap<>();
+            node = resolveNode((TypeElement) element);
+            if (Log.DEBUG) {
+                NodeData parsed = parsedNodes.get(ElementUtils.getQualifiedName((TypeElement) element));
+                if (node != null) {
+                    String dump = parsed.dump();
+                    log.message(Kind.ERROR, null, null, null, dump);
+                }
+            }
+        } finally {
+            parsedNodes = null;
+        }
+
+        return node;
+    }
+
+    @Override
+    protected NodeData filterErrorElements(NodeData model) {
+        for (Iterator<NodeData> iterator = model.getEnclosingNodes().iterator(); iterator.hasNext();) {
+            NodeData node = filterErrorElements(iterator.next());
+            if (node == null) {
+                iterator.remove();
+            }
+        }
+        if (model.hasErrors()) {
+            return null;
+        }
+        return model;
+    }
+
+    @Override
+    public boolean isDelegateToRootDeclaredType() {
+        return true;
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return null;
+    }
+
+    @Override
+    public List<Class<? extends Annotation>> getTypeDelegatedAnnotationTypes() {
+        return ANNOTATIONS;
+    }
+
+    private NodeData resolveNode(TypeElement rootType) {
+        String typeName = ElementUtils.getQualifiedName(rootType);
+        if (parsedNodes.containsKey(typeName)) {
+            return parsedNodes.get(typeName);
+        }
+
+        List<NodeData> enclosedNodes = new ArrayList<>();
+        for (TypeElement enclosedType : ElementFilter.typesIn(rootType.getEnclosedElements())) {
+            NodeData enclosedChild = resolveNode(enclosedType);
+            if (enclosedChild != null) {
+                enclosedNodes.add(enclosedChild);
+            }
+        }
+
+        NodeData node = parseNode(rootType);
+        if (node == null && !enclosedNodes.isEmpty()) {
+            node = new NodeData(context, rootType);
+        }
+
+        if (node != null) {
+            for (NodeData enclosedNode : enclosedNodes) {
+                node.addEnclosedNode(enclosedNode);
+            }
+        }
+
+        parsedNodes.put(typeName, node);
+        return node;
+    }
+
+    private NodeData parseNode(TypeElement originalTemplateType) {
+        // reloading the type elements is needed for ecj
+        TypeElement templateType = ElementUtils.fromTypeMirror(context.reloadTypeElement(originalTemplateType));
+
+        if (ElementUtils.findAnnotationMirror(processingEnv, originalTemplateType, GeneratedBy.class) != null) {
+            // generated nodes should not get called again.
+            return null;
+        }
+
+        List<TypeElement> lookupTypes = collectSuperClasses(new ArrayList<TypeElement>(), templateType);
+        if (!ElementUtils.isAssignable(templateType.asType(), context.getTruffleTypes().getNode())) {
+            return null;
+        }
+        List<Element> elements = new ArrayList<>(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType));
+
+        NodeData node = parseNodeData(templateType, elements, lookupTypes);
+
+        parseImportGuards(node, lookupTypes, elements);
+
+        if (node.hasErrors()) {
+            return node; // error sync point
+        }
+
+        node.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, node).parse(elements)));
+        initializeChildren(node);
+
+        node.getSpecializations().addAll(new SpecializationMethodParser(context, node).parse(elements));
+        node.getSpecializations().addAll(new GenericParser(context, node).parse(elements));
+        node.getCasts().addAll(new CreateCastParser(context, node).parse(elements));
+        node.getShortCircuits().addAll(new ShortCircuitParser(context, node).parse(elements));
+
+        if (node.hasErrors()) {
+            return node;  // error sync point
+        }
+
+        verifySpecializationSameLength(node);
+        initializeSpecializations(elements, node);
+        initializeShortCircuits(node); // requires specializations and polymorphic specializations
+
+        verifyVisibilities(node);
+        verifyMissingAbstractMethods(node, elements);
+        verifyConstructors(node);
+        verifyNamingConvention(node.getShortCircuits(), "needs");
+        verifySpecializationThrows(node);
+        return node;
+    }
+
+    private void parseImportGuards(NodeData node, List<TypeElement> lookupTypes, List<Element> elements) {
+        for (TypeElement lookupType : lookupTypes) {
+            AnnotationMirror importAnnotation = ElementUtils.findAnnotationMirror(processingEnv, lookupType, ImportGuards.class);
+            if (importAnnotation == null) {
+                continue;
+            }
+            AnnotationValue importClassesValue = ElementUtils.getAnnotationValue(importAnnotation, "value");
+            List<TypeMirror> importClasses = ElementUtils.getAnnotationValueList(TypeMirror.class, importAnnotation, "value");
+            if (importClasses.isEmpty()) {
+                node.addError(importAnnotation, importClassesValue, "At least import guard classes must be specified.");
+                continue;
+            }
+            for (TypeMirror importGuardClass : importClasses) {
+                if (importGuardClass.getKind() != TypeKind.DECLARED) {
+                    node.addError(importAnnotation, importClassesValue, "The specified import guard class '%s' is not a declared type.", ElementUtils.getQualifiedName(importGuardClass));
+                    continue;
+                }
+                TypeElement typeElement = ElementUtils.fromTypeMirror(importGuardClass);
+
+                // hack to reload type is necessary for incremental compiling in eclipse.
+                // otherwise methods inside of import guard types are just not found.
+                typeElement = ElementUtils.fromTypeMirror(context.reloadType(typeElement.asType()));
+
+                if (typeElement.getEnclosingElement().getKind().isClass() && !typeElement.getModifiers().contains(Modifier.PUBLIC)) {
+                    node.addError(importAnnotation, importClassesValue, "The specified import guard class '%s' must be public.", ElementUtils.getQualifiedName(importGuardClass));
+                    continue;
+                }
+
+                List<? extends ExecutableElement> importMethods = ElementFilter.methodsIn(processingEnv.getElementUtils().getAllMembers(typeElement));
+
+                for (ExecutableElement importMethod : importMethods) {
+                    if (!importMethod.getModifiers().contains(Modifier.PUBLIC) || !importMethod.getModifiers().contains(Modifier.STATIC)) {
+                        continue;
+                    }
+                    elements.add(importMethod);
+                }
+            }
+        }
+    }
+
+    private NodeData parseNodeData(TypeElement templateType, List<? extends Element> elements, List<TypeElement> typeHierarchy) {
+        AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class);
+        if (typeSystemMirror == null) {
+            NodeData nodeData = new NodeData(context, templateType);
+            nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), ElementUtils.getQualifiedName(templateType));
+            return nodeData;
+        }
+
+        TypeMirror typeSystemType = ElementUtils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value");
+        final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSystemType, true);
+        if (typeSystem == null) {
+            NodeData nodeData = new NodeData(context, templateType);
+            nodeData.addError("The used type system '%s' is invalid or not a Node.", ElementUtils.getQualifiedName(typeSystemType));
+            return nodeData;
+        }
+
+        List<String> assumptionsList = new ArrayList<>();
+        for (int i = typeHierarchy.size() - 1; i >= 0; i--) {
+            TypeElement type = typeHierarchy.get(i);
+            AnnotationMirror assumptions = ElementUtils.findAnnotationMirror(context.getEnvironment(), type, NodeAssumptions.class);
+            if (assumptions != null) {
+                List<String> assumptionStrings = ElementUtils.getAnnotationValueList(String.class, assumptions, "value");
+                for (String string : assumptionStrings) {
+                    if (assumptionsList.contains(string)) {
+                        assumptionsList.remove(string);
+                    }
+                    assumptionsList.add(string);
+                }
+            }
+        }
+        AnnotationMirror nodeInfoMirror = findFirstAnnotation(typeHierarchy, NodeInfo.class);
+        String shortName = null;
+        if (nodeInfoMirror != null) {
+            shortName = ElementUtils.getAnnotationValue(String.class, nodeInfoMirror, "shortName");
+        }
+
+        List<NodeFieldData> fields = parseFields(typeHierarchy, elements);
+        List<NodeChildData> children = parseChildren(typeHierarchy, elements);
+        List<NodeExecutionData> executions = parseExecutions(children, elements);
+
+        NodeData nodeData = new NodeData(context, templateType, shortName, typeSystem, children, executions, fields, assumptionsList);
+
+        parsedNodes.put(ElementUtils.getQualifiedName(templateType), nodeData);
+
+        return nodeData;
+    }
+
+    private List<NodeFieldData> parseFields(List<TypeElement> typeHierarchy, List<? extends Element> elements) {
+        Set<String> names = new HashSet<>();
+
+        List<NodeFieldData> fields = new ArrayList<>();
+        for (VariableElement field : ElementFilter.fieldsIn(elements)) {
+            if (field.getModifiers().contains(Modifier.STATIC)) {
+                continue;
+            }
+            if (field.getModifiers().contains(Modifier.PUBLIC) || field.getModifiers().contains(Modifier.PROTECTED)) {
+                String name = field.getSimpleName().toString();
+                fields.add(new NodeFieldData(field, null, field.asType(), name, false));
+                names.add(name);
+            }
+        }
+
+        List<TypeElement> reversedTypeHierarchy = new ArrayList<>(typeHierarchy);
+        Collections.reverse(reversedTypeHierarchy);
+        for (TypeElement typeElement : reversedTypeHierarchy) {
+            AnnotationMirror nodeChildrenMirror = ElementUtils.findAnnotationMirror(processingEnv, typeElement, NodeFields.class);
+            List<AnnotationMirror> children = ElementUtils.collectAnnotations(context, nodeChildrenMirror, "value", typeElement, NodeField.class);
+
+            for (AnnotationMirror mirror : children) {
+                String name = ElementUtils.firstLetterLowerCase(ElementUtils.getAnnotationValue(String.class, mirror, "name"));
+                TypeMirror type = ElementUtils.getAnnotationValue(TypeMirror.class, mirror, "type");
+
+                NodeFieldData field = new NodeFieldData(typeElement, mirror, type, name, true);
+                if (name.isEmpty()) {
+                    field.addError(ElementUtils.getAnnotationValue(mirror, "name"), "Field name cannot be empty.");
+                } else if (names.contains(name)) {
+                    field.addError(ElementUtils.getAnnotationValue(mirror, "name"), "Duplicate field name '%s'.", name);
+                }
+                names.add(name);
+
+                fields.add(field);
+            }
+        }
+
+        for (NodeFieldData nodeFieldData : fields) {
+            nodeFieldData.setGetter(findGetter(elements, nodeFieldData.getName(), nodeFieldData.getType()));
+        }
+
+        return fields;
+    }
+
+    private List<NodeChildData> parseChildren(final List<TypeElement> typeHierarchy, List<? extends Element> elements) {
+        Set<String> shortCircuits = new HashSet<>();
+        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
+            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
+            if (mirror != null) {
+                shortCircuits.add(ElementUtils.getAnnotationValue(String.class, mirror, "value"));
+            }
+        }
+        Map<String, TypeMirror> castNodeTypes = new HashMap<>();
+        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
+            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, CreateCast.class);
+            if (mirror != null) {
+                List<String> children = (ElementUtils.getAnnotationValueList(String.class, mirror, "value"));
+                if (children != null) {
+                    for (String child : children) {
+                        castNodeTypes.put(child, method.getReturnType());
+                    }
+                }
+            }
+        }
+
+        List<NodeChildData> parsedChildren = new ArrayList<>();
+        List<TypeElement> typeHierarchyReversed = new ArrayList<>(typeHierarchy);
+        Collections.reverse(typeHierarchyReversed);
+        for (TypeElement type : typeHierarchyReversed) {
+            AnnotationMirror nodeChildrenMirror = ElementUtils.findAnnotationMirror(processingEnv, type, NodeChildren.class);
+
+            TypeMirror nodeClassType = type.getSuperclass();
+            if (!ElementUtils.isAssignable(nodeClassType, context.getTruffleTypes().getNode())) {
+                nodeClassType = null;
+            }
+
+            List<AnnotationMirror> children = ElementUtils.collectAnnotations(context, nodeChildrenMirror, "value", type, NodeChild.class);
+            int index = 0;
+            for (AnnotationMirror childMirror : children) {
+                String name = ElementUtils.getAnnotationValue(String.class, childMirror, "value");
+                if (name.equals("")) {
+                    name = "child" + index;
+                }
+
+                Cardinality cardinality = Cardinality.ONE;
+
+                TypeMirror childType = inheritType(childMirror, "type", nodeClassType);
+                if (childType.getKind() == TypeKind.ARRAY) {
+                    cardinality = Cardinality.MANY;
+                }
+
+                TypeMirror originalChildType = childType;
+                TypeMirror castNodeType = castNodeTypes.get(name);
+                if (castNodeType != null) {
+                    childType = castNodeType;
+                }
+
+                Element getter = findGetter(elements, name, childType);
+
+                NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality);
+
+                parsedChildren.add(nodeChild);
+
+                if (nodeChild.getNodeType() == null) {
+                    nodeChild.addError("No valid node type could be resoleved.");
+                }
+                if (nodeChild.hasErrors()) {
+                    continue;
+                }
+
+                index++;
+            }
+        }
+
+        List<NodeChildData> filteredChildren = new ArrayList<>();
+        Set<String> encounteredNames = new HashSet<>();
+        for (int i = parsedChildren.size() - 1; i >= 0; i--) {
+            NodeChildData child = parsedChildren.get(i);
+            if (!encounteredNames.contains(child.getName())) {
+                filteredChildren.add(0, child);
+                encounteredNames.add(child.getName());
+            }
+        }
+
+        for (NodeChildData child : filteredChildren) {
+            List<String> executeWithStrings = ElementUtils.getAnnotationValueList(String.class, child.getMessageAnnotation(), "executeWith");
+            AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(child.getMessageAnnotation(), "executeWith");
+            List<NodeChildData> executeWith = new ArrayList<>();
+            for (String executeWithString : executeWithStrings) {
+
+                if (child.getName().equals(executeWithString)) {
+                    child.addError(executeWithValue, "The child node '%s' cannot be executed with itself.", executeWithString);
+                    continue;
+                }
+
+                NodeChildData found = null;
+                boolean before = true;
+                for (NodeChildData resolveChild : filteredChildren) {
+                    if (resolveChild == child) {
+                        before = false;
+                        continue;
+                    }
+                    if (resolveChild.getName().equals(executeWithString)) {
+                        found = resolveChild;
+                        break;
+                    }
+                }
+
+                if (found == null) {
+                    child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The child node was not found.", child.getName(), executeWithString);
+                    continue;
+                } else if (!before) {
+                    child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The node %s is executed after the current node.", child.getName(), executeWithString,
+                                    executeWithString);
+                    continue;
+                }
+                executeWith.add(found);
+            }
+            child.setExecuteWith(executeWith);
+            if (child.getNodeData() == null) {
+                continue;
+            }
+        }
+
+        return filteredChildren;
+    }
+
+    private List<NodeExecutionData> parseExecutions(List<NodeChildData> children, List<? extends Element> elements) {
+        if (children == null) {
+            return null;
+        }
+
+        // pre-parse short circuits
+        Set<String> shortCircuits = new HashSet<>();
+        List<ExecutableElement> methods = ElementFilter.methodsIn(elements);
+        for (ExecutableElement method : methods) {
+            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
+            if (mirror != null) {
+                shortCircuits.add(ElementUtils.getAnnotationValue(String.class, mirror, "value"));
+            }
+        }
+
+        boolean hasVarArgs = false;
+        int maxSignatureSize = 0;
+        if (!children.isEmpty()) {
+            int lastIndex = children.size() - 1;
+            hasVarArgs = children.get(lastIndex).getCardinality() == Cardinality.MANY;
+            if (hasVarArgs) {
+                maxSignatureSize = lastIndex;
+            } else {
+                maxSignatureSize = children.size();
+            }
+        }
+
+        // pre-parse specializations
+        for (ExecutableElement method : methods) {
+            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, Specialization.class);
+            if (mirror == null) {
+                continue;
+            }
+
+            int currentArgumentCount = 0;
+            boolean skipShortCircuit = false;
+            for (VariableElement var : method.getParameters()) {
+                TypeMirror type = var.asType();
+                if (currentArgumentCount == 0) {
+                    // skip optionals
+                    if (ElementUtils.typeEquals(type, context.getTruffleTypes().getFrame())) {
+                        continue;
+                    }
+                    // TODO skip optional fields?
+                }
+                int childIndex = currentArgumentCount < children.size() ? currentArgumentCount : children.size() - 1;
+                if (childIndex == -1) {
+                    continue;
+                }
+                if (!skipShortCircuit) {
+                    NodeChildData child = children.get(childIndex);
+                    if (shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, currentArgumentCount - childIndex))) {
+                        skipShortCircuit = true;
+                        continue;
+                    }
+                } else {
+                    skipShortCircuit = false;
+                }
+
+                currentArgumentCount++;
+            }
+            maxSignatureSize = Math.max(maxSignatureSize, currentArgumentCount);
+        }
+
+        List<NodeExecutionData> executions = new ArrayList<>();
+        for (int i = 0; i < maxSignatureSize; i++) {
+            int childIndex = i;
+            boolean varArg = false;
+            if (childIndex >= children.size() - 1) {
+                if (hasVarArgs) {
+                    childIndex = children.size() - 1;
+                    varArg = hasVarArgs;
+                } else if (childIndex >= children.size()) {
+                    break;
+                }
+            }
+            int varArgsIndex = varArg ? Math.abs(childIndex - i) : -1;
+            NodeChildData child = children.get(childIndex);
+            boolean shortCircuit = shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, varArgsIndex));
+            executions.add(new NodeExecutionData(child, varArgsIndex, shortCircuit));
+        }
+        return executions;
+    }
+
+    private static Map<Integer, List<ExecutableTypeData>> groupExecutableTypes(List<ExecutableTypeData> executableTypes) {
+        Map<Integer, List<ExecutableTypeData>> groupedTypes = new TreeMap<>();
+        for (ExecutableTypeData type : executableTypes) {
+            int evaluatedCount = type.getEvaluatedCount();
+
+            List<ExecutableTypeData> types = groupedTypes.get(evaluatedCount);
+            if (types == null) {
+                types = new ArrayList<>();
+                groupedTypes.put(evaluatedCount, types);
+            }
+            types.add(type);
+        }
+
+        for (List<ExecutableTypeData> types : groupedTypes.values()) {
+            Collections.sort(types);
+        }
+        return groupedTypes;
+    }
+
+    private void initializeChildren(NodeData node) {
+        for (NodeChildData nodeChild : node.getChildren()) {
+            NodeData fieldNodeData = resolveNode(ElementUtils.fromTypeMirror(nodeChild.getNodeType()));
+            nodeChild.setNode(fieldNodeData);
+            if (fieldNodeData == null) {
+                nodeChild.addError("Node type '%s' is invalid or not a valid Node.", ElementUtils.getQualifiedName(nodeChild.getNodeType()));
+            } else if (!ElementUtils.typeEquals(fieldNodeData.getTypeSystem().getTemplateType().asType(), (node.getTypeSystem().getTemplateType().asType()))) {
+                nodeChild.addError("The @%s of the node and the @%s of the @%s does not match. %s != %s. ", TypeSystem.class.getSimpleName(), TypeSystem.class.getSimpleName(),
+                                NodeChild.class.getSimpleName(), ElementUtils.getSimpleName(node.getTypeSystem().getTemplateType()),
+                                ElementUtils.getSimpleName(fieldNodeData.getTypeSystem().getTemplateType()));
+            }
+            if (fieldNodeData != null) {
+                List<ExecutableTypeData> types = nodeChild.findGenericExecutableTypes(context);
+                if (types.isEmpty()) {
+                    AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(nodeChild.getMessageAnnotation(), "executeWith");
+                    nodeChild.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", nodeChild.getExecuteWith().size(),
+                                    ElementUtils.getSimpleName(nodeChild.getNodeType()));
+                }
+            }
+        }
+    }
+
+    private void initializeSpecializations(List<? extends Element> elements, final NodeData node) {
+        if (node.getSpecializations().isEmpty()) {
+            return;
+        }
+
+        initializeGuards(elements, node);
+        initializeGeneric(node);
+        initializeUninitialized(node);
+        initializeOrder(node);
+        initializePolymorphism(node); // requires specializations
+        initializeReachability(node);
+        initializeContains(node);
+
+        if (!node.hasErrors()) {
+            initializeExceptions(node);
+        }
+        resolveContains(node);
+
+        List<SpecializationData> needsId = new ArrayList<>();
+        for (SpecializationData specialization : node.getSpecializations()) {
+            if (specialization.isGeneric()) {
+                specialization.setId("Generic");
+            } else if (specialization.isUninitialized()) {
+                specialization.setId("Uninitialized");
+            } else if (specialization.isPolymorphic()) {
+                specialization.setId("Polymorphic");
+            } else if (specialization.isSpecialized()) {
+                needsId.add(specialization);
+            } else {
+                throw new AssertionError();
+            }
+        }
+
+        // verify specialization parameter length
+        List<String> ids = initializeSpecializationIds(needsId);
+        for (int i = 0; i < ids.size(); i++) {
+            needsId.get(i).setId(ids.get(i));
+        }
+
+    }
+
+    private static void initializeOrder(NodeData node) {
+        List<SpecializationData> specializations = node.getSpecializations();
+        Collections.sort(specializations);
+
+        for (SpecializationData specialization : specializations) {
+            String searchName = specialization.getInsertBeforeName();
+            if (searchName == null || specialization.getMethod() == null) {
+                continue;
+            }
+            SpecializationData found = lookupSpecialization(node, searchName);
+            if (found == null || found.getMethod() == null) {
+                AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "insertBefore");
+                specialization.addError(value, "The referenced specialization '%s' could not be found.", searchName);
+                continue;
+            }
+
+            ExecutableElement currentMethod = specialization.getMethod();
+            ExecutableElement insertBeforeMethod = found.getMethod();
+
+            TypeMirror currentEnclosedType = currentMethod.getEnclosingElement().asType();
+            TypeMirror insertBeforeEnclosedType = insertBeforeMethod.getEnclosingElement().asType();
+
+            if (ElementUtils.typeEquals(currentEnclosedType, insertBeforeEnclosedType) || !ElementUtils.isSubtype(currentEnclosedType, insertBeforeEnclosedType)) {
+                AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "insertBefore");
+                specialization.addError(value, "Specializations can only be inserted before specializations in superclasses.", searchName);
+                continue;
+            }
+
+            specialization.setInsertBefore(found);
+        }
+
+        for (int i = 0; i < specializations.size(); i++) {
+            SpecializationData specialization = specializations.get(i);
+            SpecializationData insertBefore = specialization.getInsertBefore();
+            if (insertBefore != null) {
+                int insertIndex = specializations.indexOf(insertBefore);
+                if (insertIndex < i) {
+                    specializations.remove(i);
+                    specializations.add(insertIndex, specialization);
+                }
+            }
+        }
+
+        for (int i = 0; i < specializations.size(); i++) {
+            specializations.get(i).setIndex(i);
+        }
+    }
+
+    private static void initializeExceptions(NodeData node) {
+        List<SpecializationData> specializations = node.getSpecializations();
+        for (int i = 0; i < specializations.size(); i++) {
+            SpecializationData cur = specializations.get(i);
+            if (cur.getExceptions().isEmpty()) {
+                continue;
+            }
+            SpecializationData next = i + 1 < specializations.size() ? specializations.get(i + 1) : null;
+
+            if (!cur.isContainedBy(next)) {
+                next.addError("This specialiation is not a valid exceptional rewrite target for %s. To fix this make %s compatible to %s or remove the exceptional rewrite.",
+                                cur.createReferenceName(), next != null ? next.createReferenceName() : "-", cur.createReferenceName());
+                continue;
+            }
+            Set<SpecializationData> nextContains = next != null ? next.getContains() : Collections.<SpecializationData> emptySet();
+            if (!nextContains.contains(cur)) {
+                nextContains.add(cur);
+            }
+        }
+
+        for (SpecializationData cur : specializations) {
+            if (cur.getExceptions().isEmpty()) {
+                continue;
+            }
+            for (SpecializationData child : specializations) {
+                if (child != null && child != cur && child.getContains().contains(cur)) {
+                    cur.getExcludedBy().add(child);
+                }
+            }
+        }
+    }
+
+    private static void initializeContains(NodeData node) {
+        for (SpecializationData specialization : node.getSpecializations()) {
+            Set<SpecializationData> resolvedSpecializations = specialization.getContains();
+            resolvedSpecializations.clear();
+            Set<String> includeNames = specialization.getContainsNames();
+            for (String includeName : includeNames) {
+                // TODO reduce complexity of this lookup.
+                SpecializationData foundSpecialization = lookupSpecialization(node, includeName);
+
+                if (foundSpecialization == null) {
+                    AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains");
+                    specialization.addError(value, "The referenced specialization '%s' could not be found.", includeName);
+                } else {
+                    if (!foundSpecialization.isContainedBy(specialization)) {
+                        AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains");
+                        if (foundSpecialization.compareTo(specialization) > 0) {
+                            specialization.addError(value, "The contained specialization '%s' must be declared before the containing specialization.", includeName);
+                        } else {
+                            specialization.addError(value,
+                                            "The contained specialization '%s' is not fully compatible. The contained specialization must be strictly more generic than the containing one.",
+                                            includeName);
+                        }
+
+                    }
+                    resolvedSpecializations.add(foundSpecialization);
+                }
+            }
+        }
+    }
+
+    private void resolveContains(NodeData node) {
+        // flatten transitive includes
+        for (SpecializationData specialization : node.getSpecializations()) {
+            if (specialization.getContains().isEmpty()) {
+                continue;
+            }
+            Set<SpecializationData> foundSpecializations = new HashSet<>();
+            collectIncludes(specialization, foundSpecializations, new HashSet<SpecializationData>());
+            specialization.getContains().addAll(foundSpecializations);
+        }
+    }
+
+    private static SpecializationData lookupSpecialization(NodeData node, String includeName) {
+        SpecializationData foundSpecialization = null;
+        for (SpecializationData searchSpecialization : node.getSpecializations()) {
+            if (searchSpecialization.getMethodName().equals(includeName)) {
+                foundSpecialization = searchSpecialization;
+                break;
+            }
+        }
+        return foundSpecialization;
+    }
+
+    private void collectIncludes(SpecializationData specialization, Set<SpecializationData> found, Set<SpecializationData> visited) {
+        if (visited.contains(specialization)) {
+            // circle found
+            specialization.addError("Circular contained specialization '%s' found.", specialization.createReferenceName());
+            return;
+        }
+        visited.add(specialization);
+
+        for (SpecializationData included : specialization.getContains()) {
+            collectIncludes(included, found, new HashSet<>(visited));
+            found.add(included);
+        }
+    }
+
+    private static void initializeReachability(final NodeData node) {
+        List<SpecializationData> specializations = node.getSpecializations();
+        for (int i = specializations.size() - 1; i >= 0; i--) {
+            SpecializationData current = specializations.get(i);
+            if (current.isPolymorphic()) {
+                current.setReachable(true);
+                continue;
+            }
+
+            List<SpecializationData> shadowedBy = null;
+            for (int j = i - 1; j >= 0; j--) {
+                SpecializationData prev = specializations.get(j);
+                if (prev.isPolymorphic()) {
+                    continue;
+                }
+                if (!current.isReachableAfter(prev)) {
+                    if (shadowedBy == null) {
+                        shadowedBy = new ArrayList<>();
+                    }
+                    shadowedBy.add(prev);
+                }
+            }
+
+            if (shadowedBy != null) {
+                StringBuilder name = new StringBuilder();
+                String sep = "";
+                for (SpecializationData shadowSpecialization : shadowedBy) {
+                    name.append(sep);
+                    name.append(shadowSpecialization.createReferenceName());
+                    sep = ", ";
+                }
+                current.addError("%s is not reachable. It is shadowed by %s.", current.isGeneric() ? "Generic" : "Specialization", name);
+            }
+            current.setReachable(shadowedBy == null);
+        }
+    }
+
+    private static List<String> initializeSpecializationIds(List<SpecializationData> specializations) {
+        int lastSize = -1;
+        List<List<String>> signatureChunks = new ArrayList<>();
+        for (SpecializationData other : specializations) {
+            if (!other.isSpecialized()) {
+                continue;
+            }
+            List<String> paramIds = new LinkedList<>();
+            paramIds.add(ElementUtils.getTypeId(other.getReturnType().getType()));
+            for (Parameter param : other.getParameters()) {
+                if (param.getSpecification().getExecution() == null) {
+                    continue;
+                }
+                paramIds.add(ElementUtils.getTypeId(param.getType()));
+            }
+            assert lastSize == -1 || lastSize == paramIds.size();
+            if (lastSize != -1 && lastSize != paramIds.size()) {
+                throw new AssertionError();
+            }
+            signatureChunks.add(paramIds);
+            lastSize = paramIds.size();
+        }
+
+        // reduce id vertically
+        for (int i = 0; i < lastSize; i++) {
+            String prev = null;
+            boolean allSame = true;
+            for (List<String> signature : signatureChunks) {
+                String arg = signature.get(i);
+                if (prev == null) {
+                    prev = arg;
+                    continue;
+                } else if (!prev.equals(arg)) {
+                    allSame = false;
+                    break;
+                }
+                prev = arg;
+            }
+
+            if (allSame) {
+                for (List<String> signature : signatureChunks) {
+                    signature.remove(i);
+                }
+                lastSize--;
+            }
+        }
+
+        // reduce id horizontally
+        for (List<String> signature : signatureChunks) {
+            if (signature.isEmpty()) {
+                continue;
+            }
+            String prev = null;
+            boolean allSame = true;
+            for (String arg : signature) {
+                if (prev == null) {
+                    prev = arg;
+                    continue;
+                } else if (!prev.equals(arg)) {
+                    allSame = false;
+                    break;
+                }
+                prev = arg;
+            }
+
+            if (allSame) {
+                signature.clear();
+                signature.add(prev);
+            }
+        }
+
+        // create signatures
+        List<String> signatures = new ArrayList<>();
+        for (List<String> signatureChunk : signatureChunks) {
+            StringBuilder b = new StringBuilder();
+            if (signatureChunk.isEmpty()) {
+                b.append("Default");
+            } else {
+                for (String s : signatureChunk) {
+                    b.append(s);
+                }
+            }
+            signatures.add(b.toString());
+        }
+
+        Map<String, Integer> counts = new HashMap<>();
+        for (String s1 : signatures) {
+            Integer count = counts.get(s1);
+            if (count == null) {
+                count = 0;
+            }
+            count++;
+            counts.put(s1, count);
+        }
+
+        for (String s : counts.keySet()) {
+            int count = counts.get(s);
+            if (count > 1) {
+                int number = 0;
+                for (ListIterator<String> iterator = signatures.listIterator(); iterator.hasNext();) {
+                    String s2 = iterator.next();
+                    if (s.equals(s2)) {
+                        iterator.set(s2 + number);
+                        number++;
+                    }
+                }
+            }
+        }
+
+        return signatures;
+    }
+
+    private void initializeGuards(List<? extends Element> elements, NodeData node) {
+        Map<String, List<ExecutableElement>> potentialGuards = new HashMap<>();
+        for (SpecializationData specialization : node.getSpecializations()) {
+            for (GuardExpression exp : specialization.getGuards()) {
+                potentialGuards.put(exp.getGuardName(), null);
+            }
+        }
+
+        TypeMirror booleanType = context.getType(boolean.class);
+        for (ExecutableElement potentialGuard : ElementFilter.methodsIn(elements)) {
+            if (potentialGuard.getModifiers().contains(Modifier.PRIVATE)) {
+                continue;
+            }
+            String methodName = potentialGuard.getSimpleName().toString();
+            if (!potentialGuards.containsKey(methodName)) {
+                continue;
+            }
+
+            if (!ElementUtils.typeEquals(potentialGuard.getReturnType(), booleanType)) {
+                continue;
+            }
+
+            List<ExecutableElement> potentialMethods = potentialGuards.get(methodName);
+            if (potentialMethods == null) {
+                potentialMethods = new ArrayList<>();
+                potentialGuards.put(methodName, potentialMethods);
+            }
+            potentialMethods.add(potentialGuard);
+        }
+
+        for (SpecializationData specialization : node.getSpecializations()) {
+            for (GuardExpression exp : specialization.getGuards()) {
+                resolveGuardExpression(node, specialization, potentialGuards, exp);
+            }
+        }
+    }
+
+    private void resolveGuardExpression(NodeData node, TemplateMethod source, Map<String, List<ExecutableElement>> guards, GuardExpression expression) {
+        List<ExecutableElement> availableGuards = guards.get(expression.getGuardName());
+        if (availableGuards == null) {
+            source.addError("No compatible guard with method name '%s' found.", expression.getGuardName());
+            return;
+        }
+
+        String[] childNames = expression.getChildNames();
+        if (childNames != null) {
+            NodeExecutionData[] resolvedExecutions = new NodeExecutionData[childNames.length];
+            for (int i = 0; i < childNames.length; i++) {
+                String childName = childNames[i];
+                NodeExecutionData execution = node.findExecutionByExpression(childName);
+                if (execution == null) {
+                    source.addError("Guard parameter '%s' for guard '%s' could not be mapped to a declared child node.", childName, expression.getGuardName());
+                    return;
+                }
+                resolvedExecutions[i] = execution;
+            }
+            expression.setResolvedChildren(resolvedExecutions);
+        }
+
+        GuardParser parser = new GuardParser(context, node, source, expression);
+        List<GuardData> matchingGuards = parser.parse(availableGuards);
+        if (!matchingGuards.isEmpty() && matchingGuards.get(0) != null) {
+            expression.setResolvedGuard(matchingGuards.get(0));
+        } else {
+            MethodSpec spec = parser.createSpecification(source.getMethod(), source.getMarkerAnnotation());
+            spec.applyTypeDefinitions("types");
+            source.addError("No guard with name '%s' matched the required signature. Expected signature: %n%s", expression.getGuardName(), spec.toSignatureString("guard"));
+        }
+    }
+
+    private void initializeGeneric(final NodeData node) {
+        if (!node.needsRewrites(context)) {
+            return;
+        }
+
+        List<SpecializationData> generics = new ArrayList<>();
+        for (SpecializationData spec : node.getSpecializations()) {
+            if (spec.isGeneric()) {
+                generics.add(spec);
+            }
+        }
+
+        if (generics.size() == 1 && node.getSpecializations().size() == 1) {
+            // TODO this limitation should be lifted
+            for (SpecializationData generic : generics) {
+                generic.addError("@%s defined but no @%s.", Fallback.class.getSimpleName(), Specialization.class.getSimpleName());
+            }
+        }
+
+        if (generics.isEmpty()) {
+            node.getSpecializations().add(createGenericSpecialization(node));
+        } else {
+            if (generics.size() > 1) {
+                for (SpecializationData generic : generics) {
+                    generic.addError("Only one @%s is allowed per operation.", Fallback.class.getSimpleName());
+                }
+            }
+        }
+    }
+
+    private SpecializationData createGenericSpecialization(final NodeData node) {
+        GenericParser parser = new GenericParser(context, node);
+        MethodSpec specification = parser.createDefaultMethodSpec(node.getSpecializations().iterator().next().getMethod(), null, true, null);
+
+        List<TypeMirror> parameterTypes = new ArrayList<>();
+        int signatureIndex = 1;
+        for (ParameterSpec spec : specification.getRequired()) {
+            parameterTypes.add(createGenericType(spec, node.getSpecializations(), signatureIndex));
+            if (spec.isSignature()) {
+                signatureIndex++;
+            }
+        }
+
+        TypeMirror returnType = createGenericType(specification.getReturnType(), node.getSpecializations(), 0);
+        SpecializationData generic = parser.create("Generic", TemplateMethod.NO_NATURAL_ORDER, null, null, returnType, parameterTypes);
+        if (generic == null) {
+            throw new RuntimeException("Unable to create generic signature for node " + node.getNodeId() + " with " + parameterTypes + ". Specification " + specification + ".");
+        }
+
+        return generic;
+    }
+
+    private TypeMirror createGenericType(ParameterSpec spec, List<SpecializationData> specializations, int signatureIndex) {
+        NodeExecutionData execution = spec.getExecution();
+        if (execution == null) {
+            if (spec.getAllowedTypes().size() == 1) {
+                return spec.getAllowedTypes().get(0);
+            } else {
+                return ElementUtils.getCommonSuperType(context, spec.getAllowedTypes().toArray(new TypeMirror[0]));
+            }
+        } else {
+            Set<TypeData> types = new HashSet<>();
+            for (SpecializationData specialization : specializations) {
+                types.add(specialization.getTypeSignature().get(signatureIndex));
+            }
+
+            NodeChildData child = execution.getChild();
+            TypeData genericType = null;
+            if (types.size() == 1) {
+                ExecutableTypeData executable = child.findExecutableType(context, types.iterator().next());
+                if (executable != null && (signatureIndex == 0 || !executable.hasUnexpectedValue(context))) {
+                    genericType = types.iterator().next();
+                }
+            }
+            if (genericType == null) {
+                genericType = child.findAnyGenericExecutableType(context).getType();
+            }
+            return genericType.getPrimitiveType();
+        }
+    }
+
+    private static void initializeUninitialized(final NodeData node) {
+        SpecializationData generic = node.getGenericSpecialization();
+        if (generic == null) {
+            return;
+        }
+        for (Parameter parameter : generic.getReturnTypeAndParameters()) {
+            if (ElementUtils.isObject(parameter.getType())) {
+                continue;
+            }
+            Set<String> types = new HashSet<>();
+            for (SpecializationData specialization : node.getSpecializations()) {
+                Parameter actualParameter = specialization.findParameter(parameter.getLocalName());
+                if (actualParameter != null) {
+                    types.add(ElementUtils.getQualifiedName(actualParameter.getType()));
+                }
+            }
+            if (types.size() > 1) {
+                generic.replaceParameter(parameter.getLocalName(), new Parameter(parameter, node.getTypeSystem().getGenericTypeData()));
+            }
+        }
+        TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", -1, node, generic.getSpecification(), null, null, generic.getReturnType(), generic.getParameters());
+        // should not use messages from generic specialization
+        uninializedMethod.getMessages().clear();
+        node.getSpecializations().add(new SpecializationData(node, uninializedMethod, SpecializationKind.UNINITIALIZED));
+    }
+
+    private void initializePolymorphism(NodeData node) {
+        if (!node.needsRewrites(context)) {
+            return;
+        }
+
+        SpecializationData generic = node.getGenericSpecialization();
+
+        List<TypeData> polymorphicSignature = new ArrayList<>();
+        List<Parameter> updatePolymorphic = Arrays.asList();
+        for (Parameter genericParameter : updatePolymorphic) {
+            if (!genericParameter.getSpecification().isSignature()) {
+                continue;
+            }
+
+            Set<TypeData> usedTypes = new HashSet<>();
+            for (SpecializationData specialization : node.getSpecializations()) {
+                if (!specialization.isSpecialized()) {
+                    continue;
+                }
+                Parameter parameter = specialization.findParameter(genericParameter.getLocalName());
+                if (parameter == null) {
+                    throw new AssertionError("Parameter existed in generic specialization but not in specialized. param = " + genericParameter.getLocalName());
+                }
+                usedTypes.add(parameter.getTypeSystemType());
+            }
+
+            TypeData polymorphicType;
+            if (usedTypes.size() == 1) {
+                polymorphicType = usedTypes.iterator().next();
+            } else {
+                polymorphicType = node.getTypeSystem().getGenericTypeData();
+            }
+            polymorphicSignature.add(polymorphicType);
+        }
+
+        SpecializationData polymorphic = new SpecializationData(node, generic, SpecializationKind.POLYMORPHIC);
+        polymorphic.updateSignature(new TypeSignature(polymorphicSignature));
+        node.getSpecializations().add(polymorphic);
+    }
+
+    private void initializeShortCircuits(NodeData node) {
+        Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(node.getShortCircuits());
+
+        boolean valid = true;
+        List<NodeExecutionData> shortCircuitExecutions = new ArrayList<>();
+        for (NodeExecutionData execution : node.getChildExecutions()) {
+            if (!execution.isShortCircuit()) {
+                continue;
+            }
+            shortCircuitExecutions.add(execution);
+            String valueName = execution.getShortCircuitId();
+            List<ShortCircuitData> availableCircuits = groupedShortCircuits.get(valueName);
+
+            if (availableCircuits == null || availableCircuits.isEmpty()) {
+                node.addError("@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName);
+                valid = false;
+                continue;
+            }
+
+            boolean sameMethodName = true;
+            String methodName = availableCircuits.get(0).getMethodName();
+            for (ShortCircuitData circuit : availableCircuits) {
+                if (!circuit.getMethodName().equals(methodName)) {
+                    sameMethodName = false;
+                }
+            }
+
+            if (!sameMethodName) {
+                for (ShortCircuitData circuit : availableCircuits) {
+                    circuit.addError("All short circuits for short cut value '%s' must have the same method name.", valueName);
+                }
+                valid = false;
+                continue;
+            }
+
+            ShortCircuitData genericCircuit = null;
+            for (ShortCircuitData circuit : availableCircuits) {
+                if (isGenericShortCutMethod(circuit)) {
+                    genericCircuit = circuit;
+                    break;
+                }
+            }
+
+            if (genericCircuit == null) {
+                node.addError("No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName);
+                valid = false;
+                continue;
+            }
+
+            for (ShortCircuitData circuit : availableCircuits) {
+                if (circuit != genericCircuit) {
+                    circuit.setGenericShortCircuitMethod(genericCircuit);
+                }
+            }
+        }
+
+        if (!valid) {
+            return;
+        }
+
+        List<SpecializationData> specializations = new ArrayList<>();
+        specializations.addAll(node.getSpecializations());
+        for (SpecializationData specialization : specializations) {
+            List<ShortCircuitData> assignedShortCuts = new ArrayList<>(shortCircuitExecutions.size());
+
+            for (NodeExecutionData shortCircuit : shortCircuitExecutions) {
+                List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(shortCircuit.getShortCircuitId());
+
+                ShortCircuitData genericShortCircuit = null;
+                ShortCircuitData compatibleShortCircuit = null;
+                for (ShortCircuitData circuit : availableShortCuts) {
+                    if (circuit.isGeneric()) {
+                        genericShortCircuit = circuit;
+                    } else if (circuit.isCompatibleTo(specialization)) {
+                        compatibleShortCircuit = circuit;
+                    }
+                }
+
+                if (compatibleShortCircuit == null) {
+                    compatibleShortCircuit = genericShortCircuit;
+                }
+                assignedShortCuts.add(compatibleShortCircuit);
+            }
+            specialization.setShortCircuits(assignedShortCuts);
+        }
+    }
+
+    private boolean isGenericShortCutMethod(ShortCircuitData method) {
+        for (Parameter parameter : method.getParameters()) {
+            NodeExecutionData execution = parameter.getSpecification().getExecution();
+            if (execution == null) {
+                continue;
+            }
+            ExecutableTypeData found = null;
+            List<ExecutableTypeData> executableElements = execution.getChild().findGenericExecutableTypes(context);
+            for (ExecutableTypeData executable : executableElements) {
+                if (executable.getType().equalsType(parameter.getTypeSystemType())) {
+                    found = executable;
+                    break;
+                }
+            }
+            if (found == null) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static Map<String, List<ShortCircuitData>> groupShortCircuits(List<ShortCircuitData> shortCircuits) {
+        Map<String, List<ShortCircuitData>> group = new HashMap<>();
+        for (ShortCircuitData shortCircuit : shortCircuits) {
+            List<ShortCircuitData> circuits = group.get(shortCircuit.getValueName());
+            if (circuits == null) {
+                circuits = new ArrayList<>();
+                group.put(shortCircuit.getValueName(), circuits);
+            }
+            circuits.add(shortCircuit);
+        }
+        return group;
+    }
+
+    private static boolean verifySpecializationSameLength(NodeData nodeData) {
+        int lastArgs = -1;
+        for (SpecializationData specializationData : nodeData.getSpecializations()) {
+            int signatureArgs = specializationData.getSignatureSize();
+            if (lastArgs == signatureArgs) {
+                continue;
+            }
+            if (lastArgs != -1) {
+                for (SpecializationData specialization : nodeData.getSpecializations()) {
+                    specialization.addError("All specializations must have the same number of arguments.");
+                }
+                return false;
+            } else {
+                lastArgs = signatureArgs;
+            }
+        }
+        return true;
+    }
+
+    private static void verifyVisibilities(NodeData node) {
+        if (node.getTemplateType().getModifiers().contains(Modifier.PRIVATE) && node.getSpecializations().size() > 0) {
+            node.addError("Classes containing a @%s annotation must not be private.", Specialization.class.getSimpleName());
+        }
+    }
+
+    private static void verifyMissingAbstractMethods(NodeData nodeData, List<? extends Element> originalElements) {
+        if (!nodeData.needsFactory()) {
+            // missing abstract methods only needs to be implemented
+            // if we need go generate factory for it.
+            return;
+        }
+
+        List<Element> elements = new ArrayList<>(originalElements);
+        Set<Element> unusedElements = new HashSet<>(elements);
+        for (TemplateMethod method : nodeData.getAllTemplateMethods()) {
+            unusedElements.remove(method.getMethod());
+        }
+
+        for (NodeFieldData field : nodeData.getFields()) {
+            if (field.getGetter() != null) {
+                unusedElements.remove(field.getGetter());
+            }
+        }
+
+        for (NodeChildData child : nodeData.getChildren()) {
+            if (child.getAccessElement() != null) {
+                unusedElements.remove(child.getAccessElement());
+            }
+        }
+
+        for (ExecutableElement unusedMethod : ElementFilter.methodsIn(unusedElements)) {
+            if (unusedMethod.getModifiers().contains(Modifier.ABSTRACT)) {
+                nodeData.addError("The type %s must implement the inherited abstract method %s.", ElementUtils.getSimpleName(nodeData.getTemplateType()),
+                                ElementUtils.getReadableSignature(unusedMethod));
+            }
+        }
+    }
+
+    private static void verifyNamingConvention(List<? extends TemplateMethod> methods, String prefix) {
+        for (int i = 0; i < methods.size(); i++) {
+            TemplateMethod m1 = methods.get(i);
+            if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) {
+                m1.addError("Naming convention: method name must start with '%s'.", prefix);
+            }
+        }
+    }
+
+    private static void verifySpecializationThrows(NodeData node) {
+        Map<String, SpecializationData> specializationMap = new HashMap<>();
+        for (SpecializationData spec : node.getSpecializations()) {
+            specializationMap.put(spec.getMethodName(), spec);
+        }
+        for (SpecializationData sourceSpecialization : node.getSpecializations()) {
+            if (sourceSpecialization.getExceptions() != null) {
+                for (SpecializationThrowsData throwsData : sourceSpecialization.getExceptions()) {
+                    for (SpecializationThrowsData otherThrowsData : sourceSpecialization.getExceptions()) {
+                        if (otherThrowsData != throwsData && ElementUtils.typeEquals(otherThrowsData.getJavaClass(), throwsData.getJavaClass())) {
+                            throwsData.addError("Duplicate exception type.");
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private void verifyConstructors(NodeData nodeData) {
+        if (!nodeData.needsRewrites(context)) {
+            // no specialization constructor is needed if the node never rewrites.
+            return;
+        }
+
+        TypeElement type = ElementUtils.fromTypeMirror(nodeData.getNodeType());
+        List<ExecutableElement> constructors = ElementFilter.constructorsIn(type.getEnclosedElements());
+
+        boolean parametersFound = false;
+        for (ExecutableElement constructor : constructors) {
+            if (!constructor.getParameters().isEmpty() && !isSourceSectionConstructor(context, constructor)) {
+                parametersFound = true;
+            }
+        }
+        if (!parametersFound) {
+            return;
+        }
+        for (ExecutableElement e : constructors) {
+            if (e.getParameters().size() == 1) {
+                TypeMirror firstArg = e.getParameters().get(0).asType();
+                if (ElementUtils.typeEquals(firstArg, nodeData.getNodeType())) {
+                    if (e.getModifiers().contains(Modifier.PRIVATE)) {
+                        nodeData.addError("The specialization constructor must not be private.");
+                    } else if (constructors.size() <= 1) {
+                        nodeData.addError("The specialization constructor must not be the only constructor. The definition of an alternative constructor is required.");
+                    }
+                    return;
+                }
+            }
+        }
+
+        // not found
+        nodeData.addError("Specialization constructor '%s(%s previousNode) { this(...); }' is required.", ElementUtils.getSimpleName(type), ElementUtils.getSimpleName(type));
+    }
+
+    public static boolean isSourceSectionConstructor(ProcessorContext context, ExecutableElement constructor) {
+        return constructor.getParameters().size() == 1 && ElementUtils.typeEquals(constructor.getParameters().get(0).asType(), context.getTruffleTypes().getSourceSection());
+    }
+
+    private AnnotationMirror findFirstAnnotation(List<? extends Element> elements, Class<? extends Annotation> annotation) {
+        for (Element element : elements) {
+            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, element, annotation);
+            if (mirror != null) {
+                return mirror;
+            }
+        }
+        return null;
+    }
+
+    private TypeMirror inheritType(AnnotationMirror annotation, String valueName, TypeMirror parentType) {
+        TypeMirror inhertNodeType = context.getTruffleTypes().getNode();
+        TypeMirror value = ElementUtils.getAnnotationValue(TypeMirror.class, annotation, valueName);
+        if (ElementUtils.typeEquals(inhertNodeType, value)) {
+            return parentType;
+        } else {
+            return value;
+        }
+    }
+
+    private ExecutableElement findGetter(List<? extends Element> elements, String variableName, TypeMirror type) {
+        if (type == null) {
+            return null;
+        }
+        String methodName;
+        if (ElementUtils.typeEquals(type, context.getType(boolean.class))) {
+            methodName = "is" + ElementUtils.firstLetterUpperCase(variableName);
+        } else {
+            methodName = "get" + ElementUtils.firstLetterUpperCase(variableName);
+        }
+
+        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
+            if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && ElementUtils.isAssignable(type, method.getReturnType())) {
+                return method;
+            }
+        }
+        return null;
+    }
+
+    private static List<TypeElement> collectSuperClasses(List<TypeElement> collection, TypeElement element) {
+        if (element != null) {
+            collection.add(element);
+            if (element.getSuperclass() != null) {
+                collectSuperClasses(collection, ElementUtils.fromTypeMirror(element.getSuperclass()));
+            }
+        }
+        return collection;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ShortCircuitParser.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class ShortCircuitParser extends NodeMethodParser<ShortCircuitData> {
+
+    private final Set<String> shortCircuitValues;
+
+    public ShortCircuitParser(ProcessorContext context, NodeData node) {
+        super(context, node);
+
+        shortCircuitValues = new HashSet<>();
+        for (NodeExecutionData execution : node.getChildExecutions()) {
+            if (execution.isShortCircuit()) {
+                shortCircuitValues.add(execution.getShortCircuitId());
+            }
+        }
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        String shortCircuitValue = ElementUtils.getAnnotationValue(String.class, mirror, "value");
+
+        return createDefaultMethodSpec(method, mirror, true, shortCircuitValue);
+    }
+
+    @Override
+    protected ParameterSpec createReturnParameterSpec() {
+        return new ParameterSpec("has", getContext().getType(boolean.class));
+    }
+
+    @Override
+    public ShortCircuitData create(TemplateMethod method, boolean invalid) {
+        String shortCircuitValue = ElementUtils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "value");
+
+        if (!shortCircuitValues.contains(shortCircuitValue)) {
+            method.addError("Invalid short circuit value %s.", shortCircuitValue);
+        }
+
+        return new ShortCircuitData(method, shortCircuitValue);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return ShortCircuit.class;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,447 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.util.*;
+
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.model.TemplateMethod.TypeSignature;
+
+/**
+ * Class creates groups of specializations to optimize the layout of generated executeAndSpecialize
+ * and generic execute methods.
+ */
+public final class SpecializationGroup {
+
+    private final List<String> assumptions;
+    private final List<TypeGuard> typeGuards;
+    private final List<GuardExpression> guards;
+
+    private final NodeData node;
+    private final SpecializationData specialization;
+    private final List<SpecializationGroup> children = new ArrayList<>();
+
+    private SpecializationGroup parent;
+
+    private SpecializationGroup(SpecializationData data) {
+        this.node = data.getNode();
+        this.assumptions = new ArrayList<>();
+        this.typeGuards = new ArrayList<>();
+        this.guards = new ArrayList<>();
+        this.specialization = data;
+
+        this.assumptions.addAll(data.getAssumptions());
+        TypeSignature sig = data.getTypeSignature();
+        for (int i = 1; i < sig.size(); i++) {
+            typeGuards.add(new TypeGuard(sig.get(i), i - 1));
+        }
+        this.guards.addAll(data.getGuards());
+    }
+
+    public SpecializationGroup(List<SpecializationGroup> children, List<String> assumptionMatches, List<TypeGuard> typeGuardsMatches, List<GuardExpression> guardMatches) {
+        assert !children.isEmpty() : "children must not be empty";
+        this.assumptions = assumptionMatches;
+        this.typeGuards = typeGuardsMatches;
+        this.guards = guardMatches;
+        this.node = children.get(0).node;
+        this.specialization = null;
+        updateChildren(children);
+    }
+
+    public List<TypeGuard> getAllGuards() {
+        List<TypeGuard> collectedGuards = new ArrayList<>();
+        collectedGuards.addAll(typeGuards);
+        if (parent != null) {
+            collectedGuards.addAll(parent.getAllGuards());
+        }
+        return collectedGuards;
+    }
+
+    public TypeGuard findTypeGuard(int signatureIndex) {
+        for (TypeGuard guard : typeGuards) {
+            if (guard.getSignatureIndex() == signatureIndex) {
+                return guard;
+            }
+        }
+        return null;
+    }
+
+    public List<GuardExpression> findElseConnectableGuards() {
+        if (!getTypeGuards().isEmpty() || !getAssumptions().isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        if (getGuards().isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        List<GuardExpression> elseConnectableGuards = new ArrayList<>();
+        int guardIndex = 0;
+        while (guardIndex < getGuards().size() && findNegatedGuardInPrevious(getGuards().get(guardIndex)) != null) {
+            elseConnectableGuards.add(getGuards().get(guardIndex));
+            guardIndex++;
+        }
+
+        return elseConnectableGuards;
+    }
+
+    private GuardExpression findNegatedGuardInPrevious(GuardExpression guard) {
+        SpecializationGroup previous = this.getPreviousGroup();
+        if (previous == null) {
+            return null;
+        }
+        List<GuardExpression> elseConnectedGuards = previous.findElseConnectableGuards();
+
+        if (previous == null || previous.getGuards().size() != elseConnectedGuards.size() + 1) {
+            return null;
+        }
+
+        /* Guard is else branch can be connected in previous specialization. */
+        if (elseConnectedGuards.contains(guard)) {
+            return guard;
+        }
+
+        GuardExpression previousGuard = previous.getGuards().get(elseConnectedGuards.size());
+        if (guard.getResolvedGuard().getMethod().equals(previousGuard.getResolvedGuard().getMethod()) && guard.isNegated() != previousGuard.isNegated()) {
+            return guard;
+        }
+        return null;
+    }
+
+    private void updateChildren(List<SpecializationGroup> childs) {
+        if (!children.isEmpty()) {
+            children.clear();
+        }
+        this.children.addAll(childs);
+        for (SpecializationGroup child : childs) {
+            child.parent = this;
+        }
+    }
+
+    public SpecializationGroup getParent() {
+        return parent;
+    }
+
+    public List<String> getAssumptions() {
+        return assumptions;
+    }
+
+    public List<TypeGuard> getTypeGuards() {
+        return typeGuards;
+    }
+
+    public List<GuardExpression> getGuards() {
+        return guards;
+    }
+
+    public List<SpecializationGroup> getChildren() {
+        return children;
+    }
+
+    public SpecializationData getSpecialization() {
+        return specialization;
+    }
+
+    private static SpecializationGroup combine(List<SpecializationGroup> groups) {
+        if (groups.isEmpty()) {
+            throw new IllegalArgumentException("empty combinations");
+        }
+        if (groups.size() == 1) {
+            return null;
+        }
+
+        List<String> assumptionMatches = new ArrayList<>();
+        List<TypeGuard> typeGuardsMatches = new ArrayList<>();
+        List<GuardExpression> guardMatches = new ArrayList<>();
+
+        SpecializationGroup first = groups.get(0);
+        List<SpecializationGroup> others = groups.subList(1, groups.size());
+
+        outer: for (String assumption : first.assumptions) {
+            for (SpecializationGroup other : others) {
+                if (!other.assumptions.contains(assumption)) {
+                    // assumptions can be combined unordered
+                    continue outer;
+                }
+            }
+            assumptionMatches.add(assumption);
+        }
+
+        outer: for (TypeGuard typeGuard : first.typeGuards) {
+            for (SpecializationGroup other : others) {
+                if (!other.typeGuards.contains(typeGuard)) {
+                    // type guards can be combined unordered
+                    continue outer;
+                }
+            }
+            typeGuardsMatches.add(typeGuard);
+        }
+
+        outer: for (GuardExpression guard : first.guards) {
+            for (SpecializationGroup other : others) {
+                if (!other.guards.contains(guard)) {
+                    // we must break here. One guard may depend on the other.
+                    break outer;
+                }
+            }
+            guardMatches.add(guard);
+        }
+
+        // check for guards for required type casts
+        for (Iterator<GuardExpression> iterator = guardMatches.iterator(); iterator.hasNext();) {
+            GuardExpression guardMatch = iterator.next();
+
+            int signatureIndex = 0;
+            for (Parameter parameter : guardMatch.getResolvedGuard().getParameters()) {
+                signatureIndex++;
+                if (!parameter.getSpecification().isSignature()) {
+                    continue;
+                }
+
+                TypeMirror guardType = parameter.getType();
+
+                // object guards can be safely moved up
+                if (ElementUtils.isObject(guardType)) {
+                    continue;
+                }
+
+                // generic guards can be safely moved up
+                SpecializationData generic = first.node.getGenericSpecialization();
+                if (generic != null) {
+                    Parameter genericParameter = generic.findParameter(parameter.getLocalName());
+                    if (genericParameter != null && ElementUtils.typeEquals(genericParameter.getType(), guardType)) {
+                        continue;
+                    }
+                }
+
+                // signature index required for moving up guards
+                if (containsIndex(typeGuardsMatches, signatureIndex) || (first.getParent() != null && first.getParent().containsTypeGuardIndex(signatureIndex))) {
+                    continue;
+                }
+
+                iterator.remove();
+                break;
+            }
+        }
+
+        if (assumptionMatches.isEmpty() && typeGuardsMatches.isEmpty() && guardMatches.isEmpty()) {
+            return null;
+        }
+
+        for (SpecializationGroup group : groups) {
+            group.assumptions.removeAll(assumptionMatches);
+            group.typeGuards.removeAll(typeGuardsMatches);
+            group.guards.removeAll(guardMatches);
+        }
+
+        List<SpecializationGroup> newChildren = new ArrayList<>(groups);
+        return new SpecializationGroup(newChildren, assumptionMatches, typeGuardsMatches, guardMatches);
+    }
+
+    private boolean containsTypeGuardIndex(int index) {
+        if (containsIndex(typeGuards, index)) {
+            return true;
+        }
+        if (parent != null) {
+            return parent.containsTypeGuardIndex(index);
+        }
+        return false;
+    }
+
+    private static boolean containsIndex(List<TypeGuard> typeGuards, int signatureIndex) {
+        for (TypeGuard guard : typeGuards) {
+            if (guard.signatureIndex == signatureIndex) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static SpecializationGroup create(SpecializationData specialization) {
+        return new SpecializationGroup(specialization);
+    }
+
+    public static SpecializationGroup create(List<SpecializationData> specializations) {
+        List<SpecializationGroup> groups = new ArrayList<>();
+        for (SpecializationData specialization : specializations) {
+            groups.add(new SpecializationGroup(specialization));
+        }
+        return new SpecializationGroup(createCombinationalGroups(groups), Collections.<String> emptyList(), Collections.<TypeGuard> emptyList(), Collections.<GuardExpression> emptyList());
+    }
+
+    @Override
+    public String toString() {
+        return "SpecializationGroup [assumptions=" + assumptions + ", typeGuards=" + typeGuards + ", guards=" + guards + "]";
+    }
+
+    private static List<SpecializationGroup> createCombinationalGroups(List<SpecializationGroup> groups) {
+        if (groups.size() <= 1) {
+            return groups;
+        }
+        List<SpecializationGroup> newGroups = new ArrayList<>();
+
+        int i = 0;
+        for (i = 0; i < groups.size();) {
+            SpecializationGroup combined = null;
+            for (int j = groups.size(); j > i + 1; j--) {
+                combined = combine(groups.subList(i, j));
+                if (combined != null) {
+                    break;
+                }
+            }
+            SpecializationGroup newGroup;
+            if (combined == null) {
+                newGroup = groups.get(i);
+                i++;
+            } else {
+                newGroup = combined;
+                List<SpecializationGroup> originalGroups = new ArrayList<>(combined.children);
+                combined.updateChildren(createCombinationalGroups(originalGroups));
+                i += originalGroups.size();
+            }
+
+            newGroups.add(newGroup);
+
+        }
+
+        return newGroups;
+    }
+
+    public SpecializationGroup getPreviousGroup() {
+        if (parent == null || parent.children.isEmpty()) {
+            return null;
+        }
+        int index = parent.children.indexOf(this);
+        if (index <= 0) {
+            return null;
+        }
+        return parent.children.get(index - 1);
+    }
+
+    public int getUncheckedSpecializationIndex() {
+        int groupMaxIndex = getMaxSpecializationIndex();
+
+        int genericIndex = node.getSpecializations().indexOf(node.getGenericSpecialization());
+        if (groupMaxIndex >= genericIndex) {
+            // no minimum state check for an generic index
+            groupMaxIndex = -1;
+        }
+
+        if (groupMaxIndex > -1) {
+            // no minimum state check if already checked by parent group
+            int parentMaxIndex = -1;
+            if (getParent() != null) {
+                parentMaxIndex = getParent().getMaxSpecializationIndex();
+            }
+            if (groupMaxIndex == parentMaxIndex) {
+                groupMaxIndex = -1;
+            }
+        }
+        return groupMaxIndex;
+    }
+
+    public int getMaxSpecializationIndex() {
+        if (specialization != null) {
+            return specialization.getNode().getSpecializations().indexOf(specialization);
+        } else {
+            int max = Integer.MIN_VALUE;
+            for (SpecializationGroup childGroup : getChildren()) {
+                max = Math.max(max, childGroup.getMaxSpecializationIndex());
+            }
+            return max;
+        }
+    }
+
+    public static final class TypeGuard {
+
+        private final int signatureIndex;
+        private final TypeData type;
+
+        public TypeGuard(TypeData type, int signatureIndex) {
+            this.type = type;
+            this.signatureIndex = signatureIndex;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + signatureIndex;
+            result = prime * result + type.hashCode();
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            } else if (obj == null) {
+                return false;
+            } else if (getClass() != obj.getClass()) {
+                return false;
+            }
+
+            TypeGuard other = (TypeGuard) obj;
+            if (signatureIndex != other.signatureIndex) {
+                return false;
+            } else if (!type.equals(other.type)) {
+                return false;
+            }
+            return true;
+        }
+
+        public int getSignatureIndex() {
+            return signatureIndex;
+        }
+
+        public TypeData getType() {
+            return type;
+        }
+    }
+
+    public boolean isTypeGuardUsedInAnyGuardBelow(ProcessorContext context, SpecializationData source, TypeGuard typeGuard) {
+        NodeExecutionData execution = source.getNode().getChildExecutions().get(typeGuard.getSignatureIndex());
+
+        for (GuardExpression guard : guards) {
+            List<Parameter> guardParameters = guard.getResolvedGuard().findByExecutionData(execution);
+            Parameter sourceParameter = source.getSignatureParameter(typeGuard.getSignatureIndex());
+            for (Parameter guardParameter : guardParameters) {
+                if (sourceParameter.getTypeSystemType().needsCastTo(guardParameter.getType())) {
+                    return true;
+                }
+            }
+        }
+
+        for (SpecializationGroup group : getChildren()) {
+            if (group.isTypeGuardUsedInAnyGuardBelow(context, source, typeGuard)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind;
+
+public class SpecializationMethodParser extends NodeMethodParser<SpecializationData> {
+
+    public SpecializationMethodParser(ProcessorContext context, NodeData operation) {
+        super(context, operation);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        return createDefaultMethodSpec(method, mirror, true, null);
+    }
+
+    @Override
+    public SpecializationData create(TemplateMethod method, boolean invalid) {
+        return parseSpecialization(method);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return Specialization.class;
+    }
+
+    private SpecializationData parseSpecialization(TemplateMethod method) {
+        AnnotationValue rewriteValue = ElementUtils.getAnnotationValue(method.getMarkerAnnotation(), "rewriteOn");
+        List<TypeMirror> exceptionTypes = ElementUtils.getAnnotationValueList(TypeMirror.class, method.getMarkerAnnotation(), "rewriteOn");
+        List<SpecializationThrowsData> exceptionData = new ArrayList<>();
+        for (TypeMirror exceptionType : exceptionTypes) {
+            SpecializationThrowsData throwsData = new SpecializationThrowsData(method.getMarkerAnnotation(), rewriteValue, exceptionType);
+            if (!ElementUtils.canThrowType(method.getMethod().getThrownTypes(), exceptionType)) {
+                throwsData.addError("Method must specify a throws clause with the exception type '%s'.", ElementUtils.getQualifiedName(exceptionType));
+            }
+            exceptionData.add(throwsData);
+        }
+
+        Collections.sort(exceptionData, new Comparator<SpecializationThrowsData>() {
+
+            @Override
+            public int compare(SpecializationThrowsData o1, SpecializationThrowsData o2) {
+                return ElementUtils.compareByTypeHierarchy(o1.getJavaClass(), o2.getJavaClass());
+            }
+        });
+        SpecializationData specialization = new SpecializationData(getNode(), method, SpecializationKind.SPECIALIZED, exceptionData);
+
+        String insertBeforeName = ElementUtils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "insertBefore");
+        if (!insertBeforeName.equals("")) {
+            specialization.setInsertBeforeName(insertBeforeName);
+        }
+
+        List<String> guardDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards");
+        List<GuardExpression> guardExpressions = new ArrayList<>();
+        for (String guardDef : guardDefs) {
+            guardExpressions.add(new GuardExpression(guardDef, true));
+        }
+        specialization.setGuards(guardExpressions);
+
+        List<String> containsDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "contains");
+        Set<String> containsNames = specialization.getContainsNames();
+        containsNames.clear();
+        if (containsDefs != null) {
+            for (String include : containsDefs) {
+                if (!containsNames.contains(include)) {
+                    specialization.getContainsNames().add(include);
+                } else {
+                    AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains");
+                    specialization.addError(value, "Duplicate contains declaration '%s'.", include);
+                }
+            }
+
+        }
+
+        List<String> assumptionDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "assumptions");
+        specialization.setAssumptions(assumptionDefs);
+
+        for (String assumption : assumptionDefs) {
+            if (!getNode().getAssumptions().contains(assumption)) {
+                specialization.addError("Undeclared assumption '%s' used. Use @NodeAssumptions to declare them.", assumption);
+            }
+        }
+
+        return specialization;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TemplateMethodParser.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,142 @@
+/*
+ * 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.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public abstract class TemplateMethodParser<T extends Template, E extends TemplateMethod> {
+
+    protected final T template;
+    private final ProcessorContext context;
+    private final MethodSpecParser parser;
+
+    private boolean parseNullOnError;
+
+    public TemplateMethodParser(ProcessorContext context, T template) {
+        this.template = template;
+        this.context = context;
+        this.parser = new MethodSpecParser(template);
+    }
+
+    public void setParseNullOnError(boolean parseNullOnError) {
+        this.parseNullOnError = parseNullOnError;
+    }
+
+    public boolean isParseNullOnError() {
+        return parseNullOnError;
+    }
+
+    public MethodSpecParser getParser() {
+        return parser;
+    }
+
+    public ProcessorContext getContext() {
+        return context;
+    }
+
+    public TypeSystemData getTypeSystem() {
+        return template.getTypeSystem();
+    }
+
+    public abstract MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror);
+
+    public abstract E create(TemplateMethod method, boolean invalid);
+
+    public abstract boolean isParsable(ExecutableElement method);
+
+    public Class<? extends Annotation> getAnnotationType() {
+        return null;
+    }
+
+    public final List<E> parse(List<? extends Element> elements) {
+        List<ExecutableElement> methods = new ArrayList<>();
+        methods.addAll(ElementFilter.methodsIn(elements));
+
+        List<E> parsedMethods = new ArrayList<>();
+        boolean valid = true;
+        int naturalOrder = 0;
+        for (ExecutableElement method : methods) {
+            if (!isParsable(method)) {
+                continue;
+            }
+
+            Class<? extends Annotation> annotationType = getAnnotationType();
+            AnnotationMirror mirror = null;
+            if (annotationType != null) {
+                mirror = ElementUtils.findAnnotationMirror(getContext().getEnvironment(), method, annotationType);
+            }
+
+            E parsedMethod = parse(naturalOrder, method, mirror);
+
+            if (method.getModifiers().contains(Modifier.PRIVATE) && parser.isEmitErrors()) {
+                parsedMethod.addError("Method annotated with @%s must not be private.", getAnnotationType().getSimpleName());
+                parsedMethods.add(parsedMethod);
+                valid = false;
+                continue;
+            }
+
+            if (parsedMethod != null) {
+                parsedMethods.add(parsedMethod);
+            } else {
+                valid = false;
+            }
+            naturalOrder++;
+        }
+        Collections.sort(parsedMethods);
+
+        if (!valid && isParseNullOnError()) {
+            return null;
+        }
+        return parsedMethods;
+    }
+
+    private E parse(int naturalOrder, ExecutableElement method, AnnotationMirror annotation) {
+        MethodSpec methodSpecification = createSpecification(method, annotation);
+        if (methodSpecification == null) {
+            return null;
+        }
+
+        TemplateMethod templateMethod = parser.parse(methodSpecification, method, annotation, naturalOrder);
+        if (templateMethod != null) {
+            return create(templateMethod, templateMethod.hasErrors());
+        }
+        return null;
+    }
+
+    public final E create(String id, int naturalOrder, ExecutableElement methodMetadata, AnnotationMirror mirror, TypeMirror returnType, List<TypeMirror> parameterTypes) {
+        TemplateMethod method = parser.parseImpl(createSpecification(methodMetadata, mirror), naturalOrder, id, methodMetadata, mirror, returnType, parameterTypes);
+        if (method != null) {
+            return create(method, method.hasErrors());
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCastParser.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+class TypeCastParser extends TypeSystemMethodParser<TypeCastData> {
+
+    public TypeCastParser(ProcessorContext context, TypeSystemData typeSystem) {
+        super(context, typeSystem);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "as");
+        if (targetType == null) {
+            return null;
+        }
+        MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", targetType.getPrimitiveType()));
+        spec.addRequired(new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors(), getTypeSystem().getTypeIdentifiers()));
+        return spec;
+    }
+
+    @Override
+    public TypeCastData create(TemplateMethod method, boolean invalid) {
+        if (invalid) {
+            return new TypeCastData(method, null, null);
+        }
+
+        TypeData targetType = findTypeByMethodName(method, "as");
+        Parameter parameter = method.findParameter("valueValue");
+
+        TypeData sourceType = null;
+        if (parameter != null) {
+            sourceType = getTypeSystem().findTypeData(parameter.getType());
+        }
+        TypeCastData cast = new TypeCastData(method, sourceType, targetType);
+
+        if (targetType != method.getReturnType().getTypeSystemType()) {
+            cast.addError("Cast type %s does not match to the returned type %s.", ElementUtils.getSimpleName(targetType.getPrimitiveType()),
+                            method.getReturnType() != null ? ElementUtils.getSimpleName(method.getReturnType().getTypeSystemType().getPrimitiveType()) : null);
+        }
+        return cast;
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return TypeCast.class;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCheckParser.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+class TypeCheckParser extends TypeSystemMethodParser<TypeCheckData> {
+
+    public TypeCheckParser(ProcessorContext context, TypeSystemData typeSystem) {
+        super(context, typeSystem);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "is");
+        if (targetType == null) {
+            return null;
+        }
+        MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", getContext().getType(boolean.class)));
+        spec.addRequired(new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors(), getTypeSystem().getTypeIdentifiers()));
+        return spec;
+    }
+
+    @Override
+    public TypeCheckData create(TemplateMethod method, boolean invalid) {
+        TypeData checkedType = findTypeByMethodName(method, "is");
+        assert checkedType != null;
+        Parameter parameter = method.findParameter("valueValue");
+        assert parameter != null;
+        return new TypeCheckData(method, checkedType, parameter.getTypeSystemType());
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return TypeCheck.class;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemMethodParser.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+abstract class TypeSystemMethodParser<E extends TemplateMethod> extends TemplateMethodParser<TypeSystemData, E> {
+
+    public TypeSystemMethodParser(ProcessorContext context, TypeSystemData typeSystem) {
+        super(context, typeSystem);
+    }
+
+    @Override
+    public final boolean isParsable(ExecutableElement method) {
+        return ElementUtils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null;
+    }
+
+    protected TypeData findTypeByMethodName(String methodName, String prefix) {
+        String typeName = methodName.substring(prefix.length(), methodName.length());
+        TypeData type = getTypeSystem().findType(typeName);
+        return type;
+    }
+
+    protected TypeData findTypeByMethodName(TemplateMethod method, String prefix) {
+        String methodName = method.getMethodName();
+        if (!methodName.startsWith(prefix)) {
+            String annotationName = ElementUtils.getSimpleName(method.getMessageAnnotation().getAnnotationType());
+            method.addError("Methods annotated with %s must match the pattern '%s'.", annotationName, String.format("%s${typeName}", prefix));
+            return null;
+        }
+        String typeName = methodName.substring(prefix.length(), methodName.length());
+        TypeData type = getTypeSystem().findType(typeName);
+        if (type == null) {
+            String annotationName = TypeSystem.class.getSimpleName();
+            method.addError("Type '%s' is not declared in this @%s.", typeName, annotationName);
+            return null;
+        }
+
+        return type;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.generator.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class TypeSystemParser extends AbstractParser<TypeSystemData> {
+
+    public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(TypeSystem.class, ExpectError.class);
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return TypeSystem.class;
+    }
+
+    @Override
+    protected TypeSystemData parse(Element element, AnnotationMirror mirror) {
+        TypeElement templateType = (TypeElement) element;
+        AnnotationMirror templateTypeAnnotation = mirror;
+        TypeSystemData typeSystem = new TypeSystemData(context, templateType, templateTypeAnnotation);
+
+        // annotation type on class path!?
+        TypeElement annotationTypeElement = processingEnv.getElementUtils().getTypeElement(getAnnotationType().getCanonicalName());
+        if (annotationTypeElement == null) {
+            typeSystem.addError("Required class %s is not on the classpath.", getAnnotationType().getName());
+        }
+        if (templateType.getModifiers().contains(Modifier.PRIVATE)) {
+            typeSystem.addError("A @%s must have at least package protected visibility.", getAnnotationType().getName());
+        }
+
+        if (templateType.getModifiers().contains(Modifier.FINAL)) {
+            typeSystem.addError("The @%s must not be final.", getAnnotationType().getName());
+        }
+        if (typeSystem.hasErrors()) {
+            return typeSystem;
+        }
+
+        List<TypeData> types = parseTypes(typeSystem);
+
+        TypeMirror genericType = context.getType(Object.class);
+        TypeData voidType = new TypeData(typeSystem, types.size(), null, context.getType(void.class), context.getType(Void.class));
+        types.add(voidType);
+
+        typeSystem.setTypes(types);
+        if (typeSystem.hasErrors()) {
+            return typeSystem;
+        }
+
+        typeSystem.setGenericType(genericType);
+        typeSystem.setVoidType(voidType);
+
+        verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class);
+
+        List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType));
+        List<ImplicitCastData> implicitCasts = new ImplicitCastParser(context, typeSystem).parse(elements);
+        List<TypeCastData> casts = new TypeCastParser(context, typeSystem).parse(elements);
+        List<TypeCheckData> checks = new TypeCheckParser(context, typeSystem).parse(elements);
+
+        if (casts == null || checks == null || implicitCasts == null) {
+            return typeSystem;
+        }
+
+        typeSystem.setImplicitCasts(implicitCasts);
+        typeSystem.setCasts(casts);
+        typeSystem.setChecks(checks);
+
+        if (typeSystem.hasErrors()) {
+            return typeSystem;
+        }
+
+        for (TypeCheckData check : checks) {
+            check.getCheckedType().addTypeCheck(check);
+        }
+
+        for (TypeCastData cast : casts) {
+            cast.getTargetType().addTypeCast(cast);
+        }
+
+        verifyGenericTypeChecksAndCasts(typeSystem);
+        verifyMethodSignatures(typeSystem);
+        verifyNamesUnique(typeSystem);
+
+        return typeSystem;
+    }
+
+    private void verifyExclusiveMethodAnnotation(Template template, Class<?>... annotationTypes) {
+        List<ExecutableElement> methods = ElementFilter.methodsIn(template.getTemplateType().getEnclosedElements());
+        for (ExecutableElement method : methods) {
+            List<AnnotationMirror> foundAnnotations = new ArrayList<>();
+            for (int i = 0; i < annotationTypes.length; i++) {
+                Class<?> annotationType = annotationTypes[i];
+                AnnotationMirror mirror = ElementUtils.findAnnotationMirror(context.getEnvironment(), method, annotationType);
+                if (mirror != null) {
+                    foundAnnotations.add(mirror);
+                }
+            }
+            if (foundAnnotations.size() > 1) {
+                List<String> annotationNames = new ArrayList<>();
+                for (AnnotationMirror mirror : foundAnnotations) {
+                    annotationNames.add("@" + ElementUtils.getSimpleName(mirror.getAnnotationType()));
+                }
+
+                template.addError("Non exclusive usage of annotations %s.", annotationNames);
+            }
+        }
+    }
+
+    private static void verifyGenericTypeChecksAndCasts(TypeSystemData typeSystem) {
+        for (TypeData type : typeSystem.getTypes()) {
+            if (!type.getTypeChecks().isEmpty()) {
+                boolean hasGeneric = false;
+                for (TypeCheckData typeCheck : type.getTypeChecks()) {
+                    if (typeCheck.isGeneric()) {
+                        hasGeneric = true;
+                        break;
+                    }
+                }
+                if (!hasGeneric) {
+                    type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.",
+                                    TypeCheck.class.getSimpleName(), TypeSystemCodeGenerator.isTypeMethodName(type), ElementUtils.getSimpleName(type.getBoxedType()), TypeCheck.class.getSimpleName(),
+                                    Object.class.getSimpleName());
+                }
+            }
+            if (!type.getTypeCasts().isEmpty()) {
+                boolean hasGeneric = false;
+                for (TypeCastData typeCast : type.getTypeCasts()) {
+                    if (typeCast.isGeneric()) {
+                        hasGeneric = true;
+                        break;
+                    }
+                }
+                if (!hasGeneric) {
+                    type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.",
+                                    TypeCast.class.getSimpleName(), TypeSystemCodeGenerator.asTypeMethodName(type), ElementUtils.getSimpleName(type.getBoxedType()), TypeCast.class.getSimpleName(),
+                                    Object.class.getSimpleName());
+                }
+            }
+        }
+    }
+
+    private List<TypeData> parseTypes(TypeSystemData typeSystem) {
+        List<TypeData> types = new ArrayList<>();
+        List<TypeMirror> typeMirrors = ElementUtils.getAnnotationValueList(TypeMirror.class, typeSystem.getTemplateTypeAnnotation(), "value");
+        if (typeMirrors.isEmpty()) {
+            typeSystem.addError("At least one type must be defined.");
+            return types;
+        }
+
+        final AnnotationValue annotationValue = ElementUtils.getAnnotationValue(typeSystem.getTemplateTypeAnnotation(), "value");
+        final TypeMirror objectType = context.getType(Object.class);
+
+        int index = 0;
+        for (TypeMirror primitiveType : typeMirrors) {
+            TypeMirror primitive = ElementUtils.fillInGenericWildcards(primitiveType);
+
+            TypeMirror boxedType = ElementUtils.boxType(context, primitive);
+            TypeData typeData = new TypeData(typeSystem, index, annotationValue, primitive, boxedType);
+
+            if (isPrimitiveWrapper(primitive)) {
+                typeData.addError("Types must not contain primitive wrapper types.");
+            }
+
+            if (ElementUtils.typeEquals(boxedType, objectType)) {
+                typeData.addError("Types must not contain the generic type java.lang.Object.");
+            }
+
+            types.add(typeData);
+            index++;
+        }
+
+        verifyTypeOrder(types);
+
+        types.add(new TypeData(typeSystem, index, annotationValue, objectType, objectType));
+        return types;
+    }
+
+    private static void verifyTypeOrder(List<TypeData> types) {
+        Map<String, List<String>> invalidTypes = new HashMap<>();
+
+        for (int i = types.size() - 1; i >= 0; i--) {
+            TypeData typeData = types.get(i);
+            TypeMirror type = typeData.getBoxedType();
+            if (invalidTypes.containsKey(ElementUtils.getQualifiedName(type))) {
+                typeData.addError("Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", invalidTypes.get(ElementUtils.getQualifiedName(type)),
+                                ElementUtils.getQualifiedName(type));
+            }
+            List<String> nextInvalidTypes = ElementUtils.getQualifiedSuperTypeNames(ElementUtils.fromTypeMirror(type));
+            nextInvalidTypes.add(getQualifiedName(type));
+
+            for (String qualifiedName : nextInvalidTypes) {
+                List<String> inheritedTypes = invalidTypes.get(qualifiedName);
+                if (inheritedTypes == null) {
+                    inheritedTypes = new ArrayList<>();
+                    invalidTypes.put(qualifiedName, inheritedTypes);
+                }
+                inheritedTypes.add(ElementUtils.getQualifiedName(typeData.getBoxedType()));
+            }
+        }
+    }
+
+    private boolean isPrimitiveWrapper(TypeMirror type) {
+        Types types = context.getEnvironment().getTypeUtils();
+        for (TypeKind kind : TypeKind.values()) {
+            if (!kind.isPrimitive()) {
+                continue;
+            }
+            if (ElementUtils.typeEquals(type, types.boxedClass(types.getPrimitiveType(kind)).asType())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void verifyMethodSignatures(TypeSystemData typeSystem) {
+        Set<String> generatedIsMethodNames = new HashSet<>();
+        Set<String> generatedAsMethodNames = new HashSet<>();
+        Set<String> generatedExpectMethodNames = new HashSet<>();
+
+        for (TypeData typeData : typeSystem.getTypes()) {
+            generatedIsMethodNames.add(TypeSystemCodeGenerator.isTypeMethodName(typeData));
+            generatedAsMethodNames.add(TypeSystemCodeGenerator.asTypeMethodName(typeData));
+            generatedExpectMethodNames.add(TypeSystemCodeGenerator.expectTypeMethodName(typeData));
+        }
+
+        List<ExecutableElement> methods = ElementFilter.methodsIn(typeSystem.getTemplateType().getEnclosedElements());
+        for (ExecutableElement method : methods) {
+            if (method.getModifiers().contains(Modifier.PRIVATE)) {
+                // will not conflict overridden methods
+                continue;
+            } else if (method.getParameters().size() != 1) {
+                continue;
+            }
+            String methodName = method.getSimpleName().toString();
+            if (generatedIsMethodNames.contains(methodName)) {
+                verifyIsMethod(typeSystem, method);
+            } else if (generatedAsMethodNames.contains(methodName)) {
+                verifyAsMethod(typeSystem, method);
+            } else if (generatedExpectMethodNames.contains(methodName)) {
+                verifyExpectMethod(typeSystem);
+            }
+        }
+    }
+
+    private boolean verifyIsMethod(TypeSystemData typeSystem, ExecutableElement method) {
+        AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, TypeCheck.class);
+        if (mirror == null) {
+            typeSystem.addError("Method starting with the pattern is${typeName} must be annotated with @%s.", TypeCheck.class.getSimpleName());
+            return false;
+        }
+        return true;
+    }
+
+    private boolean verifyAsMethod(TypeSystemData typeSystem, ExecutableElement method) {
+        AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, TypeCast.class);
+        if (mirror == null) {
+            typeSystem.addError("Method starting with the pattern as${typeName} must be annotated with @%s.", TypeCast.class.getSimpleName());
+            return false;
+        }
+        return true;
+    }
+
+    private static boolean verifyExpectMethod(TypeSystemData typeSystem) {
+        typeSystem.addError("Method starting with the pattern expect${typeName} must not be declared manually.");
+        return false;
+    }
+
+    private static void verifyNamesUnique(TypeSystemData typeSystem) {
+        List<TypeData> types = typeSystem.getTypes();
+        for (int i = 0; i < types.size(); i++) {
+            for (int j = i + 1; j < types.size(); j++) {
+                String name1 = ElementUtils.getSimpleName(types.get(i).getBoxedType());
+                String name2 = ElementUtils.getSimpleName(types.get(j).getBoxedType());
+                if (name1.equalsIgnoreCase(name2)) {
+                    typeSystem.addError("Two types result in the same name: %s, %s.", name1, name2);
+                }
+            }
+        }
+    }
+}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.template;
-
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public class ActualParameter {
-
-    private final ParameterSpec specification;
-    private TypeData typeSystemType;
-    private TemplateMethod method;
-    private final String localName;
-    private final int specificationVarArgsIndex;
-    private final int typeVarArgsIndex;
-    private final TypeMirror actualType;
-
-    public ActualParameter(ParameterSpec specification, TypeMirror actualType, int specificationVarArgsIndex, int typeVarArgsIndex) {
-        this.specification = specification;
-        this.actualType = actualType;
-        this.typeSystemType = null;
-
-        this.specificationVarArgsIndex = specificationVarArgsIndex;
-
-        String valueName = specification.getName() + "Value";
-        if (specificationVarArgsIndex > -1) {
-            valueName += specificationVarArgsIndex;
-        }
-        this.typeVarArgsIndex = typeVarArgsIndex;
-        this.localName = valueName;
-    }
-
-    public ActualParameter(ParameterSpec specification, TypeData actualType, int specificationIndex, int varArgsIndex) {
-        this(specification, actualType.getPrimitiveType(), specificationIndex, varArgsIndex);
-        this.typeSystemType = actualType;
-    }
-
-    public ActualParameter(ActualParameter parameter, TypeData otherType) {
-        this(parameter.specification, otherType, parameter.specificationVarArgsIndex, parameter.typeVarArgsIndex);
-    }
-
-    public ActualParameter(ActualParameter parameter) {
-        this.specification = parameter.specification;
-        this.actualType = parameter.actualType;
-        this.typeSystemType = parameter.typeSystemType;
-        this.specificationVarArgsIndex = parameter.specificationVarArgsIndex;
-        this.localName = parameter.localName;
-        this.typeVarArgsIndex = parameter.typeVarArgsIndex;
-    }
-
-    public int getTypeVarArgsIndex() {
-        return typeVarArgsIndex;
-    }
-
-    public int getSpecificationVarArgsIndex() {
-        return specificationVarArgsIndex;
-    }
-
-    public String getLocalName() {
-        return localName;
-    }
-
-    void setMethod(TemplateMethod method) {
-        this.method = method;
-    }
-
-    public ParameterSpec getSpecification() {
-        return specification;
-    }
-
-    public TemplateMethod getMethod() {
-        return method;
-    }
-
-    public TypeMirror getType() {
-        return actualType;
-    }
-
-    public TypeData getTypeSystemType() {
-        return typeSystemType;
-    }
-
-    public boolean isTypeVarArgs() {
-        return typeVarArgsIndex >= 0;
-    }
-
-    public ActualParameter getPreviousParameter() {
-        return method.getPreviousParam(this);
-    }
-
-    @Override
-    public String toString() {
-        return Utils.getSimpleName(actualType);
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ClassElementFactory.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.template;
-
-import static com.oracle.truffle.dsl.processor.Utils.*;
-import static javax.lang.model.element.Modifier.*;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.ast.*;
-
-public abstract class ClassElementFactory<M> extends CodeElementFactory<M> {
-
-    public ClassElementFactory(ProcessorContext context) {
-        super(context);
-    }
-
-    @Override
-    protected abstract CodeTypeElement create(M m);
-
-    @Override
-    public CodeTypeElement getElement() {
-        return (CodeTypeElement) super.getElement();
-    }
-
-    protected CodeExecutableElement createConstructorUsingFields(Set<Modifier> modifiers, CodeTypeElement clazz) {
-        CodeExecutableElement method = new CodeExecutableElement(modifiers, null, clazz.getSimpleName().toString());
-        CodeTreeBuilder builder = method.createBuilder();
-        TypeElement superClass = fromTypeMirror(clazz.getSuperclass());
-        ExecutableElement constructor = findConstructor(superClass);
-        if (constructor != null && constructor.getParameters().size() > 0) {
-            builder.startStatement();
-            builder.startSuperCall();
-            for (VariableElement parameter : constructor.getParameters()) {
-                method.addParameter(new CodeVariableElement(parameter.asType(), parameter.getSimpleName().toString()));
-                builder.string(parameter.getSimpleName().toString());
-            }
-            builder.end(); // super
-            builder.end(); // statement
-        }
-
-        for (VariableElement field : clazz.getFields()) {
-            if (field.getModifiers().contains(STATIC)) {
-                continue;
-            }
-            String fieldName = field.getSimpleName().toString();
-            method.addParameter(new CodeVariableElement(field.asType(), fieldName));
-            builder.startStatement();
-            builder.string("this.");
-            builder.string(fieldName);
-            builder.string(" = ");
-            if (isAssignable(getContext(), field.asType(), getContext().getTruffleTypes().getNode())) {
-                builder.string("adoptChild(").string(fieldName).string(")");
-            } else {
-                builder.string(fieldName);
-            }
-            builder.end(); // statement
-        }
-
-        return method;
-    }
-
-    private static ExecutableElement findConstructor(TypeElement clazz) {
-        List<ExecutableElement> constructors = ElementFilter.constructorsIn(clazz.getEnclosedElements());
-        if (constructors.isEmpty()) {
-            return null;
-        } else {
-            return constructors.get(0);
-        }
-    }
-
-    protected CodeExecutableElement createSuperConstructor(TypeElement type, ExecutableElement element) {
-        if (element.getModifiers().contains(Modifier.PRIVATE)) {
-            return null;
-        }
-        CodeExecutableElement executable = CodeExecutableElement.clone(getContext().getEnvironment(), element);
-        executable.setReturnType(null);
-        executable.setSimpleName(CodeNames.of(type.getSimpleName().toString()));
-        CodeTreeBuilder b = executable.createBuilder();
-        b.startStatement();
-        b.startSuperCall();
-        for (VariableElement v : element.getParameters()) {
-            b.string(v.getSimpleName().toString());
-        }
-        b.end();
-        b.end();
-
-        return executable;
-    }
-
-    protected CodeTypeElement createClass(Template model, Set<Modifier> modifiers, String simpleName, TypeMirror superType, boolean enumType) {
-        TypeElement templateType = model.getTemplateType();
-
-        PackageElement pack = getContext().getEnvironment().getElementUtils().getPackageOf(templateType);
-        CodeTypeElement clazz = new CodeTypeElement(modifiers, enumType ? ElementKind.ENUM : ElementKind.CLASS, pack, simpleName);
-        TypeMirror resolvedSuperType = superType;
-        if (resolvedSuperType == null) {
-            resolvedSuperType = getContext().getType(Object.class);
-        }
-        clazz.setSuperClass(resolvedSuperType);
-
-        CodeAnnotationMirror generatedByAnnotation = new CodeAnnotationMirror((DeclaredType) getContext().getType(GeneratedBy.class));
-        generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("value"), new CodeAnnotationValue(templateType.asType()));
-        if (model.getTemplateMethodName() != null) {
-            generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("methodName"), new CodeAnnotationValue(model.getTemplateMethodName()));
-        }
-
-        clazz.addAnnotationMirror(generatedByAnnotation);
-
-        context.registerType(model.getTemplateType(), clazz.asType());
-
-        return clazz;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/CodeElementFactory.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.template;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.ast.*;
-
-public abstract class CodeElementFactory<M> {
-
-    protected final ProcessorContext context;
-    private M model;
-
-    private CodeElement<? super Element> element;
-
-    public CodeElementFactory(ProcessorContext context) {
-        this.context = context;
-    }
-
-    protected abstract CodeElement<?> create(M m);
-
-    @SuppressWarnings("unused")
-    protected void createChildren(M m) {
-    }
-
-    @SuppressWarnings({"unchecked", "rawtypes"})
-    public CodeElement<?> process(CodeElement parent, M m) {
-        model = m;
-        element = (CodeElement<? super Element>) create(model);
-        if (parent != null) {
-            parent.add(element);
-        }
-        if (element != null) {
-            createChildren(model);
-        }
-        return element;
-    }
-
-    @SuppressWarnings("rawtypes")
-    public CodeElement getElement() {
-        return element;
-    }
-
-    protected <MO, K extends Element> void add(CodeElementFactory<MO> factory, MO m) {
-        factory.process(this.element, m);
-    }
-
-    public ProcessorContext getContext() {
-        return context;
-    }
-
-    public M getModel() {
-        return model;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/CompilationUnitFactory.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.template;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.ast.*;
-
-public abstract class CompilationUnitFactory<M> extends CodeElementFactory<M> {
-
-    public CompilationUnitFactory(ProcessorContext context) {
-        super(context);
-    }
-
-    @Override
-    public final CodeCompilationUnit create(M m) {
-        return new CodeCompilationUnit();
-    }
-
-    @SuppressWarnings("rawtypes")
-    @Override
-    public CodeCompilationUnit process(CodeElement parent, M m) {
-        return (CodeCompilationUnit) super.process(parent, m);
-    }
-
-    @Override
-    protected abstract void createChildren(M m);
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,276 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.template;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.tools.Diagnostic.Kind;
-
-import com.oracle.truffle.dsl.processor.*;
-
-public abstract class MessageContainer {
-
-    private final List<Message> messages = new ArrayList<>();
-
-    public final void addWarning(String text, Object... params) {
-        getMessages().add(new Message(null, this, String.format(text, params), Kind.WARNING));
-    }
-
-    public final void addError(String text, Object... params) {
-        addError(null, text, params);
-    }
-
-    public final void addError(AnnotationValue value, String text, Object... params) {
-        getMessages().add(new Message(value, this, String.format(text, params), Kind.ERROR));
-    }
-
-    protected List<MessageContainer> findChildContainers() {
-        return Collections.emptyList();
-    }
-
-    public abstract Element getMessageElement();
-
-    public final void emitMessages(ProcessorContext context, TypeElement baseElement, Log log) {
-        emitMessagesImpl(context, baseElement, log, new HashSet<MessageContainer>(), null);
-    }
-
-    private void emitMessagesImpl(ProcessorContext context, TypeElement baseElement, Log log, Set<MessageContainer> visitedSinks, List<Message> verifiedMessages) {
-        List<Message> childMessages;
-        if (verifiedMessages == null) {
-            childMessages = collectMessagesWithElementChildren(new HashSet<MessageContainer>(), getMessageElement());
-        } else {
-            childMessages = verifiedMessages;
-        }
-        verifyExpectedMessages(context, log, childMessages);
-
-        for (int i = getMessages().size() - 1; i >= 0; i--) {
-            emitDefault(context, baseElement, log, getMessages().get(i));
-        }
-
-        for (MessageContainer sink : findChildContainers()) {
-            if (visitedSinks.contains(sink)) {
-                continue;
-            }
-
-            visitedSinks.add(sink);
-            if (sink.getMessageElement() == this.getMessageElement()) {
-                sink.emitMessagesImpl(context, baseElement, log, visitedSinks, childMessages);
-            } else {
-                sink.emitMessagesImpl(context, baseElement, log, visitedSinks, null);
-            }
-        }
-    }
-
-    private List<Message> collectMessagesWithElementChildren(Set<MessageContainer> visitedSinks, Element e) {
-        if (visitedSinks.contains(this)) {
-            return Collections.emptyList();
-        }
-        visitedSinks.add(this);
-
-        List<Message> foundMessages = new ArrayList<>();
-        if (Utils.typeEquals(getMessageElement().asType(), e.asType())) {
-            foundMessages.addAll(getMessages());
-        }
-        for (MessageContainer sink : findChildContainers()) {
-            foundMessages.addAll(sink.collectMessagesWithElementChildren(visitedSinks, e));
-        }
-        return foundMessages;
-    }
-
-    private void verifyExpectedMessages(ProcessorContext context, Log log, List<Message> msgs) {
-        TypeElement expectError = context.getTruffleTypes().getExpectError();
-        if (expectError != null) {
-            Element element = getMessageElement();
-            AnnotationMirror mirror = Utils.findAnnotationMirror(element.getAnnotationMirrors(), expectError);
-            if (mirror != null) {
-                List<String> values = Utils.getAnnotationValueList(String.class, mirror, "value");
-                if (values == null) {
-                    values = Collections.emptyList();
-                }
-                if (values.size() != msgs.size()) {
-                    log.message(Kind.ERROR, element, mirror, Utils.getAnnotationValue(mirror, "value"), String.format("Error count expected %s but was %s.", values.size(), msgs.size()));
-                }
-            }
-        }
-    }
-
-    private void emitDefault(ProcessorContext context, TypeElement baseType, Log log, Message message) {
-        Kind kind = message.getKind();
-
-        Element messageElement = getMessageElement();
-        AnnotationMirror messageAnnotation = getMessageAnnotation();
-        AnnotationValue messageValue = getMessageAnnotationValue();
-        if (message.getAnnotationValue() != null) {
-            messageValue = message.getAnnotationValue();
-        }
-
-        String text = message.getText();
-
-        TypeElement rootEnclosing = Utils.findRootEnclosingType(getMessageElement());
-        TypeElement baseEnclosing = Utils.findRootEnclosingType(baseType);
-        if (rootEnclosing == null || !Utils.typeEquals(baseEnclosing.asType(), rootEnclosing.asType())) {
-            // redirect message
-            MessageContainer original = message.getOriginalContainer();
-            messageElement = baseType;
-            messageAnnotation = null;
-            messageValue = null;
-            text = wrapText(original.getMessageElement(), original.getMessageAnnotation(), message.getText());
-        }
-
-        TypeElement expectError = context.getTruffleTypes().getExpectError();
-        if (expectError != null) {
-            AnnotationMirror mirror = Utils.findAnnotationMirror(messageElement.getAnnotationMirrors(), expectError);
-            if (mirror != null) {
-                List<String> expectedTexts = Utils.getAnnotationValueList(String.class, mirror, "value");
-                boolean found = false;
-                for (String expectedText : expectedTexts) {
-                    if (expectedText.endsWith("%") && text.startsWith(expectedText.substring(0, expectedText.length() - 1))) {
-                        found = true;
-                        break;
-                    } else if (text.equals(expectedText)) {
-                        found = true;
-                        break;
-                    }
-                }
-                if (!found) {
-                    log.message(kind, messageElement, mirror, Utils.getAnnotationValue(mirror, "value"), "Message expected one of '%s' but was '%s'.", expectedTexts, text);
-                } else {
-                    return;
-                }
-
-            }
-        }
-
-        log.message(kind, messageElement, messageAnnotation, messageValue, text);
-    }
-
-    private static String wrapText(Element element, AnnotationMirror mirror, String text) {
-        StringBuilder b = new StringBuilder();
-        if (element != null) {
-            b.append("Element " + element.toString());
-        }
-        if (mirror != null) {
-            b.append(" at annotation @" + Utils.getSimpleName(mirror.getAnnotationType()));
-        }
-
-        if (b.length() > 0) {
-            b.append(" is erroneous: ").append(text);
-            return b.toString();
-        } else {
-            return text;
-        }
-    }
-
-    public AnnotationMirror getMessageAnnotation() {
-        return null;
-    }
-
-    public AnnotationValue getMessageAnnotationValue() {
-        return null;
-    }
-
-    public final boolean hasErrors() {
-        return hasErrorsImpl(new HashSet<MessageContainer>());
-    }
-
-    public final List<Message> collectMessages() {
-        List<Message> collectedMessages = new ArrayList<>();
-        collectMessagesImpl(collectedMessages, new HashSet<MessageContainer>());
-        return collectedMessages;
-    }
-
-    private void collectMessagesImpl(List<Message> collectedMessages, Set<MessageContainer> visitedSinks) {
-        collectedMessages.addAll(getMessages());
-        for (MessageContainer sink : findChildContainers()) {
-            if (visitedSinks.contains(sink)) {
-                return;
-            }
-
-            visitedSinks.add(sink);
-            sink.collectMessagesImpl(collectedMessages, visitedSinks);
-        }
-    }
-
-    private boolean hasErrorsImpl(Set<MessageContainer> visitedSinks) {
-        for (Message msg : getMessages()) {
-            if (msg.getKind() == Kind.ERROR) {
-                return true;
-            }
-        }
-        for (MessageContainer sink : findChildContainers()) {
-            if (visitedSinks.contains(sink)) {
-                return false;
-            }
-
-            visitedSinks.add(sink);
-
-            if (sink.hasErrorsImpl(visitedSinks)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public List<Message> getMessages() {
-        return messages;
-    }
-
-    public static final class Message {
-
-        private final MessageContainer originalContainer;
-        private final AnnotationValue annotationValue;
-        private final String text;
-        private final Kind kind;
-
-        public Message(AnnotationValue annotationValue, MessageContainer originalContainer, String text, Kind kind) {
-            this.annotationValue = annotationValue;
-            this.originalContainer = originalContainer;
-            this.text = text;
-            this.kind = kind;
-        }
-
-        public AnnotationValue getAnnotationValue() {
-            return annotationValue;
-        }
-
-        public MessageContainer getOriginalContainer() {
-            return originalContainer;
-        }
-
-        public String getText() {
-            return text;
-        }
-
-        public Kind getKind() {
-            return kind;
-        }
-
-        @Override
-        public String toString() {
-            return kind + ": " + text;
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MethodSpec.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,239 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.template;
-
-import java.util.*;
-
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-
-public class MethodSpec {
-
-    private final ParameterSpec returnType;
-    private final List<ParameterSpec> optional = new ArrayList<>();
-    private final List<ParameterSpec> required = new ArrayList<>();
-
-    private boolean ignoreAdditionalParameters;
-    private boolean ignoreAdditionalSpecifications;
-    private boolean variableRequiredParameters;
-
-    private List<TypeDef> typeDefinitions;
-
-    public MethodSpec(ParameterSpec returnType) {
-        this.returnType = returnType;
-    }
-
-    public void setVariableRequiredParameters(boolean variableRequiredParameters) {
-        this.variableRequiredParameters = variableRequiredParameters;
-    }
-
-    public boolean isVariableRequiredParameters() {
-        return variableRequiredParameters;
-    }
-
-    public void setIgnoreAdditionalParameters(boolean ignoreAdditionalParameter) {
-        this.ignoreAdditionalParameters = ignoreAdditionalParameter;
-    }
-
-    public boolean isIgnoreAdditionalParameters() {
-        return ignoreAdditionalParameters;
-    }
-
-    public void addOptional(ParameterSpec spec) {
-        optional.add(spec);
-    }
-
-    public ParameterSpec addRequired(ParameterSpec spec) {
-        required.add(spec);
-        return spec;
-    }
-
-    public ParameterSpec getReturnType() {
-        return returnType;
-    }
-
-    public List<ParameterSpec> getRequired() {
-        return required;
-    }
-
-    public List<ParameterSpec> getOptional() {
-        return optional;
-    }
-
-    public List<ParameterSpec> getAll() {
-        List<ParameterSpec> specs = new ArrayList<>();
-        specs.add(getReturnType());
-        specs.addAll(getOptional());
-        specs.addAll(getRequired());
-        return specs;
-    }
-
-    public ParameterSpec findParameterSpec(String name) {
-        for (ParameterSpec spec : getAll()) {
-            if (spec.getName().equals(name)) {
-                return spec;
-            }
-        }
-        return null;
-    }
-
-    public void applyTypeDefinitions(String prefix) {
-        this.typeDefinitions = createTypeDefinitions(prefix);
-    }
-
-    private List<TypeDef> createTypeDefinitions(String prefix) {
-        List<TypeDef> typeDefs = new ArrayList<>();
-
-        int defIndex = 0;
-        for (ParameterSpec spec : getAll()) {
-            List<TypeMirror> allowedTypes = spec.getAllowedTypes();
-            List<TypeMirror> types = spec.getAllowedTypes();
-            if (types != null && allowedTypes.size() > 1) {
-                TypeDef foundDef = null;
-                for (TypeDef def : typeDefs) {
-                    if (allowedTypes.equals(def.getTypes())) {
-                        foundDef = def;
-                        break;
-                    }
-                }
-                if (foundDef == null) {
-                    foundDef = new TypeDef(types, prefix + defIndex);
-                    typeDefs.add(foundDef);
-                    defIndex++;
-                }
-
-                spec.setTypeDefinition(foundDef);
-            }
-        }
-
-        return typeDefs;
-    }
-
-    public String toSignatureString(String methodName) {
-        StringBuilder b = new StringBuilder();
-        b.append("    ");
-        b.append(createTypeSignature(returnType, true));
-
-        b.append(" ");
-        b.append(methodName);
-        b.append("(");
-
-        String sep = "";
-
-        for (ParameterSpec optionalSpec : getOptional()) {
-            b.append(sep);
-            b.append("[");
-            b.append(createTypeSignature(optionalSpec, false));
-            b.append("]");
-            sep = ", ";
-        }
-
-        for (int i = 0; i < getRequired().size(); i++) {
-            ParameterSpec requiredSpec = getRequired().get(i);
-            b.append(sep);
-
-            if (isVariableRequiredParameters() && i == getRequired().size() - 1) {
-                b.append(("{"));
-            }
-            b.append(createTypeSignature(requiredSpec, false));
-            if (isVariableRequiredParameters() && i == getRequired().size() - 1) {
-                b.append(("}"));
-            }
-
-            sep = ", ";
-        }
-
-        b.append(")");
-
-        if (typeDefinitions != null && !typeDefinitions.isEmpty()) {
-            b.append("\n\n");
-
-            String lineSep = "";
-            for (TypeDef def : typeDefinitions) {
-                b.append(lineSep);
-                b.append("    <").append(def.getName()).append(">");
-                b.append(" = {");
-                String separator = "";
-                for (TypeMirror type : def.getTypes()) {
-                    b.append(separator).append(Utils.getSimpleName(type));
-                    separator = ", ";
-                }
-                b.append("}");
-                lineSep = "\n";
-
-            }
-        }
-        return b.toString();
-    }
-
-    private static String createTypeSignature(ParameterSpec spec, boolean typeOnly) {
-        StringBuilder builder = new StringBuilder();
-        TypeDef foundTypeDef = spec.getTypeDefinition();
-        if (foundTypeDef != null) {
-            builder.append("<" + foundTypeDef.getName() + ">");
-        } else if (spec.getAllowedTypes().size() >= 1) {
-            builder.append(Utils.getSimpleName(spec.getAllowedTypes().get(0)));
-        } else {
-            builder.append("void");
-        }
-        if (!typeOnly) {
-            builder.append(" ");
-            builder.append(spec.getName());
-        }
-        return builder.toString();
-    }
-
-    @Override
-    public String toString() {
-        return toSignatureString("methodName");
-    }
-
-    static class TypeDef {
-
-        private final List<TypeMirror> types;
-        private final String name;
-
-        public TypeDef(List<TypeMirror> types, String name) {
-            this.types = types;
-            this.name = name;
-        }
-
-        public List<TypeMirror> getTypes() {
-            return types;
-        }
-
-        public String getName() {
-            return name;
-        }
-    }
-
-    public void setIgnoreAdditionalSpecifications(boolean ignoreAdditoinalSpecifications) {
-        this.ignoreAdditionalSpecifications = ignoreAdditoinalSpecifications;
-    }
-
-    public boolean isIgnoreAdditionalSpecifications() {
-        return ignoreAdditionalSpecifications;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ParameterSpec.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.template;
-
-import java.util.*;
-
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.*;
-import com.oracle.truffle.dsl.processor.template.MethodSpec.TypeDef;
-
-public class ParameterSpec {
-
-    private final String name;
-    private final List<TypeMirror> allowedTypes;
-
-    /** Type is bound to local final variable. */
-    private boolean local;
-    private boolean signature;
-
-    /** Optional bound execution of node. */
-    private NodeExecutionData execution;
-    private TypeDef typeDefinition;
-
-    public ParameterSpec(String name, List<TypeMirror> allowedTypes) {
-        this.name = name;
-        this.allowedTypes = allowedTypes;
-    }
-
-    public ParameterSpec(String name, TypeMirror type) {
-        this(name, Arrays.asList(type));
-    }
-
-    public ParameterSpec(ParameterSpec o, List<TypeMirror> allowedTypes) {
-        this.name = o.name;
-        this.local = o.local;
-        this.typeDefinition = o.typeDefinition;
-        this.execution = o.execution;
-        this.signature = o.signature;
-        this.allowedTypes = allowedTypes;
-    }
-
-    public NodeExecutionData getExecution() {
-        return execution;
-    }
-
-    public void setExecution(NodeExecutionData executionData) {
-        this.execution = executionData;
-        this.signature = execution != null;
-    }
-
-    public void setSignature(boolean signature) {
-        this.signature = signature;
-    }
-
-    void setTypeDefinition(TypeDef typeDefinition) {
-        this.typeDefinition = typeDefinition;
-    }
-
-    TypeDef getTypeDefinition() {
-        return typeDefinition;
-    }
-
-    public void setLocal(boolean local) {
-        this.local = local;
-    }
-
-    public boolean isSignature() {
-        return signature;
-    }
-
-    public boolean isLocal() {
-        return local;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public List<TypeMirror> getAllowedTypes() {
-        return allowedTypes;
-    }
-
-    public boolean matches(TypeMirror actualType) {
-        for (TypeMirror mirror : allowedTypes) {
-            if (Utils.typeEquals(actualType, mirror)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public String toString() {
-        return toSignatureString(false);
-    }
-
-    public String toSignatureString(boolean typeOnly) {
-        StringBuilder builder = new StringBuilder();
-        if (typeDefinition != null) {
-            builder.append("<" + typeDefinition.getName() + ">");
-        } else if (getAllowedTypes().size() >= 1) {
-            builder.append(Utils.getSimpleName(getAllowedTypes().get(0)));
-        } else {
-            builder.append("void");
-        }
-        if (!typeOnly) {
-            builder.append(" ");
-            builder.append(getName());
-        }
-        return builder.toString();
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/Template.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.template;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public abstract class Template extends MessageContainer {
-
-    private final TypeElement templateType;
-    private final String templateMethodName;
-    private final AnnotationMirror annotation;
-
-    public Template(TypeElement templateType, String templateMethodName, AnnotationMirror annotation) {
-        this.templateType = templateType;
-        this.templateMethodName = templateMethodName;
-        this.annotation = annotation;
-    }
-
-    public abstract TypeSystemData getTypeSystem();
-
-    @Override
-    public Element getMessageElement() {
-        return templateType;
-    }
-
-    @Override
-    protected List<MessageContainer> findChildContainers() {
-        return Collections.emptyList();
-    }
-
-    public String getTemplateMethodName() {
-        return templateMethodName;
-    }
-
-    public TypeElement getTemplateType() {
-        return templateType;
-    }
-
-    public AnnotationMirror getTemplateTypeAnnotation() {
-        return annotation;
-    }
-
-    @Override
-    public String toString() {
-        return getClass().getSimpleName() + "[" + Utils.getSimpleName(getTemplateType()) + "]";
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,489 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.template;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-import com.oracle.truffle.dsl.processor.util.*;
-
-/**
- * Note: this class has a natural ordering that is inconsistent with equals.
- */
-public class TemplateMethod extends MessageContainer implements Comparable<TemplateMethod> {
-
-    private String id;
-    private final Template template;
-    private final MethodSpec specification;
-    private final ExecutableElement method;
-    private final AnnotationMirror markerAnnotation;
-    private ActualParameter returnType;
-    private List<ActualParameter> parameters;
-
-    public TemplateMethod(String id, Template template, MethodSpec specification, ExecutableElement method, AnnotationMirror markerAnnotation, ActualParameter returnType,
-                    List<ActualParameter> parameters) {
-        this.template = template;
-        this.specification = specification;
-        this.method = method;
-        this.markerAnnotation = markerAnnotation;
-        this.returnType = returnType;
-        this.parameters = new ArrayList<>();
-        for (ActualParameter param : parameters) {
-            ActualParameter newParam = new ActualParameter(param);
-            this.parameters.add(newParam);
-            newParam.setMethod(this);
-        }
-        this.id = id;
-    }
-
-    public TemplateMethod(TemplateMethod method) {
-        this(method.id, method.template, method.specification, method.method, method.markerAnnotation, method.returnType, method.parameters);
-        getMessages().addAll(method.getMessages());
-    }
-
-    public TemplateMethod(TemplateMethod method, ExecutableElement executable) {
-        this(method.id, method.template, method.specification, executable, method.markerAnnotation, method.returnType, method.parameters);
-        getMessages().addAll(method.getMessages());
-    }
-
-    public void setParameters(List<ActualParameter> parameters) {
-        this.parameters = parameters;
-    }
-
-    @Override
-    public Element getMessageElement() {
-        return method;
-    }
-
-    @Override
-    public AnnotationMirror getMessageAnnotation() {
-        return markerAnnotation;
-    }
-
-    @Override
-    protected List<MessageContainer> findChildContainers() {
-        return Collections.emptyList();
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getId() {
-        return id;
-    }
-
-    public Template getTemplate() {
-        return template;
-    }
-
-    public MethodSpec getSpecification() {
-        return specification;
-    }
-
-    public ActualParameter getReturnType() {
-        return returnType;
-    }
-
-    public void replaceParameter(String localName, ActualParameter newParameter) {
-        if (returnType.getLocalName().equals(localName)) {
-            returnType = newParameter;
-            returnType.setMethod(this);
-        }
-
-        for (ListIterator<ActualParameter> iterator = parameters.listIterator(); iterator.hasNext();) {
-            ActualParameter parameter = iterator.next();
-            if (parameter.getLocalName().equals(localName)) {
-                iterator.set(newParameter);
-                newParameter.setMethod(this);
-            }
-        }
-    }
-
-    public List<ActualParameter> getRequiredParameters() {
-        List<ActualParameter> requiredParameters = new ArrayList<>();
-        for (ActualParameter parameter : getParameters()) {
-            if (getSpecification().getRequired().contains(parameter.getSpecification())) {
-                requiredParameters.add(parameter);
-            }
-        }
-        return requiredParameters;
-    }
-
-    public Iterable<ActualParameter> getSignatureParameters() {
-        return new FilteredIterable<>(getParameters(), new Predicate<ActualParameter>() {
-            public boolean evaluate(ActualParameter value) {
-                return value.getSpecification().isSignature();
-            }
-        });
-    }
-
-    public List<ActualParameter> getParameters() {
-        return parameters;
-    }
-
-    public List<ActualParameter> findParameters(ParameterSpec spec) {
-        List<ActualParameter> foundParameters = new ArrayList<>();
-        for (ActualParameter param : getReturnTypeAndParameters()) {
-            if (param.getSpecification().getName().equals(spec.getName())) {
-                foundParameters.add(param);
-            }
-        }
-        return foundParameters;
-    }
-
-    public ActualParameter findParameter(String valueName) {
-        for (ActualParameter param : getReturnTypeAndParameters()) {
-            if (param.getLocalName().equals(valueName)) {
-                return param;
-            }
-        }
-        return null;
-    }
-
-    public List<ActualParameter> getReturnTypeAndParameters() {
-        List<ActualParameter> allParameters = new ArrayList<>(getParameters().size() + 1);
-        if (getReturnType() != null) {
-            allParameters.add(getReturnType());
-        }
-        allParameters.addAll(getParameters());
-        return Collections.unmodifiableList(allParameters);
-    }
-
-    public boolean canBeAccessedByInstanceOf(ProcessorContext context, TypeMirror type) {
-        TypeMirror methodType = Utils.findNearestEnclosingType(getMethod()).asType();
-        return Utils.isAssignable(context, type, methodType) || Utils.isAssignable(context, methodType, type);
-    }
-
-    public ExecutableElement getMethod() {
-        return method;
-    }
-
-    public String getMethodName() {
-        if (getMethod() != null) {
-            return getMethod().getSimpleName().toString();
-        } else {
-            return "$synthetic";
-        }
-    }
-
-    public AnnotationMirror getMarkerAnnotation() {
-        return markerAnnotation;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("%s [id = %s, method = %s]", getClass().getSimpleName(), getId(), getMethod());
-    }
-
-    public ActualParameter getPreviousParam(ActualParameter searchParam) {
-        ActualParameter prev = null;
-        for (ActualParameter param : getParameters()) {
-            if (param == searchParam) {
-                return prev;
-            }
-            prev = param;
-        }
-        return prev;
-    }
-
-    @SuppressWarnings("unused")
-    public int getSignatureSize() {
-        int signatureSize = 0;
-        for (ActualParameter parameter : getSignatureParameters()) {
-            signatureSize++;
-        }
-        return signatureSize;
-    }
-
-    public TypeSignature getTypeSignature() {
-        TypeSignature signature = new TypeSignature();
-        signature.types.add(getReturnType().getTypeSystemType());
-        for (ActualParameter parameter : getSignatureParameters()) {
-            TypeData typeData = parameter.getTypeSystemType();
-            if (typeData != null) {
-                signature.types.add(typeData);
-            }
-        }
-        return signature;
-    }
-
-    public ActualParameter getSignatureParameter(int searchIndex) {
-        int index = 0;
-        for (ActualParameter parameter : getParameters()) {
-            if (!parameter.getSpecification().isSignature()) {
-                continue;
-            }
-            if (index == searchIndex) {
-                return parameter;
-            }
-            index++;
-        }
-        return null;
-    }
-
-    public void updateSignature(TypeSignature signature) {
-        // TODO(CH): fails in normal usage - output ok though
-        // assert signature.size() >= 1;
-
-        int signatureIndex = 0;
-        for (ActualParameter parameter : getReturnTypeAndParameters()) {
-            if (!parameter.getSpecification().isSignature()) {
-                continue;
-            }
-            if (signatureIndex >= signature.size()) {
-                break;
-            }
-            TypeData newType = signature.get(signatureIndex++);
-            if (!parameter.getTypeSystemType().equals(newType)) {
-                replaceParameter(parameter.getLocalName(), new ActualParameter(parameter, newType));
-            }
-        }
-    }
-
-    @Override
-    public int compareTo(TemplateMethod o) {
-        if (this == o) {
-            return 0;
-        }
-
-        int compare = compareBySignature(o);
-        if (compare == 0) {
-            // if signature sorting failed sort by id
-            compare = getId().compareTo(o.getId());
-        }
-        if (compare == 0) {
-            // if still no difference sort by enclosing type name
-            TypeElement enclosingType1 = Utils.findNearestEnclosingType(getMethod());
-            TypeElement enclosingType2 = Utils.findNearestEnclosingType(o.getMethod());
-            compare = enclosingType1.getQualifiedName().toString().compareTo(enclosingType2.getQualifiedName().toString());
-        }
-        return compare;
-    }
-
-    public List<ActualParameter> getParametersAfter(ActualParameter genericParameter) {
-        boolean found = false;
-        List<ActualParameter> foundParameters = new ArrayList<>();
-        for (ActualParameter param : getParameters()) {
-            if (param.getLocalName().equals(genericParameter.getLocalName())) {
-                found = true;
-            } else if (found) {
-                foundParameters.add(param);
-            }
-        }
-        return foundParameters;
-    }
-
-    public int compareBySignature(TemplateMethod compareMethod) {
-        final TypeSystemData typeSystem = getTemplate().getTypeSystem();
-        if (typeSystem != compareMethod.getTemplate().getTypeSystem()) {
-            throw new IllegalStateException("Cannot compare two methods with different type systems.");
-        }
-
-        List<TypeMirror> signature1 = getSignatureTypes(this);
-        List<TypeMirror> signature2 = getSignatureTypes(compareMethod);
-        if (signature1.size() != signature2.size()) {
-            return signature2.size() - signature1.size();
-        }
-
-        int result = 0;
-        for (int i = 1; i < signature1.size(); i++) {
-            TypeMirror t1 = signature1.get(i);
-            TypeMirror t2 = signature2.get(i);
-
-            int typeResult = compareParameter(typeSystem, t1, t2);
-            if (result == 0) {
-                result = typeResult;
-            } else if (typeResult != 0 && Math.signum(result) != Math.signum(typeResult)) {
-                // We cannot define an order.
-                return 0;
-            }
-        }
-        if (result == 0 && signature1.size() > 0) {
-            result = compareParameter(typeSystem, signature1.get(0), signature2.get(0));
-        }
-
-        return result;
-    }
-
-    private static int compareParameter(TypeSystemData data, TypeMirror signature1, TypeMirror signature2) {
-        if (Utils.typeEquals(signature1, signature2)) {
-            return 0;
-        }
-
-        int index1 = data.findType(signature1);
-        int index2 = data.findType(signature2);
-        if (index1 != -1 && index2 != -1) {
-            return index1 - index2;
-        }
-
-        if (signature1.getKind() == TypeKind.DECLARED && signature2.getKind() == TypeKind.DECLARED) {
-            TypeElement element1 = Utils.fromTypeMirror(signature1);
-            TypeElement element2 = Utils.fromTypeMirror(signature2);
-
-            if (Utils.getDirectSuperTypes(element1).contains(element2)) {
-                return -1;
-            } else if (Utils.getDirectSuperTypes(element2).contains(element1)) {
-                return 1;
-            }
-        }
-        return Utils.getSimpleName(signature1).compareTo(Utils.getSimpleName(signature2));
-    }
-
-    public static List<TypeMirror> getSignatureTypes(TemplateMethod method) {
-        List<TypeMirror> types = new ArrayList<>();
-        types.add(method.getReturnType().getType());
-        for (ActualParameter param : method.getSignatureParameters()) {
-            types.add(param.getType());
-        }
-        return types;
-    }
-
-    public static class TypeSignature implements Iterable<TypeData>, Comparable<TypeSignature> {
-
-        final List<TypeData> types;
-
-        public TypeSignature() {
-            this.types = new ArrayList<>();
-        }
-
-        public TypeSignature(List<TypeData> signature) {
-            this.types = signature;
-        }
-
-        @Override
-        public int hashCode() {
-            return types.hashCode();
-        }
-
-        public int size() {
-            return types.size();
-        }
-
-        public TypeData get(int index) {
-            return types.get(index);
-        }
-
-        public int compareTo(TypeSignature other) {
-            if (this == other) {
-                return 0;
-            } else if (types.size() != other.types.size()) {
-                return types.size() - other.types.size();
-            } else if (types.isEmpty()) {
-                return 0;
-            }
-
-            for (int i = 0; i < types.size(); i++) {
-                TypeData type1 = types.get(i);
-                TypeData type2 = other.types.get(i);
-
-                int comparison = type1.compareTo(type2);
-                if (comparison != 0) {
-                    return comparison;
-                }
-            }
-
-            return 0;
-        }
-
-        public TypeSignature combine(TypeSignature genericSignature, TypeSignature other) {
-            assert types.size() == other.types.size();
-            assert genericSignature.types.size() == other.types.size();
-
-            if (this.equals(other)) {
-                return this;
-            }
-
-            TypeSignature signature = new TypeSignature();
-            for (int i = 0; i < types.size(); i++) {
-                TypeData type1 = types.get(i);
-                TypeData type2 = other.types.get(i);
-                if (type1.equals(type2)) {
-                    signature.types.add(type1);
-                } else {
-                    signature.types.add(genericSignature.types.get(i));
-                }
-            }
-            return signature;
-        }
-
-        public boolean equalsParameters(TypeSignature other) {
-            if (size() != other.size()) {
-                return false;
-            }
-            return types.subList(1, types.size()).equals(other.types.subList(1, other.types.size()));
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof TypeSignature) {
-                return ((TypeSignature) obj).types.equals(types);
-            }
-            return super.equals(obj);
-        }
-
-        public Iterator<TypeData> iterator() {
-            return types.iterator();
-        }
-
-        @Override
-        public String toString() {
-            return types.toString();
-        }
-
-        public boolean hasAnyParameterMatch(TypeSignature other) {
-            for (int i = 1; i < types.size(); i++) {
-                TypeData type1 = types.get(i);
-                TypeData type2 = other.types.get(i);
-                if (type1.equals(type2)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        public boolean isCompatibleTo(TypeSignature signature) {
-            if (size() != signature.size()) {
-                return false;
-            }
-
-            for (int i = 0; i < size(); i++) {
-                TypeData o1 = get(i);
-                TypeData o2 = signature.get(i);
-                if (o1.equals(o2)) {
-                    continue;
-                } else if (o2.isGeneric()) {
-                    continue;
-                } else {
-                    return false;
-                }
-            }
-            return true;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,355 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.template;
-
-import static com.oracle.truffle.dsl.processor.Utils.*;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public abstract class TemplateMethodParser<T extends Template, E extends TemplateMethod> {
-
-    private final ProcessorContext context;
-
-    protected final T template;
-
-    private boolean emitErrors = true;
-    private boolean parseNullOnError = false;
-    private boolean useVarArgs = false;
-
-    public TemplateMethodParser(ProcessorContext context, T template) {
-        this.template = template;
-        this.context = context;
-    }
-
-    protected void setUseVarArgs(boolean useVarArgs) {
-        this.useVarArgs = useVarArgs;
-    }
-
-    public boolean isUseVarArgs() {
-        return useVarArgs;
-    }
-
-    public boolean isEmitErrors() {
-        return emitErrors;
-    }
-
-    public void setParseNullOnError(boolean nullOnError) {
-        this.parseNullOnError = nullOnError;
-    }
-
-    public boolean isParseNullOnError() {
-        return parseNullOnError;
-    }
-
-    public void setEmitErrors(boolean emitErrors) {
-        this.emitErrors = emitErrors;
-    }
-
-    public ProcessorContext getContext() {
-        return context;
-    }
-
-    public TypeSystemData getTypeSystem() {
-        return template.getTypeSystem();
-    }
-
-    public abstract MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror);
-
-    public abstract E create(TemplateMethod method, boolean invalid);
-
-    public abstract boolean isParsable(ExecutableElement method);
-
-    public Class<? extends Annotation> getAnnotationType() {
-        return null;
-    }
-
-    public final List<E> parse(List<? extends Element> elements) {
-        List<ExecutableElement> methods = new ArrayList<>();
-        methods.addAll(ElementFilter.methodsIn(elements));
-
-        List<E> parsedMethods = new ArrayList<>();
-        boolean valid = true;
-        for (ExecutableElement method : methods) {
-            if (!isParsable(method)) {
-                continue;
-            }
-
-            Class<? extends Annotation> annotationType = getAnnotationType();
-            AnnotationMirror mirror = null;
-            if (annotationType != null) {
-                mirror = Utils.findAnnotationMirror(getContext().getEnvironment(), method, annotationType);
-            }
-
-            E parsedMethod = parse(method, mirror);
-
-            if (method.getModifiers().contains(Modifier.PRIVATE) && emitErrors) {
-                parsedMethod.addError("Method annotated with @%s must not be private.", getAnnotationType().getSimpleName());
-                parsedMethods.add(parsedMethod);
-                valid = false;
-                continue;
-            }
-
-            if (parsedMethod != null) {
-                parsedMethods.add(parsedMethod);
-            } else {
-                valid = false;
-            }
-        }
-        Collections.sort(parsedMethods);
-
-        if (!valid && parseNullOnError) {
-            return null;
-        }
-        return parsedMethods;
-    }
-
-    private E parse(ExecutableElement method, AnnotationMirror annotation) {
-        MethodSpec methodSpecification = createSpecification(method, annotation);
-        if (methodSpecification == null) {
-            return null;
-        }
-
-        methodSpecification.applyTypeDefinitions("types");
-
-        String id = method.getSimpleName().toString();
-        TypeMirror returnType = method.getReturnType();
-        List<TypeMirror> parameterTypes = new ArrayList<>();
-        for (VariableElement var : method.getParameters()) {
-            parameterTypes.add(var.asType());
-        }
-
-        return parseImpl(methodSpecification, id, method, annotation, returnType, parameterTypes);
-    }
-
-    private E parseImpl(MethodSpec methodSpecification, String id, ExecutableElement method, AnnotationMirror annotation, TypeMirror returnType, List<TypeMirror> parameterTypes) {
-        ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
-        ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, returnType, template, -1, -1);
-        if (returnTypeMirror == null) {
-            if (emitErrors) {
-                E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()), true);
-                String expectedReturnType = returnTypeSpec.toSignatureString(true);
-                String actualReturnType = Utils.getSimpleName(returnType);
-
-                String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
-                                methodSpecification.toSignatureString(method.getSimpleName().toString()));
-                invalidMethod.addError(message);
-                return invalidMethod;
-            } else {
-                return null;
-            }
-        }
-
-        List<ActualParameter> parameters = parseParameters(methodSpecification, parameterTypes, isUseVarArgs() && method != null ? method.isVarArgs() : false);
-        if (parameters == null) {
-            if (isEmitErrors() && method != null) {
-                E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()), true);
-                String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(method),
-                                methodSpecification.toSignatureString(method.getSimpleName().toString()));
-                invalidMethod.addError(message);
-                return invalidMethod;
-            } else {
-                return null;
-            }
-        }
-
-        return create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, parameters), false);
-    }
-
-    private static String createActualSignature(ExecutableElement method) {
-        StringBuilder b = new StringBuilder("(");
-        String sep = "";
-        if (method != null) {
-            for (VariableElement var : method.getParameters()) {
-                b.append(sep);
-                b.append(Utils.getSimpleName(var.asType()));
-                sep = ", ";
-            }
-        }
-        b.append(")");
-        return b.toString();
-    }
-
-    /*
-     * Parameter parsing tries to parse required arguments starting from offset 0 with increasing
-     * offset until it finds a signature end that matches the required specification. If there is no
-     * end matching the required arguments, parsing fails. Parameters prior to the parsed required
-     * ones are cut and used to parse the optional parameters.
-     */
-    private List<ActualParameter> parseParameters(MethodSpec spec, List<TypeMirror> parameterTypes, boolean varArgs) {
-        List<ActualParameter> parsedRequired = null;
-        int offset = 0;
-        for (; offset <= parameterTypes.size(); offset++) {
-            List<TypeMirror> parameters = new ArrayList<>();
-            parameters.addAll(parameterTypes.subList(offset, parameterTypes.size()));
-            parsedRequired = parseParametersRequired(spec, parameters, varArgs);
-            if (parsedRequired != null) {
-                break;
-            }
-        }
-
-        if (parsedRequired == null) {
-            return null;
-        }
-
-        if (parsedRequired.isEmpty() && offset == 0) {
-            offset = parameterTypes.size();
-        }
-        List<TypeMirror> potentialOptionals = parameterTypes.subList(0, offset);
-        List<ActualParameter> parsedOptionals = parseParametersOptional(spec, potentialOptionals);
-        if (parsedOptionals == null) {
-            return null;
-        }
-
-        List<ActualParameter> finalParameters = new ArrayList<>();
-        finalParameters.addAll(parsedOptionals);
-        finalParameters.addAll(parsedRequired);
-        return finalParameters;
-    }
-
-    private List<ActualParameter> parseParametersOptional(MethodSpec spec, List<TypeMirror> types) {
-        List<ActualParameter> parsedParams = new ArrayList<>();
-
-        int typeStartIndex = 0;
-        List<ParameterSpec> specifications = spec.getOptional();
-        outer: for (int specIndex = 0; specIndex < specifications.size(); specIndex++) {
-            ParameterSpec specification = specifications.get(specIndex);
-            for (int typeIndex = typeStartIndex; typeIndex < types.size(); typeIndex++) {
-                TypeMirror actualType = types.get(typeIndex);
-                ActualParameter optionalParam = matchParameter(specification, actualType, template, -1, -1);
-                if (optionalParam != null) {
-                    parsedParams.add(optionalParam);
-                    typeStartIndex = typeIndex + 1;
-                    continue outer;
-                }
-            }
-        }
-
-        if (typeStartIndex < types.size()) {
-            // not enough types found
-            return null;
-        }
-        return parsedParams;
-    }
-
-    private List<ActualParameter> parseParametersRequired(MethodSpec spec, List<TypeMirror> types, boolean typeVarArgs) {
-        List<ActualParameter> parsedParams = new ArrayList<>();
-        List<ParameterSpec> specifications = spec.getRequired();
-        boolean specVarArgs = spec.isVariableRequiredParameters();
-        int typeIndex = 0;
-        int specificationIndex = 0;
-
-        ParameterSpec specification;
-        while ((specification = nextSpecification(specifications, specificationIndex, specVarArgs)) != null) {
-            TypeMirror actualType = nextActualType(types, typeIndex, typeVarArgs);
-            if (actualType == null) {
-                if (spec.isIgnoreAdditionalSpecifications()) {
-                    break;
-                }
-                return null;
-            }
-
-            int typeVarArgsIndex = typeVarArgs ? typeIndex - types.size() + 1 : -1;
-            int specVarArgsIndex = specVarArgs ? specificationIndex - specifications.size() + 1 : -1;
-
-            if (typeVarArgsIndex >= 0 && specVarArgsIndex >= 0) {
-                // both specifications and types have a variable number of arguments
-                // we would get into an endless loop if we would continue
-                break;
-            }
-
-            ActualParameter resolvedParameter = matchParameter(specification, actualType, template, specVarArgsIndex, typeVarArgsIndex);
-            if (resolvedParameter == null) {
-                return null;
-            }
-            parsedParams.add(resolvedParameter);
-            typeIndex++;
-            specificationIndex++;
-        }
-
-        if (typeIndex < types.size()) {
-            // additional types available
-            if (spec.isIgnoreAdditionalParameters()) {
-                return parsedParams;
-            } else {
-                return null;
-            }
-        }
-
-        return parsedParams;
-    }
-
-    private static ParameterSpec nextSpecification(List<ParameterSpec> specifications, int specIndex, boolean varArgs) {
-        if (varArgs && specIndex >= specifications.size() - 1 && !specifications.isEmpty()) {
-            return specifications.get(specifications.size() - 1);
-        } else if (specIndex < specifications.size()) {
-            return specifications.get(specIndex);
-        } else {
-            return null;
-        }
-    }
-
-    private static TypeMirror nextActualType(List<TypeMirror> types, int typeIndex, boolean varArgs) {
-        if (varArgs && typeIndex >= types.size() - 1 && !types.isEmpty()) {
-            // unpack varargs array argument
-            TypeMirror actualType = types.get(types.size() - 1);
-            if (actualType.getKind() == TypeKind.ARRAY) {
-                actualType = ((ArrayType) actualType).getComponentType();
-            }
-            return actualType;
-        } else if (typeIndex < types.size()) {
-            return types.get(typeIndex);
-        } else {
-            return null;
-        }
-    }
-
-    protected final ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template originalTemplate, int specificationIndex, int varArgsIndex) {
-        TypeMirror resolvedType = mirror;
-        if (hasError(resolvedType)) {
-            resolvedType = context.resolveNotYetCompiledType(mirror, originalTemplate);
-        }
-
-        if (!specification.matches(resolvedType)) {
-            return null;
-        }
-
-        TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType);
-        if (resolvedTypeData != null) {
-            return new ActualParameter(specification, resolvedTypeData, specificationIndex, varArgsIndex);
-        } else {
-            return new ActualParameter(specification, resolvedType, specificationIndex, varArgsIndex);
-        }
-    }
-
-    public final E create(String id, ExecutableElement methodMetadata, AnnotationMirror mirror, TypeMirror returnType, List<TypeMirror> parameterTypes) {
-        return parseImpl(createSpecification(methodMetadata, mirror), id, methodMetadata, mirror, returnType, parameterTypes);
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardData.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import com.oracle.truffle.dsl.processor.node.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class GuardData extends TemplateMethod {
-
-    private final SpecializationData specialization;
-    private final boolean negated;
-
-    public GuardData(TemplateMethod method, SpecializationData specialization, boolean negated) {
-        super(method);
-        this.negated = negated;
-        this.specialization = specialization;
-    }
-
-    public boolean isNegated() {
-        return negated;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof GuardData) {
-            GuardData other = (GuardData) obj;
-            return getMethod().equals(other.getMethod()) && negated == other.negated;
-        }
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        return getMethod().hashCode();
-    }
-
-    public SpecializationData getSpecialization() {
-        return specialization;
-    }
-
-    @Override
-    public String toString() {
-        return (negated ? "!" : "") + getMethodName() + getParameters().toString();
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import java.lang.annotation.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class GuardParser extends NodeMethodParser<GuardData> {
-
-    private final SpecializationData specialization;
-    private final String guardName;
-    private final boolean negated;
-
-    public GuardParser(ProcessorContext context, SpecializationData specialization, String guardDefinition) {
-        super(context, specialization.getNode());
-        this.specialization = specialization;
-        if (guardDefinition.startsWith("!")) {
-            this.guardName = guardDefinition.substring(1, guardDefinition.length());
-            this.negated = true;
-        } else {
-            this.guardName = guardDefinition;
-            this.negated = false;
-        }
-        setEmitErrors(false);
-        setParseNullOnError(false);
-    }
-
-    @Override
-    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
-        return super.createValueParameterSpec(execution);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        MethodSpec spec = createDefaultMethodSpec(method, mirror, true, null);
-        spec.setIgnoreAdditionalSpecifications(true);
-        spec.getRequired().clear();
-
-        for (ActualParameter parameter : specialization.getRequiredParameters()) {
-            spec.addRequired(new ParameterSpec(parameter.getSpecification(), Utils.getAssignableTypes(getContext(), parameter.getType())));
-        }
-
-        return spec;
-    }
-
-    @Override
-    protected ParameterSpec createReturnParameterSpec() {
-        return new ParameterSpec("returnType", getContext().getType(boolean.class));
-    }
-
-    @Override
-    public boolean isParsable(ExecutableElement method) {
-        return method.getSimpleName().toString().equals(guardName);
-    }
-
-    @Override
-    public GuardData create(TemplateMethod method, boolean invalid) {
-        return new GuardData(method, specialization, negated);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return null;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastData.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class ImplicitCastData extends TemplateMethod {
-
-    private final TypeData sourceType;
-    private final TypeData targetType;
-
-    public ImplicitCastData(TemplateMethod method, TypeData sourceType, TypeData targetType) {
-        super(method);
-        this.sourceType = sourceType;
-        this.targetType = targetType;
-    }
-
-    public TypeData getSourceType() {
-        return sourceType;
-    }
-
-    public TypeData getTargetType() {
-        return targetType;
-    }
-
-    @Override
-    public int compareTo(TemplateMethod o) {
-        if (o instanceof ImplicitCastData && sourceType != null) {
-            // implicit casts are ordered by source type since
-            // its also the order in which they are checked.
-            TypeData otherSourceType = ((ImplicitCastData) o).getSourceType();
-            if (otherSourceType != null) {
-                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	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class ImplicitCastParser extends TypeSystemMethodParser<ImplicitCastData> {
-
-    public ImplicitCastParser(ProcessorContext context, TypeSystemData typeSystem) {
-        super(context, typeSystem);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return ImplicitCast.class;
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        List<TypeMirror> types = new ArrayList<>();
-        for (TypeData typeData : getTypeSystem().getTypes()) {
-            types.add(typeData.getPrimitiveType());
-        }
-        MethodSpec spec = new MethodSpec(new ParameterSpec("target", types));
-        spec.addRequired(new ParameterSpec("source", types));
-        return spec;
-    }
-
-    @Override
-    public ImplicitCastData create(TemplateMethod method, boolean invalid) {
-        if (invalid) {
-            return new ImplicitCastData(method, null, null);
-        }
-
-        ActualParameter target = method.findParameter("targetValue");
-        ActualParameter source = method.findParameter("sourceValue");
-
-        TypeData targetType = target.getTypeSystemType();
-        TypeData sourceType = source.getTypeSystemType();
-
-        if (targetType.equals(sourceType)) {
-            method.addError("Target type and source type of an @%s must not be the same type.", ImplicitCast.class.getSimpleName());
-        }
-
-        return new ImplicitCastData(method, sourceType, targetType);
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastData.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class TypeCastData extends TemplateMethod {
-
-    private final TypeData targetType;
-    private final TypeData sourceType;
-
-    public TypeCastData(TemplateMethod method, TypeData sourceType, TypeData targetType) {
-        super(method);
-        this.sourceType = sourceType;
-        this.targetType = targetType;
-    }
-
-    public boolean isGeneric() {
-        return sourceType.isGeneric();
-    }
-
-    public TypeData getSourceType() {
-        return sourceType;
-    }
-
-    public TypeData getTargetType() {
-        return targetType;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastParser.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import java.lang.annotation.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-class TypeCastParser extends TypeSystemMethodParser<TypeCastData> {
-
-    public TypeCastParser(ProcessorContext context, TypeSystemData typeSystem) {
-        super(context, typeSystem);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "as");
-        if (targetType == null) {
-            return null;
-        }
-        MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", targetType.getPrimitiveType()));
-        spec.addRequired(new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors()));
-        return spec;
-    }
-
-    @Override
-    public TypeCastData create(TemplateMethod method, boolean invalid) {
-        if (invalid) {
-            return new TypeCastData(method, null, null);
-        }
-
-        TypeData targetType = findTypeByMethodName(method, "as");
-        ActualParameter parameter = method.findParameter("valueValue");
-
-        TypeData sourceType = null;
-        if (parameter != null) {
-            sourceType = getTypeSystem().findTypeData(parameter.getType());
-        }
-        TypeCastData cast = new TypeCastData(method, sourceType, targetType);
-
-        if (targetType != method.getReturnType().getTypeSystemType()) {
-            cast.addError("Cast type %s does not match to the returned type %s.", Utils.getSimpleName(targetType.getPrimitiveType()),
-                            method.getReturnType() != null ? Utils.getSimpleName(method.getReturnType().getTypeSystemType().getPrimitiveType()) : null);
-        }
-        return cast;
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return TypeCast.class;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckData.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class TypeCheckData extends TemplateMethod {
-
-    private final TypeData checkedType;
-    private final TypeData valueType;
-
-    public TypeCheckData(TemplateMethod method, TypeData checkedType, TypeData valueType) {
-        super(method);
-        this.checkedType = checkedType;
-        this.valueType = valueType;
-    }
-
-    public boolean isGeneric() {
-        return valueType.isGeneric();
-    }
-
-    public TypeData getCheckedType() {
-        return checkedType;
-    }
-
-    public TypeData getValueType() {
-        return valueType;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckParser.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import java.lang.annotation.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-class TypeCheckParser extends TypeSystemMethodParser<TypeCheckData> {
-
-    public TypeCheckParser(ProcessorContext context, TypeSystemData typeSystem) {
-        super(context, typeSystem);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "is");
-        if (targetType == null) {
-            return null;
-        }
-        MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", getContext().getType(boolean.class)));
-        spec.addRequired(new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors()));
-        return spec;
-    }
-
-    @Override
-    public TypeCheckData create(TemplateMethod method, boolean invalid) {
-        TypeData checkedType = findTypeByMethodName(method, "is");
-        assert checkedType != null;
-        ActualParameter parameter = method.findParameter("valueValue");
-        assert parameter != null;
-        return new TypeCheckData(method, checkedType, parameter.getTypeSystemType());
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return TypeCheck.class;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeData.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class TypeData extends MessageContainer implements Comparable<TypeData> {
-
-    private final TypeSystemData typeSystem;
-    private final AnnotationValue annotationValue;
-    private final TypeMirror primitiveType;
-    private final TypeMirror boxedType;
-
-    private final int index;
-    private final List<TypeCastData> typeCasts = new ArrayList<>();
-    private final List<TypeCheckData> typeChecks = new ArrayList<>();
-
-    public TypeData(TypeSystemData typeSystem, int index, AnnotationValue value, TypeMirror primitiveType, TypeMirror boxedType) {
-        this.index = index;
-        this.typeSystem = typeSystem;
-        this.annotationValue = value;
-        this.primitiveType = primitiveType;
-        this.boxedType = boxedType;
-    }
-
-    @Override
-    public Element getMessageElement() {
-        return typeSystem.getMessageElement();
-    }
-
-    @Override
-    public AnnotationMirror getMessageAnnotation() {
-        return typeSystem.getMessageAnnotation();
-    }
-
-    @Override
-    public AnnotationValue getMessageAnnotationValue() {
-        return annotationValue;
-    }
-
-    void addTypeCast(TypeCastData typeCast) {
-        this.typeCasts.add(typeCast);
-    }
-
-    void addTypeCheck(TypeCheckData typeCheck) {
-        this.typeChecks.add(typeCheck);
-    }
-
-    public List<TypeCastData> getTypeCasts() {
-        return typeCasts;
-    }
-
-    public List<TypeCheckData> getTypeChecks() {
-        return typeChecks;
-    }
-
-    public TypeSystemData getTypeSystem() {
-        return typeSystem;
-    }
-
-    public TypeMirror getPrimitiveType() {
-        return primitiveType;
-    }
-
-    public TypeMirror getBoxedType() {
-        return boxedType;
-    }
-
-    public boolean isGeneric() {
-        return Utils.typeEquals(boxedType, getTypeSystem().getGenericType());
-    }
-
-    public boolean isVoid() {
-        if (getTypeSystem().getVoidType() == null) {
-            return false;
-        }
-        return Utils.typeEquals(boxedType, getTypeSystem().getVoidType().getBoxedType());
-    }
-
-    public int compareTo(TypeData o) {
-        if (this.equals(o)) {
-            return 0;
-        }
-        return index - o.index;
-    }
-
-    @Override
-    public String toString() {
-        return getClass().getSimpleName() + "[" + Utils.getSimpleName(primitiveType) + "]";
-    }
-
-    public boolean equalsType(TypeData actualTypeData) {
-        return Utils.typeEquals(boxedType, actualTypeData.boxedType);
-    }
-
-    public boolean needsCastTo(ProcessorContext context, TypeData targetType) {
-        return Utils.needsCastTo(context, getPrimitiveType(), targetType.getPrimitiveType());
-    }
-
-    public boolean isPrimitive() {
-        return Utils.isPrimitive(getPrimitiveType());
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemCodeGenerator.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,308 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import static com.oracle.truffle.dsl.processor.Utils.*;
-import static javax.lang.model.element.Modifier.*;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.ast.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class TypeSystemCodeGenerator extends CompilationUnitFactory<TypeSystemData> {
-
-    public TypeSystemCodeGenerator(ProcessorContext context) {
-        super(context);
-    }
-
-    public static String isTypeMethodName(TypeData type) {
-        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());
-    }
-
-    /**
-     * Finds the generated singleton field for a TypeSytemData instance. TypeSystemCodeGenerator
-     * must be applied to the TypeSystemData model before use.
-     */
-    public static VariableElement findSingleton(ProcessorContext context, TypeSystemData typeSystem) {
-        TypeMirror type = context.findGeneratedClassBySimpleName(TypeClassFactory.typeName(typeSystem), typeSystem);
-        return Utils.findDeclaredField(type, TypeClassFactory.singletonName(typeSystem.getTemplateType().asType()));
-    }
-
-    @Override
-    protected void createChildren(TypeSystemData m) {
-        add(new TypeClassFactory(context), m);
-    }
-
-    protected static class TypeClassFactory extends ClassElementFactory<TypeSystemData> {
-
-        private static final String LOCAL_VALUE = "value";
-
-        public TypeClassFactory(ProcessorContext context) {
-            super(context);
-        }
-
-        @Override
-        public CodeTypeElement create(TypeSystemData typeSystem) {
-            String name = typeName(typeSystem);
-            CodeTypeElement clazz = createClass(typeSystem, modifiers(PUBLIC, FINAL), name, typeSystem.getTemplateType().asType(), false);
-
-            clazz.add(createConstructorUsingFields(modifiers(PROTECTED), clazz));
-            CodeVariableElement singleton = createSingleton(clazz);
-            clazz.add(singleton);
-
-            for (TypeData type : typeSystem.getTypes()) {
-                if (!type.isGeneric()) {
-                    clazz.addOptional(createIsTypeMethod(type));
-                    clazz.addOptional(createAsTypeMethod(type));
-
-                    for (TypeData sourceType : collectExpectSourceTypes(type)) {
-                        clazz.addOptional(createExpectTypeMethod(type, sourceType));
-                    }
-
-                    clazz.addOptional(createAsImplicitTypeMethod(type, true));
-                    clazz.addOptional(createAsImplicitTypeMethod(type, false));
-                    clazz.addOptional(createIsImplicitTypeMethod(type, true));
-                    clazz.addOptional(createIsImplicitTypeMethod(type, false));
-                    clazz.addOptional(createGetTypeIndex(type));
-                }
-            }
-
-            return clazz;
-        }
-
-        private static List<TypeData> collectExpectSourceTypes(TypeData type) {
-            Set<TypeData> sourceTypes = new HashSet<>();
-            sourceTypes.add(type.getTypeSystem().getGenericTypeData());
-            for (TypeCastData cast : type.getTypeCasts()) {
-                sourceTypes.add(cast.getSourceType());
-            }
-            for (TypeCheckData cast : type.getTypeChecks()) {
-                sourceTypes.add(cast.getCheckedType());
-            }
-            return new ArrayList<>(sourceTypes);
-        }
-
-        private static String typeName(TypeSystemData typeSystem) {
-            String name = getSimpleName(typeSystem.getTemplateType());
-            return name + "Gen";
-        }
-
-        private static String singletonName(TypeMirror type) {
-            return createConstantName(getSimpleName(type));
-        }
-
-        private CodeVariableElement createSingleton(CodeTypeElement clazz) {
-            CodeVariableElement field = new CodeVariableElement(modifiers(PUBLIC, STATIC, FINAL), clazz.asType(), singletonName(getModel().getTemplateType().asType()));
-            field.createInitBuilder().startNew(clazz.asType()).end();
-            return field;
-        }
-
-        private CodeExecutableElement createIsImplicitTypeMethod(TypeData type, boolean typed) {
-            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));
-            if (typed) {
-                method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "typeHint"));
-            }
-            CodeTreeBuilder builder = method.createBuilder();
-
-            List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
-
-            builder.startReturn();
-            String sep = "";
-            for (TypeData sourceType : sourceTypes) {
-                builder.string(sep);
-                if (typed) {
-                    builder.string("(typeHint == ").typeLiteral(sourceType.getPrimitiveType()).string(" && ");
-                }
-                builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end();
-                if (typed) {
-                    builder.string(")");
-                }
-                if (sourceTypes.lastIndexOf(sourceType) != sourceTypes.size() - 1) {
-                    builder.newLine();
-                }
-                if (sep.equals("")) {
-                    builder.startIndention();
-                }
-                sep = " || ";
-            }
-            builder.end();
-            builder.end();
-            return method;
-        }
-
-        private CodeExecutableElement createAsImplicitTypeMethod(TypeData type, boolean typed) {
-            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));
-            if (typed) {
-                method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "typeHint"));
-            }
-
-            List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
-
-            CodeTreeBuilder builder = method.createBuilder();
-            boolean elseIf = false;
-            for (TypeData sourceType : sourceTypes) {
-                elseIf = builder.startIf(elseIf);
-                if (typed) {
-                    builder.string("typeHint == ").typeLiteral(sourceType.getPrimitiveType());
-                } else {
-                    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(), "transferToInterpreterAndInvalidate").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(), "transferToInterpreterAndInvalidate").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;
-            }
-
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(boolean.class), TypeSystemCodeGenerator.isTypeMethodName(type));
-            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
-
-            DeclaredType suppressWarnings = (DeclaredType) getContext().getType(SuppressWarnings.class);
-            CodeAnnotationMirror annotationMirror = new CodeAnnotationMirror(suppressWarnings);
-            annotationMirror.setElementValue(annotationMirror.findExecutableElement("value"), new CodeAnnotationValue("static-method"));
-            method.getAnnotationMirrors().add(annotationMirror);
-
-            CodeTreeBuilder body = method.createBuilder();
-            body.startReturn().instanceOf(LOCAL_VALUE, type.getBoxedType()).end();
-
-            return method;
-        }
-
-        private CodeExecutableElement createAsTypeMethod(TypeData type) {
-            if (!type.getTypeCasts().isEmpty()) {
-                return null;
-            }
-
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asTypeMethodName(type));
-            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
-
-            CodeTreeBuilder body = method.createBuilder();
-            String assertMessage = typeName(getModel()) + "." + asTypeMethodName(type) + ": " + Utils.getSimpleName(type.getBoxedType()) + " expected";
-            body.startAssert().startCall(isTypeMethodName(type)).string(LOCAL_VALUE).end().string(" : ").doubleQuote(assertMessage).end();
-            body.startReturn().cast(type.getPrimitiveType(), body.create().string(LOCAL_VALUE).getTree()).end();
-
-            return method;
-        }
-
-        private CodeExecutableElement createExpectTypeMethod(TypeData expectedType, TypeData sourceType) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), expectedType.getPrimitiveType(), TypeSystemCodeGenerator.expectTypeMethodName(expectedType));
-            method.addParameter(new CodeVariableElement(sourceType.getPrimitiveType(), LOCAL_VALUE));
-            method.addThrownType(getContext().getTruffleTypes().getUnexpectedValueException());
-
-            CodeTreeBuilder body = method.createBuilder();
-            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();
-
-            return method;
-        }
-
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemData.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,227 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class TypeSystemData extends Template {
-
-    private List<TypeData> types;
-    private List<TypeMirror> primitiveTypeMirrors = new ArrayList<>();
-    private List<TypeMirror> boxedTypeMirrors = new ArrayList<>();
-
-    private List<ImplicitCastData> implicitCasts;
-    private List<TypeCastData> casts;
-    private List<TypeCheckData> checks;
-
-    private TypeMirror genericType;
-    private TypeData voidType;
-
-    public TypeSystemData(TypeElement templateType, AnnotationMirror annotation) {
-        super(templateType, null, annotation);
-    }
-
-    @Override
-    public TypeSystemData getTypeSystem() {
-        return this;
-    }
-
-    void setTypes(List<TypeData> types) {
-        this.types = types;
-        if (types != null) {
-            for (TypeData typeData : types) {
-                primitiveTypeMirrors.add(typeData.getPrimitiveType());
-                boxedTypeMirrors.add(typeData.getBoxedType());
-            }
-        }
-    }
-
-    public void setImplicitCasts(List<ImplicitCastData> implicitCasts) {
-        this.implicitCasts = implicitCasts;
-    }
-
-    public List<ImplicitCastData> getImplicitCasts() {
-        return implicitCasts;
-    }
-
-    public void setCasts(List<TypeCastData> casts) {
-        this.casts = casts;
-    }
-
-    public void setChecks(List<TypeCheckData> checks) {
-        this.checks = checks;
-    }
-
-    void setGenericType(TypeMirror genericType) {
-        this.genericType = genericType;
-    }
-
-    void setVoidType(TypeData voidType) {
-        this.voidType = voidType;
-    }
-
-    @Override
-    protected List<MessageContainer> findChildContainers() {
-        List<MessageContainer> sinks = new ArrayList<>();
-        if (types != null) {
-            sinks.addAll(types);
-        }
-        if (checks != null) {
-            sinks.addAll(checks);
-        }
-        if (casts != null) {
-            sinks.addAll(casts);
-        }
-        if (implicitCasts != null) {
-            sinks.addAll(implicitCasts);
-        }
-        return sinks;
-    }
-
-    public boolean isGeneric(TypeMirror type) {
-        return Utils.typeEquals(getGenericType(), type);
-    }
-
-    public TypeData getVoidType() {
-        return voidType;
-    }
-
-    public List<TypeMirror> getBoxedTypeMirrors() {
-        return boxedTypeMirrors;
-    }
-
-    public List<TypeMirror> getPrimitiveTypeMirrors() {
-        return primitiveTypeMirrors;
-    }
-
-    public List<TypeData> getTypes() {
-        return types;
-    }
-
-    public TypeMirror getGenericType() {
-        return genericType;
-    }
-
-    public TypeData getGenericTypeData() {
-        TypeData result = types.get(types.size() - 1);
-        assert result.getBoxedType() == genericType;
-        return result;
-    }
-
-    public TypeData findType(String simpleName) {
-        for (TypeData type : types) {
-            if (Utils.getSimpleName(type.getBoxedType()).equals(simpleName)) {
-                return type;
-            }
-        }
-        return null;
-    }
-
-    public TypeData findTypeData(TypeMirror type) {
-        if (Utils.typeEquals(voidType.getPrimitiveType(), type)) {
-            return voidType;
-        }
-
-        int index = findType(type);
-        if (index == -1) {
-            return null;
-        }
-        return types.get(index);
-    }
-
-    public int findType(TypeData typeData) {
-        return findType(typeData.getPrimitiveType());
-    }
-
-    public int findType(TypeMirror type) {
-        for (int i = 0; i < types.size(); i++) {
-            if (Utils.typeEquals(types.get(i).getPrimitiveType(), type)) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    @Override
-    public String toString() {
-        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/TypeSystemMethodParser.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-abstract class TypeSystemMethodParser<E extends TemplateMethod> extends TemplateMethodParser<TypeSystemData, E> {
-
-    public TypeSystemMethodParser(ProcessorContext context, TypeSystemData typeSystem) {
-        super(context, typeSystem);
-    }
-
-    @Override
-    public final boolean isParsable(ExecutableElement method) {
-        return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null;
-    }
-
-    protected TypeData findTypeByMethodName(String methodName, String prefix) {
-        String typeName = methodName.substring(prefix.length(), methodName.length());
-        TypeData type = getTypeSystem().findType(typeName);
-        return type;
-    }
-
-    protected TypeData findTypeByMethodName(TemplateMethod method, String prefix) {
-        String methodName = method.getMethodName();
-        if (!methodName.startsWith(prefix)) {
-            String annotationName = Utils.getSimpleName(method.getMessageAnnotation().getAnnotationType());
-            method.addError("Methods annotated with %s must match the pattern '%s'.", annotationName, String.format("%s${typeName}", prefix));
-            return null;
-        }
-        String typeName = methodName.substring(prefix.length(), methodName.length());
-        TypeData type = getTypeSystem().findType(typeName);
-        if (type == null) {
-            String annotationName = TypeSystem.class.getSimpleName();
-            method.addError("Type '%s' is not declared in this @%s.", typeName, annotationName);
-            return null;
-        }
-
-        return type;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,309 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import static com.oracle.truffle.dsl.processor.Utils.*;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class TypeSystemParser extends AbstractParser<TypeSystemData> {
-
-    public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(TypeSystem.class, ExpectError.class);
-
-    public TypeSystemParser(ProcessorContext c) {
-        super(c);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return TypeSystem.class;
-    }
-
-    @Override
-    protected TypeSystemData parse(Element element, AnnotationMirror mirror) {
-        TypeElement templateType = (TypeElement) element;
-        AnnotationMirror templateTypeAnnotation = mirror;
-        TypeSystemData typeSystem = new TypeSystemData(templateType, templateTypeAnnotation);
-
-        // annotation type on class path!?
-        TypeElement annotationTypeElement = processingEnv.getElementUtils().getTypeElement(getAnnotationType().getCanonicalName());
-        if (annotationTypeElement == null) {
-            typeSystem.addError("Required class %s is not on the classpath.", getAnnotationType().getName());
-        }
-        if (templateType.getModifiers().contains(Modifier.PRIVATE)) {
-            typeSystem.addError("A @%s must have at least package protected visibility.", getAnnotationType().getName());
-        }
-
-        if (templateType.getModifiers().contains(Modifier.FINAL)) {
-            typeSystem.addError("The @%s must not be final.", getAnnotationType().getName());
-        }
-        if (typeSystem.hasErrors()) {
-            return typeSystem;
-        }
-
-        typeSystem.setTypes(parseTypes(typeSystem));
-        if (typeSystem.hasErrors()) {
-            return typeSystem;
-        }
-
-        TypeMirror genericType = context.getType(Object.class);
-        TypeData voidType = new TypeData(typeSystem, typeSystem.getTypes().size(), null, context.getType(void.class), context.getType(Void.class));
-
-        typeSystem.setGenericType(genericType);
-        typeSystem.setVoidType(voidType);
-
-        verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class);
-
-        List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType));
-        List<ImplicitCastData> implicitCasts = new ImplicitCastParser(context, typeSystem).parse(elements);
-        List<TypeCastData> casts = new TypeCastParser(context, typeSystem).parse(elements);
-        List<TypeCheckData> checks = new TypeCheckParser(context, typeSystem).parse(elements);
-
-        if (casts == null || checks == null || implicitCasts == null) {
-            return typeSystem;
-        }
-
-        typeSystem.setImplicitCasts(implicitCasts);
-        typeSystem.setCasts(casts);
-        typeSystem.setChecks(checks);
-
-        if (typeSystem.hasErrors()) {
-            return typeSystem;
-        }
-
-        for (TypeCheckData check : checks) {
-            check.getCheckedType().addTypeCheck(check);
-        }
-
-        for (TypeCastData cast : casts) {
-            cast.getTargetType().addTypeCast(cast);
-        }
-
-        verifyGenericTypeChecksAndCasts(typeSystem);
-        verifyMethodSignatures(typeSystem);
-        verifyNamesUnique(typeSystem);
-
-        return typeSystem;
-    }
-
-    protected void verifyExclusiveMethodAnnotation(Template template, Class<?>... annotationTypes) {
-        List<ExecutableElement> methods = ElementFilter.methodsIn(template.getTemplateType().getEnclosedElements());
-        for (ExecutableElement method : methods) {
-            List<AnnotationMirror> foundAnnotations = new ArrayList<>();
-            for (int i = 0; i < annotationTypes.length; i++) {
-                Class<?> annotationType = annotationTypes[i];
-                AnnotationMirror mirror = Utils.findAnnotationMirror(context.getEnvironment(), method, annotationType);
-                if (mirror != null) {
-                    foundAnnotations.add(mirror);
-                }
-            }
-            if (foundAnnotations.size() > 1) {
-                List<String> annotationNames = new ArrayList<>();
-                for (AnnotationMirror mirror : foundAnnotations) {
-                    annotationNames.add("@" + Utils.getSimpleName(mirror.getAnnotationType()));
-                }
-
-                template.addError("Non exclusive usage of annotations %s.", annotationNames);
-            }
-        }
-    }
-
-    private static void verifyGenericTypeChecksAndCasts(TypeSystemData typeSystem) {
-        for (TypeData type : typeSystem.getTypes()) {
-            if (!type.getTypeChecks().isEmpty()) {
-                boolean hasGeneric = false;
-                for (TypeCheckData typeCheck : type.getTypeChecks()) {
-                    if (typeCheck.isGeneric()) {
-                        hasGeneric = true;
-                        break;
-                    }
-                }
-                if (!hasGeneric) {
-                    type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.",
-                                    TypeCheck.class.getSimpleName(), TypeSystemCodeGenerator.isTypeMethodName(type), Utils.getSimpleName(type.getBoxedType()), TypeCheck.class.getSimpleName(),
-                                    Object.class.getSimpleName());
-                }
-            }
-            if (!type.getTypeCasts().isEmpty()) {
-                boolean hasGeneric = false;
-                for (TypeCastData typeCast : type.getTypeCasts()) {
-                    if (typeCast.isGeneric()) {
-                        hasGeneric = true;
-                        break;
-                    }
-                }
-                if (!hasGeneric) {
-                    type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.",
-                                    TypeCast.class.getSimpleName(), TypeSystemCodeGenerator.asTypeMethodName(type), Utils.getSimpleName(type.getBoxedType()), TypeCast.class.getSimpleName(),
-                                    Object.class.getSimpleName());
-                }
-            }
-        }
-    }
-
-    private List<TypeData> parseTypes(TypeSystemData typeSystem) {
-        List<TypeData> types = new ArrayList<>();
-        List<TypeMirror> typeMirrors = Utils.getAnnotationValueList(TypeMirror.class, typeSystem.getTemplateTypeAnnotation(), "value");
-        if (typeMirrors.isEmpty()) {
-            typeSystem.addError("At least one type must be defined.");
-            return types;
-        }
-
-        final AnnotationValue annotationValue = Utils.getAnnotationValue(typeSystem.getTemplateTypeAnnotation(), "value");
-        final TypeMirror objectType = context.getType(Object.class);
-
-        int index = 0;
-        for (TypeMirror primitiveType : typeMirrors) {
-            TypeMirror boxedType = Utils.boxType(context, primitiveType);
-            TypeData typeData = new TypeData(typeSystem, index, annotationValue, primitiveType, boxedType);
-
-            if (isPrimitiveWrapper(primitiveType)) {
-                typeData.addError("Types must not contain primitive wrapper types.");
-            }
-
-            if (Utils.typeEquals(boxedType, objectType)) {
-                typeData.addError("Types must not contain the generic type java.lang.Object.");
-            }
-
-            types.add(typeData);
-            index++;
-        }
-
-        verifyTypeOrder(types);
-
-        types.add(new TypeData(typeSystem, index, annotationValue, objectType, objectType));
-
-        return types;
-    }
-
-    private static void verifyTypeOrder(List<TypeData> types) {
-        Map<String, List<String>> invalidTypes = new HashMap<>();
-
-        for (int i = types.size() - 1; i >= 0; i--) {
-            TypeData typeData = types.get(i);
-            TypeMirror type = typeData.getBoxedType();
-            if (invalidTypes.containsKey(Utils.getQualifiedName(type))) {
-                typeData.addError("Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", invalidTypes.get(Utils.getQualifiedName(type)), Utils.getQualifiedName(type));
-            }
-            List<String> nextInvalidTypes = Utils.getQualifiedSuperTypeNames(Utils.fromTypeMirror(type));
-            nextInvalidTypes.add(getQualifiedName(type));
-
-            for (String qualifiedName : nextInvalidTypes) {
-                List<String> inheritedTypes = invalidTypes.get(qualifiedName);
-                if (inheritedTypes == null) {
-                    inheritedTypes = new ArrayList<>();
-                    invalidTypes.put(qualifiedName, inheritedTypes);
-                }
-                inheritedTypes.add(Utils.getQualifiedName(typeData.getBoxedType()));
-            }
-        }
-    }
-
-    private boolean isPrimitiveWrapper(TypeMirror type) {
-        Types types = context.getEnvironment().getTypeUtils();
-        for (TypeKind kind : TypeKind.values()) {
-            if (!kind.isPrimitive()) {
-                continue;
-            }
-            if (Utils.typeEquals(type, types.boxedClass(types.getPrimitiveType(kind)).asType())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private void verifyMethodSignatures(TypeSystemData typeSystem) {
-        Set<String> generatedIsMethodNames = new HashSet<>();
-        Set<String> generatedAsMethodNames = new HashSet<>();
-        Set<String> generatedExpectMethodNames = new HashSet<>();
-
-        for (TypeData typeData : typeSystem.getTypes()) {
-            generatedIsMethodNames.add(TypeSystemCodeGenerator.isTypeMethodName(typeData));
-            generatedAsMethodNames.add(TypeSystemCodeGenerator.asTypeMethodName(typeData));
-            generatedExpectMethodNames.add(TypeSystemCodeGenerator.expectTypeMethodName(typeData));
-        }
-
-        List<ExecutableElement> methods = ElementFilter.methodsIn(typeSystem.getTemplateType().getEnclosedElements());
-        for (ExecutableElement method : methods) {
-            if (method.getModifiers().contains(Modifier.PRIVATE)) {
-                // will not conflict overridden methods
-                continue;
-            } else if (method.getParameters().size() != 1) {
-                continue;
-            }
-            String methodName = method.getSimpleName().toString();
-            if (generatedIsMethodNames.contains(methodName)) {
-                verifyIsMethod(typeSystem, method);
-            } else if (generatedAsMethodNames.contains(methodName)) {
-                verifyAsMethod(typeSystem, method);
-            } else if (generatedExpectMethodNames.contains(methodName)) {
-                verifyExpectMethod(typeSystem);
-            }
-        }
-    }
-
-    private boolean verifyIsMethod(TypeSystemData typeSystem, ExecutableElement method) {
-        AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCheck.class);
-        if (mirror == null) {
-            typeSystem.addError("Method starting with the pattern is${typeName} must be annotated with @%s.", TypeCheck.class.getSimpleName());
-            return false;
-        }
-        return true;
-    }
-
-    private boolean verifyAsMethod(TypeSystemData typeSystem, ExecutableElement method) {
-        AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCast.class);
-        if (mirror == null) {
-            typeSystem.addError("Method starting with the pattern as${typeName} must be annotated with @%s.", TypeCast.class.getSimpleName());
-            return false;
-        }
-        return true;
-    }
-
-    private static boolean verifyExpectMethod(TypeSystemData typeSystem) {
-        typeSystem.addError("Method starting with the pattern expect${typeName} must not be declared manually.");
-        return false;
-    }
-
-    private static void verifyNamesUnique(TypeSystemData typeSystem) {
-        List<TypeData> types = typeSystem.getTypes();
-        for (int i = 0; i < types.size(); i++) {
-            for (int j = i + 1; j < types.size(); j++) {
-                String name1 = Utils.getSimpleName(types.get(i).getBoxedType());
-                String name2 = Utils.getSimpleName(types.get(j).getBoxedType());
-                if (name1.equalsIgnoreCase(name2)) {
-                    typeSystem.addError("Two types result in the same name: %s, %s.", name1, name2);
-                }
-            }
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2014, 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.sl.test.instrument;
+
+import java.io.*;
+import java.nio.charset.*;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.util.*;
+
+import org.junit.*;
+import org.junit.internal.*;
+import org.junit.runner.*;
+import org.junit.runner.manipulation.*;
+import org.junit.runner.notification.*;
+import org.junit.runners.*;
+import org.junit.runners.model.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.instrument.*;
+import com.oracle.truffle.sl.parser.*;
+import com.oracle.truffle.sl.runtime.*;
+import com.oracle.truffle.sl.test.instrument.SLInstrumentTestRunner.InstrumentTestCase;
+
+/**
+ * This class builds and executes the tests for instrumenting SL. Although much of this class is
+ * written with future automation in mind, at the moment the tests that are created are hard-coded
+ * according to the file name of the test. To be automated, an automatic way of generating both the
+ * node visitor and the node prober is necessary.
+ *
+ * Testing is done via JUnit via comparing execution outputs with expected outputs.
+ */
+public final class SLInstrumentTestRunner extends ParentRunner<InstrumentTestCase> {
+
+    private static final String SOURCE_SUFFIX = ".sl";
+    private static final String INPUT_SUFFIX = ".input";
+    private static final String OUTPUT_SUFFIX = ".output";
+    private static final String ASSIGNMENT_VALUE_SUFFIX = "_assnCount";
+
+    private static final String LF = System.getProperty("line.separator");
+    private static SLContext slContext;
+
+    static class InstrumentTestCase {
+        protected final Description name;
+        protected final Path path;
+        protected final String baseName;
+        protected final String sourceName;
+        protected final String testInput;
+        protected final String expectedOutput;
+        protected String actualOutput;
+
+        protected InstrumentTestCase(Class<?> testClass, String baseName, String sourceName, Path path, String testInput, String expectedOutput) {
+            this.name = Description.createTestDescription(testClass, baseName);
+            this.baseName = baseName;
+            this.sourceName = sourceName;
+            this.path = path;
+            this.testInput = testInput;
+            this.expectedOutput = expectedOutput;
+        }
+    }
+
+    private final List<InstrumentTestCase> testCases;
+
+    public SLInstrumentTestRunner(Class<?> testClass) throws InitializationError {
+        super(testClass);
+        try {
+            testCases = createTests(testClass);
+        } catch (IOException e) {
+            throw new InitializationError(e);
+        }
+    }
+
+    @Override
+    protected List<InstrumentTestCase> getChildren() {
+        return testCases;
+    }
+
+    @Override
+    protected Description describeChild(InstrumentTestCase child) {
+        return child.name;
+    }
+
+    /**
+     * Tests are created based on the files that exist in the directory specified in the passed in
+     * annotation. Each test must have a source file and an expected output file. Optionally, each
+     * test can also include an input file. Source files have an ".sl" extension. Expected output
+     * have a ".output" extension. Input files have an ".input" extension. All these files must
+     * share the same base name to be correctly grouped. For example: "test1_assnCount.sl",
+     * "test1_assnCount.output" and "test1_assnCount.input" would all be used to create a single
+     * test called "test1_assnCount".
+     *
+     * This method iterates over the files in the directory and creates a new InstrumentTestCase for
+     * each group of related files. Each file is also expected to end with an identified at the end
+     * of the base name to indicate what visitor needs to be attached. Currently, visitors are hard
+     * coded to work on specific lines, so the code here is not currently generalizable.
+     *
+     * @param c The annotation containing the directory with tests
+     * @return A list of {@link InstrumentTestCase}s to run.
+     * @throws IOException If the directory is invalid.
+     * @throws InitializationError If no directory is provided.
+     *
+     * @see #runChild(InstrumentTestCase, RunNotifier)
+     */
+    protected static List<InstrumentTestCase> createTests(final Class<?> c) throws IOException, InitializationError {
+        SLInstrumentTestSuite suite = c.getAnnotation(SLInstrumentTestSuite.class);
+        if (suite == null) {
+            throw new InitializationError(String.format("@%s annotation required on class '%s' to run with '%s'.", SLInstrumentTestSuite.class.getSimpleName(), c.getName(),
+                            SLInstrumentTestRunner.class.getSimpleName()));
+        }
+
+        String[] paths = suite.value();
+
+        Path root = null;
+        for (String path : paths) {
+            root = FileSystems.getDefault().getPath(path);
+            if (Files.exists(root)) {
+                break;
+            }
+        }
+        if (root == null && paths.length > 0) {
+            throw new FileNotFoundException(paths[0]);
+        }
+
+        final Path rootPath = root;
+
+        final List<InstrumentTestCase> testCases = new ArrayList<>();
+
+        // Scaffolding in place for future automation
+        Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
+            @Override
+            public FileVisitResult visitFile(Path sourceFile, BasicFileAttributes attrs) throws IOException {
+                String sourceName = sourceFile.getFileName().toString();
+                if (sourceName.endsWith(SOURCE_SUFFIX)) {
+                    String baseName = sourceName.substring(0, sourceName.length() - SOURCE_SUFFIX.length());
+
+                    Path inputFile = sourceFile.resolveSibling(baseName + INPUT_SUFFIX);
+                    String testInput = "";
+                    if (Files.exists(inputFile)) {
+                        testInput = readAllLines(inputFile);
+                    }
+
+                    Path outputFile = sourceFile.resolveSibling(baseName + OUTPUT_SUFFIX);
+                    String expectedOutput = "";
+                    if (Files.exists(outputFile)) {
+                        expectedOutput = readAllLines(outputFile);
+                    }
+
+                    testCases.add(new InstrumentTestCase(c, baseName, sourceName, sourceFile, testInput, expectedOutput));
+
+                }
+                return FileVisitResult.CONTINUE;
+            }
+        });
+
+        return testCases;
+    }
+
+    private static String readAllLines(Path file) throws IOException {
+        // fix line feeds for non unix os
+        StringBuilder outFile = new StringBuilder();
+        for (String line : Files.readAllLines(file, Charset.defaultCharset())) {
+            outFile.append(line).append(LF);
+        }
+        return outFile.toString();
+    }
+
+    /**
+     * Executes the passed in test case. Instrumentation is added according to the name of the file
+     * as explained in {@link #createTests(Class)}. Note that this code is not generalizable.
+     */
+    @Override
+    protected void runChild(InstrumentTestCase testCase, RunNotifier notifier) {
+        // TODO Current tests are hard-coded, automate this eventually
+        notifier.fireTestStarted(testCase.name);
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        PrintStream printer = new PrintStream(out);
+        try {
+            // We use the name of the file to determine what visitor to attach to it.
+            if (testCase.baseName.endsWith(ASSIGNMENT_VALUE_SUFFIX)) {
+                // Set up the execution context for Simple and register our two listeners
+                slContext = new SLContext(new BufferedReader(new StringReader(testCase.testInput)), printer);
+
+                final Source source = Source.fromText(readAllLines(testCase.path), testCase.sourceName);
+                Parser.parseSL(slContext, source);
+                List<SLFunction> functionList = slContext.getFunctionRegistry().getFunctions();
+
+                // Since only functions can be global in SL, this guarantees that we instrument
+                // everything of interest. Parsing must occur before accepting the visitors since
+                // the visitor which creates our instrumentation points expects a complete AST.
+
+                for (SLFunction function : functionList) {
+                    RootCallTarget rootCallTarget = function.getCallTarget();
+                    rootCallTarget.getRootNode().accept(new SLInstrumenter(slContext));
+                }
+
+                // We iterate over all tags the SLInsturmenter tagged as assignments and attach our
+                // test instrument to those.
+                for (Probe probe : slContext.findProbesTaggedAs(StandardSyntaxTag.ASSIGNMENT)) {
+                    if (probe.isTaggedAs(StandardSyntaxTag.ASSIGNMENT)) {
+                        probe.addInstrument(new SLPrintAssigmentValueInstrument(printer));
+                    }
+                }
+
+                SLFunction main = slContext.getFunctionRegistry().lookup("main");
+                main.getCallTarget().call();
+            } else {
+                notifier.fireTestFailure(new Failure(testCase.name, new UnsupportedOperationException("No instrumentation found.")));
+            }
+
+            String actualOutput = new String(out.toByteArray());
+            Assert.assertEquals(testCase.expectedOutput, actualOutput);
+        } catch (Throwable ex) {
+            notifier.fireTestFailure(new Failure(testCase.name, ex));
+        } finally {
+            notifier.fireTestFinished(testCase.name);
+        }
+
+    }
+
+    public static void runInMain(Class<?> testClass, String[] args) throws InitializationError, NoTestsRemainException {
+        JUnitCore core = new JUnitCore();
+        core.addListener(new TextListener(System.out));
+        SLInstrumentTestRunner suite = new SLInstrumentTestRunner(testClass);
+        if (args.length > 0) {
+            suite.filter(new NameFilter(args[0]));
+        }
+        Result r = core.run(suite);
+        if (!r.wasSuccessful()) {
+            System.exit(1);
+        }
+    }
+
+    private static final class NameFilter extends Filter {
+        private final String pattern;
+
+        private NameFilter(String pattern) {
+            this.pattern = pattern.toLowerCase();
+        }
+
+        @Override
+        public boolean shouldRun(Description description) {
+            return description.getMethodName().toLowerCase().contains(pattern);
+        }
+
+        @Override
+        public String describe() {
+            return "Filter contains " + pattern;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestSuite.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014, 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.sl.test.instrument;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface SLInstrumentTestSuite {
+
+    /**
+     * Defines the base path of the test suite. Multiple base paths can be specified. However only
+     * the first base that exists is used to lookup the test cases.
+     */
+    String[] value();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLPrintAssigmentValueInstrument.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, 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.sl.test.instrument;
+
+import java.io.*;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.sl.nodes.local.*;
+
+/**
+ * This sample instrument provides prints the value of an assignment (after the assignment is
+ * complete) to the {@link PrintStream} specified in the constructor. This instrument can only be
+ * attached to a wrapped {@link SLWriteLocalVariableNode}, but provides no guards to protect it from
+ * being attached elsewhere.
+ */
+public final class SLPrintAssigmentValueInstrument extends Instrument {
+
+    private PrintStream output;
+
+    public SLPrintAssigmentValueInstrument(PrintStream output) {
+        this.output = output;
+    }
+
+    @Override
+    public void leave(Node astNode, VirtualFrame frame, Object result) {
+        output.println(result);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLSimpleInstrumentTestSuite.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014, 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.sl.test.instrument;
+
+import org.junit.*;
+import org.junit.runner.*;
+
+@RunWith(SLInstrumentTestRunner.class)
+@SLInstrumentTestSuite({"graal/com.oracle.truffle.sl.test/tests_instrumentation", "tests_instrumentation"})
+public class SLSimpleInstrumentTestSuite {
+
+    public static void main(String[] args) throws Exception {
+        SLInstrumentTestRunner.runInMain(SLSimpleInstrumentTestSuite.class, args);
+    }
+
+    /*
+     * Our "mx unittest" command looks for methods that are annotated with @Test. By just defining
+     * an empty method, this class gets included and the test suite is properly executed.
+     */
+    @Test
+    public void unittest() {
+    }
+}
--- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError02.output	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.sl.test/tests/error/TypeError02.output	Mon Aug 25 21:15:59 2014 -0700
@@ -1,1 +1,1 @@
-Type error at TypeError02.sl line 2 col 6: operation "if" not defined for String "4"
+Type error at TypeError02.sl line 2 col 3: operation "if" not defined for String "4"
--- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError04.output	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.sl.test/tests/error/TypeError04.output	Mon Aug 25 21:15:59 2014 -0700
@@ -1,1 +1,1 @@
-Type error at TypeError04.sl line 2 col 4: operation "||" not defined for Boolean false, Number 4
+Type error at TypeError04.sl line 2 col 3: operation "||" not defined for Boolean false, Number 4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.output	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,103 @@
+100
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+100
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.sl	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,11 @@
+function loop(count) {  
+  i = 0;  
+  while (i < count) {  
+    i = i + 1;  
+  }  
+  return i;  
+}
+
+function main() {
+  count = loop(100);
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java	Mon Aug 25 21:15:59 2014 -0700
@@ -152,7 +152,7 @@
         if (sourceCallback != null) {
             sourceCallback.startLoading(source);
         }
-        Parser.parseSL(context, source, null);
+        Parser.parseSL(context, source);
         if (sourceCallback != null) {
             sourceCallback.endLoading(source);
         }
@@ -192,6 +192,7 @@
         } finally {
             printScript("after execution", context, logOutput, printASTToLog, printSourceAttributionToLog, dumpASTToIGV);
         }
+        return;
     }
 
     /**
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java	Mon Aug 25 21:15:59 2014 -0700
@@ -50,6 +50,6 @@
     private static void doDefineFunction(SLContext context, String code) {
         Source source = Source.fromText(code, "[defineFunction]");
         /* The same parsing code as for parsing the initial source. */
-        Parser.parseSL(context, source, null);
+        Parser.parseSL(context, source);
     }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java	Mon Aug 25 21:15:59 2014 -0700
@@ -29,8 +29,6 @@
 
 public final class SLContextFactory {
 
-    private static SLASTProber astProber;
-
     private SLContextFactory() {
 
     }
@@ -39,12 +37,6 @@
         final SLContext slContext = new SLContext(new BufferedReader(new InputStreamReader(System.in)), System.out);
         slContext.initialize();
         slContext.setVisualizer(new SLDefaultVisualizer());
-        astProber = new SLASTProber();
-        slContext.setASTNodeProber(astProber);
         return slContext;
     }
-
-    public static void addNodeProber(SLNodeProber nodeProber) {
-        astProber.addNodeProber(nodeProber);
-    }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLExpressionNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLExpressionNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,10 +24,13 @@
 
 import java.math.*;
 
+import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.instrument.*;
 import com.oracle.truffle.sl.runtime.*;
 
 /**
@@ -87,4 +90,20 @@
     public SLNull executeNull(VirtualFrame frame) throws UnexpectedResultException {
         return SLTypesGen.SLTYPES.expectSLNull(executeGeneric(frame));
     }
+
+    @Override
+    public Probe probe(ExecutionContext context) {
+        Node parent = getParent();
+
+        if (parent == null)
+            throw new IllegalStateException("Cannot probe a node without a parent");
+
+        if (parent instanceof SLExpressionWrapper)
+            return ((SLExpressionWrapper) parent).getProbe();
+
+        SLExpressionWrapper wrapper = new SLExpressionWrapper((SLContext) context, this);
+        this.replace(wrapper);
+        wrapper.insertChild();
+        return wrapper.getProbe();
+    }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -22,9 +22,15 @@
  */
 package com.oracle.truffle.sl.nodes;
 
+import java.io.*;
+
+import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.instrument.*;
+import com.oracle.truffle.sl.runtime.*;
 
 /**
  * The base class of all Truffle nodes for SL. All nodes (even expressions) can be used as
@@ -32,7 +38,7 @@
  * local variables.
  */
 @NodeInfo(language = "Simple Language", description = "The abstract base node for all statements")
-public abstract class SLStatementNode extends Node {
+public abstract class SLStatementNode extends Node implements Instrumentable {
 
     public SLStatementNode(SourceSection src) {
         super(src);
@@ -46,4 +52,53 @@
     public SLStatementNode getNonWrapperNode() {
         return this;
     }
+
+    @Override
+    public String toString() {
+        return formatSourceSection(this);
+    }
+
+    /**
+     * Formats a source section of a node in human readable form. If no source section could be
+     * found it looks up the parent hierarchy until it finds a source section. Nodes where this was
+     * required append a <code>'~'</code> at the end.
+     *
+     * @param node the node to format.
+     * @return a formatted source section string
+     */
+    private static String formatSourceSection(Node node) {
+        if (node == null) {
+            return "<unknown>";
+        }
+        SourceSection section = node.getSourceSection();
+        boolean estimated = false;
+        if (section == null) {
+            section = node.getEncapsulatingSourceSection();
+            estimated = true;
+        }
+
+        if (section == null || section.getSource() == null) {
+            return "<unknown source>";
+        } else {
+            String sourceName = new File(section.getSource().getName()).getName();
+            int startLine = section.getStartLine();
+            return String.format("%s:%d%s", sourceName, startLine, estimated ? "~" : "");
+        }
+    }
+
+    @Override
+    public Probe probe(ExecutionContext context) {
+        Node parent = getParent();
+
+        if (parent == null)
+            throw new IllegalStateException("Cannot probe a node without a parent");
+
+        if (parent instanceof SLStatementWrapper)
+            return ((SLStatementWrapper) parent).getProbe();
+
+        SLStatementWrapper wrapper = new SLStatementWrapper((SLContext) context, this);
+        this.replace(wrapper);
+        wrapper.insertChild();
+        return wrapper.getProbe();
+    }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -41,7 +41,7 @@
      */
     @Children private final SLStatementNode[] bodyNodes;
 
-    public SLBlockNode(SourceSection src, SLStatementNode[] bodyNodes) {
+    public SLBlockNode(SourceSection src, SLStatementNode... bodyNodes) {
         super(src);
         this.bodyNodes = bodyNodes;
     }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.api.utilities.*;
 import com.oracle.truffle.sl.nodes.*;
 import com.oracle.truffle.sl.runtime.*;
@@ -49,8 +50,8 @@
     private final BranchProfile exceptionTaken = new BranchProfile();
     private final BranchProfile nullTaken = new BranchProfile();
 
-    public SLFunctionBodyNode(SLStatementNode bodyNode) {
-        super(null);
+    public SLFunctionBodyNode(SourceSection src, SLStatementNode bodyNode) {
+        super(src);
         this.bodyNode = bodyNode;
     }
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -46,12 +46,13 @@
     @Child private SLStatementNode elsePartNode;
 
     /**
-     * Profiling information, collected by the interpreter, capturing whether the then-branch was
-     * used (analogously for the {@link #elseTaken else-branch}). This allows the compiler to
-     * generate better code for conditions that are always true or always false.
+     * Profiling information, collected by the interpreter, capturing the profiling information of
+     * the condition. This allows the compiler to generate better code for conditions that are
+     * always true or always false. Additionally the {@link CountingConditionProfile} implementation
+     * (as opposed to {@link BinaryConditionProfile} implementation) transmits the probability of
+     * the condition to be true to the compiler.
      */
-    private final BranchProfile thenTaken = new BranchProfile();
-    private final BranchProfile elseTaken = new BranchProfile();
+    private final ConditionProfile condition = ConditionProfile.createCountingProfile();
 
     public SLIfNode(SourceSection src, SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) {
         super(src);
@@ -62,14 +63,14 @@
 
     @Override
     public void executeVoid(VirtualFrame frame) {
-        if (evaluateCondition(frame)) {
-            /* In the interpreter, record profiling information that the then-branch was used. */
-            thenTaken.enter();
+        /*
+         * In the interpreter, record profiling information that the condition was executed and with
+         * which outcome.
+         */
+        if (condition.profile(evaluateCondition(frame))) {
             /* Execute the then-branch. */
             thenPartNode.executeVoid(frame);
         } else {
-            /* In the interpreter, record profiling information that the else-branch was used. */
-            elseTaken.enter();
             /* Execute the else-branch (which is optional according to the SL syntax). */
             if (elsePartNode != null) {
                 elsePartNode.executeVoid(frame);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLRepeatingNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2012, 2014, 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.sl.nodes.controlflow;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.api.utilities.*;
+import com.oracle.truffle.sl.nodes.*;
+
+public final class SLRepeatingNode extends Node implements RepeatingNode {
+
+    /**
+     * The condition of the loop. This in a {@link SLExpressionNode} because we require a result
+     * value. We do not have a node type that can only return a {@code boolean} value, so
+     * {@link #evaluateCondition executing the condition} can lead to a type error.
+     */
+    @Child private SLExpressionNode conditionNode;
+
+    /** Statement (or {@link SLBlockNode block}) executed as long as the condition is true. */
+    @Child private SLStatementNode bodyNode;
+
+    /**
+     * Profiling information, collected by the interpreter, capturing whether a {@code continue}
+     * statement was used in this loop. This allows the compiler to generate better code for loops
+     * without a {@code continue}.
+     */
+    private final BranchProfile continueTaken = new BranchProfile();
+    private final BranchProfile breakTaken = new BranchProfile();
+
+    public SLRepeatingNode(SourceSection src, SLExpressionNode conditionNode, SLStatementNode bodyNode) {
+        super(src);
+        this.conditionNode = conditionNode;
+        this.bodyNode = bodyNode;
+    }
+
+    public boolean executeRepeating(VirtualFrame frame) {
+        if (evaluateCondition(frame)) {
+            try {
+                /* Execute the loop body. */
+                bodyNode.executeVoid(frame);
+            } catch (SLContinueException ex) {
+                /* In the interpreter, record profiling information that the loop uses continue. */
+                continueTaken.enter();
+                /* Fall through to next loop iteration. */
+            } catch (SLBreakException ex) {
+                /* In the interpreter, record profiling information that the loop uses break. */
+                breakTaken.enter();
+                /* Done executing this loop, exit method to execute statement following the loop. */
+                return false;
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private boolean evaluateCondition(VirtualFrame frame) {
+        try {
+            /*
+             * The condition must evaluate to a boolean value, so we call the boolean-specialized
+             * execute method.
+             */
+            return (conditionNode.executeBoolean(frame));
+        } catch (UnexpectedResultException ex) {
+            /*
+             * The condition evaluated to a non-boolean result. This is a type error in the SL
+             * program. We report it with the same exception that Truffle DSL generated nodes use to
+             * report type errors.
+             */
+            throw new UnsupportedSpecializationException(this, new Node[]{conditionNode}, ex.getResult());
+        }
+    }
+
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -23,89 +23,24 @@
 package com.oracle.truffle.sl.nodes.controlflow;
 
 import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.api.utilities.*;
 import com.oracle.truffle.sl.nodes.*;
 
 @NodeInfo(shortName = "while", description = "The node implementing a while loop")
 public final class SLWhileNode extends SLStatementNode {
 
-    /**
-     * The condition of the loop. This in a {@link SLExpressionNode} because we require a result
-     * value. We do not have a node type that can only return a {@code boolean} value, so
-     * {@link #evaluateCondition executing the condition} can lead to a type error.
-     */
-    @Child private SLExpressionNode conditionNode;
-
-    /** Statement (or {@link SLBlockNode block}) executed as long as the condition is true. */
-    @Child private SLStatementNode bodyNode;
-
-    /**
-     * Profiling information, collected by the interpreter, capturing whether a {@code continue}
-     * statement was used in this loop. This allows the compiler to generate better code for loops
-     * without a {@code continue}.
-     */
-    private final BranchProfile continueTaken = new BranchProfile();
-    private final BranchProfile breakTaken = new BranchProfile();
+    @Child private LoopNode loopNode;
 
     public SLWhileNode(SourceSection src, SLExpressionNode conditionNode, SLStatementNode bodyNode) {
         super(src);
-        this.conditionNode = conditionNode;
-        this.bodyNode = bodyNode;
+        this.loopNode = Truffle.getRuntime().createLoopNode(new SLRepeatingNode(src, conditionNode, bodyNode));
     }
 
     @Override
     public void executeVoid(VirtualFrame frame) {
-        int count = 0;
-        try {
-            while (evaluateCondition(frame)) {
-                try {
-                    /* Execute the loop body. */
-                    bodyNode.executeVoid(frame);
-
-                    if (CompilerDirectives.inInterpreter()) {
-                        /* In the interpreter, profile the the number of loop iteration. */
-                        count++;
-                    }
-                } catch (SLContinueException ex) {
-                    /* In the interpreter, record profiling information that the loop uses continue. */
-                    continueTaken.enter();
-                    /* Fall through to next loop iteration. */
-                }
-            }
-        } catch (SLBreakException ex) {
-            /* In the interpreter, record profiling information that the loop uses break. */
-            breakTaken.enter();
-            /* Done executing this loop, exit method to execute statement following the loop. */
-
-        } finally {
-            if (CompilerDirectives.inInterpreter()) {
-                /*
-                 * In the interpreter, report the loop count to the Truffle system. It is used for
-                 * compilation and inlining decisions.
-                 */
-                getRootNode().reportLoopCount(count);
-            }
-        }
+        loopNode.executeLoop(frame);
     }
 
-    private boolean evaluateCondition(VirtualFrame frame) {
-        try {
-            /*
-             * The condition must evaluate to a boolean value, so we call the boolean-specialized
-             * execute method.
-             */
-            return conditionNode.executeBoolean(frame);
-        } catch (UnexpectedResultException ex) {
-            /*
-             * The condition evaluated to a non-boolean result. This is a type error in the SL
-             * program. We report it with the same exception that Truffle DSL generated nodes use to
-             * report type errors.
-             */
-            throw new UnsupportedSpecializationException(this, new Node[]{conditionNode}, ex.getResult());
-        }
-    }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLEqualNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLEqualNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -83,11 +83,11 @@
     }
 
     /**
-     * The {@link Generic} annotation informs the Truffle DSL that this method should be executed
+     * The {@link Fallback} annotation informs the Truffle DSL that this method should be executed
      * when no {@link Specialization specialized method} matches. The operand types must be
      * {@link Object}.
      */
-    @Generic
+    @Fallback
     protected boolean equal(Object left, Object right) {
         /*
          * We covered all the cases that can return true in specializations. If we compare two
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLParenExpressionNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014, 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.sl.nodes.expression;
+
+import java.math.*;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * A {@link SLExpressionNode} that represents a parenthesized expression; it simply returns the
+ * value of the enclosed (child) expression. It is represented separately in the AST for the purpose
+ * of correct source attribution; this preserves the lexical relationship between the two
+ * parentheses and allows a tool to describe the expression as distinct from its contents.
+ */
+@NodeInfo(description = "A parenthesized expression")
+public class SLParenExpressionNode extends SLExpressionNode {
+
+    private final SLExpressionNode expression;
+
+    public SLParenExpressionNode(SourceSection src, SLExpressionNode expression) {
+        super(src);
+        this.expression = insert(expression);
+    }
+
+    @Override
+    public Object executeGeneric(VirtualFrame frame) {
+        return expression.executeGeneric(frame);
+    }
+
+    @Override
+    public long executeLong(VirtualFrame frame) throws UnexpectedResultException {
+        return expression.executeLong(frame);
+    }
+
+    @Override
+    public BigInteger executeBigInteger(VirtualFrame frame) throws UnexpectedResultException {
+        return expression.executeBigInteger(frame);
+    }
+
+    @Override
+    public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException {
+        return expression.executeBoolean(frame);
+    }
+
+    @Override
+    public String executeString(VirtualFrame frame) throws UnexpectedResultException {
+        return expression.executeString(frame);
+    }
+
+    @Override
+    public SLFunction executeFunction(VirtualFrame frame) throws UnexpectedResultException {
+        return expression.executeFunction(frame);
+    }
+
+    @Override
+    public SLNull executeNull(VirtualFrame frame) throws UnexpectedResultException {
+        return expression.executeNull(frame);
+    }
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTProber.java	Mon Aug 25 14:42:42 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, 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.sl.nodes.instrument;
-
-import java.util.*;
-
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * SLASTProber contains the collection of {@link SLNodeProber}s and methods to attach the probers to
- * nodes.
- */
-public final class SLASTProber implements ASTProber, SLNodeProber {
-
-    private ArrayList<SLNodeProber> nodeProbers = new ArrayList<>();
-
-    public SLASTProber() {
-    }
-
-    /**
-     * Adds a {@link SLNodeProber} to this SLASTProber. Probes must be of type {@link SLNodeProber}
-     * and must not already have been added.
-     *
-     * @param nodeProber the {@link SLNodeProber} to add.
-     */
-    public void addNodeProber(ASTNodeProber nodeProber) {
-        if (nodeProber instanceof SLNodeProber) {
-            assert !nodeProbers.contains(nodeProber);
-            nodeProbers.add((SLNodeProber) nodeProber);
-        } else {
-            throw new IllegalArgumentException("invalid prober for SL implementation");
-        }
-    }
-
-    /**
-     * Unimplemented, does nothing.
-     */
-    public Node probeAs(Node astNode, SyntaxTag tag, Object... args) {
-        return astNode;
-    }
-
-    /**
-     * Attaches the current probers to the given {@link SLStatementNode} as a statement.
-     *
-     * @param node The {@link SLStatementNode} to attach the stored set of probers to.
-     */
-    @Override
-    public SLStatementNode probeAsStatement(SLStatementNode node) {
-        SLStatementNode result = node;
-        for (SLNodeProber nodeProber : nodeProbers) {
-            result = nodeProber.probeAsStatement(result);
-        }
-        return result;
-    }
-
-    /**
-     * Attaches the current probers to the given {@link SLExpressionNode} as a call. This will wrap
-     * the passed in node in an {@link SLExpressionWrapper}, tag it as a call and attach an
-     * instrument to it.
-     *
-     * @param node The {@link SLExpressionNode} to attach the stored set of probers to.
-     * @param callName The name of the call ???
-     *
-     */
-    @Override
-    public SLExpressionNode probeAsCall(SLExpressionNode node, String callName) {
-        SLExpressionNode result = node;
-        for (SLNodeProber nodeProber : nodeProbers) {
-            result = nodeProber.probeAsCall(node, callName);
-        }
-        return result;
-    }
-
-    /**
-     * Attaches the current probers to the given {@link SLExpressionNode} as an assignment. This
-     * will wrap the passed in node in an {@link SLExpressionWrapper}, tag it as an assignment and
-     * attach an instrument to it.
-     *
-     * @param node The {@link SLExpressionNode} to attached the stored set of probers to.
-     * @param localName The name of the assignment ???
-     *
-     */
-    @Override
-    public SLExpressionNode probeAsLocalAssignment(SLExpressionNode node, String localName) {
-        SLExpressionNode result = node;
-        for (SLNodeProber nodeProber : nodeProbers) {
-            result = nodeProber.probeAsLocalAssignment(result, localName);
-        }
-        return result;
-    }
-
-    public ASTNodeProber getCombinedNodeProber() {
-        return nodeProbers.isEmpty() ? null : this;
-    }
-
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapper.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapper.java	Mon Aug 25 21:15:59 2014 -0700
@@ -46,11 +46,19 @@
 
     private final Probe probe;
 
+    /**
+     * Constructor.
+     *
+     * @param context The current Simple execution context
+     * @param child The {@link SLExpressionNode} that this wrapper is wrapping
+     */
     public SLExpressionWrapper(SLContext context, SLExpressionNode child) {
         super(child.getSourceSection());
         assert !(child instanceof SLExpressionWrapper);
-        this.child = insert(child);
-        this.probe = context.getProbe(child.getSourceSection());
+        this.probe = context.createProbe(child.getSourceSection());
+        this.child = child;
+        // The child should only be inserted after a replace, so we defer inserting the child to the
+        // creator of the wrapper.
     }
 
     @Override
@@ -145,4 +153,11 @@
     public SLNull executeNull(VirtualFrame frame) throws UnexpectedResultException {
         return SLTypesGen.SLTYPES.expectSLNull(executeGeneric(frame));
     }
+
+    /**
+     * Sets the parent pointer of this wrapper's child.
+     */
+    public void insertChild() {
+        insert(this.child);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLInstrumenter.java	Mon Aug 25 21:15:59 2014 -0700
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014, 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.sl.nodes.instrument;
+
+import static com.oracle.truffle.api.instrument.StandardSyntaxTag.*;
+
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.nodes.controlflow.*;
+import com.oracle.truffle.sl.nodes.local.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * This is a general purpose visitor which traverses a completely parsed Simple AST and instruments
+ * all the nodes within it. This visitor is designed to visit the tree immediately after it has been
+ * parsed.
+ *
+ */
+public class SLInstrumenter implements NodeVisitor {
+
+    private final SLContext context;
+
+    public SLInstrumenter(SLContext context) {
+        this.context = context;
+    }
+
+    /**
+     * Instruments and tags all relevant {@link SLStatementNode}s and {@link SLExpressionNode}s.
+     * Currently, only SLStatementNodes that are not SLExpressionNodes are tagged as statements.
+     */
+    public boolean visit(Node node) {
+        // We have to distinguish between SLExpressionNode and SLStatementNode since some of the
+        // generated factories have methods that require SLExpressionNodes as parameters. Since
+        // SLExpressionNodes are a subclass of SLStatementNode, we check if something is an
+        // SLExpressionNode first.
+        if (node instanceof SLExpressionNode && node.getParent() != null) {
+            SLExpressionNode expressionNode = (SLExpressionNode) node;
+            if (expressionNode.getSourceSection() != null) {
+                Probe probe = expressionNode.probe(context);
+                // probe.tagAs(STATEMENT);
+
+                if (node instanceof SLWriteLocalVariableNode)
+                    probe.tagAs(ASSIGNMENT);
+            }
+        } else if (node instanceof SLStatementNode && node.getParent() != null) {
+
+            SLStatementNode statementNode = (SLStatementNode) node;
+            if (statementNode.getSourceSection() != null) {
+                Probe probe = statementNode.probe(context);
+                probe.tagAs(STATEMENT);
+
+                if (node instanceof SLWhileNode)
+                    probe.tagAs(START_LOOP);
+            }
+        }
+
+        return true;
+    }
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapper.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapper.java	Mon Aug 25 21:15:59 2014 -0700
@@ -48,8 +48,10 @@
     public SLStatementWrapper(SLContext context, SLStatementNode child) {
         super(child.getSourceSection());
         assert !(child instanceof SLStatementWrapper);
-        this.child = insert(child);
-        this.probe = context.getProbe(child.getSourceSection());
+        this.probe = context.createProbe(child.getSourceSection());
+        this.child = child;
+        // The child should only be inserted after a replace, so we defer inserting the child to the
+        // creator of the wrapper.
     }
 
     @Override
@@ -94,6 +96,12 @@
             probe.leaveExceptional(child, frame, e);
             throw (e);
         }
+    }
 
+    /**
+     * Sets the parent pointer of this wrapper's child.
+     */
+    public void insertChild() {
+        insert(this.child);
     }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadLocalVariableNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadLocalVariableNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -57,7 +57,7 @@
         return frame.getBoolean(getSlot());
     }
 
-    @Specialization(order = 1, rewriteOn = FrameSlotTypeException.class)
+    @Specialization(rewriteOn = FrameSlotTypeException.class)
     protected Object readObject(VirtualFrame frame) throws FrameSlotTypeException {
         return frame.getObject(getSlot());
     }
@@ -66,7 +66,7 @@
      * This is the generic case that always succeeds. Since we already have another specialization
      * with the same signature above, we need to order them explicitly with the order attribute.
      */
-    @Specialization(order = 2)
+    @Specialization(contains = {"readLong", "readBoolean", "readObject"})
     protected Object read(VirtualFrame frame) {
         return frame.getValue(getSlot());
     }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java	Mon Aug 25 21:15:59 2014 -0700
@@ -52,13 +52,13 @@
      * {@link #isLongKind() custom guard} is specified.
      */
     @Specialization(guards = "isLongKind")
-    protected long write(VirtualFrame frame, long value) {
+    protected long writeLong(VirtualFrame frame, long value) {
         frame.setLong(getSlot(), value);
         return value;
     }
 
     @Specialization(guards = "isBooleanKind")
-    protected boolean write(VirtualFrame frame, boolean value) {
+    protected boolean writeBoolean(VirtualFrame frame, boolean value) {
         frame.setBoolean(getSlot(), value);
         return value;
     }
@@ -66,14 +66,14 @@
     /**
      * Generic write method that works for all possible types.
      * <p>
-     * Why is this method annotated with {@link Specialization} and not {@link Generic}? For a
-     * {@link Generic} method, the Truffle DSL generated code would try all other specializations
+     * Why is this method annotated with {@link Specialization} and not {@link Fallback}? For a
+     * {@link Fallback} method, the Truffle DSL generated code would try all other specializations
      * first before calling this method. We know that all these specializations would fail their
      * guards, so there is no point in calling them. Since this method takes a value of type
      * {@link Object}, it is guaranteed to never fail, i.e., once we are in this specialization the
      * node will never be re-specialized.
      */
-    @Specialization
+    @Specialization(contains = {"writeLong", "writeBoolean"})
     protected Object write(VirtualFrame frame, Object value) {
         if (getSlot().getKind() != FrameSlotKind.Object) {
             /*
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame	Mon Aug 25 21:15:59 2014 -0700
@@ -33,7 +33,6 @@
 import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.*;
 import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.nodes.instrument.*;
 import com.oracle.truffle.sl.runtime.*;
 
 // Checkstyle: stop
@@ -52,9 +51,9 @@
     public final Errors errors;
     private final SLNodeFactory factory;
     -->declarations
-    public Parser(SLContext context, Source source, SLNodeProber astProber) {
+    public Parser(SLContext context, Source source) {
         this.scanner = new Scanner(source.getInputStream());
-        this.factory = new SLNodeFactory(context, source, astProber);
+        this.factory = new SLNodeFactory(context, source);
         errors = new Errors();
     }
 
@@ -135,8 +134,8 @@
 -->initialization
     };
 
-    public static void parseSL(SLContext context, Source source, SLNodeProber astProber) {
-        Parser parser = new Parser(context, source, astProber);
+    public static void parseSL(SLContext context, Source source) {
+        Parser parser = new Parser(context, source);
         parser.Parse();
         if (parser.errors.errors.size() > 0) {
             StringBuilder msg = new StringBuilder("Error(s) parsing script:\n");
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java	Mon Aug 25 21:15:59 2014 -0700
@@ -30,7 +30,6 @@
 import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.*;
 import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.nodes.instrument.*;
 import com.oracle.truffle.sl.runtime.*;
 
 // Checkstyle: stop
@@ -54,9 +53,9 @@
     public final Errors errors;
     private final SLNodeFactory factory;
 
-    public Parser(SLContext context, Source source, SLNodeProber astProber) {
+    public Parser(SLContext context, Source source) {
         this.scanner = new Scanner(source.getInputStream());
-        this.factory = new SLNodeFactory(context, source, astProber);
+        this.factory = new SLNodeFactory(context, source);
         errors = new Errors();
     }
 
@@ -134,8 +133,10 @@
 	void Function() {
 		Expect(4);
 		Expect(1);
-		factory.startFunction(t);
+		Token identifierToken = t;
 		Expect(5);
+		int bodyStartPos = t.charPos;
+		factory.startFunction(identifierToken, bodyStartPos);
 		if (la.kind == 1) {
 			Get();
 			factory.addFormalParameter(t);
@@ -155,14 +156,14 @@
 		factory.startBlock();
 		List<SLStatementNode> body = new ArrayList<>();
 		Expect(8);
-		int lBracePos = t.charPos;
+		int start = t.charPos;
 		while (StartOf(1)) {
 			SLStatementNode s = Statement(inLoop);
 			body.add(s);
 		}
 		Expect(9);
-		int length = (t.charPos + t.val.length()) - lBracePos;
-		result = factory.finishBlock(body, lBracePos, length);
+		int length = (t.charPos + t.val.length()) - start;
+		result = factory.finishBlock(body, start, length);
 		return result;
 	}
 
@@ -207,8 +208,8 @@
 	SLStatementNode  WhileStatement() {
 		SLStatementNode  result;
 		Expect(13);
+		Token whileToken = t;
 		Expect(5);
-		Token whileToken = t;
 		SLExpressionNode condition = Expression();
 		Expect(7);
 		SLStatementNode body = Block(true);
@@ -219,8 +220,8 @@
 	SLStatementNode  IfStatement(boolean inLoop) {
 		SLStatementNode  result;
 		Expect(14);
+		Token ifToken = t;
 		Expect(5);
-		Token ifToken = t;
 		SLExpressionNode condition = Expression();
 		Expect(7);
 		SLStatementNode thenPart = Block(inLoop);
@@ -376,8 +377,12 @@
 			result = factory.createNumericLiteral(t);
 		} else if (la.kind == 5) {
 			Get();
+			int start = t.charPos;
 			result = Expression();
+			SLExpressionNode expr = result;
 			Expect(7);
+			int length = (t.charPos + t.val.length()) - start;
+			result = factory.createParenExpression(expr, start, length);
 		} else SynErr(33);
 		return result;
 	}
@@ -402,8 +407,8 @@
 
     };
 
-    public static void parseSL(SLContext context, Source source, SLNodeProber astProber) {
-        Parser parser = new Parser(context, source, astProber);
+    public static void parseSL(SLContext context, Source source) {
+        Parser parser = new Parser(context, source);
         parser.Parse();
         if (parser.errors.errors.size() > 0) {
             StringBuilder msg = new StringBuilder("Error(s) parsing script:\n");
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java	Mon Aug 25 21:15:59 2014 -0700
@@ -32,7 +32,6 @@
 import com.oracle.truffle.sl.nodes.call.*;
 import com.oracle.truffle.sl.nodes.controlflow.*;
 import com.oracle.truffle.sl.nodes.expression.*;
-import com.oracle.truffle.sl.nodes.instrument.*;
 import com.oracle.truffle.sl.nodes.local.*;
 import com.oracle.truffle.sl.runtime.*;
 
@@ -65,7 +64,9 @@
     private final Source source;
 
     /* State while parsing a function. */
+    private int functionStartPos;
     private String functionName;
+    private int functionBodyStartPos; // includes parameter list
     private int parameterCount;
     private FrameDescriptor frameDescriptor;
     private List<SLStatementNode> methodNodes;
@@ -73,21 +74,22 @@
     /* State while parsing a block. */
     private LexicalScope lexicalScope;
 
-    private final SLNodeProber prober;
-
-    public SLNodeFactory(SLContext context, Source source, SLNodeProber prober) {
+    public SLNodeFactory(SLContext context, Source source) {
         this.context = context;
         this.source = source;
-        this.prober = prober;
     }
 
-    public void startFunction(Token nameToken) {
+    public void startFunction(Token nameToken, int bodyStartPos) {
+        assert functionStartPos == 0;
         assert functionName == null;
+        assert functionBodyStartPos == 0;
         assert parameterCount == 0;
         assert frameDescriptor == null;
         assert lexicalScope == null;
 
+        functionStartPos = nameToken.charPos;
         functionName = nameToken.val;
+        functionBodyStartPos = bodyStartPos;
         frameDescriptor = new FrameDescriptor();
         methodNodes = new ArrayList<>();
         startBlock();
@@ -99,24 +101,27 @@
          * ensures that accesses to parameters are specialized the same way as local variables are
          * specialized.
          */
-        final SourceSection src = source.createSection(nameToken.val, nameToken.charPos, nameToken.val.length());
-        SLReadArgumentNode readArg = new SLReadArgumentNode(src, parameterCount);
+        final SourceSection src = srcFromToken(nameToken);
+        final SLReadArgumentNode readArg = new SLReadArgumentNode(src, parameterCount);
         methodNodes.add(createAssignment(nameToken, readArg));
         parameterCount++;
     }
 
     public void finishFunction(SLStatementNode bodyNode) {
         methodNodes.add(bodyNode);
-        // TODO (mlvdv) testing
-        SLStatementNode methodBlock = finishBlock(methodNodes, -1, -1);
+        final int bodyEndPos = bodyNode.getSourceSection().getCharEndIndex();
+        final SourceSection functionSrc = source.createSection(functionName, functionStartPos, bodyEndPos - functionStartPos);
+        final SLStatementNode methodBlock = finishBlock(methodNodes, functionBodyStartPos, bodyEndPos - functionBodyStartPos);
         assert lexicalScope == null : "Wrong scoping of blocks in parser";
 
-        SLFunctionBodyNode functionBodyNode = new SLFunctionBodyNode(methodBlock);
-        SLRootNode rootNode = new SLRootNode(frameDescriptor, functionBodyNode, functionName);
+        final SLFunctionBodyNode functionBodyNode = new SLFunctionBodyNode(functionSrc, methodBlock);
+        final SLRootNode rootNode = new SLRootNode(frameDescriptor, functionBodyNode, functionName);
 
         context.getFunctionRegistry().register(functionName, rootNode);
 
+        functionStartPos = 0;
         functionName = null;
+        functionBodyStartPos = 0;
         parameterCount = 0;
         frameDescriptor = null;
         lexicalScope = null;
@@ -126,34 +131,14 @@
         lexicalScope = new LexicalScope(lexicalScope);
     }
 
-    public SLStatementNode finishBlock(List<SLStatementNode> bodyNodes, int lBracePos, int length) {
+    public SLStatementNode finishBlock(List<SLStatementNode> bodyNodes, int startPos, int length) {
         lexicalScope = lexicalScope.outer;
 
         List<SLStatementNode> flattenedNodes = new ArrayList<>(bodyNodes.size());
         flattenBlocks(bodyNodes, flattenedNodes);
 
-        if (lBracePos >= 0) {
-            final SourceSection src = source.createSection("block", lBracePos, length);
-            return new SLBlockNode(src, flattenedNodes.toArray(new SLStatementNode[flattenedNodes.size()]));
-        }
-        if (flattenedNodes.size() == 0) {
-            // TODO (mlvdv) for error reporting, should have the character position, even if the
-            // block is empty.
-            return new SLBlockNode(null, new SLStatementNode[0]);
-        }
-        if (flattenedNodes.size() == 1) {
-            /*
-             * A block containing one other node, not surrounded by braces is unnecessary, we can
-             * just that other node.
-             */
-            return flattenedNodes.get(0);
-        }
-        /*
-         * A "block" not surrounded by braces.
-         */
-        final int start = flattenedNodes.get(0).getSourceSection().getCharIndex();
-        final int end = flattenedNodes.get(flattenedNodes.size() - 1).getSourceSection().getCharEndIndex();
-        return new SLBlockNode(source.createSection("block", start, end - start), flattenedNodes.toArray(new SLStatementNode[flattenedNodes.size()]));
+        final SourceSection src = source.createSection("block", startPos, length);
+        return new SLBlockNode(src, flattenedNodes.toArray(new SLStatementNode[flattenedNodes.size()]));
     }
 
     private void flattenBlocks(Iterable<? extends Node> bodyNodes, List<SLStatementNode> flattenedNodes) {
@@ -166,40 +151,82 @@
         }
     }
 
-    public SLStatementNode createBreak(Token t) {
-        return new SLBreakNode(source.createSection(t.val, t.charPos, t.val.length()));
+    /**
+     * Returns an {@link SLBreakNode} for the given token.
+     *
+     * @param breakToken The token containing the break node's info.
+     * @return A SLBreakNode for the given token.
+     */
+    public SLStatementNode createBreak(Token breakToken) {
+        final SLBreakNode breakNode = new SLBreakNode(srcFromToken(breakToken));
+        return breakNode;
     }
 
-    public SLStatementNode createContinue(Token t) {
-        return new SLContinueNode(source.createSection(t.val, t.charPos, t.val.length()));
-    }
-
-    public SLStatementNode createWhile(Token t, SLExpressionNode conditionNode, SLStatementNode bodyNode) {
-        final int start = t.charPos;
-        final int end = bodyNode.getSourceSection().getCharEndIndex();
-        return new SLWhileNode(source.createSection(t.val, start, end - start), conditionNode, bodyNode);
+    /**
+     * Returns an {@link SLContinueNode} for the given token.
+     *
+     * @param continueToken The token containing the continue node's info.
+     * @return A SLContinueNode built using the given token.
+     */
+    public SLStatementNode createContinue(Token continueToken) {
+        final SLContinueNode continueNode = new SLContinueNode(srcFromToken(continueToken));
+        return continueNode;
     }
 
-    public SLStatementNode createIf(Token t, SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) {
-        final int start = t.charPos;
-        final int end = elsePartNode == null ? thenPartNode.getSourceSection().getCharEndIndex() : elsePartNode.getSourceSection().getCharEndIndex();
-
-        // if (prober != null) {
-        // SLStatementNode wrappedThenNode = prober.probeAsStatement(thenPartNode);
-        // // SLStatementNode wrappedElseNode = prober.probeAsStatement(elsePartNode);
-        // return new SLIfNode(source.createSection(t.val, start, end - start), conditionNode,
-        // wrappedThenNode, elsePartNode);
-        // }
-
-        return new SLIfNode(source.createSection(t.val, start, end - start), conditionNode, thenPartNode, elsePartNode);
+    /**
+     * Returns an {@link SLWhileNode} for the given parameters.
+     *
+     * @param whileToken The token containing the while node's info
+     * @param conditionNode The conditional node for this while loop
+     * @param bodyNode The body of the while loop
+     * @return A SLWhileNode built using the given parameters.
+     */
+    public SLStatementNode createWhile(Token whileToken, SLExpressionNode conditionNode, SLStatementNode bodyNode) {
+        final int start = whileToken.charPos;
+        final int end = bodyNode.getSourceSection().getCharEndIndex();
+        final SLWhileNode whileNode = new SLWhileNode(source.createSection(whileToken.val, start, end - start), conditionNode, bodyNode);
+        return whileNode;
     }
 
+    /**
+     * Returns an {@link SLIfNode} for the given parameters.
+     *
+     * @param ifToken The token containing the if node's info
+     * @param conditionNode The condition node of this if statement
+     * @param thenPartNode The then part of the if
+     * @param elsePartNode The else part of the if
+     * @return An SLIfNode for the given parameters.
+     */
+    public SLStatementNode createIf(Token ifToken, SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) {
+        final int start = ifToken.charPos;
+        final int end = elsePartNode == null ? thenPartNode.getSourceSection().getCharEndIndex() : elsePartNode.getSourceSection().getCharEndIndex();
+        final SLIfNode ifNode = new SLIfNode(source.createSection(ifToken.val, start, end - start), conditionNode, thenPartNode, elsePartNode);
+        return ifNode;
+    }
+
+    /**
+     * Returns an {@link SLReturnNode} for the given parameters.
+     *
+     * @param t The token containing the return node's info
+     * @param valueNode The value of the return
+     * @return An SLReturnNode for the given parameters.
+     */
     public SLStatementNode createReturn(Token t, SLExpressionNode valueNode) {
         final int start = t.charPos;
         final int length = valueNode == null ? t.val.length() : valueNode.getSourceSection().getCharEndIndex() - start;
-        return new SLReturnNode(source.createSection(t.val, start, length), valueNode);
+        final SLReturnNode returnNode = new SLReturnNode(source.createSection(t.val, start, length), valueNode);
+        return returnNode;
     }
 
+    /**
+     * Returns the corresponding subclass of {@link SLExpressionNode} for binary expressions.
+     * </br>These nodes are currently not instrumented.
+     *
+     * @param opToken The operator of the binary expression
+     * @param leftNode The left node of the expression
+     * @param rightNode The right node of the expression
+     * @return A subclass of SLExpressionNode using the given parameters based on the given opToken.
+     */
     public SLExpressionNode createBinary(Token opToken, SLExpressionNode leftNode, SLExpressionNode rightNode) {
         int start = leftNode.getSourceSection().getCharIndex();
         int length = rightNode.getSourceSection().getCharEndIndex() - start;
@@ -234,33 +261,52 @@
         }
     }
 
+    /**
+     * Returns an {@link SLInvokeNode} for the given parameters.
+     *
+     * @param nameToken The name of the function being called
+     * @param parameterNodes The parameters of the function call
+     * @param finalToken A token used to determine the end of the sourceSelection for this call
+     * @return An SLInvokeNode for the given parameters.
+     */
     public SLExpressionNode createCall(Token nameToken, List<SLExpressionNode> parameterNodes, Token finalToken) {
         final int startPos = nameToken.charPos;
         final int endPos = finalToken.charPos + finalToken.val.length();
         final SourceSection src = source.createSection(nameToken.val, startPos, endPos - startPos);
         SLExpressionNode functionNode = createRead(nameToken);
-        if (prober != null) {
-            SLExpressionNode wrappedNode = prober.probeAsCall(functionNode, nameToken.val);
-            return SLInvokeNode.create(src, wrappedNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()]));
-        }
         return SLInvokeNode.create(src, functionNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()]));
     }
 
+    /**
+     * Returns an {@link SLWriteLocalVariableNode} for the given parameters.
+     *
+     * @param nameToken The name of the variable being assigned
+     * @param valueNode The value to be assigned
+     * @return An SLExpressionNode for the given parameters.
+     */
     public SLExpressionNode createAssignment(Token nameToken, SLExpressionNode valueNode) {
         FrameSlot frameSlot = frameDescriptor.findOrAddFrameSlot(nameToken.val);
         lexicalScope.locals.put(nameToken.val, frameSlot);
         final int start = nameToken.charPos;
         final int length = valueNode.getSourceSection().getCharEndIndex() - start;
-        if (prober != null) {
-            final SLExpressionNode wrappedNode = prober.probeAsLocalAssignment(valueNode, nameToken.val);
-            return SLWriteLocalVariableNodeFactory.create(source.createSection("=", start, length), wrappedNode, frameSlot);
-        }
         return SLWriteLocalVariableNodeFactory.create(source.createSection("=", start, length), valueNode, frameSlot);
     }
 
+    /**
+     * Returns a {@link SLReadLocalVariableNode} if this read is a local variable or a
+     * {@link SLFunctionLiteralNode} if this read is global. In Simple, the only global names are
+     * functions. </br> There is currently no instrumentation for this node.
+     *
+     * @param nameToken The name of the variable/function being read
+     * @return either:
+     *         <ul>
+     *         <li>A SLReadLocalVariableNode representing the local variable being read.</li>
+     *         <li>A SLFunctionLiteralNode representing the function definition</li>
+     *         </ul>
+     */
     public SLExpressionNode createRead(Token nameToken) {
         final FrameSlot frameSlot = lexicalScope.locals.get(nameToken.val);
-        final SourceSection src = source.createSection(nameToken.val, nameToken.charPos, nameToken.val.length());
+        final SourceSection src = srcFromToken(nameToken);
         if (frameSlot != null) {
             /* Read of a local variable. */
             return SLReadLocalVariableNodeFactory.create(src, frameSlot);
@@ -274,14 +320,14 @@
         /* Remove the trailing and ending " */
         String literal = literalToken.val;
         assert literal.length() >= 2 && literal.startsWith("\"") && literal.endsWith("\"");
-        final SourceSection src = source.createSection(literalToken.val, literalToken.charPos, literalToken.val.length());
+        final SourceSection src = srcFromToken(literalToken);
         literal = literal.substring(1, literal.length() - 1);
 
         return new SLStringLiteralNode(src, literal);
     }
 
     public SLExpressionNode createNumericLiteral(Token literalToken) {
-        final SourceSection src = source.createSection(literalToken.val, literalToken.charPos, literalToken.val.length());
+        final SourceSection src = srcFromToken(literalToken);
         try {
             /* Try if the literal is small enough to fit into a long value. */
             return new SLLongLiteralNode(src, Long.parseLong(literalToken.val));
@@ -291,4 +337,16 @@
         }
     }
 
+    public SLExpressionNode createParenExpression(SLExpressionNode expressionNode, int start, int length) {
+        final SourceSection src = source.createSection("()", start, length);
+        return new SLParenExpressionNode(src, expressionNode);
+    }
+
+    /**
+     * Creates source description of a single token.
+     */
+    private SourceSection srcFromToken(Token token) {
+        return source.createSection(token.val, token.charPos, token.val.length());
+    }
+
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg	Mon Aug 25 21:15:59 2014 -0700
@@ -65,9 +65,10 @@
 
 Function
 =
-"function"                                      
-identifier                                      (. factory.startFunction(t); .)
-"("
+"function"
+identifier            							(. Token identifierToken = t; .)                          
+"("												(. int bodyStartPos = t.charPos; .)
+												(. factory.startFunction(identifierToken, bodyStartPos); .)
 [
     identifier                                  (. factory.addFormalParameter(t); .)
     {
@@ -84,12 +85,12 @@
 Block<out SLStatementNode result, boolean inLoop>
 =                                               (. factory.startBlock();
                                                    List<SLStatementNode> body = new ArrayList<>(); .)
-"{"    											(. int lBracePos = t.charPos; .)
+"{"    											(. int start = t.charPos; .)
 {
     Statement<out SLStatementNode s, inLoop>    (. body.add(s); .)
 }
-"}"                                             (. int length = (t.charPos + t.val.length()) - lBracePos; .)
-												(. result = factory.finishBlock(body, lBracePos, length); .)
+"}"                                             (. int length = (t.charPos + t.val.length()) - start; .)
+												(. result = factory.finishBlock(body, start, length); .)
 .
 
 
@@ -115,8 +116,8 @@
 
 WhileStatement<out SLStatementNode result>
 =
-"while"
-"("                                             (. Token whileToken = t; .)
+"while"											(. Token whileToken = t; .)
+"("                                             
 Expression<out SLExpressionNode condition>
 ")" 
 Block<out SLStatementNode body, true>           (. result = factory.createWhile(whileToken, condition, body); .)
@@ -125,8 +126,8 @@
 
 IfStatement<out SLStatementNode result, boolean inLoop>
 =
-"if" 
-"("                                             (. Token ifToken = t; .)
+"if" 											(. Token ifToken = t; .)
+"("
 Expression<out SLExpressionNode condition> 
 ")"
 Block<out SLStatementNode thenPart, inLoop>     (. SLStatementNode elsePart = null; .)                             
@@ -225,7 +226,10 @@
 |
     numericLiteral                              (. result = factory.createNumericLiteral(t); .)
 |
-    "(" Expression<out result> ")"
+    "(" 										(. int start = t.charPos; .)
+    Expression<out result> 						(. SLExpressionNode expr = result; .)
+    ")"											(. int length = (t.charPos + t.val.length()) - start; .)
+    											(. result = factory.createParenExpression(expr, start, length); .)
 ) 
 .
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Mon Aug 25 21:15:59 2014 -0700
@@ -33,7 +33,6 @@
 import com.oracle.truffle.sl.*;
 import com.oracle.truffle.sl.builtins.*;
 import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.nodes.instrument.*;
 import com.oracle.truffle.sl.nodes.local.*;
 import com.oracle.truffle.sl.parser.*;
 
@@ -52,7 +51,6 @@
     private final PrintStream output;
     private final SLFunctionRegistry functionRegistry;
     private SourceCallback sourceCallback = null;
-    private SLASTProber astProber;
 
     public SLContext(BufferedReader input, PrintStream output) {
         this.input = input;
@@ -138,13 +136,23 @@
         getFunctionRegistry().register(name, rootNode);
     }
 
+    /**
+     * This function will parse the given source code, parse the code using the {@link Parser}, and
+     * then execute the function named main. To use this method with instrumentation,
+     * setASTNodeProber must have been already called. There is currently no guard to check if this
+     * is the case. <br/>
+     * Due to the experimental nature of the instrumentation framework, the parse that happens in
+     * this method will remove any previously added instrumentation.
+     *
+     * @param source The {@link Source} to execute.
+     */
     public void executeMain(Source source) {
 
         if (sourceCallback != null) {
             sourceCallback.startLoading(source);
         }
 
-        Parser.parseSL(this, source, astProber);
+        Parser.parseSL(this, source);
 
         if (sourceCallback != null) {
             sourceCallback.endLoading(source);
@@ -156,9 +164,4 @@
         }
         main.getCallTarget().call();
     }
-
-    public void setASTNodeProber(SLASTProber astProber) {
-        // TODO Auto-generated method stub
-        this.astProber = astProber;
-    }
 }
--- a/make/Makefile	Mon Aug 25 14:42:42 2014 -0700
+++ b/make/Makefile	Mon Aug 25 21:15:59 2014 -0700
@@ -567,6 +567,9 @@
 $(EXPORT_JRE_LIB_DIR)/%.jar: $(SHARED_DIR)/%.jar
 	$(install-file)
 
+$(EXPORT_JRE_LIB_EXT_DIR)/%.jar: $(SHARED_DIR)/%.jar
+	$(install-file)
+
 $(EXPORT_INCLUDE_DIR)/%: $(HS_SRC_DIR)/share/vm/code/%
 	$(install-file)
 
--- a/make/defs.make	Mon Aug 25 14:42:42 2014 -0700
+++ b/make/defs.make	Mon Aug 25 21:15:59 2014 -0700
@@ -331,6 +331,7 @@
 EXPORT_JRE_DIR = $(EXPORT_PATH)/jre
 EXPORT_JRE_BIN_DIR = $(EXPORT_JRE_DIR)/bin
 EXPORT_JRE_LIB_DIR = $(EXPORT_JRE_DIR)/lib
+EXPORT_JRE_LIB_EXT_DIR = $(EXPORT_JRE_LIB_DIR)/ext
 EXPORT_JRE_LIB_ARCH_DIR = $(EXPORT_JRE_LIB_DIR)/$(LIBARCH)
 
 # non-universal macosx builds need to appear universal
@@ -347,6 +348,9 @@
 EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/$(JDK_INCLUDE_SUBDIR)/jni_md.h
 EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jmm.h
 EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/graal.jar
+EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/graal-truffle.jar
+EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/graal-loader.jar
+EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/truffle.jar
 
 .PHONY: $(HS_ALT_MAKE)/defs.make
 
--- a/mx/mx_graal.py	Mon Aug 25 14:42:42 2014 -0700
+++ b/mx/mx_graal.py	Mon Aug 25 21:15:59 2014 -0700
@@ -83,8 +83,21 @@
 
 _minVersion = mx.VersionSpec('1.8')
 
+class JDKDeployedDist:
+    def __init__(self, name, isExtension):
+        self.name = name
+        self.isExtension = isExtension
+
+_jdkDeployedDists = [
+    JDKDeployedDist('TRUFFLE', isExtension=False),
+    JDKDeployedDist('GRAAL_LOADER', isExtension=False),
+    JDKDeployedDist('GRAAL', isExtension=False),
+    JDKDeployedDist('GRAAL_TRUFFLE', isExtension=False)
+]
+
 JDK_UNIX_PERMISSIONS_DIR = 0755
 JDK_UNIX_PERMISSIONS_FILE = 0644
+JDK_UNIX_PERMISSIONS_EXEC = 0755
 
 def isVMSupported(vm):
     if 'client' in vm and len(platform.mac_ver()[0]) != 0:
@@ -458,10 +471,10 @@
             _handle_missing_VM(build, vmToCheck if vmToCheck else 'graal')
 
     if installJars:
-        _installDistInJdks(mx.distribution('GRAAL'))
-        _installDistInJdks(mx.distribution('GRAAL_LOADER'))
-        _installDistInJdks(mx.distribution('TRUFFLE'))
-        _installDistInJdks(mx.distribution('GRAAL_TRUFFLE'))
+        for jdkDist in _jdkDeployedDists:
+            dist = mx.distribution(jdkDist.name)
+            if exists(dist.path):
+                _installDistInJdks(dist, jdkDist.isExtension)
 
     if vmToCheck is not None:
         jvmCfg = _vmCfgInJdk(jdk)
@@ -545,7 +558,29 @@
         os.unlink(javaSource)
         os.unlink(javaClass)
 
-def _installDistInJdks(dist):
+def _copyToJdk(src, dst, permissions=JDK_UNIX_PERMISSIONS_FILE):
+    name = os.path.basename(src)
+    dstLib = join(dst, name)
+    if mx.get_env('SYMLINK_GRAAL_JAR', None) == 'true':
+        # Using symlinks is much faster than copying but may
+        # cause issues if the lib is being updated while
+        # the VM is running.
+        if not os.path.islink(dstLib) or not os.path.realpath(dstLib) == src:
+            if exists(dstLib):
+                os.remove(dstLib)
+            os.symlink(src, dstLib)
+    else:
+        # do a copy and then a move to get atomic updating (on Unix)
+        fd, tmp = tempfile.mkstemp(suffix='', prefix=name, dir=dst)
+        shutil.copyfile(src, tmp)
+        os.close(fd)
+        shutil.move(tmp, dstLib)
+        os.chmod(dstLib, permissions)
+
+def _installDistInJdksExt(dist):
+    _installDistInJdks(dist, True)
+
+def _installDistInJdks(dist, ext=False):
     """
     Installs the jar(s) for a given Distribution into all existing Graal JDKs
     """
@@ -557,29 +592,12 @@
     if exists(jdks):
         for e in os.listdir(jdks):
             jreLibDir = join(jdks, e, 'jre', 'lib')
+            if ext:
+                jreLibDir = join(jreLibDir, 'ext')
             if exists(jreLibDir):
-                def install(srcJar, dstDir):
-                    name = os.path.basename(srcJar)
-                    dstJar = join(dstDir, name)
-                    if mx.get_env('SYMLINK_GRAAL_JAR', None) == 'true':
-                        # Using symlinks is much faster than copying but may
-                        # cause issues if the jar is being updated while
-                        # the VM is running.
-                        if not os.path.islink(dstJar) or not os.path.realpath(dstJar) == srcJar:
-                            if exists(dstJar):
-                                os.remove(dstJar)
-                            os.symlink(srcJar, dstJar)
-                    else:
-                        # do a copy and then a move to get atomic updating (on Unix)
-                        fd, tmp = tempfile.mkstemp(suffix='', prefix=name, dir=dstDir)
-                        shutil.copyfile(srcJar, tmp)
-                        os.close(fd)
-                        shutil.move(tmp, dstJar)
-                        os.chmod(dstJar, JDK_UNIX_PERMISSIONS_FILE)
-
-                install(dist.path, jreLibDir)
+                _copyToJdk(dist.path, jreLibDir)
                 if dist.sourcesPath:
-                    install(dist.sourcesPath, join(jdks, e))
+                    _copyToJdk(dist.sourcesPath, join(jdks, e))
 
 # run a command in the windows SDK Debug Shell
 def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo=None):
@@ -679,17 +697,19 @@
         # extract latest release tag for graal
         try:
             tags = [x.split() for x in subprocess.check_output(['hg', '-R', _graal_home, 'tags']).split('\n') if x.startswith("graal-")]
-            current_revision = subprocess.check_output(['hg', '-R', _graal_home, 'id', '-i']).strip()
+            current_id = subprocess.check_output(['hg', '-R', _graal_home, 'log', '--template', '{rev}\n', '--rev', 'tip']).strip()
         except:
             # not a mercurial repository or hg commands are not available.
             tags = None
 
-        if tags and current_revision:
+        if tags and current_id:
             sorted_tags = sorted(tags, key=lambda e: [int(x) for x in e[0][len("graal-"):].split('.')], reverse=True)
             most_recent_tag_name, most_recent_tag_revision = sorted_tags[0]
+            most_recent_tag_id = most_recent_tag_revision[:most_recent_tag_revision.index(":")]
             most_recent_tag_version = most_recent_tag_name[len("graal-"):]
 
-            if current_revision == most_recent_tag_revision:
+            # tagged commit is one-off with commit that tags it
+            if int(current_id) - int(most_recent_tag_id) <= 1:
                 cached_graal_version = most_recent_tag_version
             else:
                 major, minor = map(int, most_recent_tag_version.split('.'))
@@ -731,8 +751,19 @@
         else:
             assert os.path.isdir(opts2.export_dir), '{} is not a directory'.format(opts2.export_dir)
 
-        shutil.copy(mx.distribution('GRAAL').path, opts2.export_dir)
-        shutil.copy(mx.distribution('GRAAL_LOADER').path, opts2.export_dir)
+        defsPath = join(_graal_home, 'make', 'defs.make')
+        with open(defsPath) as fp:
+            defs = fp.read()
+        for jdkDist in _jdkDeployedDists:
+            dist = mx.distribution(jdkDist.name)
+            defLine = 'EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/' + basename(dist.path)
+            if jdkDist.isExtension:
+                defLine = 'EXPORT_LIST += $(EXPORT_JRE_LIB_EXT_DIR)/' + basename(dist.path)
+            else:
+                defLine = 'EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/' + basename(dist.path)
+            if defLine not in defs:
+                mx.abort('Missing following line in ' + defsPath + '\n' + defLine)
+            shutil.copy(dist.path, opts2.export_dir)
         graalOptions = join(_graal_home, 'graal.options')
         if exists(graalOptions):
             shutil.copy(graalOptions, opts2.export_dir)
@@ -765,7 +796,7 @@
             if build is None or len(build) == 0:
                 continue
 
-        jdk = _jdk(build, create=True)
+        jdk = _jdk(build, create=True, installJars=vm != 'original' and not opts2.java)
 
         if vm == 'original':
             if build != 'product':
@@ -981,6 +1012,10 @@
         if  len(ignoredArgs) > 0:
             mx.log("Warning: The following options will be ignored by the vm because they come after the '-version' argument: " + ' '.join(ignoredArgs))
 
+    if vm == 'original':
+        truffle_jar = mx.archive(['@TRUFFLE'])[0]
+        args = ['-Xbootclasspath/p:' + truffle_jar] + args
+
     args = mx.java().processArgs(args)
     return (pfx, exe, vm, args, cwd)
 
@@ -1119,9 +1154,11 @@
         # access core Graal classes.
         cp = prefixCp + coreCp + os.pathsep + projectsCp
         if isGraalEnabled(_get_vm()):
-            graalDist = mx.distribution('GRAAL')
-            graalJarCp = set([d.output_dir() for d in graalDist.sorted_deps()])
-            cp = os.pathsep.join([e for e in cp.split(os.pathsep) if e not in graalJarCp])
+            excluded = set()
+            for jdkDist in _jdkDeployedDists:
+                dist = mx.distribution(jdkDist.name)
+                excluded.update([d.output_dir() for d in dist.sorted_deps()])
+            cp = os.pathsep.join([e for e in cp.split(os.pathsep) if e not in excluded])
             vmArgs = ['-XX:-UseGraalClassLoader'] + vmArgs
 
         if len(testclasses) == 1:
@@ -1541,11 +1578,12 @@
             mx.logv('[This execution may take a while as the NetBeans platform needs to be downloaded]')
         mx.run(['ant', '-f', join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml'), '-l', fp.name, 'run'], env=env)
 
-def install(args):
+def maven_install_truffle(args):
     """install Truffle into your local Maven repository"""
-    mx.archive(["@TRUFFLE"])
-    mx.run(['mvn', 'install:install-file', '-DgroupId=com.oracle', '-DartifactId=truffle', '-Dversion=' + graal_version('SNAPSHOT'), '-Dpackaging=jar', '-Dfile=truffle.jar'])
-    mx.run(['mvn', 'install:install-file', '-DgroupId=com.oracle', '-DartifactId=truffle-dsl-processor', '-Dversion=' + graal_version('SNAPSHOT'), '-Dpackaging=jar', '-Dfile=truffle-dsl-processor.jar'])
+    for name in ['TRUFFLE', 'TRUFFLE-DSL-PROCESSOR']:
+        mx.archive(["@" + name])
+        path = mx._dists[name].path
+        mx.run(['mvn', 'install:install-file', '-DgroupId=com.oracle', '-DartifactId=' + name.lower(), '-Dversion=' + graal_version('SNAPSHOT'), '-Dpackaging=jar', '-Dfile=' + path])
 
 def c1visualizer(args):
     """run the Cl Compiler Visualizer"""
@@ -1878,7 +1916,7 @@
     _run_benchmark(args, sorted(availableBenchmarks), launcher)
 
 def specjbb2013(args):
-    """runs the composite SPECjbb2013 benchmark"""
+    """run the composite SPECjbb2013 benchmark"""
 
     def launcher(bm, harnessArgs, extraVmOpts):
         assert bm is None
@@ -1887,7 +1925,7 @@
     _run_benchmark(args, None, launcher)
 
 def specjbb2005(args):
-    """runs the composite SPECjbb2005 benchmark"""
+    """run the composite SPECjbb2005 benchmark"""
 
     def launcher(bm, harnessArgs, extraVmOpts):
         assert bm is None
@@ -2156,7 +2194,7 @@
     cmd = ['-jar', findbugsJar, '-textui', '-low', '-maxRank', '15']
     if sys.stdout.isatty():
         cmd.append('-progress')
-    cmd = cmd + ['-auxclasspath', mx.classpath(['GRAAL'] + [p.name for p in nonTestProjects]), '-output', findbugsResults, '-exitcode'] + args + outputDirs
+    cmd = cmd + ['-auxclasspath', mx.classpath([d.name for d in _jdkDeployedDists] + [p.name for p in nonTestProjects]), '-output', findbugsResults, '-exitcode'] + args + outputDirs
     exitcode = mx.run_java(cmd, nonZeroIsFatal=False)
     if exitcode != 0:
         with open(findbugsResults) as fp:
@@ -2206,7 +2244,7 @@
         'hsdis': [hsdis, '[att]'],
         'hcfdis': [hcfdis, ''],
         'igv' : [igv, ''],
-        'install' : [install, ''],
+        'maven-install-truffle' : [maven_install_truffle, ''],
         'jdkhome': [print_jdkhome, ''],
         'jmh': [jmh, '[VM options] [filters|JMH-args-as-json...]'],
         'dacapo': [dacapo, '[VM options] benchmarks...|"all" [DaCapo options]'],
@@ -2272,7 +2310,8 @@
     global _vm_prefix
     _vm_prefix = opts.vm_prefix
 
-    mx.distribution('GRAAL').add_update_listener(_installDistInJdks)
-    mx.distribution('GRAAL_LOADER').add_update_listener(_installDistInJdks)
-    mx.distribution('TRUFFLE').add_update_listener(_installDistInJdks)
-    mx.distribution('GRAAL_TRUFFLE').add_update_listener(_installDistInJdks)
+    for jdkDist in _jdkDeployedDists:
+        if jdkDist.isExtension:
+            mx.distribution(jdkDist.name).add_update_listener(_installDistInJdksExt)
+        else:
+            mx.distribution(jdkDist.name).add_update_listener(_installDistInJdks)
--- a/mx/projects	Mon Aug 25 14:42:42 2014 -0700
+++ b/mx/projects	Mon Aug 25 21:15:59 2014 -0700
@@ -77,14 +77,15 @@
 library@JAVA_ALLOCATION_INSTRUMENTER@sourcePath=lib/java-allocation-instrumenter.jar
 library@JAVA_ALLOCATION_INSTRUMENTER@urls=http://lafo.ssw.uni-linz.ac.at/java-allocation-instrumenter/java-allocation-instrumenter-8f0db117e64e.jar
 library@JAVA_ALLOCATION_INSTRUMENTER@sha1=476d9a44cd19d6b55f81571077dfa972a4f8a083
+library@JAVA_ALLOCATION_INSTRUMENTER@bootClassPathAgent=true
 
 library@VECMATH@path=lib/vecmath-1.3.1.jar
 library@VECMATH@urls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/vecmath-1.3.1.jar,http://mirrors.ibiblio.org/pub/mirrors/maven/java3d/jars/vecmath-1.3.1.jar
 library@VECMATH@sha1=a0ae4f51da409fa0c20fa0ca59e6bbc9413ae71d
 
-distribution@GRAAL@path=graal.jar
+distribution@GRAAL@path=build/graal.jar
 distribution@GRAAL@subDir=graal
-distribution@GRAAL@sourcesPath=graal.src.zip
+distribution@GRAAL@sourcesPath=build/graal.src.zip
 distribution@GRAAL@dependencies=\
 com.oracle.graal.hotspot.amd64,\
 com.oracle.graal.hotspot.ptx,\
@@ -94,33 +95,48 @@
 com.oracle.graal.hotspot.hsail
 distribution@GRAAL@exclude=FINDBUGS
 
-distribution@GRAAL_LOADER@path=graal-loader.jar
+distribution@GRAAL_LOADER@path=build/graal-loader.jar
 distribution@GRAAL_LOADER@subDir=graal
-distribution@GRAAL_LOADER@sourcesPath=graal-loader.src.zip
+distribution@GRAAL_LOADER@sourcesPath=build/graal-loader.src.zip
 distribution@GRAAL_LOADER@dependencies=com.oracle.graal.hotspot.loader
 
-distribution@TRUFFLE@path=truffle.jar
+distribution@TRUFFLE@path=build/truffle.jar
 distribution@TRUFFLE@subDir=graal
-distribution@TRUFFLE@sourcesPath=truffle-sources.jar
+distribution@TRUFFLE@sourcesPath=build/truffle.src.zip
 distribution@TRUFFLE@dependencies=\
-com.oracle.truffle.api.dsl
+com.oracle.truffle.api.dsl,\
+com.oracle.nfi
 
-distribution@GRAAL_TRUFFLE@path=graal-truffle.jar
+distribution@GRAAL_TRUFFLE@path=build/graal-truffle.jar
 distribution@GRAAL_TRUFFLE@subDir=graal
-distribution@GRAAL_TRUFFLE@sourcesPath=graal-truffle-sources.jar
+distribution@GRAAL_TRUFFLE@sourcesPath=build/graal-truffle.src.zip
 distribution@GRAAL_TRUFFLE@dependencies=\
 com.oracle.graal.truffle,\
 com.oracle.graal.truffle.hotspot.amd64
 distribution@GRAAL_TRUFFLE@exclude=FINDBUGS
 distribution@GRAAL_TRUFFLE@distDependencies=GRAAL,TRUFFLE
 
-distribution@TRUFFLE-DSL-PROCESSOR@path=truffle-dsl-processor.jar
+distribution@TRUFFLE-DSL-PROCESSOR@path=build/truffle-dsl-processor.jar
 distribution@TRUFFLE-DSL-PROCESSOR@subDir=graal
-distribution@TRUFFLE-DSL-PROCESSOR@sourcesPath=truffle-dsl-processor-sources.jar
+distribution@TRUFFLE-DSL-PROCESSOR@sourcesPath=build/truffle-dsl-processor.src.zip
 distribution@TRUFFLE-DSL-PROCESSOR@dependencies=\
 com.oracle.truffle.dsl.processor
 distribution@TRUFFLE-DSL-PROCESSOR@distDependencies=TRUFFLE
 
+# nfi
+project@com.oracle.nfi@subDir=graal
+project@com.oracle.nfi@sourceDirs=src
+project@com.oracle.nfi@dependencies=
+project@com.oracle.nfi@checkstyle=com.oracle.graal.graph
+project@com.oracle.nfi@javaCompliance=1.7
+
+# nfi.test
+project@com.oracle.nfi.test@subDir=graal
+project@com.oracle.nfi.test@sourceDirs=test
+project@com.oracle.nfi.test@dependencies=com.oracle.nfi,com.oracle.graal.compiler.common,JUNIT
+project@com.oracle.nfi.test@checkstyle=com.oracle.graal.graph
+project@com.oracle.nfi.test@javaCompliance=1.7
+
 # graal.api.collections
 project@com.oracle.graal.api.collections@subDir=graal
 project@com.oracle.graal.api.collections@sourceDirs=src
@@ -212,14 +228,13 @@
 project@com.oracle.graal.hotspotvmconfig@dependencies=com.oracle.graal.compiler.common
 project@com.oracle.graal.hotspotvmconfig@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspotvmconfig@annotationProcessors=com.oracle.graal.service.processor
-project@com.oracle.graal.hotspotvmconfig@annotationProcessorForDependents=true
 project@com.oracle.graal.hotspotvmconfig@javaCompliance=1.8
 project@com.oracle.graal.hotspotvmconfig@workingSets=Graal,HotSpot
 
 # graal.hotspot
 project@com.oracle.graal.hotspot@subDir=graal
 project@com.oracle.graal.hotspot@sourceDirs=src
-project@com.oracle.graal.hotspot@dependencies=com.oracle.graal.replacements,com.oracle.graal.runtime,com.oracle.graal.printer,com.oracle.graal.baseline,com.oracle.graal.hotspotvmconfig
+project@com.oracle.graal.hotspot@dependencies=com.oracle.graal.replacements,com.oracle.graal.runtime,com.oracle.graal.printer,com.oracle.graal.baseline,com.oracle.graal.hotspotvmconfig,com.oracle.nfi
 project@com.oracle.graal.hotspot@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot@annotationProcessors=com.oracle.graal.replacements.verifier,com.oracle.graal.service.processor
 project@com.oracle.graal.hotspot@javaCompliance=1.8
@@ -303,18 +318,10 @@
 project@com.oracle.graal.hotspot.test@javaCompliance=1.8
 project@com.oracle.graal.hotspot.test@workingSets=Graal,HotSpot,Test
 
-# graal.hotspot.jdk8.test
-project@com.oracle.graal.hotspot.jdk8.test@subDir=graal
-project@com.oracle.graal.hotspot.jdk8.test@sourceDirs=src
-project@com.oracle.graal.hotspot.jdk8.test@dependencies=com.oracle.graal.compiler.test
-project@com.oracle.graal.hotspot.jdk8.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.hotspot.jdk8.test@javaCompliance=1.8
-project@com.oracle.graal.hotspot.jdk8.test@workingSets=Graal,HotSpot,Test
-
 # graal.hotspot.amd64.test
 project@com.oracle.graal.hotspot.amd64.test@subDir=graal
 project@com.oracle.graal.hotspot.amd64.test@sourceDirs=src
-project@com.oracle.graal.hotspot.amd64.test@dependencies=com.oracle.graal.asm.amd64,com.oracle.graal.compiler.test
+project@com.oracle.graal.hotspot.amd64.test@dependencies=com.oracle.graal.asm.amd64,com.oracle.graal.compiler.test,com.oracle.graal.hotspot
 project@com.oracle.graal.hotspot.amd64.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.amd64.test@javaCompliance=1.8
 project@com.oracle.graal.hotspot.amd64.test@workingSets=Graal,HotSpot,AMD64,Test
@@ -324,7 +331,6 @@
 project@com.oracle.graal.options@sourceDirs=src
 project@com.oracle.graal.options@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.options@javaCompliance=1.8
-project@com.oracle.graal.options@annotationProcessorForDependents=true
 project@com.oracle.graal.options@workingSets=Graal,Codegen
 
 # graal.options.test
@@ -335,11 +341,27 @@
 project@com.oracle.graal.options.test@javaCompliance=1.8
 project@com.oracle.graal.options.test@workingSets=Graal
 
+# graal.nodeinfo
+project@com.oracle.graal.nodeinfo@subDir=graal
+project@com.oracle.graal.nodeinfo@sourceDirs=src
+project@com.oracle.graal.nodeinfo@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.nodeinfo@javaCompliance=1.8
+project@com.oracle.graal.nodeinfo@workingSets=Graal,Graph
+
+# graal.nodeinfo.processor
+project@com.oracle.graal.nodeinfo.processor@subDir=graal
+project@com.oracle.graal.nodeinfo.processor@sourceDirs=src
+project@com.oracle.graal.nodeinfo.processor@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.nodeinfo.processor@dependencies=com.oracle.graal.nodeinfo,com.oracle.truffle.dsl.processor
+project@com.oracle.graal.nodeinfo.processor@javaCompliance=1.8
+project@com.oracle.graal.nodeinfo.processor@workingSets=Graal,Graph
+
 # graal.graph
 project@com.oracle.graal.graph@subDir=graal
 project@com.oracle.graal.graph@sourceDirs=src
-project@com.oracle.graal.graph@dependencies=com.oracle.graal.debug,com.oracle.graal.compiler.common,com.oracle.graal.api.collections,com.oracle.graal.api.runtime,FINDBUGS
+project@com.oracle.graal.graph@dependencies=com.oracle.graal.nodeinfo,com.oracle.graal.debug,com.oracle.graal.compiler.common,com.oracle.graal.api.collections,com.oracle.graal.api.runtime,FINDBUGS
 project@com.oracle.graal.graph@javaCompliance=1.8
+project@com.oracle.graal.graph@annotationProcessors=com.oracle.graal.nodeinfo.processor
 project@com.oracle.graal.graph@workingSets=Graal,Graph
 
 # graal.graph.test
@@ -519,7 +541,6 @@
 project@com.oracle.graal.compiler@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler@javaCompliance=1.8
 project@com.oracle.graal.compiler@annotationProcessors=com.oracle.graal.service.processor
-project@com.oracle.graal.compiler@annotationProcessorForDependents=true
 project@com.oracle.graal.compiler@workingSets=Graal
 
 # graal.compiler.amd64
--- a/mxtool/mx.py	Mon Aug 25 14:42:42 2014 -0700
+++ b/mxtool/mx.py	Mon Aug 25 21:15:59 2014 -0700
@@ -76,12 +76,18 @@
         self.excludedDependencies = excludedDependencies
         self.distDependencies = distDependencies
 
-    def sorted_deps(self, includeLibs=False):
+    def sorted_deps(self, includeLibs=False, transitive=False):
+        deps = []
+        if transitive:
+            for depDist in [distribution(name) for name in self.distDependencies]:
+                for d in depDist.sorted_deps(includeLibs=includeLibs, transitive=True):
+                    if d not in deps:
+                        deps.append(d)
         try:
             excl = [dependency(d) for d in self.excludedDependencies]
         except SystemExit as e:
             abort('invalid excluded dependency for {} distribution: {}'.format(self.name, e))
-        return [d for d in sorted_deps(self.deps, includeLibs=includeLibs) if d not in excl]
+        return deps + [d for d in sorted_deps(self.deps, includeLibs=includeLibs) if d not in excl]
 
     def __str__(self):
         return self.name
@@ -89,6 +95,21 @@
     def add_update_listener(self, listener):
         self.update_listeners.add(listener)
 
+    """
+    Gets the directory in which the IDE project configuration
+    for this distribution is generated. If this is a distribution
+    derived from a project defining an annotation processor, then
+    None is return to indicate no IDE configuration should be
+    created for this distribution.
+    """
+    def get_ide_project_dir(self):
+        if hasattr(self, 'definingProject') and self.definingProject.definedAnnotationProcessorsDist == self:
+            return None
+        if hasattr(self, 'subDir'):
+            return join(self.suite.dir, self.subDir, self.name + '.dist')
+        else:
+            return join(self.suite.dir, self.name + '.dist')
+
     def make_archive(self):
         # are sources combined into main archive?
         unified = self.path == self.sourcesPath
@@ -234,6 +255,11 @@
         self.workingSets = workingSets
         self.dir = d
 
+        # The annotation processors defined by this project
+        self.definedAnnotationProcessors = None
+        self.definedAnnotationProcessorsDist = None
+
+
         # Verify that a JDK exists for this project if its compliance level is
         # less than the compliance level of the default JDK
         jdk = java(self.javaCompliance)
@@ -435,20 +461,47 @@
         self._init_packages_and_imports()
         return self._imported_java_packages
 
+    """
+    Gets the list of projects defining the annotation processors that will be applied
+    when compiling this project. This includes the projects declared by the annotationProcessors property
+    of this project and any of its project dependencies. It also includes
+    any project dependencies that define an annotation processors.
+    """
     def annotation_processors(self):
         if not hasattr(self, '_annotationProcessors'):
-            ap = set()
+            aps = set()
             if hasattr(self, '_declaredAnnotationProcessors'):
-                ap = set(self._declaredAnnotationProcessors)
-
-            # find dependencies that auto-inject themselves as annotation processors to all dependents
+                aps = set(self._declaredAnnotationProcessors)
+                for ap in aps:
+                    if project(ap).definedAnnotationProcessorsDist is None:
+                        config = join(project(ap).source_dirs()[0], 'META-INF', 'services', 'javax.annotation.processing.Processor')
+                        if not exists(config):
+                            TimeStampFile(config).touch()
+                        abort('Project ' + ap + ' declared in annotationProcessors property of ' + self.name + ' does not define any annotation processors.\n' +
+                              'Please specify the annotation processors in ' + config)
+
             allDeps = self.all_deps([], includeLibs=False, includeSelf=False, includeAnnotationProcessors=False)
             for p in allDeps:
-                if hasattr(p, 'annotationProcessorForDependents') and p.annotationProcessorForDependents.lower() == 'true':
-                    ap.add(p.name)
-            self._annotationProcessors = list(ap)
+                # Add an annotation processor dependency
+                if p.definedAnnotationProcessorsDist is not None:
+                    aps.add(p.name)
+
+                # Inherit annotation processors from dependencies
+                aps.update(p.annotation_processors())
+
+            self._annotationProcessors = list(aps)
         return self._annotationProcessors
 
+    """
+    Gets the class path composed of the distribution jars containing the 
+    annotation processors that will be applied when compiling this project.
+    """
+    def annotation_processors_path(self):
+        aps = [project(ap) for ap in self.annotation_processors()]
+        if len(aps):
+            return os.pathsep.join([ap.definedAnnotationProcessorsDist.path for ap in aps if ap.definedAnnotationProcessorsDist])
+        return None
+
     def update_current_annotation_processors_file(self):
         aps = self.annotation_processors()
         outOfDate = False
@@ -497,7 +550,7 @@
             d.update(buf)
         return d.hexdigest()
 
-def download_file_with_sha1(name, path, urls, sha1, sha1path, resolve, mustExist, sources=False):
+def download_file_with_sha1(name, path, urls, sha1, sha1path, resolve, mustExist, sources=False, canSymlink=True):
     def _download_lib():
         cacheDir = get_env('MX_CACHE_DIR', join(_opts.user_home, '.mx', 'cache'))
         if not exists(cacheDir):
@@ -514,7 +567,8 @@
         d = dirname(path)
         if d != '' and not exists(d):
             os.makedirs(d)
-        if 'symlink' in dir(os):
+
+        if canSymlink and 'symlink' in dir(os):
             if exists(path):
                 os.unlink(path)
             os.symlink(cachePath, path)
@@ -557,16 +611,16 @@
         return not result
 
 """
-A library that will be provided by the JDK but may be absent.
+A library that will be provided by the JRE but may be absent.
 Any project or normal library that depends on a missing library
 will be removed from the global project and library dictionaries
 (i.e., _projects and _libs).
 
 This mechanism exists primarily to be able to support code
-that may use functionality in one JDK (e.g., Oracle JDK)
-that is not present in another JDK (e.g., OpenJDK). A
+that may use functionality in one JRE (e.g., Oracle JRE)
+that is not present in another JRE (e.g., OpenJDK). A
 motivating example is the Java Flight Recorder library
-found in the Oracle JDK. 
+found in the Oracle JRE. 
 """
 class JreLibrary(BaseLibrary):
     def __init__(self, suite, name, jar, optional):
@@ -648,7 +702,9 @@
         if includedInJDK and java().javaCompliance >= JavaCompliance(includedInJDK):
             return None
 
-        return download_file_with_sha1(self.name, path, self.urls, self.sha1, sha1path, resolve, not self.optional)
+        bootClassPathAgent = getattr(self, 'bootClassPathAgent').lower() == 'true' if hasattr(self, 'bootClassPathAgent') else False
+
+        return download_file_with_sha1(self.name, path, self.urls, self.sha1, sha1path, resolve, not self.optional, canSymlink=not bootClassPathAgent)
 
     def get_source_path(self, resolve):
         if self.sourcePath is None:
@@ -824,7 +880,6 @@
             srcDirs = pop_list(attrs, 'sourceDirs')
             deps = pop_list(attrs, 'dependencies')
             ap = pop_list(attrs, 'annotationProcessors')
-            # deps += ap
             javaCompliance = attrs.pop('javaCompliance', None)
             subDir = attrs.pop('subDir', None)
             if subDir is None:
@@ -874,6 +929,52 @@
             d.__dict__.update(attrs)
             self.dists.append(d)
 
+        # Create a distribution for each project that defines annotation processors
+        for p in self.projects:
+            annotationProcessors = None
+            for srcDir in p.source_dirs():
+                configFile = join(srcDir, 'META-INF', 'services', 'javax.annotation.processing.Processor')
+                if exists(configFile):
+                    with open(configFile) as fp:
+                        annotationProcessors = [ap.strip() for ap in fp]
+                        if len(annotationProcessors) != 0:
+                            for ap in annotationProcessors:
+                                if not ap.startswith(p.name):
+                                    abort(ap + ' in ' + configFile + ' does not start with ' + p.name)
+            if annotationProcessors:
+                dname = p.name.replace('.', '_').upper()
+                apDir = join(p.dir, 'ap')
+                path = join(apDir, p.name + '.jar')
+                sourcesPath = None
+                deps = [p.name]
+                mainClass = None
+                exclDeps = []
+                distDeps = []
+                d = Distribution(self, dname, path, sourcesPath, deps, mainClass, exclDeps, distDeps)
+                d.subDir = os.path.relpath(os.path.dirname(p.dir), self.dir)
+                self.dists.append(d)
+                p.definedAnnotationProcessors = annotationProcessors
+                p.definedAnnotationProcessorsDist = d
+                d.definingProject = p
+
+                # Restrict exported annotation processors to those explicitly defined by the project
+                def _refineAnnotationProcessorServiceConfig(dist):
+                    aps = dist.definingProject.definedAnnotationProcessors
+                    apsJar = dist.path
+                    config = 'META-INF/services/javax.annotation.processing.Processor'
+                    with zipfile.ZipFile(apsJar, 'r') as zf:
+                        currentAps = zf.read(config).split()
+                    if currentAps != aps:
+                        logv('[updating ' + config + ' in ' + apsJar + ']')
+                        with Archiver(apsJar) as arc, zipfile.ZipFile(apsJar, 'r') as lp:
+                            for arcname in lp.namelist():
+                                if arcname == config:
+                                    arc.zf.writestr(arcname, '\n'.join(aps))
+                                else:
+                                    arc.zf.writestr(arcname, lp.read(arcname))
+                d.add_update_listener(_refineAnnotationProcessorServiceConfig)
+                self.dists.append(d)
+
         if self.name is None:
             abort('Missing "suite=<name>" in ' + projectsFile)
 
@@ -2044,9 +2145,8 @@
 
         processorArgs = []
 
-        aps = self.proj.annotation_processors()
-        if len(aps) > 0:
-            processorPath = classpath(aps, resolve=True)
+        processorPath = self.proj.annotation_processors_path()
+        if processorPath:
             genDir = self.proj.source_gen_dir()
             if exists(genDir):
                 shutil.rmtree(genDir)
@@ -2125,6 +2225,11 @@
                 jdtArgs.append('@' + argfile.name)
 
                 run_java(jdtVmArgs + jdtArgs)
+
+            # Create annotation processor jar for a project that defines annotation processors
+            if self.proj.definedAnnotationProcessorsDist:
+                self.proj.definedAnnotationProcessorsDist.make_archive()
+
         finally:
             for n in toBeDeleted:
                 os.remove(n)
@@ -2208,6 +2313,7 @@
         return outputDir
 
     tasks = {}
+    updatedAnnotationProcessorDists = set()
     for p in sortedProjects:
         if p.native:
             if args.native:
@@ -2234,13 +2340,12 @@
         sourceDirs = p.source_dirs()
         buildReason = 'forced build' if args.force else None
         taskDeps = []
-        if not buildReason:
-            for dep in p.all_deps([], includeLibs=False, includeAnnotationProcessors=True):
-                taskDep = tasks.get(dep.name)
-                if taskDep:
-                    if not buildReason:
-                        buildReason = dep.name + ' rebuilt'
-                    taskDeps.append(taskDep)
+        for dep in p.all_deps([], includeLibs=False, includeAnnotationProcessors=True):
+            taskDep = tasks.get(dep.name)
+            if taskDep:
+                if not buildReason:
+                    buildReason = dep.name + ' rebuilt'
+                taskDeps.append(taskDep)
 
         jasminAvailable = None
         javafilelist = []
@@ -2309,6 +2414,8 @@
             continue
 
         task = JavaCompileTask(args, p, buildReason, javafilelist, jdk, outputDir, jdtJar, taskDeps)
+        if p.definedAnnotationProcessorsDist:
+            updatedAnnotationProcessorDists.add(p.definedAnnotationProcessorsDist)
 
         if args.parallelize:
             # Best to initialize class paths on main process
@@ -2409,8 +2516,10 @@
                 log('Compiling {} failed'.format(t.proj.name))
             abort('{} Java compilation tasks failed'.format(len(failed)))
 
-    for dist in sorted_dists():
-        archive(['@' + dist.name])
+    if args.java:
+        for dist in sorted_dists():
+            if dist not in updatedAnnotationProcessorDists:
+                archive(['@' + dist.name])
 
     if suppliedParser:
         return args
@@ -2591,18 +2700,13 @@
         _processorjars_suite(s)
 
 def _processorjars_suite(s):
-    projs = set()
-    candidates = sorted_project_deps(s.projects)
-    for p in candidates:
-        if _isAnnotationProcessorDependency(p):
-            projs.add(p)
-
+    projs = [p for p in s.projects if p.definedAnnotationProcessors is not None]
     if len(projs) <= 0:
         return []
 
     pnames = [p.name for p in projs]
     build(['--jdt-warning-as-error', '--projects', ",".join(pnames)])
-    return archive(pnames)
+    return [p.definedAnnotationProcessorsDist.path for p in s.projects if p.definedAnnotationProcessorsDist is not None]
 
 def pylint(args):
     """run pylint (if available) over Python source files (found by 'hg locate' or by tree walk with -walk)"""
@@ -2681,6 +2785,8 @@
 
     def __enter__(self):
         if self.path:
+            if not isdir(dirname(self.path)):
+                os.makedirs(dirname(self.path))
             fd, tmp = tempfile.mkstemp(suffix='', prefix=basename(self.path) + '.', dir=dirname(self.path))
             self.tmpFd = fd
             self.tmpPath = tmp
@@ -2947,7 +3053,7 @@
         shutil.rmtree(path)
 
     def _rmIfExists(name):
-        if os.path.isfile(name):
+        if name and os.path.isfile(name):
             os.unlink(name)
 
     for p in projects_opt_limit_to_suites():
@@ -3372,14 +3478,23 @@
             out.element('arguments', data='')
             out.close('buildCommand')
 
-    # The path should always be p.name/dir. independent of where the workspace actually is.
-    # So we use the parent folder of the project, whatever that is, to generate such a relative path.
-    logicalWorkspaceRoot = os.path.dirname(p.dir)
-    binFolder = os.path.relpath(p.output_dir(), logicalWorkspaceRoot)
-
-    if _isAnnotationProcessorDependency(p):
-        refreshFile = os.path.relpath(join(p.dir, p.name + '.jar'), logicalWorkspaceRoot)
-        _genEclipseBuilder(out, p, 'Jar', 'archive ' + p.name, refresh=True, refreshFile=refreshFile, relevantResources=[binFolder], async=True, xmlIndent='', xmlStandalone='no')
+    if p.definedAnnotationProcessorsDist:
+        # Create a launcher that will (re)build the annotation processor
+        # jar any time one of its sources is modified.
+        dist = p.definedAnnotationProcessorsDist
+
+        distProjects = [d for d in dist.sorted_deps(transitive=True) if d.isProject()]
+        relevantResources = []
+        for p in distProjects:
+            for srcDir in p.source_dirs():
+                relevantResources.append(join(p.name, os.path.relpath(srcDir, p.dir)))
+            relevantResources.append(join(p.name, os.path.relpath(p.output_dir(), p.dir)))
+
+        # The path should always be p.name/dir independent of where the workspace actually is.
+        # So we use the parent folder of the project, whatever that is, to generate such a relative path.
+        logicalWorkspaceRoot = os.path.dirname(p.dir)
+        refreshFile = os.path.relpath(p.definedAnnotationProcessorsDist.path, logicalWorkspaceRoot)
+        _genEclipseBuilder(out, p, 'CreateAnnotationProcessorJar', 'archive @' + dist.name, refresh=True, refreshFile=refreshFile, relevantResources=relevantResources, async=True, xmlIndent='', xmlStandalone='no')
 
     out.close('buildSpec')
     out.open('natures')
@@ -3436,22 +3551,13 @@
         if files:
             files.append(join(settingsDir, name))
 
-    if len(p.annotation_processors()) > 0:
+    processorPath = p.annotation_processors_path()
+    if processorPath:
         out = XMLDoc()
         out.open('factorypath')
         out.element('factorypathentry', {'kind' : 'PLUGIN', 'id' : 'org.eclipse.jst.ws.annotations.core', 'enabled' : 'true', 'runInBatchMode' : 'false'})
-        for ap in p.annotation_processors():
-            for dep in dependency(ap).all_deps([], True):
-                if dep.isLibrary():
-                    # 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 = _make_absolute(dep.get_path(resolve=True), p.suite.dir)
-                    out.element('factorypathentry', {'kind' : 'EXTJAR', 'id' : path, 'enabled' : 'true', 'runInBatchMode' : 'false'})
-                    if files:
-                        files.append(path)
-                elif dep.isProject():
-                    out.element('factorypathentry', {'kind' : 'WKSPJAR', 'id' : '/' + dep.name + '/' + dep.name + '.jar', 'enabled' : 'true', 'runInBatchMode' : 'false'})
+        for e in processorPath.split(os.pathsep):
+            out.element('factorypathentry', {'kind' : 'EXTJAR', 'id' : e, 'enabled' : 'true', 'runInBatchMode' : 'false'})
         out.close('factorypath')
         update_file(join(p.dir, '.factorypath'), out.xml(indent='\t', newl='\n'))
         if files:
@@ -3467,8 +3573,6 @@
         logv('[Eclipse configurations are up to date - skipping]')
         return
 
-
-
     files = []
     libFiles = []
     if buildProcessorJars:
@@ -3477,24 +3581,21 @@
     for p in suite.projects:
         if p.native:
             continue
-        _eclipseinit_project(p)
+        _eclipseinit_project(p, files, libFiles)
 
     _, launchFile = make_eclipse_attach(suite, 'localhost', '8000', deps=sorted_deps(projectNames=None, includeLibs=True))
     files.append(launchFile)
 
-    _zip_files(files, suite.dir, configZip.path)
-    _zip_files(libFiles, suite.dir, configLibsZip)
-
     # Create an Eclipse project for each distribution that will create/update the archive
-    # for the distribution whenever any project of the distribution is updated.
+    # for the distribution whenever any (transitively) dependent project of the
+    # distribution is updated.
     for dist in suite.dists:
-        if hasattr(dist, 'subDir'):
-            projectDir = join(suite.dir, dist.subDir, dist.name + '.dist')
-        else:
-            projectDir = join(suite.dir, dist.name + '.dist')
+        projectDir = dist.get_ide_project_dir()
+        if not projectDir:
+            continue
         if not exists(projectDir):
             os.makedirs(projectDir)
-        distProjects = [d for d in dist.sorted_deps() if d.isProject()]
+        distProjects = [d for d in dist.sorted_deps(transitive=True) if d.isProject()]
         relevantResources = []
         for p in distProjects:
             for srcDir in p.source_dirs():
@@ -3512,7 +3613,7 @@
         out.close('projects')
         out.open('buildSpec')
         dist.dir = projectDir
-        dist.javaCompliance = max([p.javaCompliance for p in distProjects] + [JavaCompliance('1.8')])
+        dist.javaCompliance = max([p.javaCompliance for p in distProjects])
         _genEclipseBuilder(out, dist, 'Create' + dist.name + 'Dist', 'archive @' + dist.name, relevantResources=relevantResources, logToFile=True, refresh=False, async=True)
         out.close('buildSpec')
         out.open('natures')
@@ -3523,6 +3624,9 @@
         update_file(projectFile, out.xml(indent='\t', newl='\n'))
         files.append(projectFile)
 
+    _zip_files(files, suite.dir, configZip.path)
+    _zip_files(libFiles, suite.dir, configLibsZip)
+
 def _zip_files(files, baseDir, zipPath):
     fd, tmp = tempfile.mkstemp(suffix='', prefix=basename(zipPath), dir=baseDir)
     try:
@@ -3541,12 +3645,6 @@
         if exists(tmp):
             os.remove(tmp)
 
-def _isAnnotationProcessorDependency(p):
-    """
-    Determines if a given project is part of an annotation processor.
-    """
-    return p in sorted_deps(annotation_processors())
-
 def _genEclipseBuilder(dotProjectDoc, p, name, mxCommand, refresh=True, refreshFile=None, relevantResources=None, async=False, logToConsole=False, logToFile=False, appendToLogFile=True, xmlIndent='\t', xmlStandalone=None):
     externalToolDir = join(p.dir, '.externalToolBuilders')
     launchOut = XMLDoc()
@@ -3922,8 +4020,8 @@
 # Space-separated list of extra javac options
 javac.compilerargs=
 javac.deprecation=false
-javac.source=1.7
-javac.target=1.7
+javac.source=""" + str(p.javaCompliance) + """
+javac.target=""" + str(p.javaCompliance) + """
 javac.test.classpath=\\
     ${javac.classpath}:\\
     ${build.classes.dir}
@@ -4242,6 +4340,9 @@
         except:
             log("Error removing {0}".format(p.name + '.jar'))
 
+    for d in _dists.itervalues():
+        if d.get_ide_project_dir():
+            shutil.rmtree(d.get_ide_project_dir(), ignore_errors=True)
 
 def ideinit(args, refreshOnly=False, buildProcessorJars=True):
     """(re)generate Eclipse, NetBeans and Intellij project configurations"""
--- a/src/cpu/x86/vm/assembler_x86.cpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/cpu/x86/vm/assembler_x86.cpp	Mon Aug 25 21:15:59 2014 -0700
@@ -666,21 +666,35 @@
     // Check second byte
     NOT_LP64(assert((0xC0 & *ip) == 0xC0, "shouldn't have LDS and LES instructions"));
 
+    int vex_opcode;
     // First byte
     if ((0xFF & *inst) == VEX_3bytes) {
+      vex_opcode = VEX_OPCODE_MASK & *ip;
       ip++; // third byte
       is_64bit = ((VEX_W & *ip) == VEX_W);
+    } else {
+      vex_opcode = VEX_OPCODE_0F;
     }
     ip++; // opcode
     // To find the end of instruction (which == end_pc_operand).
-    switch (0xFF & *ip) {
-    case 0x61: // pcmpestri r, r/a, #8
-    case 0x70: // pshufd r, r/a, #8
-    case 0x73: // psrldq r, #8
-      tail_size = 1;  // the imm8
-      break;
-    default:
-      break;
+    switch (vex_opcode) {
+      case VEX_OPCODE_0F:
+        switch (0xFF & *ip) {
+        case 0x70: // pshufd r, r/a, #8
+        case 0x71: // ps[rl|ra|ll]w r, #8
+        case 0x72: // ps[rl|ra|ll]d r, #8
+        case 0x73: // ps[rl|ra|ll]q r, #8
+        case 0xC2: // cmp[ps|pd|ss|sd] r, r, r/a, #8
+        case 0xC4: // pinsrw r, r, r/a, #8
+        case 0xC5: // pextrw r/a, r, #8
+        case 0xC6: // shufp[s|d] r, r, r/a, #8
+          tail_size = 1;  // the imm8
+          break;
+        }
+        break;
+      case VEX_OPCODE_0F_3A:
+        tail_size = 1;
+        break;
     }
     ip++; // skip opcode
     debug_only(has_disp32 = true); // has both kinds of operands!
--- a/src/cpu/x86/vm/assembler_x86.hpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/cpu/x86/vm/assembler_x86.hpp	Mon Aug 25 21:15:59 2014 -0700
@@ -521,7 +521,8 @@
     VEX_OPCODE_NONE  = 0x0,
     VEX_OPCODE_0F    = 0x1,
     VEX_OPCODE_0F_38 = 0x2,
-    VEX_OPCODE_0F_3A = 0x3
+    VEX_OPCODE_0F_3A = 0x3,
+    VEX_OPCODE_MASK  = 0x1F
   };
 
   enum WhichOperand {
--- a/src/gpu/hsail/vm/gpu_hsail.cpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/gpu/hsail/vm/gpu_hsail.cpp	Mon Aug 25 21:15:59 2014 -0700
@@ -66,7 +66,7 @@
 JNINativeMethod Hsail::HSAIL_methods[] = {
   {CC"initialize",       CC"()Z",                               FN_PTR(Hsail::initialize)},
   {CC"generateKernel",   CC"([B" STRING ")J",                   FN_PTR(Hsail::generate_kernel)},
-  {CC"executeKernel0",   CC"("HS_INSTALLED_CODE"I["OBJECT"["JLTHREAD"I[I)Z",  FN_PTR(Hsail::execute_kernel_void_1d)},
+  {CC"executeKernel0",   CC"("HS_INSTALLED_CODE"I["OBJECT"II[I)Z",  FN_PTR(Hsail::execute_kernel_void_1d)},
 };
 
 void* Hsail::_device_context = NULL;
@@ -100,7 +100,7 @@
 }
 
 GPU_VMENTRY(jboolean, Hsail::execute_kernel_void_1d, (JNIEnv* env, jclass, jobject kernel_handle, jint dimX, jobject args,
-                                                      jobject donor_threads, jint allocBytesPerWorkitem, jobject oop_map_array))
+                                                      jint num_tlabs, jint allocBytesPerWorkitem, jobject oop_map_array))
 
   ResourceMark rm;
   jlong nmethodValue = InstalledCode::address(kernel_handle);
@@ -116,7 +116,7 @@
     SharedRuntime::throw_and_post_jvmti_exception(JavaThread::current(), vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL);
   }
 
-return execute_kernel_void_1d_internal((address) kernel, dimX, args, mh, nm, donor_threads, allocBytesPerWorkitem, oop_map_array, CHECK_0);
+return execute_kernel_void_1d_internal((address) kernel, dimX, args, mh, nm, num_tlabs, allocBytesPerWorkitem, oop_map_array, CHECK_0);
 GPU_END
 
 static void showRanges(jboolean* a, int len) {
@@ -137,14 +137,16 @@
 }
 
 jboolean Hsail::execute_kernel_void_1d_internal(address kernel, int dimX, jobject args, methodHandle& mh, nmethod* nm,
-                                                jobject donor_threads, int allocBytesPerWorkitem, jobject oop_map_array, TRAPS) {
+                                                jint num_tlabs, int allocBytesPerWorkitem, jobject oop_map_array, TRAPS) {
   ResourceMark rm(THREAD);
   objArrayOop argsArray = (objArrayOop) JNIHandles::resolve(args);
+  // Note this length does not include the iteration variable since it is replaced by the HSA workitemid
+  int argsArrayLength = argsArray->length();
   assert(THREAD->is_Java_thread(), "must be a JavaThread");
 
   // We avoid HSAILAllocationInfo logic if kernel does not allocate
-  // in which case the donor_thread array passed in will be null
-  HSAILAllocationInfo* allocInfo = (donor_threads == NULL ? NULL : new HSAILAllocationInfo(donor_threads, dimX, allocBytesPerWorkitem));
+  // in which case the num_tlabs passed in will be 0
+  HSAILAllocationInfo* allocInfo = (num_tlabs == 0 ?  NULL : new HSAILAllocationInfo(num_tlabs, dimX, allocBytesPerWorkitem));
   
   // Reset the kernel arguments
   _okra_clear_args(kernel);
@@ -296,7 +298,8 @@
             KlassHandle methKlass = mh->method_holder();
             Thread* THREAD = Thread::current();
             JavaValue result(T_VOID);
-            JavaCallArguments javaArgs;
+            // Add the iteration variable to the HSA args length
+            JavaCallArguments javaArgs(argsArrayLength + 1);
             // re-resolve the args_handle here
             objArrayOop resolvedArgsArray = (objArrayOop) JNIHandles::resolve(args);
 
@@ -344,8 +347,11 @@
   // The kernel entrypoint is always run for the time being  
   const char* entryPointName = "&run";
   jlong okra_kernel;
-  jint okra_status = _okra_create_kernel(_device_context, code, entryPointName, (void**)&okra_kernel);
-  guarantee(okra_status==0, "_okra_create_kernel failed");
+  {
+    TraceTime t("generate kernel ", TraceGPUInteraction);
+    jint okra_status = _okra_create_kernel(_device_context, code, entryPointName, (void**)&okra_kernel);
+    guarantee(okra_status==0, "_okra_create_kernel failed");
+  }
   return (jlong) okra_kernel;
 GPU_END
 
--- a/src/gpu/hsail/vm/gpu_hsail.hpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/gpu/hsail/vm/gpu_hsail.hpp	Mon Aug 25 21:15:59 2014 -0700
@@ -185,10 +185,10 @@
 
   // static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args);
   JNIEXPORT static jboolean execute_kernel_void_1d(JNIEnv* env, jclass, jobject hotspotInstalledCode, jint dimX, jobject args,
-                                                   jobject donorThreads, int allocBytesPerWorkitem, jobject oop_map_array);
+                                                   jint num_tlabs, int allocBytesPerWorkitem, jobject oop_map_array);
 
   static jboolean execute_kernel_void_1d_internal(address kernel, int dimX, jobject args, methodHandle& mh, nmethod* nm,
-                                                  jobject donorThreads, int allocBytesPerWorkitem, jobject oop_map_array, TRAPS);
+                                                  jint num_tlabs, int allocBytesPerWorkitem, jobject oop_map_array, TRAPS);
 
   static GraalEnv::CodeInstallResult install_code(Handle& compiled_code, CodeBlob*& cb, Handle installed_code, Handle triggered_deoptimizations);
 
--- a/src/gpu/hsail/vm/gpu_hsail_Tlab.hpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/gpu/hsail/vm/gpu_hsail_Tlab.hpp	Mon Aug 25 21:15:59 2014 -0700
@@ -41,7 +41,7 @@
   HeapWord* _end;
   HeapWord* _last_good_top;
   HeapWord* _original_top;
-  JavaThread* _donor_thread;         // donor thread associated with this tlabInfo
+  ThreadLocalAllocBuffer* _tlab;      // tlab associated with this tlabInfo
   HSAILAllocationInfo* _alloc_info;   // same as what is in HSAILDeoptimizationInfo
 
   // Accessors
@@ -50,11 +50,12 @@
   HeapWord* end() { return _end; }
   HeapWord* last_good_top() { return _last_good_top; }
   HeapWord* original_top() { return _original_top; }
-  void initialize(HeapWord* start, HeapWord* top, HeapWord* end, JavaThread* donorThread, HSAILAllocationInfo* allocInfo) {
+  ThreadLocalAllocBuffer* tlab() { return _tlab; }
+  void initialize(HeapWord* start, HeapWord* top, HeapWord* end, ThreadLocalAllocBuffer* tlab, HSAILAllocationInfo* allocInfo) {
     _start = start;
     _top = _original_top = top;
     _end = end;
-    _donor_thread = donorThread;
+    _tlab = tlab;
     _alloc_info = allocInfo;
   }
 };
@@ -63,54 +64,56 @@
 class HSAILAllocationInfo : public CHeapObj<mtInternal> {
   friend class VMStructs;
 private:
-  JavaThread** donorThreads;
-  jint _num_donor_threads;
-  size_t _tlab_align_reserve_bytes;    // filled in from ThreadLocalAllocBuffer::alignment_reserve_in_bytes()
-  HSAILTlabInfo** _cur_tlab_infos;    // array of current tlab info pointers, one per donor_thread
+  jint   _num_tlabs;
+  size_t _tlab_align_reserve_bytes;         // filled in from ThreadLocalAllocBuffer::alignment_reserve_in_bytes()
+  HSAILTlabInfo** _cur_tlab_infos;          // array of current tlab info pointers, one per num_tlabs
   HSAILTlabInfo* _tlab_infos_pool_start;    // pool for new tlab_infos
   HSAILTlabInfo* _tlab_infos_pool_next;     // where next will be allocated from
   HSAILTlabInfo* _tlab_infos_pool_end;      // where next will be allocated from
 
 public:
-  HSAILAllocationInfo(jobject donor_threads_jobj, int dimX, int allocBytesPerWorkitem) {
-    // fill in the donorThreads array
-    objArrayOop donorThreadObjects = (objArrayOop) JNIHandles::resolve(donor_threads_jobj);
-    _num_donor_threads = donorThreadObjects->length();
-    guarantee(_num_donor_threads > 0, "need at least one donor thread");
-    donorThreads = NEW_C_HEAP_ARRAY(JavaThread*, _num_donor_threads, mtInternal);
-    for (int i = 0; i < _num_donor_threads; i++) {
-      donorThreads[i] = java_lang_Thread::thread(donorThreadObjects->obj_at(i));
+  HSAILAllocationInfo(jint num_tlabs, int dimX, int allocBytesPerWorkitem) {
+    _num_tlabs = num_tlabs;
+    // if this thread doesn't have gpu_hsail_tlabs allocated yet, do so now
+    JavaThread* thread = JavaThread::current();
+    if (thread->get_gpu_hsail_tlabs_count() == 0) {
+      thread->initialize_gpu_hsail_tlabs(num_tlabs);
+      if (TraceGPUInteraction) {
+        for (int i = 0; i < num_tlabs; i++) {
+          ThreadLocalAllocBuffer* tlab = thread->get_gpu_hsail_tlab_at(i);
+          tty->print("initialized gpu_hsail_tlab %d at %p -> ", i, tlab);
+          printTlabInfoFromThread(tlab);
+        }
+      }
     }
-    
+
     // Compute max_tlab_infos based on amount of free heap space
     size_t max_tlab_infos;
     {
-      JavaThread* donorThread = donorThreads[0];
-      ThreadLocalAllocBuffer* tlab = &donorThread->tlab();
+      ThreadLocalAllocBuffer* tlab = &thread->tlab();
       size_t new_tlab_size = tlab->compute_size(0);
-      size_t heap_bytes_free = Universe::heap()->unsafe_max_tlab_alloc(donorThread);
+      size_t heap_bytes_free = Universe::heap()->unsafe_max_tlab_alloc(thread);
       if (new_tlab_size != 0) {
-        max_tlab_infos = MIN2(heap_bytes_free / new_tlab_size, (size_t)(64 * _num_donor_threads));
+        max_tlab_infos = MIN2(heap_bytes_free / new_tlab_size, (size_t)(64 * _num_tlabs));
       } else {
-        max_tlab_infos = 8 * _num_donor_threads;   // an arbitrary multiple
+        max_tlab_infos = 8 * _num_tlabs;   // an arbitrary multiple
       }
       if (TraceGPUInteraction) {
         tty->print_cr("heapFree = %ld, newTlabSize=%ld, tlabInfos allocated = %ld", heap_bytes_free, new_tlab_size, max_tlab_infos);
       }
     }
 
-    _cur_tlab_infos = NEW_C_HEAP_ARRAY(HSAILTlabInfo*, _num_donor_threads, mtInternal);
+    _cur_tlab_infos = NEW_C_HEAP_ARRAY(HSAILTlabInfo*, _num_tlabs, mtInternal);
     _tlab_infos_pool_start = NEW_C_HEAP_ARRAY(HSAILTlabInfo, max_tlab_infos, mtInternal);
-    _tlab_infos_pool_next = &_tlab_infos_pool_start[_num_donor_threads];
+    _tlab_infos_pool_next = &_tlab_infos_pool_start[_num_tlabs];
     _tlab_infos_pool_end = &_tlab_infos_pool_start[max_tlab_infos];
     _tlab_align_reserve_bytes = ThreadLocalAllocBuffer::alignment_reserve_in_bytes();
       
-    // we will fill the first N tlabInfos from the donor threads
-    for (int i = 0; i < _num_donor_threads; i++) {
-      JavaThread* donorThread = donorThreads[i];
-      ThreadLocalAllocBuffer* tlab = &donorThread->tlab();
+    // we will fill the first N tlabInfos from the gpu_hsail_tlabs
+    for (int i = 0; i < _num_tlabs; i++) {
+      ThreadLocalAllocBuffer* tlab = thread->get_gpu_hsail_tlab_at(i);
       if (TraceGPUInteraction) {
-        tty->print("donorThread %d, is %p, tlab at %p -> ", i, donorThread, tlab);
+        tty->print("gpu_hsail_tlab %d at %p -> ", i, tlab);
         printTlabInfoFromThread(tlab);
       }
       
@@ -122,13 +125,13 @@
       // here, it might make sense to do a gc now rather than to start
       // the kernel and have it deoptimize.  How to do that?
       if (tlab->end() == NULL) {
-        bool success = getNewTlabForDonorThread(tlab, i);
+        bool success = getNewGpuHsailTlab(tlab);
         if (TraceGPUInteraction) {
           if (success) {
-            tty->print("donorThread %d, refilled tlab, -> ", i);
+            tty->print("gpu_hsail_tlab %d, refilled tlab, -> ", i);
             printTlabInfoFromThread(tlab);
           } else {
-            tty->print("donorThread %d, could not refill tlab, left as ", i);
+            tty->print("gpu_hsail_tlab %d, could not refill tlab, left as ", i);
             printTlabInfoFromThread(tlab);
           }
         }
@@ -137,20 +140,19 @@
       // extract the necessary tlab fields into a TlabInfo record
       HSAILTlabInfo* pTlabInfo = &_tlab_infos_pool_start[i];
       _cur_tlab_infos[i] = pTlabInfo;
-      pTlabInfo->initialize(tlab->start(), tlab->top(), tlab->end(), donorThread, this);
+      pTlabInfo->initialize(tlab->start(), tlab->top(), tlab->end(), tlab, this);
     }
   }
 
   ~HSAILAllocationInfo() {
     FREE_C_HEAP_ARRAY(HSAILTlabInfo*, _cur_tlab_infos, mtInternal);
     FREE_C_HEAP_ARRAY(HSAILTlabInfo, _tlab_infos_pool_start, mtInternal);
-    FREE_C_HEAP_ARRAY(JavaThread*, donorThreads, mtInternal);
   }
 
   void postKernelCleanup() {
     // go thru all the tlabInfos, fix up any tlab tops that overflowed
     // complete the tlabs if they overflowed
-    // update the donor threads tlabs when appropriate
+    // update the gpu_hsail_tlabs when appropriate
     bool anyOverflows = false;
     size_t bytesAllocated = 0;
     // if there was an overflow in allocating tlabInfos, correct it here
@@ -166,8 +168,7 @@
         tty->print_cr("postprocess tlabInfo %p, start=%p, top=%p, end=%p, last_good_top=%p", tlabInfo, 
                       tlabInfo->start(), tlabInfo->top(), tlabInfo->end(), tlabInfo->last_good_top());
       }
-      JavaThread* donorThread = tlabInfo->_donor_thread;
-      ThreadLocalAllocBuffer* tlab = &donorThread->tlab();
+      ThreadLocalAllocBuffer* tlab = tlabInfo->tlab();
       bool overflowed = false;
       // if a tlabInfo has NULL fields, i.e. we could not prime it on entry,
       // or we could not get a tlab from the gpu, so ignore tlabInfo here
@@ -177,14 +178,14 @@
           overflowed = true;
           if (TraceGPUInteraction) {
             long overflowAmount = (long) tlabInfo->top() - (long) tlabInfo->last_good_top(); 
-            tty->print_cr("tlabInfo %p (donorThread = %p) overflowed by %ld bytes, setting last good top to %p", tlabInfo, donorThread, overflowAmount, tlabInfo->last_good_top());
+            tty->print_cr("tlabInfo %p (tlab = %p) overflowed by %ld bytes, setting last good top to %p", tlabInfo, tlab, overflowAmount, tlabInfo->last_good_top());
           }
           tlabInfo->_top = tlabInfo->last_good_top();
         }
 
-        // fill the donor thread tlab with the tlabInfo information
+        // fill the gpu_hsail_tlab with the tlabInfo information
         // we do this even if it will get overwritten by a later tlabinfo
-        // because it helps with tlab statistics for that donor thread
+        // because it helps with tlab statistics for that tlab
         tlab->fill(tlabInfo->start(), tlabInfo->top(), (tlabInfo->end() - tlabInfo->start()) + tlab->alignment_reserve());
 
         // if there was an overflow, make it parsable with retire = true
@@ -215,7 +216,7 @@
 private:
   // fill and retire old tlab and get a new one
   // if we can't get one, no problem someone will eventually do a gc
-  bool getNewTlabForDonorThread(ThreadLocalAllocBuffer* tlab, int idx) {
+  bool getNewGpuHsailTlab(ThreadLocalAllocBuffer* tlab) {
 
     tlab->clear_before_allocation();    // fill and retire old tlab (will also check for null)
     
--- a/src/gpu/hsail/vm/vmStructs_hsail.hpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/gpu/hsail/vm/vmStructs_hsail.hpp	Mon Aug 25 21:15:59 2014 -0700
@@ -58,8 +58,8 @@
   nonstatic_field(HSAILTlabInfo, _end,                                                     HeapWord*)                                 \
   nonstatic_field(HSAILTlabInfo, _last_good_top,                                           HeapWord*)                                 \
   nonstatic_field(HSAILTlabInfo, _original_top,                                            HeapWord*)                                 \
-  nonstatic_field(HSAILTlabInfo, _donor_thread,                                            JavaThread*)                               \
   nonstatic_field(HSAILTlabInfo, _alloc_info,                                              HSAILAllocationInfo*)                      \
+  nonstatic_field(HSAILTlabInfo, _tlab,                                                    ThreadLocalAllocBuffer*)                   \
 
 #define VM_TYPES_GPU_HSAIL(declare_type, declare_toplevel_type)      \
   declare_toplevel_type(HSAILFrame)                                  \
--- a/src/os/bsd/vm/os_bsd.cpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/os/bsd/vm/os_bsd.cpp	Mon Aug 25 21:15:59 2014 -0700
@@ -3805,6 +3805,11 @@
   return fetcher.result();
 }
 
+address os::get_pc(void* context) {
+  ucontext_t *uc = (ucontext_t*)context;
+  return os::Bsd::ucontext_get_pc(uc);
+}
+
 int os::Bsd::safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime)
 {
   return pthread_cond_timedwait(_cond, _mutex, _abstime);
--- a/src/os/linux/vm/os_linux.cpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/os/linux/vm/os_linux.cpp	Mon Aug 25 21:15:59 2014 -0700
@@ -5035,6 +5035,11 @@
   return fetcher.result();
 }
 
+address os::get_pc(void* context) {
+  ucontext_t *uc = (ucontext_t*)context;
+  return os::Linux::ucontext_get_pc(uc);
+}
+
 int os::Linux::safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime)
 {
    if (is_NPTL()) {
--- a/src/os/solaris/vm/os_solaris.cpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/os/solaris/vm/os_solaris.cpp	Mon Aug 25 21:15:59 2014 -0700
@@ -4379,6 +4379,10 @@
   return fetcher.result();
 }
 
+address os::get_pc(void* context) {
+  ucontext_t *uc = (ucontext_t*)context;
+  return os::Solaris::ucontext_get_pc(uc);
+}
 
 // This does not do anything on Solaris. This is basically a hook for being
 // able to use structured exception handling (thread-local exception filters) on, e.g., Win32.
--- a/src/os/windows/vm/os_windows.cpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/os/windows/vm/os_windows.cpp	Mon Aug 25 21:15:59 2014 -0700
@@ -3672,6 +3672,16 @@
 #endif
 }
 
+address os::get_pc(void* context) {
+  CONTEXT* uc = (CONTEXT*)context;
+#ifdef _M_AMD64
+  return (address) uc->Rip;
+#else
+  return (address) uc->Eip;
+#endif
+}
+
+
 // GetCurrentThreadId() returns DWORD
 intx os::current_thread_id()          { return GetCurrentThreadId(); }
 
--- a/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSlider.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSlider.java	Mon Aug 25 21:15:59 2014 -0700
@@ -26,24 +26,26 @@
 
 import com.sun.hotspot.igv.data.ChangedListener;
 import java.awt.*;
+import java.awt.geom.*;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.awt.event.MouseMotionListener;
 import java.util.List;
-import javax.swing.JComponent;
+import javax.swing.*;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
-public class RangeSlider extends JComponent implements ChangedListener<RangeSliderModel>, MouseListener, MouseMotionListener {
+public class RangeSlider extends JComponent implements ChangedListener<RangeSliderModel>, MouseListener, MouseMotionListener, Scrollable {
 
     public static final int HEIGHT = 40;
-    public static final int BAR_HEIGHT = 22;
-    public static final int BAR_SELECTION_ENDING_HEIGHT = 16;
-    public static final int BAR_SELECTION_HEIGHT = 10;
-    public static final int BAR_THICKNESS = 2;
-    public static final int BAR_CIRCLE_SIZE = 9;
+    public static final float BAR_HEIGHT = 22;
+    public static final float BAR_SELECTION_ENDING_HEIGHT = 16;
+    public static final float BAR_SELECTION_HEIGHT = 10;
+    public static final float BAR_THICKNESS = 2;
+    public static final float BAR_CIRCLE_SIZE = 9;
+    public static final float BAR_CIRCLE_CONNECTOR_SIZE = 6;
     public static final int MOUSE_ENDING_OFFSET = 3;
     public static final Color BACKGROUND_COLOR = Color.white;
     public static final Color BAR_COLOR = Color.black;
@@ -90,15 +92,61 @@
         return model;
     }
 
+    /**
+     * Returns the preferred size of the viewport for a view component.
+     * For example, the preferred size of a <code>JList</code> component
+     * is the size required to accommodate all of the cells in its list.
+     * However, the value of <code>preferredScrollableViewportSize</code>
+     * is the size required for <code>JList.getVisibleRowCount</code> rows.
+     * A component without any properties that would affect the viewport
+     * size should just return <code>getPreferredSize</code> here.
+     *
+     * @return the preferredSize of a <code>JViewport</code> whose view
+     *    is this <code>Scrollable</code>
+     * @see JViewport#getPreferredSize
+     */
+    public Dimension getPreferredScrollableViewportSize() {
+        return getPreferredSize();
+    }
+
+    public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
+        if (orientation == SwingConstants.VERTICAL) {
+            return 1;
+        }
+
+        return (int)(BAR_CIRCLE_SIZE + BAR_CIRCLE_CONNECTOR_SIZE);
+    }
+
+    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
+        return orientation == SwingConstants.VERTICAL ? visibleRect.height / 2 : visibleRect.width / 2;
+    }
+
+    public boolean getScrollableTracksViewportWidth() {
+        return false;
+    }
+
+    public boolean getScrollableTracksViewportHeight() {
+        return true;
+    }
+
     @Override
     public Dimension getPreferredSize() {
         Dimension d = super.getPreferredSize();
         d.height = HEIGHT;
+        d.width = Math.max(d.width, (int)(2 * BAR_CIRCLE_CONNECTOR_SIZE + getPaintingModel().getPositions().size() * (BAR_CIRCLE_SIZE + BAR_CIRCLE_CONNECTOR_SIZE)));
         return d;
     }
 
     @Override
     public void changed(RangeSliderModel source) {
+        revalidate();
+
+        float barStartY = getBarStartY();
+        int circleCenterY = (int)(barStartY + BAR_HEIGHT / 2);
+        int startX = (int)getStartXPosition(model.getFirstPosition());
+        int endX = (int)getEndXPosition(model.getSecondPosition());
+        Rectangle r = new Rectangle(startX, circleCenterY, endX - startX, 1);
+        scrollRectToVisible(r);
         update();
     }
 
@@ -106,22 +154,22 @@
         this.repaint();
     }
 
-    private int getXPosition(int index) {
+    private float getXPosition(int index) {
         assert index >= 0 && index < getPaintingModel().getPositions().size();
         return getXOffset() * (index + 1);
     }
 
-    private int getXOffset() {
+    private float getXOffset() {
         int size = getPaintingModel().getPositions().size();
-        int width = getWidth();
+        float width = (float)getWidth();
         return (width / (size + 1));
     }
 
-    private int getEndXPosition(int index) {
+    private float getEndXPosition(int index) {
         return getXPosition(index) + getXOffset() / 2;
     }
 
-    private int getStartXPosition(int index) {
+    private float getStartXPosition(int index) {
         return getXPosition(index) - getXOffset() / 2;
     }
 
@@ -135,7 +183,7 @@
         int height = getHeight();
 
         g2.setColor(BACKGROUND_COLOR);
-        g2.fillRect(0, 0, width, height);
+        g2.fill(new Rectangle2D.Float(0, 0, width, height));
 
         // Nothing to paint?
         if (getPaintingModel() == null || getPaintingModel().getPositions().size() == 0) {
@@ -150,30 +198,30 @@
 
     }
 
-    private int getBarStartY() {
-        return getHeight() - BAR_HEIGHT;
+    private float getBarStartY() {
+        return getHeight() / 2 - BAR_HEIGHT / 2;
     }
 
     private void paintBar(Graphics2D g) {
         List<String> list = getPaintingModel().getPositions();
-        int barStartY = getBarStartY();
+        float barStartY = getBarStartY();
 
         g.setColor(BAR_COLOR);
-        g.fillRect(getXPosition(0), barStartY + BAR_HEIGHT / 2 - BAR_THICKNESS / 2, getXPosition(list.size() - 1) - getXPosition(0), BAR_THICKNESS);
+        g.fill(new Rectangle2D.Float(getXPosition(0), barStartY + BAR_HEIGHT / 2 - BAR_THICKNESS / 2, getXPosition(list.size() - 1) - getXPosition(0), BAR_THICKNESS));
 
-        int circleCenterY = barStartY + BAR_HEIGHT / 2;
+        float circleCenterY = barStartY + BAR_HEIGHT / 2;
         for (int i = 0; i < list.size(); i++) {
-            int curX = getXPosition(i);
+            float curX = getXPosition(i);
             g.setColor(getPaintingModel().getColors().get(i));
-            g.fillOval(curX - BAR_CIRCLE_SIZE / 2, circleCenterY - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE);
+            g.fill(new Ellipse2D.Float(curX - BAR_CIRCLE_SIZE / 2, circleCenterY - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE));
             g.setColor(Color.black);
-            g.drawOval(curX - BAR_CIRCLE_SIZE / 2, circleCenterY - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE);
+            g.draw(new Ellipse2D.Float(curX - BAR_CIRCLE_SIZE / 2, circleCenterY - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE));
 
 
             String curS = list.get(i);
             if (curS != null && curS.length() > 0) {
-                int startX = getStartXPosition(i);
-                int endX = getEndXPosition(i);
+                float startX = getStartXPosition(i);
+                float endX = getEndXPosition(i);
                 FontMetrics metrics = g.getFontMetrics();
                 Rectangle bounds = metrics.getStringBounds(curS, g).getBounds();
                 if (bounds.width < endX - startX && bounds.height < barStartY) {
@@ -187,10 +235,10 @@
 
     private void paintSelected(Graphics2D g, int start, int end) {
 
-        int startX = getStartXPosition(start);
-        int endX = getEndXPosition(end);
-        int barStartY = getBarStartY();
-        int barSelectionEndingStartY = barStartY + BAR_HEIGHT / 2 - BAR_SELECTION_ENDING_HEIGHT / 2;
+        float startX = getStartXPosition(start);
+        float endX = getEndXPosition(end);
+        float barStartY = getBarStartY();
+        float barSelectionEndingStartY = barStartY + BAR_HEIGHT / 2 - BAR_SELECTION_ENDING_HEIGHT / 2;
         paintSelectedEnding(g, startX, barSelectionEndingStartY);
         paintSelectedEnding(g, endX, barSelectionEndingStartY);
 
@@ -200,18 +248,18 @@
         } else if (isOverBar) {
             g.setColor(BAR_SELECTION_COLOR_ROLLOVER);
         }
-        g.fillRect(startX, barStartY + BAR_HEIGHT / 2 - BAR_SELECTION_HEIGHT / 2, endX - startX, BAR_SELECTION_HEIGHT);
+        g.fill(new Rectangle2D.Float(startX, barStartY + BAR_HEIGHT / 2 - BAR_SELECTION_HEIGHT / 2, endX - startX, BAR_SELECTION_HEIGHT));
     }
 
-    private void paintSelectedEnding(Graphics g, int x, int y) {
+    private void paintSelectedEnding(Graphics2D g, float x, float y) {
         g.setColor(BAR_COLOR);
-        g.fillRect(x - BAR_THICKNESS / 2, y, BAR_THICKNESS, BAR_SELECTION_ENDING_HEIGHT);
+        g.fill(new Rectangle2D.Float(x - BAR_THICKNESS / 2, y, BAR_THICKNESS, BAR_SELECTION_ENDING_HEIGHT));
     }
 
     private boolean isOverSecondPosition(Point p) {
         if (p.y >= getBarStartY()) {
-            int destX = getEndXPosition(getPaintingModel().getSecondPosition());
-            int off = Math.abs(destX - p.x);
+            float destX = getEndXPosition(getPaintingModel().getSecondPosition());
+            float off = Math.abs(destX - p.x);
             return off <= MOUSE_ENDING_OFFSET;
         }
         return false;
@@ -219,8 +267,8 @@
 
     private boolean isOverFirstPosition(Point p) {
         if (p.y >= getBarStartY()) {
-            int destX = getStartXPosition(getPaintingModel().getFirstPosition());
-            int off = Math.abs(destX - p.x);
+            float destX = getStartXPosition(getPaintingModel().getFirstPosition());
+            float off = Math.abs(destX - p.x);
             return off <= MOUSE_ENDING_OFFSET;
         }
         return false;
@@ -235,9 +283,12 @@
 
     @Override
     public void mouseDragged(MouseEvent e) {
+        Rectangle r = new Rectangle(e.getX(), e.getY(), 1, 1);
+        scrollRectToVisible(r);
+
         if (state == State.DragBar) {
-            int firstX = this.getStartXPosition(model.getFirstPosition());
-            int newFirstX = firstX + e.getPoint().x - startPoint.x;
+            float firstX = this.getStartXPosition(model.getFirstPosition());
+            float newFirstX = firstX + e.getPoint().x - startPoint.x;
             int newIndex = getIndexFromPosition(newFirstX) + 1;
             if (newIndex + model.getSecondPosition() - model.getFirstPosition() >= model.getPositions().size()) {
                 newIndex = model.getPositions().size() - (model.getSecondPosition() - model.getFirstPosition()) - 1;
@@ -264,13 +315,13 @@
         }
     }
 
-    private int getIndexFromPosition(int x) {
+    private int getIndexFromPosition(float x) {
         if (x < getXPosition(0)) {
             return -1;
         }
         for (int i = 0; i < getPaintingModel().getPositions().size() - 1; i++) {
-            int startX = getXPosition(i);
-            int endX = getXPosition(i + 1);
+            float startX = getXPosition(i);
+            float endX = getXPosition(i + 1);
             if (x >= startX && x <= endX) {
                 return i;
             }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java	Mon Aug 25 21:15:59 2014 -0700
@@ -197,7 +197,8 @@
         rangeSliderModel = new DiagramViewModel(diagram.getGraph().getGroup(), filterChain, sequence);
         rangeSlider = new RangeSlider();
         rangeSlider.setModel(rangeSliderModel);
-        container.add(BorderLayout.CENTER, rangeSlider);
+        JScrollPane pane = new JScrollPane(rangeSlider, ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+        container.add(BorderLayout.CENTER, pane);
 
         scene = new DiagramScene(actions, rangeSliderModel);
         content = new InstanceContent();
--- a/src/share/tools/IdealGraphVisualizer/nbproject/project.properties	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/share/tools/IdealGraphVisualizer/nbproject/project.properties	Mon Aug 25 21:15:59 2014 -0700
@@ -40,5 +40,5 @@
 
 # Disable assertions for RequestProcessor to prevent annoying messages in case
 # of multiple SceneAnimator update tasks in the default RequestProcessor.
-run.args.extra = -J-server -J-da:org.openide.util.RequestProcessor -J-Xms2g -J-Xmx8g
+run.args.extra = -J-server -J-da:org.openide.util.RequestProcessor -J-Xms2g -J-Xmx8g -J-Djava.lang.Integer.IntegerCache.high=20000
 debug.args.extra = -J-server -J-da:org.openide.util.RequestProcessor
--- a/src/share/vm/classfile/javaClasses.cpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/share/vm/classfile/javaClasses.cpp	Mon Aug 25 21:15:59 2014 -0700
@@ -594,6 +594,12 @@
       set_init_lock(mirror(), r);
 
       // Set protection domain also
+#ifdef GRAAL
+      if (k->class_loader() == SystemDictionary::graal_loader()) {
+        // Same protection domain as for classes loaded by the boot loader
+        protection_domain = Handle();
+      }
+#endif
       set_protection_domain(mirror(), protection_domain());
 
       // Initialize static fields
--- a/src/share/vm/compiler/disassembler.cpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/share/vm/compiler/disassembler.cpp	Mon Aug 25 21:15:59 2014 -0700
@@ -493,6 +493,10 @@
 
 void Disassembler::decode(CodeBlob* cb, outputStream* st) {
   if (!load_library())  return;
+  if (cb->is_nmethod()) {
+    decode((nmethod*)cb, st);
+    return;
+  }
   decode_env env(cb, st);
   env.output()->print_cr("----------------------------------------------------------------------");
   env.output()->print_cr("%s at  [" PTR_FORMAT ", " PTR_FORMAT "]  %d bytes", cb->name(), cb->code_begin(), cb->code_end(), ((jlong)(cb->code_end() - cb->code_begin())) * sizeof(unsigned char*));
--- a/src/share/vm/gc_interface/collectedHeap.cpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/share/vm/gc_interface/collectedHeap.cpp	Mon Aug 25 21:15:59 2014 -0700
@@ -503,7 +503,12 @@
          "Attempt to fill tlabs before main thread has been added"
          " to threads list is doomed to failure!");
   for (JavaThread *thread = Threads::first(); thread; thread = thread->next()) {
-     if (use_tlab) thread->tlab().make_parsable(retire_tlabs);
+     if (use_tlab) {
+       thread->tlab().make_parsable(retire_tlabs);
+#ifdef GRAAL
+       thread->gpu_hsail_tlabs_make_parsable(retire_tlabs);
+#endif
+     }     
 #if defined(COMPILER2) || defined(GRAAL)
      // The deferred store barriers must all have been flushed to the
      // card-table (or other remembered set structure) before GC starts
--- a/src/share/vm/graal/graalRuntime.cpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/share/vm/graal/graalRuntime.cpp	Mon Aug 25 21:15:59 2014 -0700
@@ -39,6 +39,7 @@
 
 address GraalRuntime::_external_deopt_i2c_entry = NULL;
 jobject GraalRuntime::_HotSpotGraalRuntime_instance = NULL;
+bool GraalRuntime::_HotSpotGraalRuntime_initialized = false;
 
 void GraalRuntime::initialize_natives(JNIEnv *env, jclass c2vmClass) {
   uintptr_t heap_end = (uintptr_t) Universe::heap()->reserved_region().end();
@@ -486,7 +487,7 @@
   }
 JRT_END
 
-JRT_ENTRY(void, GraalRuntime::log_object(JavaThread* thread, oopDesc* obj, jint flags))
+JRT_LEAF(void, GraalRuntime::log_object(JavaThread* thread, oopDesc* obj, jint flags))
   bool string =  mask_bits_are_true(flags, LOG_OBJECT_STRING);
   bool addr = mask_bits_are_true(flags, LOG_OBJECT_ADDRESS);
   bool newline = mask_bits_are_true(flags, LOG_OBJECT_NEWLINE);
@@ -599,7 +600,7 @@
   }
 JRT_END
 
-JRT_ENTRY(void, GraalRuntime::log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline))
+JRT_LEAF(void, GraalRuntime::log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline))
   union {
       jlong l;
       jdouble d;
@@ -663,6 +664,28 @@
   return JNIHandles::make_local((oop) result.get_jobject());
 JVM_END
 
+// private static NativeFunctionInterfaceRuntime.createInterface()
+JVM_ENTRY(jobject, JVM_CreateNativeFunctionInterface(JNIEnv *env, jclass c))
+  const char* backendName = NULL;
+  #ifdef TARGET_ARCH_x86
+  #ifdef _LP64
+    backendName = "com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend";
+  #endif 
+  #endif
+
+  if (backendName == NULL) {
+    return NULL;
+  }
+  TempNewSymbol name = SymbolTable::new_symbol(backendName, CHECK_NULL);
+  KlassHandle klass = GraalRuntime::resolve_or_fail(name, CHECK_NULL);
+
+  TempNewSymbol makeInstance = SymbolTable::new_symbol("createNativeFunctionInterface", CHECK_NULL);
+  TempNewSymbol sig = SymbolTable::new_symbol("()Lcom/oracle/nfi/api/NativeFunctionInterface;", CHECK_NULL);
+  JavaValue result(T_OBJECT);
+  JavaCalls::call_static(&result, klass, makeInstance, sig, CHECK_NULL);
+  return JNIHandles::make_local((oop) result.get_jobject());
+JVM_END
+
 void GraalRuntime::check_generated_sources_sha1(TRAPS) {
   TempNewSymbol name = SymbolTable::new_symbol("GeneratedSourcesSha1", CHECK_ABORT);
   KlassHandle klass = load_required_class(name);
@@ -681,6 +704,7 @@
 
 Handle GraalRuntime::get_HotSpotGraalRuntime() {
   if (JNIHandles::resolve(_HotSpotGraalRuntime_instance) == NULL) {
+    guarantee(!_HotSpotGraalRuntime_initialized, "cannot reinitialize HotSpotGraalRuntime");
     Thread* THREAD = Thread::current();
     check_generated_sources_sha1(CHECK_ABORT_(Handle()));
     TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotGraalRuntime", CHECK_ABORT_(Handle()));
@@ -690,6 +714,7 @@
     JavaValue result(T_OBJECT);
     JavaCalls::call_static(&result, klass, runtime, sig, CHECK_ABORT_(Handle()));
     _HotSpotGraalRuntime_instance = JNIHandles::make_global((oop) result.get_jobject());
+    _HotSpotGraalRuntime_initialized = true;
   }
   return Handle(JNIHandles::resolve_non_null(_HotSpotGraalRuntime_instance));
 }
@@ -703,7 +728,8 @@
 JVM_ENTRY(jboolean, JVM_ParseGraalOptions(JNIEnv *env, jclass c))
   HandleMark hm;
   KlassHandle hotSpotOptionsClass(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c)));
-  return GraalRuntime::parse_arguments(hotSpotOptionsClass, CHECK_false);
+  bool result = GraalRuntime::parse_arguments(hotSpotOptionsClass, CHECK_false);
+  return result;
 JVM_END
 
 jint GraalRuntime::check_arguments(TRAPS) {
@@ -749,7 +775,7 @@
   return CITime || CITimeEach;
 }
 
-void GraalRuntime::check_required_value(const char* name, int name_len, const char* value, TRAPS) {
+void GraalRuntime::check_required_value(const char* name, size_t name_len, const char* value, TRAPS) {
   if (value == NULL) {
     char buf[200];
     jio_snprintf(buf, sizeof(buf), "Must use '-G:%.*s=<value>' format for %.*s option", name_len, name, name_len, name);
@@ -765,7 +791,7 @@
   if (first == '+' || first == '-') {
     name = arg + 1;
     name_len = strlen(name);
-    recognized = set_option(hotSpotOptionsClass, name, (int)name_len, arg, CHECK);
+    recognized = set_option_bool(hotSpotOptionsClass, name, name_len, first, CHECK);
   } else {
     char* sep = strchr(arg, '=');
     name = arg;
@@ -776,13 +802,13 @@
     } else {
       name_len = strlen(name);
     }
-    recognized = set_option(hotSpotOptionsClass, name, (int)name_len, value, CHECK);
+    recognized = set_option(hotSpotOptionsClass, name, name_len, value, CHECK);
   }
 
   if (!recognized) {
     bool throw_err = hotSpotOptionsClass.is_null();
     if (!hotSpotOptionsClass.is_null()) {
-      set_option_helper(hotSpotOptionsClass, name, (int)name_len, Handle(), ' ', Handle(), 0L);
+      set_option_helper(hotSpotOptionsClass, name, name_len, Handle(), ' ', Handle(), 0L);
       if (!HAS_PENDING_EXCEPTION) {
         throw_err = true;
       }
@@ -798,7 +824,7 @@
 
 void GraalRuntime::parse_graal_options_file(KlassHandle hotSpotOptionsClass, TRAPS) {
   const char* home = Arguments::get_java_home();
-  int path_len = (int)strlen(home) + (int)strlen("/lib/graal.options") + 1;
+  size_t path_len = strlen(home) + strlen("/lib/graal.options") + 1;
   char* path = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, path_len);
   char sep = os::file_separator()[0];
   sprintf(path, "%s%clib%cgraal.options", home, sep, sep);
@@ -843,7 +869,7 @@
   }
 }
 
-jlong GraalRuntime::parse_primitive_option_value(char spec, const char* name, int name_len, const char* value, TRAPS) {
+jlong GraalRuntime::parse_primitive_option_value(char spec, const char* name, size_t name_len, const char* value, TRAPS) {
   check_required_value(name, name_len, value, CHECK_(0L));
   union {
     jint i;
@@ -880,11 +906,11 @@
   THROW_MSG_(vmSymbols::java_lang_InternalError(), buf, 0L);
 }
 
-void GraalRuntime::set_option_helper(KlassHandle hotSpotOptionsClass, char* name, int name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue) {
+void GraalRuntime::set_option_helper(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue) {
   Thread* THREAD = Thread::current();
   Handle name_handle;
   if (name != NULL) {
-    if ((int) strlen(name) > name_len) {
+    if (strlen(name) > name_len) {
       // Temporarily replace '=' with NULL to create the Java string for the option name
       char save = name[name_len];
       name[name_len] = '\0';
@@ -894,7 +920,7 @@
         return;
       }
     } else {
-      assert((int) strlen(name) == name_len, "must be");
+      assert(strlen(name) == name_len, "must be");
       name_handle = java_lang_String::create_from_str(name, CHECK);
     }
   }
@@ -990,6 +1016,12 @@
   CLEAR_PENDING_EXCEPTION;
   tty->print_cr(message);
   call_printStackTrace(exception, THREAD);
+
+  // Give other aborting threads to also print their stack traces.
+  // This can be very useful when debugging class initialization
+  // failures.
+  os::sleep(THREAD, 200, false);
+
   vm_abort(dump_core);
 }
 
--- a/src/share/vm/graal/graalRuntime.hpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/share/vm/graal/graalRuntime.hpp	Mon Aug 25 21:15:59 2014 -0700
@@ -32,6 +32,7 @@
  private:
 
   static jobject _HotSpotGraalRuntime_instance;
+  static bool _HotSpotGraalRuntime_initialized;
   static address _external_deopt_i2c_entry;
   static const char* _generated_sources_sha1;
 
@@ -51,7 +52,7 @@
    * @param value string value to parse
    * @throws InternalError if value could not be parsed according to spec
    */
-  static jlong parse_primitive_option_value(char spec, const char* name, int name_len, const char* value, TRAPS);
+  static jlong parse_primitive_option_value(char spec, const char* name, size_t name_len, const char* value, TRAPS);
 
   /**
    * Loads default option value overrides from a <jre_home>/lib/graal.options if it exists. Each
@@ -69,6 +70,21 @@
   static void parse_argument(KlassHandle hotSpotOptionsClass, char* arg, TRAPS);
 
   /**
+   * Searches for a Boolean Graal option denoted by a given name and sets it value.
+   *
+   * The definition of this method is in graalRuntime.inline.hpp
+   * which is generated by com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp.
+   *
+   * @param hotSpotOptionsClass the HotSpotOptions klass or NULL if only checking for valid option
+   * @param name option name
+   * @param name_len length of option name
+   * @param value '+' to set the option, '-' to reset the option
+   * @returns true if the option was found
+   * @throws InternalError if there was a problem setting the option's value
+   */
+  static bool set_option_bool(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, char value, TRAPS);
+
+  /**
    * Searches for a Graal option denoted by a given name and sets it value.
    *
    * The definition of this method is in graalRuntime.inline.hpp
@@ -80,12 +96,12 @@
    * @returns true if the option was found
    * @throws InternalError if there was a problem setting the option's value
    */
-  static bool set_option(KlassHandle hotSpotOptionsClass, char* name, int name_len, const char* value, TRAPS);
+  static bool set_option(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, const char* value, TRAPS);
 
   /**
    * Raises an InternalError for an option that expects a value but was specified without a "=<value>" prefix.
    */
-  static void check_required_value(const char* name, int name_len, const char* value, TRAPS);
+  static void check_required_value(const char* name, size_t name_len, const char* value, TRAPS);
 
   /**
    * Java call to HotSpotOptions.setOption(String name, OptionValue<?> option, char spec, String stringValue, long primitiveValue)
@@ -93,7 +109,7 @@
    * @param name option name
    * @param name_len length of option name
    */
-  static void set_option_helper(KlassHandle hotSpotOptionsClass, char* name, int name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue);
+  static void set_option_helper(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue);
 
   /**
    * Instantiates a service object, calls its default constructor and returns it.
@@ -111,7 +127,7 @@
 
   static void initialize_natives(JNIEnv *env, jclass c2vmClass);
 
-  static bool is_HotSpotGraalRuntime_initialized() { return _HotSpotGraalRuntime_instance != NULL; }
+  static bool is_HotSpotGraalRuntime_initialized() { return _HotSpotGraalRuntime_initialized; }
 
   /**
    * Gets the singleton HotSpotGraalRuntime instance, initializing it if necessary
--- a/src/share/vm/memory/threadLocalAllocBuffer.cpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/share/vm/memory/threadLocalAllocBuffer.cpp	Mon Aug 25 21:15:59 2014 -0700
@@ -48,6 +48,13 @@
   for(JavaThread *thread = Threads::first(); thread; thread = thread->next()) {
     thread->tlab().accumulate_statistics();
     thread->tlab().initialize_statistics();
+#ifdef GRAAL
+    for (jint i = 0; i < thread->get_gpu_hsail_tlabs_count(); i++) {
+      thread->get_gpu_hsail_tlab_at(i)->accumulate_statistics();
+      thread->get_gpu_hsail_tlab_at(i)->initialize_statistics();
+    }
+#endif
+
   }
 
   // Publish new stats if some allocation occurred.
@@ -129,6 +136,11 @@
 void ThreadLocalAllocBuffer::resize_all_tlabs() {
   for(JavaThread *thread = Threads::first(); thread; thread = thread->next()) {
     thread->tlab().resize();
+#ifdef GRAAL
+    for (jint i = 0; i < thread->get_gpu_hsail_tlabs_count(); i++) {
+      thread->get_gpu_hsail_tlab_at(i)->resize();
+    }
+#endif
   }
 }
 
@@ -188,11 +200,12 @@
   invariants();
 }
 
-void ThreadLocalAllocBuffer::initialize() {
+void ThreadLocalAllocBuffer::initialize(Thread* owning_thread) {
   initialize(NULL,                    // start
              NULL,                    // top
              NULL);                   // end
 
+  _owning_thread = owning_thread;
   set_desired_size(initial_desired_size());
 
   // Following check is needed because at startup the main (primordial)
@@ -221,7 +234,7 @@
   // During jvm startup, the main (primordial) thread is initialized
   // before the heap is initialized.  So reinitialize it now.
   guarantee(Thread::current()->is_Java_thread(), "tlab initialization thread not Java thread");
-  Thread::current()->tlab().initialize();
+  Thread::current()->tlab().initialize(Thread::current());
 
   if (PrintTLAB && Verbose) {
     gclog_or_tty->print("TLAB min: " SIZE_FORMAT " initial: " SIZE_FORMAT " max: " SIZE_FORMAT "\n",
@@ -303,9 +316,7 @@
 }
 
 Thread* ThreadLocalAllocBuffer::myThread() {
-  return (Thread*)(((char *)this) +
-                   in_bytes(start_offset()) -
-                   in_bytes(Thread::tlab_start_offset()));
+  return _owning_thread;
 }
 
 
--- a/src/share/vm/memory/threadLocalAllocBuffer.hpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/share/vm/memory/threadLocalAllocBuffer.hpp	Mon Aug 25 21:15:59 2014 -0700
@@ -38,6 +38,9 @@
 //            used to make it available for such multiplexing.
 class ThreadLocalAllocBuffer: public CHeapObj<mtThread> {
   friend class VMStructs;
+#ifdef GRAAL
+  friend class HSAILAllocationInfo;
+#endif
 private:
   HeapWord* _start;                              // address of TLAB
   HeapWord* _top;                                // address after last allocation
@@ -53,6 +56,7 @@
   unsigned  _slow_refill_waste;
   unsigned  _gc_waste;
   unsigned  _slow_allocations;
+  Thread*   _owning_thread;
 
   AdaptiveWeightedAverage _allocation_fraction;  // fraction of eden allocated in tlabs
 
@@ -153,7 +157,7 @@
   static void resize_all_tlabs();
 
   void fill(HeapWord* start, HeapWord* top, size_t new_size);
-  void initialize();
+  void initialize(Thread* owning_thread);
 
   static size_t refill_waste_limit_increment()   { return TLABWasteIncrement; }
 
--- a/src/share/vm/prims/nativeLookup.cpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/share/vm/prims/nativeLookup.cpp	Mon Aug 25 21:15:59 2014 -0700
@@ -128,6 +128,7 @@
   jobject  JNICALL JVM_GetGraalRuntime(JNIEnv *env, jclass c);
   jobject  JNICALL JVM_GetGraalServiceImpls(JNIEnv *env, jclass c);
   jobject  JNICALL JVM_CreateTruffleRuntime(JNIEnv *env, jclass c);
+  jobject  JNICALL JVM_CreateNativeFunctionInterface(JNIEnv *env, jclass c);
   jboolean JNICALL JVM_ParseGraalOptions(JNIEnv *env, jclass hotspotOptionsClass);
 #ifdef COMPILERGRAAL
   void     JNICALL JVM_PrintAndResetGraalCompRate(JNIEnv *env, jclass c);
@@ -144,11 +145,12 @@
   { CC"Java_sun_misc_Perf_registerNatives",                        NULL, FN_PTR(JVM_RegisterPerfMethods)         },
   { CC"Java_sun_hotspot_WhiteBox_registerNatives",                 NULL, FN_PTR(JVM_RegisterWhiteBoxMethods)     },
 #ifdef GRAAL
-  { CC"Java_com_oracle_graal_api_runtime_Graal_initializeRuntime",            NULL, FN_PTR(JVM_GetGraalRuntime)           },
-  { CC"Java_com_oracle_graal_api_runtime_Services_getServiceImpls",           NULL, FN_PTR(JVM_GetGraalServiceImpls)      },
-  { CC"Java_com_oracle_truffle_api_Truffle_createRuntime",                    NULL, FN_PTR(JVM_CreateTruffleRuntime)      },
-  { CC"Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_init",           NULL, FN_PTR(JVM_InitializeGraalNatives)    },
-  { CC"Java_com_oracle_graal_hotspot_HotSpotOptions_parseVMOptions",          NULL, FN_PTR(JVM_ParseGraalOptions)         },
+  { CC"Java_com_oracle_graal_api_runtime_Graal_initializeRuntime",                                        NULL, FN_PTR(JVM_GetGraalRuntime)                    },
+  { CC"Java_com_oracle_graal_api_runtime_Services_getServiceImpls",                                       NULL, FN_PTR(JVM_GetGraalServiceImpls)               },
+  { CC"Java_com_oracle_truffle_api_Truffle_createRuntime",                                                NULL, FN_PTR(JVM_CreateTruffleRuntime)               },
+  { CC"Java_com_oracle_nfi_NativeFunctionInterfaceRuntime_createInterface",                               NULL, FN_PTR(JVM_CreateNativeFunctionInterface)      },
+  { CC"Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_init",                                       NULL, FN_PTR(JVM_InitializeGraalNatives)             },
+  { CC"Java_com_oracle_graal_hotspot_HotSpotOptions_parseVMOptions",                                      NULL, FN_PTR(JVM_ParseGraalOptions)                  },
 #endif
 };
 
--- a/src/share/vm/runtime/os.cpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/share/vm/runtime/os.cpp	Mon Aug 25 21:15:59 2014 -0700
@@ -1269,6 +1269,8 @@
 #endif
 #ifdef GRAAL
         "%/lib/graal-loader.jar:"
+#endif
+#ifndef NO_TRUFFLE_JAR
         "%/lib/truffle.jar:"
 #endif
         "%/classes";
--- a/src/share/vm/runtime/os.hpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/share/vm/runtime/os.hpp	Mon Aug 25 21:15:59 2014 -0700
@@ -563,6 +563,9 @@
   static void *find_agent_function(AgentLibrary *agent_lib, bool check_lib,
                                    const char *syms[], size_t syms_len);
 
+
+  static address get_pc(void* context);
+
   // Print out system information; they are called by fatal error handler.
   // Output format may be different on different platforms.
   static void print_os_info(outputStream* st);
--- a/src/share/vm/runtime/sharedRuntime.cpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Mon Aug 25 21:15:59 2014 -0700
@@ -853,8 +853,8 @@
           if (!cb->is_nmethod()) {
             bool is_in_blob = cb->is_adapter_blob() || cb->is_method_handles_adapter_blob();
             if (!is_in_blob) {
-              cb->print();
-              fatal(err_msg("exception happened outside interpreter, nmethods and vtable stubs at pc " INTPTR_FORMAT, pc));
+              // Allow normal crash reporting to handle this
+              return NULL;
             }
             Events::log_exception(thread, "NullPointerException in code blob at " INTPTR_FORMAT, pc);
             // There is no handler here, so we will simply unwind.
--- a/src/share/vm/runtime/thread.cpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/share/vm/runtime/thread.cpp	Mon Aug 25 21:15:59 2014 -0700
@@ -1474,7 +1474,9 @@
 #ifdef GRAAL
   set_gpu_exception_bci(0);
   set_gpu_exception_method(NULL);  
-  set_gpu_hsail_deopt_info(NULL);  
+  set_gpu_hsail_deopt_info(NULL);
+  _gpu_hsail_tlabs_count = 0;
+  _gpu_hsail_tlabs = NULL;
 #endif
   set_thread_state(_thread_new);
 #if INCLUDE_NMT
@@ -1694,6 +1696,8 @@
     }
     FREE_C_HEAP_ARRAY(jlong, _graal_counters, mtInternal);
   }
+
+  delete_gpu_hsail_tlabs();
 #endif // GRAAL
 }
 
@@ -1968,7 +1972,7 @@
   remove_stack_guard_pages();
 
   if (UseTLAB) {
-    tlab().make_parsable(true);  // retire TLAB
+    tlabs_make_parsable(true);   // retire TLABs, if any
   }
 
   if (JvmtiEnv::environments_might_exist()) {
@@ -2047,7 +2051,7 @@
   remove_stack_guard_pages();
 
   if (UseTLAB) {
-    tlab().make_parsable(true);  // retire TLAB, if any
+    tlabs_make_parsable(true);   // retire TLABs, if any
   }
 
 #if INCLUDE_ALL_GCS
@@ -4792,3 +4796,54 @@
   VMThread* thread = VMThread::vm_thread();
   if (thread != NULL) thread->verify();
 }
+
+void JavaThread::tlabs_make_parsable(bool retire) {
+  // do the primary tlab for this thread
+  tlab().make_parsable(retire);
+#ifdef GRAAL
+  // do the gpu_hsail tlabs if any
+  gpu_hsail_tlabs_make_parsable(retire);
+#endif
+}
+
+
+#ifdef GRAAL
+void JavaThread::initialize_gpu_hsail_tlabs(jint count) {
+  if (!UseTLAB) return;
+  // create tlabs
+  _gpu_hsail_tlabs = NEW_C_HEAP_ARRAY(ThreadLocalAllocBuffer*, count, mtInternal);
+  // initialize
+  for (jint i = 0; i < count; i++) {
+    _gpu_hsail_tlabs[i] = new ThreadLocalAllocBuffer();
+    _gpu_hsail_tlabs[i]->initialize(Thread::current());
+  }
+  _gpu_hsail_tlabs_count = count;
+}
+
+ThreadLocalAllocBuffer* JavaThread::get_gpu_hsail_tlab_at(jint idx) {
+  assert(idx >= 0 && idx < get_gpu_hsail_tlabs_count(), "illegal gpu tlab index");
+  return _gpu_hsail_tlabs[idx];
+}
+
+void JavaThread::gpu_hsail_tlabs_make_parsable(bool retire) {
+  for (jint i = 0; i < get_gpu_hsail_tlabs_count(); i++) {
+    get_gpu_hsail_tlab_at(i)->make_parsable(retire);
+  }
+}
+
+void JavaThread::delete_gpu_hsail_tlabs() {
+  if (!UseTLAB) return;
+  if (_gpu_hsail_tlabs_count == 0) return;
+
+  gpu_hsail_tlabs_make_parsable(true);
+  for (jint i = 0; i < get_gpu_hsail_tlabs_count(); i++) {
+    delete get_gpu_hsail_tlab_at(i);
+  }
+  FREE_C_HEAP_ARRAY(ThreadLocalAllocBuffer*, _gpu_hsail_tlabs, mtInternal);
+  _gpu_hsail_tlabs = NULL;
+  _gpu_hsail_tlabs_count = 0;
+}
+
+
+#endif
+
--- a/src/share/vm/runtime/thread.hpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/share/vm/runtime/thread.hpp	Mon Aug 25 21:15:59 2014 -0700
@@ -436,7 +436,7 @@
   ThreadLocalAllocBuffer& tlab()                 { return _tlab; }
   void initialize_tlab() {
     if (UseTLAB) {
-      tlab().initialize();
+      tlab().initialize(this);
     }
   }
 
@@ -950,6 +950,8 @@
   Method* _gpu_exception_method;
   // Record the hsailDeoptimization info so gc oops_do processing can find it
   void*   _gpu_hsail_deopt_info;
+  jint    _gpu_hsail_tlabs_count;
+  ThreadLocalAllocBuffer** _gpu_hsail_tlabs;
 #endif
 
  public:
@@ -960,9 +962,17 @@
   Method* get_gpu_exception_method()             { return _gpu_exception_method; }
   void set_gpu_hsail_deopt_info(void * deoptInfo) { _gpu_hsail_deopt_info = deoptInfo; }
   void* get_gpu_hsail_deopt_info()               { return _gpu_hsail_deopt_info; }
+  jint  get_gpu_hsail_tlabs_count()              { return _gpu_hsail_tlabs_count; }
+
+  void  initialize_gpu_hsail_tlabs(jint count);
+  ThreadLocalAllocBuffer* get_gpu_hsail_tlab_at(jint idx);
+  void gpu_hsail_tlabs_make_parsable(bool retire);
+  void  delete_gpu_hsail_tlabs();
 #endif
-  
+
  private:  
+  void tlabs_make_parsable(bool retire);
+
   // support for JNI critical regions
   jint    _jni_active_critical;                  // count of entries into JNI critical region
 
--- a/src/share/vm/utilities/vmError.cpp	Mon Aug 25 14:42:42 2014 -0700
+++ b/src/share/vm/utilities/vmError.cpp	Mon Aug 25 21:15:59 2014 -0700
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "compiler/compileBroker.hpp"
+#include "compiler/disassembler.hpp"
 #include "gc_interface/collectedHeap.hpp"
 #include "prims/whitebox.hpp"
 #include "runtime/arguments.hpp"
@@ -532,6 +533,32 @@
        st->cr();
      }
 
+  STEP(102, "(printing code blob if possible)")
+
+     if (_verbose && _context) {
+       address pc = os::get_pc(_context);
+       CodeBlob* cb = CodeCache::find_blob(pc);
+       if (cb != NULL) {
+         if (Interpreter::contains(pc)) {
+           // The interpreter CodeBlob is very large so try to print the codelet instead.
+           InterpreterCodelet* codelet = Interpreter::codelet_containing(pc);
+           if (codelet != NULL) {
+             codelet->print_on(st);
+             Disassembler::decode(codelet->code_begin(), codelet->code_end(), st);
+           }
+         } else {
+           StubCodeDesc* desc = StubCodeDesc::desc_for(pc);
+           if (desc != NULL) {
+             desc->print_on(st);
+             Disassembler::decode(desc->begin(), desc->end(), st);
+           } else {
+             Disassembler::decode(cb, st);
+             st->cr();
+           }
+         }
+       }
+     }
+
   STEP(105, "(printing register info)")
 
      // decode register contents if possible