changeset 16746:ef3c7944261b

Merge.
author Christian Humer <christian.humer@gmail.com>
date Mon, 11 Aug 2014 15:45:18 +0200
parents bda327903f96 (current diff) 3507ad1b0c44 (diff)
children d9d496d77d37
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.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.hotspot.jdk8.test/src/com/oracle/graal/hotspot/jdk8/test/CRC32UpdateByteBufferSubstitutionTest.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java
diffstat 214 files changed, 4685 insertions(+), 1785 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Mon Aug 11 15:44:52 2014 +0200
+++ b/.hgignore	Mon Aug 11 15:45:18 2014 +0200
@@ -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/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionHandle.java	Mon Aug 11 15:44:52 2014 +0200
+++ /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 11 15:44:52 2014 +0200
+++ /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 11 15:44:52 2014 +0200
+++ /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 11 15:44:52 2014 +0200
+++ /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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaType.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:45:18 2014 +0200
@@ -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 can be use to mark 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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/Services.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Mon Aug 11 15:45:18 2014 +0200
@@ -324,7 +324,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.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Mon Aug 11 15:45:18 2014 +0200
@@ -63,8 +63,8 @@
         protected static final int OP2_SHIFT = 22;
 
         // @formatter:off
-        protected static final int OP_MASK  = 0b11000000000000000000000000000000;
-        protected static final int OP2_MASK = 0b00000001110000000000000000000000;
+        protected static final int OP_MASK  = 0b1100_0000_0000_0000_0000_0000_0000_0000;
+        protected static final int OP2_MASK = 0b0000_0001_1100_0000_0000_0000_0000_0000;
         // @formatter:off
 
         private int op2;
@@ -1264,31 +1264,31 @@
         Prefetch(0b101101, "prefetch"),
         Prefetcha(0b111101, "prefetcha"),
 
-        Lduw(0b00000, "lduw"),
-        Ldub(0b00001, "ldub"),
-        Lduh(0b00010, "lduh"),
-        Stw(0b000100, "stw"),
-        Stb(0b000101, "stb"),
-        Sth(0b000110, "sth"),
-        Ldsw(0b001000, "ldsw"),
-        Ldsb(0b001001, "ldsb"),
-        Ldsh(0b001010, "ldsh"),
-        Ldx(0b001011, "ldx"),
-        Stx(0b001110, "stx"),
-
-        Ldf(0b100000, "ldf"),
-        Ldfsr(0x21, "ldfsr"),
-        Ldaf(0x22, "ldaf"),
-        Lddf(0b100011, "lddf"),
-        Stf(0b100100, "stf"),
-        Stfsr(0x25, "stfsr"),
-        Staf(0x26, "staf"),
-        Stdf(0b100111, "stdf"),
-
-        Fcmp(0b110101, "fcmp"),
-
-        Ldxa (0b01_1011, "ldxa"),
-        Lduwa(0b01_0000, "lduwa");
+        Lduw  (0b00_0000, "lduw"),
+        Ldub  (0b00_0001, "ldub"),
+        Lduh  (0b00_0010, "lduh"),
+        Stw   (0b00_0100, "stw"),
+        Stb   (0b00_0101, "stb"),
+        Sth   (0b00_0110, "sth"),
+        Ldsw  (0b00_1000, "ldsw"),
+        Ldsb  (0b00_1001, "ldsb"),
+        Ldsh  (0b00_1010, "ldsh"),
+        Ldx   (0b00_1011, "ldx"),
+        Stx   (0b00_1110, "stx"),
+
+        Ldf   (0b10_0000, "ldf"),
+        Ldfsr (0b10_0001, "ldfsr"),
+        Ldaf  (0b10_0010, "ldaf"),
+        Lddf  (0b10_0011, "lddf"),
+        Stf   (0b10_0100, "stf"),
+        Stfsr (0b10_0101, "stfsr"),
+        Staf  (0x10_0110, "staf"),
+        Stdf  (0b10_0111, "stdf"),
+
+        Fcmp  (0b11_0101, "fcmp"),
+
+        Ldxa  (0b01_1011, "ldxa"),
+        Lduwa (0b01_0000, "lduwa");
 
         // @formatter:on
 
@@ -3405,6 +3405,10 @@
         public Jmpl(Register src, int simm13, Register dst) {
             super(Op3s.Jmpl, src, simm13, dst);
         }
+
+        public Jmpl(Register src1, Register src2, Register dst) {
+            super(Op3s.Jmpl, src1, src2, dst);
+        }
     }
 
     public static class Lddf extends Fmt11 {
@@ -3687,6 +3691,8 @@
         public Return(Register src1, Register src2) {
             super(Op3s.Rett, src1, src2, r0);
         }
+
+        public static int PC_RETURN_OFFSET = 8;
     }
 
     public static class Save extends Fmt10 {
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/UnsafeAccess.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/UnsafeAccess.java	Mon Aug 11 15:45:18 2014 +0200
@@ -31,22 +31,15 @@
     /**
      * An instance of {@link Unsafe} for use within Graal.
      */
-    public static final Unsafe unsafe = getUnsafe();
+    public static final Unsafe unsafe;
 
-    private static Unsafe getUnsafe() {
-        try {
-            // this will fail if Graal is not part of the boot class path
-            return Unsafe.getUnsafe();
-        } catch (SecurityException e) {
-            // nothing to do
-        }
+    static {
         try {
             Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
             theUnsafeInstance.setAccessible(true);
-            return (Unsafe) theUnsafeInstance.get(Unsafe.class);
+            unsafe = (Unsafe) theUnsafeInstance.get(Unsafe.class);
         } catch (Exception e) {
-            // currently we rely on being able to use Unsafe...
-            throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
+            throw new RuntimeException("exception while trying to get Unsafe", e);
         }
     }
 
@@ -55,7 +48,7 @@
      * terminated C string. The native memory buffer is allocated via
      * {@link Unsafe#allocateMemory(long)}. The caller is responsible for releasing the buffer when
      * it is no longer needed via {@link Unsafe#freeMemory(long)}.
-     * 
+     *
      * @return the native memory pointer of the C string created from {@code s}
      */
     public static long createCString(String s) {
@@ -65,7 +58,7 @@
     /**
      * Reads a {@code '\0'} terminated C string from native memory and converts it to a
      * {@link String}.
-     * 
+     *
      * @return a Java string
      */
     public static String readCString(long address) {
@@ -88,7 +81,7 @@
      * terminated C string. The caller is responsible for ensuring the buffer is at least
      * {@code s.length() + 1} bytes long. The caller is also responsible for releasing the buffer
      * when it is no longer.
-     * 
+     *
      * @return the value of {@code buf}
      */
     public static long writeCString(String s, long buf) {
--- a/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleCosTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleNextAfterTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleNextUpTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleSinTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleTanTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatCosTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatNextAfterTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatNextUpTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatSinTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatTanTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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/StringBuilderTest.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringBuilderTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Aug 11 15:45:18 2014 +0200
@@ -221,7 +221,7 @@
     @Override
     public void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination,
                     double trueDestinationProbability) {
-        boolean mirrored = emitCompare(left, right);
+        boolean mirrored = emitCompare(cmpKind, left, right);
         Condition finalCondition = mirrored ? cond.mirror() : cond;
         Kind kind = left.getKind().getStackKind();
         switch (kind) {
@@ -262,7 +262,7 @@
 
     @Override
     public Variable emitConditionalMove(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
-        boolean mirrored = emitCompare(left, right);
+        boolean mirrored = emitCompare(cmpKind, left, right);
         Condition finalCondition = mirrored ? cond.mirror() : cond;
 
         Variable result = newVariable(trueValue.getLIRKind());
@@ -287,11 +287,12 @@
      * This method emits the compare instruction, and may reorder the operands. It returns true if
      * it did so.
      *
+     * @param cmpKind Kind how a and b have to be compared
      * @param a the left operand of the comparison
      * @param b the right operand of the comparison
      * @return true if the left and right operands were switched, false otherwise
      */
-    protected boolean emitCompare(Value a, Value b) {
+    protected boolean emitCompare(PlatformKind cmpKind, Value a, Value b) {
         Variable left;
         Value right;
         boolean mirrored;
@@ -304,7 +305,14 @@
             right = loadNonConst(b);
             mirrored = false;
         }
-        switch (left.getKind().getStackKind()) {
+        switch ((Kind) cmpKind) {
+            case Short:
+            case Char:
+                append(new CompareOp(ICMP, emitZeroExtend(left, 16, 32), emitZeroExtend(right, 16, 32)));
+                break;
+            case Byte:
+                append(new CompareOp(ICMP, emitZeroExtend(left, 8, 32), emitZeroExtend(right, 8, 32)));
+                break;
             case Int:
                 append(new CompareOp(ICMP, left, right));
                 break;
@@ -653,33 +661,36 @@
     }
 
     @Override
-    public Value emitUDiv(Value a, Value b, LIRFrameState state) {
-        // LIRFrameState state = state(deopting);
+    public Value emitURem(Value a, Value b, LIRFrameState state) {
+        Variable result = newVariable(LIRKind.derive(a, b));
         switch (a.getKind().getStackKind()) {
             case Int:
-                // emitDivRem(IUDIV, a, b, state);
-                // return emitMove(RAX_I);
+                append(new RemOp(IUREM, result, a, loadNonConst(b), state, this));
+                break;
             case Long:
-                // emitDivRem(LUDIV, a, b, state);
-                // return emitMove(RAX_L);
+                append(new RemOp(LUREM, result, a, loadNonConst(b), state, this));
+                break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
+        return result;
+
     }
 
     @Override
-    public Value emitURem(Value a, Value b, LIRFrameState state) {
-        // LIRFrameState state = state(deopting);
+    public Value emitUDiv(Value a, Value b, LIRFrameState state) {
+        SPARCArithmetic op;
         switch (a.getKind().getStackKind()) {
             case Int:
-                // emitDivRem(IUREM, a, b, state);
-                // return emitMove(RDX_I);
+                op = IUDIV;
+                break;
             case Long:
-                // emitDivRem(LUREM, a, b, state);
-                // return emitMove(RDX_L);
+                op = LUDIV;
+                break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
+        return emitBinary(op, false, a, b, state);
     }
 
     @Override
@@ -903,14 +914,16 @@
         } else {
             assert inputVal.getKind() == Kind.Int || inputVal.getKind() == Kind.Short || inputVal.getKind() == Kind.Byte : inputVal.getKind();
             Variable result = newVariable(LIRKind.derive(inputVal).changeType(Kind.Int));
-            int mask = (int) IntegerStamp.defaultMask(fromBits);
-            Constant constant = Constant.forInt(mask);
+            long mask = IntegerStamp.defaultMask(fromBits);
+            Constant constant = Constant.forLong(mask);
             if (canInlineConstant(constant)) {
                 append(new BinaryRegConst(SPARCArithmetic.IAND, result, asAllocatable(inputVal), constant, null));
+            } else if (fromBits == 32) {
+                append(new ShiftOp(IUSHR, result, inputVal, Constant.forInt(0)));
             } else {
                 Variable maskVar = newVariable(LIRKind.derive(inputVal).changeType(Kind.Int));
                 emitMove(maskVar, constant);
-                append(new BinaryRegReg(IAND, result, maskVar, (inputVal)));
+                append(new BinaryRegReg(IAND, result, maskVar, asAllocatable(inputVal)));
             }
             if (toBits > 32) {
                 Variable longResult = newVariable(LIRKind.derive(inputVal).changeType(Kind.Long));
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java	Mon Aug 11 15:45:18 2014 +0200
@@ -118,12 +118,15 @@
                         // 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) {
@@ -168,13 +171,15 @@
     /**
      * 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 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);
     }
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -376,7 +376,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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSensitiveReductionTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -144,7 +144,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,7 +172,7 @@
 
     @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();
@@ -200,7 +200,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 +231,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 +249,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 +274,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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IntegerEqualsCanonicalizerTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -600,7 +600,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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MergeCanonicalizerTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -83,7 +83,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 +105,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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PhiCreationTests.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushThroughIfTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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/StampCanonicalizerTest.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -196,7 +196,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 +208,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 +256,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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -48,7 +48,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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/MonitorDeoptTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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/IterativeInliningTest.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -243,7 +243,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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PoorMansEATest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -231,7 +231,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 11 15:44:52 2014 +0200
+++ /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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/CompilerThread.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Mon Aug 11 15:45:18 2014 +0200
@@ -70,7 +70,7 @@
             }
         }
 
-        appendPhase(new CleanTypeProfileProxyPhase());
+        appendPhase(new CleanTypeProfileProxyPhase(canonicalizer));
 
         if (FullUnroll.getValue()) {
             appendPhase(new LoopFullUnrollPhase(canonicalizer));
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/HostBackend.java	Mon Aug 11 15:44:52 2014 +0200
+++ /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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Mon Aug 11 15:45:18 2014 +0200
@@ -1082,19 +1082,31 @@
     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;
     }
 
+    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
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MemUseTrackerImpl.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MemUseTrackerImpl.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/AMD64HotSpotFrameOmissionTest.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/AMD64HotSpotFrameOmissionTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 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/AMD64HotSpotLIRGenerator.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Mon Aug 11 15:45:18 2014 +0200
@@ -559,8 +559,20 @@
     }
 
     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();
+            System.out.println("compressed null check: " + address + " - " + address.getKind());
+            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/AMD64HotSpotMove.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Mon Aug 11 15:45:18 2014 +0200
@@ -686,7 +686,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 +701,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;
--- a/graal/com.oracle.graal.hotspot.jdk8.test/src/com/oracle/graal/hotspot/jdk8/test/CRC32UpdateByteBufferSubstitutionTest.java	Mon Aug 11 15:44:52 2014 +0200
+++ /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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.loader/src/com/oracle/graal/hotspot/loader/Factory.java	Mon Aug 11 15:45:18 2014 +0200
@@ -26,27 +26,30 @@
 import java.net.*;
 
 /**
- * Utility to create a separate class loader for loading classes in {@code graal.jar}.
+ * Utility to create a separate class loader for loading classes in {@code graal.jar} and
+ * {@code graal-truffle.jar}.
  */
 public class Factory {
 
     /**
-     * Creates a new class loader for loading classes in {@code graal.jar}.
+     * Creates a new class loader for loading classes in {@code graal.jar} and
+     * {@code graal-truffle.jar}
      *
      * Called from the VM.
      */
     @SuppressWarnings("unused")
     private static ClassLoader newClassLoader() throws MalformedURLException {
-        URL[] urls = {getGraalJarUrl()};
-        return URLClassLoader.newInstance(urls);
+        URL[] urls = {getGraalJarUrl("graal"), getGraalJarUrl("graal-truffle")};
+        ClassLoader parent = null;
+        return URLClassLoader.newInstance(urls, parent);
     }
 
     /**
-     * Gets the URL for {@code graal.jar}.
+     * Gets the URL for {@code base.jar}.
      */
-    private static URL getGraalJarUrl() throws MalformedURLException {
+    private static URL getGraalJarUrl(String base) throws MalformedURLException {
         File file = new File(System.getProperty("java.home"));
-        for (String name : new String[]{"lib", "graal.jar"}) {
+        for (String name : new String[]{"lib", base + ".jar"}) {
             file = new File(file, name);
         }
 
--- a/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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.*;
@@ -37,26 +38,43 @@
  */
 public class GenGraalRuntimeInlineHpp {
 
-    private static final ZipFile graalJar;
+    public static class GraalJars implements Iterable<ZipEntry> {
+        private final List<ZipFile> jars = new ArrayList<>(2);
 
-    static {
-        String path = null;
-        String classPath = System.getProperty("java.class.path");
-        for (String e : classPath.split(File.pathSeparator)) {
-            if (e.endsWith("graal.jar")) {
-                path = e;
-                break;
+        public GraalJars() {
+            String classPath = System.getProperty("java.class.path");
+            for (String e : classPath.split(File.pathSeparator)) {
+                if (e.endsWith(File.separatorChar + "graal.jar") || e.endsWith(File.separatorChar + "graal-truffle.jar")) {
+                    try {
+                        jars.add(new ZipFile(e));
+                    } catch (IOException ioe) {
+                        throw new InternalError(ioe);
+                    }
+                }
+            }
+            if (jars.size() != 2) {
+                throw new InternalError("Could not find graal.jar or graal-truffle.jar on class path: " + classPath);
             }
         }
-        ZipFile zipFile = null;
-        try {
-            zipFile = new ZipFile(Objects.requireNonNull(path, "Could not find graal.jar on class path: " + classPath));
-        } catch (IOException e) {
-            throw new InternalError(e);
+
+        public Iterator<ZipEntry> iterator() {
+            Stream<ZipEntry> entries = jars.stream().flatMap(ZipFile::stream);
+            return entries.iterator();
         }
-        graalJar = zipFile;
+
+        public InputStream getInputStream(String classFilePath) throws IOException {
+            for (ZipFile jar : jars) {
+                ZipEntry entry = jar.getEntry(classFilePath);
+                if (entry != null) {
+                    return jar.getInputStream(entry);
+                }
+            }
+            return null;
+        }
     }
 
+    private static final GraalJars graalJars = new GraalJars();
+
     public static void main(String[] args) {
         PrintStream out = System.out;
         try {
@@ -73,8 +91,7 @@
      */
     private static void genGetServiceImpls(PrintStream out) throws Exception {
         final List<Class<? extends Service>> services = new ArrayList<>();
-        for (final Enumeration<? extends ZipEntry> e = graalJar.entries(); e.hasMoreElements();) {
-            final ZipEntry zipEntry = e.nextElement();
+        for (ZipEntry zipEntry : graalJars) {
             String name = zipEntry.getName();
             if (name.startsWith("META-INF/services/")) {
                 String serviceName = name.substring("META-INF/services/".length());
@@ -223,7 +240,7 @@
         Set<Class<?>> checked = new HashSet<>();
         for (final OptionDescriptor option : options.values()) {
             Class<?> cls = option.getDeclaringClass();
-            OptionsVerifier.checkClass(cls, option, checked, graalJar);
+            OptionsVerifier.checkClass(cls, option, checked, graalJars);
         }
         return options;
     }
--- a/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/OptionsVerifier.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/OptionsVerifier.java	Mon Aug 11 15:45:18 2014 +0200
@@ -27,11 +27,11 @@
 import java.io.*;
 import java.lang.reflect.*;
 import java.util.*;
-import java.util.zip.*;
 
 import jdk.internal.org.objectweb.asm.*;
 import jdk.internal.org.objectweb.asm.Type;
 
+import com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp.GraalJars;
 import com.oracle.graal.options.*;
 
 /**
@@ -42,17 +42,16 @@
  */
 final class OptionsVerifier extends ClassVisitor {
 
-    public static void checkClass(Class<?> cls, OptionDescriptor option, Set<Class<?>> checked, ZipFile graalJar) throws IOException {
+    public static void checkClass(Class<?> cls, OptionDescriptor option, Set<Class<?>> checked, GraalJars graalJars) throws IOException {
         if (!checked.contains(cls)) {
             checked.add(cls);
             Class<?> superclass = cls.getSuperclass();
             if (superclass != null && !superclass.equals(Object.class)) {
-                checkClass(superclass, option, checked, graalJar);
+                checkClass(superclass, option, checked, graalJars);
             }
 
             String classFilePath = cls.getName().replace('.', '/') + ".class";
-            ZipEntry entry = Objects.requireNonNull(graalJar.getEntry(classFilePath), "Could not find class file for " + cls.getName());
-            ClassReader cr = new ClassReader(graalJar.getInputStream(entry));
+            ClassReader cr = new ClassReader(Objects.requireNonNull(graalJars.getInputStream(classFilePath), "Could not find class file for " + cls.getName()));
 
             ClassVisitor cv = new OptionsVerifier(cls, option);
             cr.accept(cv, 0);
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Mon Aug 11 15:45:18 2014 +0200
@@ -44,7 +44,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.*;
@@ -172,6 +171,7 @@
     public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRes, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
         SPARCHotSpotLIRGenerationResult gen = (SPARCHotSpotLIRGenerationResult) lirGenRes;
         FrameMap frameMap = gen.getFrameMap();
+        LIR lir = gen.getLIR();
         assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame";
 
         Stub stub = gen.getStub();
@@ -186,10 +186,10 @@
         }
 
         if (stub != null) {
-            // SPARC stubs always enter a frame which saves the registers.
-            Set<Register> destroyedRegisters = Collections.emptySet();
-            Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = Collections.emptyMap();
-            updateStub(stub, destroyedRegisters, calleeSaveInfo, frameMap);
+            // Even on sparc we need to save floating point registers
+            Set<Register> definedRegisters = gatherDefinedRegisters(lir);
+            Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = gen.getCalleeSaveInfo();
+            updateStub(stub, definedRegisters, calleeSaveInfo, frameMap);
         }
 
         return crb;
@@ -246,9 +246,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/SPARCHotSpotCRuntimeCallEpilogueOp.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallEpilogueOp.java	Mon Aug 11 15:45:18 2014 +0200
@@ -22,13 +22,14 @@
  */
 package com.oracle.graal.hotspot.sparc;
 
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 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.Stw;
 import com.oracle.graal.asm.sparc.SPARCAssembler.Stx;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.sparc.*;
@@ -40,19 +41,21 @@
     private final int threadLastJavaPcOffset;
     private final int threadJavaFrameAnchorFlagsOffset;
     private final Register thread;
+    @Use({REG, STACK}) protected Value threadTemp;
 
-    public SPARCHotSpotCRuntimeCallEpilogueOp(int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadJavaFrameAnchorFlagsOffset, Register thread) {
+    public SPARCHotSpotCRuntimeCallEpilogueOp(int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadJavaFrameAnchorFlagsOffset, Register thread, Value threadTemp) {
         this.threadLastJavaSpOffset = threadLastJavaSpOffset;
         this.threadLastJavaPcOffset = threadLastJavaPcOffset;
         this.threadJavaFrameAnchorFlagsOffset = threadJavaFrameAnchorFlagsOffset;
         this.thread = thread;
+        this.threadTemp = threadTemp;
     }
 
     @Override
     public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
 
         // Restore the thread register when coming back from the runtime.
-        new Mov(l7, thread).emit(masm);
+        SPARCMove.move(crb, masm, thread.asValue(LIRKind.value(Kind.Long)), threadTemp);
 
         // Reset last Java frame, last Java PC and flags.
         new Stx(g0, new SPARCAddress(thread, threadLastJavaSpOffset)).emit(masm);
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java	Mon Aug 11 15:45:18 2014 +0200
@@ -22,13 +22,14 @@
  */
 package com.oracle.graal.hotspot.sparc;
 
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 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.Add;
 import com.oracle.graal.asm.sparc.SPARCAssembler.Stx;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.sparc.*;
@@ -39,11 +40,13 @@
     private final int threadLastJavaSpOffset;
     private final Register thread;
     private final Register stackPointer;
+    @Def({REG, STACK}) protected Value threadTemp;
 
-    public SPARCHotSpotCRuntimeCallPrologueOp(int threadLastJavaSpOffset, Register thread, Register stackPointer) {
+    public SPARCHotSpotCRuntimeCallPrologueOp(int threadLastJavaSpOffset, Register thread, Register stackPointer, Value threadTemp) {
         this.threadLastJavaSpOffset = threadLastJavaSpOffset;
         this.thread = thread;
         this.stackPointer = stackPointer;
+        this.threadTemp = threadTemp;
     }
 
     @Override
@@ -53,6 +56,6 @@
         new Stx(g4, new SPARCAddress(thread, threadLastJavaSpOffset)).emit(masm);
 
         // Save the thread register when calling out to the runtime.
-        new Mov(thread, l7).emit(masm);
+        SPARCMove.move(crb, masm, threadTemp, thread.asValue(LIRKind.value(Kind.Long)));
     }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Mon Aug 11 15:45:18 2014 +0200
@@ -27,6 +27,8 @@
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.sparc.SPARC.*;
 
+import java.util.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
@@ -46,6 +48,7 @@
 
     final HotSpotVMConfig config;
     private HotSpotLockStack lockStack;
+    private LIRFrameState currentRuntimeCallInfo;
 
     public SPARCHotSpotLIRGenerator(HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) {
         super(providers, cc, lirGenRes);
@@ -90,6 +93,21 @@
     }
 
     @Override
+    public void beforeRegisterAllocation() {
+        super.beforeRegisterAllocation();
+        boolean hasDebugInfo = getResult().getLIR().hasDebugInfo();
+        if (hasDebugInfo) {
+            ((SPARCHotSpotLIRGenerationResult) getResult()).setDeoptimizationRescueSlot(getResult().getFrameMap().allocateSpillSlot(LIRKind.value(Kind.Long)));
+        }
+    }
+
+    @Override
+    protected void emitForeignCall(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info) {
+        currentRuntimeCallInfo = info;
+        super.emitForeignCall(linkage, result, arguments, temps, info);
+    }
+
+    @Override
     public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args) {
         HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage;
         Variable result;
@@ -103,10 +121,11 @@
         if (hotspotLinkage.needsJavaFrameAnchor()) {
             HotSpotRegistersProvider registers = getProviders().getRegisters();
             Register thread = registers.getThreadRegister();
+            Value threadTemp = newVariable(LIRKind.value(Kind.Long));
             Register stackPointer = registers.getStackPointerRegister();
-            append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread, stackPointer));
+            append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread, stackPointer, threadTemp));
             result = super.emitForeignCall(hotspotLinkage, deoptInfo, args);
-            append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), thread));
+            append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), thread, threadTemp));
         } else {
             result = super.emitForeignCall(hotspotLinkage, deoptInfo, args);
         }
@@ -278,10 +297,16 @@
         ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(UNCOMMON_TRAP);
 
         Register threadRegister = getProviders().getRegisters().getThreadRegister();
+        Value threadTemp = newVariable(LIRKind.value(Kind.Long));
         Register stackPointerRegister = getProviders().getRegisters().getStackPointerRegister();
-        append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister));
+        append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister, threadTemp));
         Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(LIRKind.value(Kind.Long)), trapRequest);
-        append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister));
+        append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister, threadTemp));
+
+        Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = ((SPARCHotSpotLIRGenerationResult) getResult()).getCalleeSaveInfo();
+        assert currentRuntimeCallInfo != null;
+        assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo);
+        calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp);
 
         return result;
     }
@@ -291,10 +316,16 @@
         ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(FETCH_UNROLL_INFO);
 
         Register threadRegister = getProviders().getRegisters().getThreadRegister();
+        Value threadTemp = newVariable(LIRKind.value(Kind.Long));
         Register stackPointerRegister = getProviders().getRegisters().getStackPointerRegister();
-        append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister));
+        append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister, threadTemp));
         Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(LIRKind.value(Kind.Long)));
-        append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister));
+        append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister, threadTemp));
+
+        Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = ((SPARCHotSpotLIRGenerationResult) getResult()).getCalleeSaveInfo();
+        assert currentRuntimeCallInfo != null;
+        assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo);
+        calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp);
 
         return result;
     }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java	Mon Aug 11 15:45:18 2014 +0200
@@ -73,7 +73,8 @@
         Value offset = operand(x.offset());
         Variable cmpValue = (Variable) gen.loadNonConst(operand(x.expectedValue()));
         Variable newValue = gen.load(operand(x.newValue()));
-
+        Variable newValueTemp = gen.newVariable(newValue.getLIRKind());
+        getGen().emitMove(newValueTemp, newValue);
         LIRKind kind = cmpValue.getLIRKind();
         assert kind.equals(newValue.getLIRKind());
 
@@ -88,8 +89,8 @@
             }
         }
 
-        append(new CompareAndSwapOp(address, cmpValue, newValue));
-        setResult(x, gen.emitMove(newValue));
+        append(new CompareAndSwapOp(address, cmpValue, newValueTemp));
+        setResult(x, gen.emitMove(newValueTemp));
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java	Mon Aug 11 15:45:18 2014 +0200
@@ -26,9 +26,9 @@
 import static com.oracle.graal.sparc.SPARC.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
 import com.oracle.graal.asm.sparc.SPARCAssembler.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
@@ -48,19 +48,7 @@
 
     @Override
     public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-        // FIXME This is non-trivial. On SPARC we need to flush all register windows first before we
-        // can patch the return address (see: frame::patch_pc).
-        new Flushw().emit(masm);
-        // int frameSize = crb.frameMap.frameSize();
-        // new SPARCAssembler.Ldx(new SPARCAddress(o7, 1), g3).emit(masm);
-        // new Setx(8 * 15 - 1, g4, false).emit(masm);
-        new Mov(asLongReg(address), g4).emit(masm);
-        new Save(sp, -2000, sp).emit(masm);
-
-        new Sub(g4, 0, i7).emit(masm);
-        new Stx(i7, new SPARCAddress(fp, 8 * 15)).emit(masm);
-        new Restore(g0, g0, g0).emit(masm);
-        new Flushw().emit(masm);
-        // new Ldx(new SPARCAddress(g0, 0x123), g0).emit(masm);
+        Register addrRegister = asLongReg(address);
+        new Sub(addrRegister, Return.PC_RETURN_OFFSET, i7).emit(masm);
     }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Mon Aug 11 15:45:18 2014 +0200
@@ -59,7 +59,8 @@
         for (Register reg : getAllocatableRegisters()) {
             if (architecture.canStoreValue(reg.getRegisterCategory(), kind)) {
                 // Special treatment for double precision
-                if (kind == Kind.Double) {
+                // TODO: This is wasteful it uses only half of the registers as float.
+                if (kind == Kind.Double || kind == Kind.Float) {
                     // Only even register numbers are valid double precision regs
                     if (reg.number % 2 == 0) {
                         list.add(reg);
@@ -235,8 +236,14 @@
             }
 
             if (locations[i] == null) {
+                // Stack slot is always aligned to its size in bytes but minimum wordsize
+                int typeSize = SPARC.spillSlotSize(target, kind);
+                int modulus = currentStackOffset % typeSize;
+                if (modulus != 0) {
+                    currentStackOffset += typeSize - modulus;
+                }
                 locations[i] = StackSlot.get(target.getLIRKind(kind.getStackKind()), currentStackOffset, !type.out);
-                currentStackOffset += Math.max(target.getSizeInBytes(kind), target.wordSize);
+                currentStackOffset += typeSize;
             }
         }
 
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java	Mon Aug 11 15:45:18 2014 +0200
@@ -62,12 +62,12 @@
     }
 
     public static void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm, HotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) {
-        final int pos = masm.position();
         new Setx(config.safepointPollingAddress, scratch).emit(masm);
         MarkId.recordMark(crb, atReturn ? MarkId.POLL_RETURN_FAR : MarkId.POLL_FAR);
+        final int pos = masm.position();
+        new Ldx(new SPARCAddress(scratch, 0), g0).emit(masm);
         if (state != null) {
             crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
         }
-        new Ldx(new SPARCAddress(scratch, 0), g0).emit(masm);
     }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java	Mon Aug 11 15:45:18 2014 +0200
@@ -24,9 +24,10 @@
 
 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.SPARCMacroAssembler.Setx;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
 import com.oracle.graal.lir.*;
@@ -54,7 +55,8 @@
         // The mark for an invocation that uses an inline cache must be placed at the
         // instruction that loads the Klass from the inline cache.
         MarkId.recordMark(crb, invokeKind == InvokeKind.Virtual ? MarkId.INVOKEVIRTUAL : MarkId.INVOKEINTERFACE);
-        new Setx(HotSpotGraalRuntime.runtime().getConfig().nonOopBits, g3, true).emit(masm);
+        Register scratchRegister = g5;
+        new Setx(HotSpotGraalRuntime.runtime().getConfig().nonOopBits, scratchRegister, true).emit(masm);
         super.emitCode(crb, masm);
     }
 }
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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/CRC32SubstitutionsTest.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CRC32SubstitutionsTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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/HotSpotNmethodTest.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNmethodTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:45:18 2014 +0200
@@ -0,0 +1,175 @@
+/*
+ * 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) {
+        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;
+        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++) {
+            try (MemoryUsageCloseable c = verbose ? new MemoryUsageCloseable(methodName + "[warmup-" + i + "]") : null) {
+                doCompilation(methodName);
+            }
+        }
+
+        try (MemoryUsageCloseable c = new MemoryUsageCloseable(methodName)) {
+            doCompilation(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();
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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/CompileTheWorld.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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.*;
 
@@ -158,6 +159,7 @@
     private int classFileCounter = 0;
     private int compiledMethodsCounter = 0;
     private long compileTime = 0;
+    private long memoryUsed = 0;
 
     private boolean verbose;
     private final Config config;
@@ -311,7 +313,7 @@
         }
 
         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 {
@@ -346,11 +348,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
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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/HotSpotOptionsLoader.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptionsLoader.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Mon Aug 11 15:45:18 2014 +0200
@@ -848,6 +848,8 @@
     @HotSpotVMType(name = "vtableEntry", get = HotSpotVMType.Type.SIZE) @Stable public int vtableEntrySize;
     @HotSpotVMField(name = "vtableEntry::_method", type = "Method*", get = HotSpotVMField.Type.OFFSET) @Stable public int vtableEntryMethodOffset;
     @HotSpotVMValue(expression = "InstanceKlass::vtable_start_offset() * HeapWordSize") @Stable public int instanceKlassVtableStartOffset;
+    @HotSpotVMValue(expression = "InstanceKlass::vtable_length_offset() * HeapWordSize") @Stable public int instanceKlassVtableLengthOffset;
+    @HotSpotVMValue(expression = "Universe::base_vtable_size() / vtableEntry::size()") @Stable public int baseVtableLength;
 
     /**
      * The offset of the array length word in an array object's header.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Mon Aug 11 15:45:18 2014 +0200
@@ -488,11 +488,24 @@
             long totalCount = 0;
             int entries = 0;
 
-            for (int i = 0; i < typeProfileWidth; i++) {
+            outer: for (int i = 0; i < typeProfileWidth; i++) {
                 long receiverKlass = data.readWord(position, getTypeOffset(i));
                 if (receiverKlass != 0) {
-                    types[entries] = HotSpotResolvedObjectType.fromMetaspaceKlass(receiverKlass);
+                    ResolvedJavaType klass = HotSpotResolvedObjectType.fromMetaspaceKlass(receiverKlass);
                     long count = data.readUnsignedInt(position, getTypeCountOffset(i));
+                    /*
+                     * Because of races in the profile collection machinery it's possible for a
+                     * class to appear multiple times so merge them to make the profile look
+                     * rational.
+                     */
+                    for (int j = 0; j < entries; j++) {
+                        if (types[j].equals(klass)) {
+                            totalCount += count;
+                            counts[j] += count;
+                            continue outer;
+                        }
+                    }
+                    types[entries] = klass;
                     totalCount += count;
                     counts[entries] = count;
                     entries++;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Mon Aug 11 15:45:18 2014 +0200
@@ -612,21 +612,26 @@
     public int vtableEntryOffset(ResolvedJavaType resolved) {
         guarantee(isInVirtualMethodTable(resolved), "%s does not have a vtable entry", this);
         HotSpotVMConfig config = runtime().getConfig();
-        final int vtableIndex = getVtableIndex(resolved);
+        final int vtableIndex = getVtableIndex((HotSpotResolvedObjectType) resolved);
         return config.instanceKlassVtableStartOffset + vtableIndex * config.vtableEntrySize + config.vtableEntryMethodOffset;
     }
 
     @Override
     public boolean isInVirtualMethodTable(ResolvedJavaType resolved) {
-        return getVtableIndex(resolved) >= 0;
+        if (resolved instanceof HotSpotResolvedObjectType) {
+            HotSpotResolvedObjectType hotspotResolved = (HotSpotResolvedObjectType) resolved;
+            int vtableIndex = getVtableIndex(hotspotResolved);
+            return vtableIndex >= 0 && vtableIndex < hotspotResolved.getVtableLength();
+        }
+        return false;
     }
 
-    private int getVtableIndex(ResolvedJavaType resolved) {
+    private int getVtableIndex(HotSpotResolvedObjectType resolved) {
         if (!holder.isLinked()) {
             return runtime().getConfig().invalidVtableIndex;
         }
         if (holder.isInterface()) {
-            if (resolved.isArray() || resolved.isInterface()) {
+            if (resolved.isInterface()) {
                 return runtime().getConfig().invalidVtableIndex;
             }
             return getVtableIndexForInterface(resolved);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Mon Aug 11 15:45:18 2014 +0200
@@ -436,6 +436,17 @@
         return method;
     }
 
+    public int getVtableLength() {
+        HotSpotVMConfig config = runtime().getConfig();
+        if (isInterface() || isArray()) {
+            /* Everything has the core vtable of java.lang.Object */
+            return config.baseVtableLength;
+        }
+        int result = unsafe.getInt(getMetaspaceKlass() + config.instanceKlassVtableLengthOffset) / (config.vtableEntrySize / config.heapWordSize);
+        assert result >= config.baseVtableLength : unsafe.getInt(getMetaspaceKlass() + config.instanceKlassVtableLengthOffset) + " " + config.vtableEntrySize;
+        return result;
+    }
+
     /**
      * Gets the mask used to filter out HotSpot internal flags for fields when a {@link Field}
      * object is created. This is the value of {@code JVM_RECOGNIZED_FIELD_MODIFIERS} in
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionHandle.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionHandle.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 {
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionPointer.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionPointer.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeLibraryHandle.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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/replacements/MonitorSnippets.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Mon Aug 11 15:45:18 2014 +0200
@@ -253,7 +253,7 @@
             // assuming both the stack pointer and page_size have their least
             // significant 2 bits cleared and page_size is a power of 2
             final Word alignedMask = Word.unsigned(wordSize() - 1);
-            final Word stackPointer = registerAsWord(stackPointerRegister);
+            final Word stackPointer = registerAsWord(stackPointerRegister).add(config().stackBias);
             if (probability(VERY_SLOW_PATH_PROBABILITY, currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).notEqual(0))) {
                 // Most likely not a recursive lock, go into a slow runtime call
                 traceObject(trace, "+lock{stub:failed-cas}", object, true);
--- a/graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMConfigProcessor.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMConfigProcessor.java	Mon Aug 11 15:45:18 2014 +0200
@@ -26,6 +26,7 @@
 import java.lang.annotation.*;
 import java.util.*;
 import java.util.Map.Entry;
+import java.util.function.*;
 
 import javax.annotation.processing.*;
 import javax.lang.model.*;
@@ -142,7 +143,6 @@
         "void VMStructs::initHotSpotVMConfig(oop vmconfig_oop) {",
         "  InstanceKlass* vmconfig_klass = InstanceKlass::cast(vmconfig_oop->klass());",
         "",
-        "  for (JavaFieldStream fs(vmconfig_klass); !fs.done(); fs.next()) {",
     };
     //@formatter:on
 
@@ -158,7 +158,29 @@
                 out.println(line);
             }
 
-            out.println();
+            Map<String, Integer> expectedValues = new HashMap<>();
+            for (VMConfigField value : annotations.values()) {
+                if (!value.optional) {
+                    String key = value.define != null ? value.define : "";
+                    if (expectedValues.get(key) == null) {
+                        expectedValues.put(key, 1);
+                    } else {
+                        expectedValues.put(key, expectedValues.get(key) + 1);
+                    }
+                }
+            }
+
+            out.printf("  int expected = %s;%n", expectedValues.get(""));
+            for (Entry<String, Integer> entry : expectedValues.entrySet()) {
+                if (entry.getKey().equals("")) {
+                    continue;
+                }
+                out.printf("#if %s%n", entry.getKey());
+                out.printf("  expected += %s;%n", entry.getValue());
+                out.printf("#endif%n");
+            }
+            out.println("  int assigned = 0;");
+            out.println("  for (JavaFieldStream fs(vmconfig_klass); !fs.done(); fs.next()) {");
 
             Set<String> fieldTypes = new HashSet<>();
             for (VMConfigField key : annotations.values()) {
@@ -194,6 +216,7 @@
                 out.println("    } // if");
             }
             out.println("  } // for");
+            out.println("  guarantee(assigned == expected, \"Didn't find all fields during init of HotSpotVMConfig.  Maybe recompile?\");");
             out.println("}");
         }
     }
@@ -215,21 +238,84 @@
         }
     }
 
-    class VMConfigField {
+    static class VMConfigField {
+        final String setter;
+        final String define;
+        private boolean optional;
         final VariableElement field;
-        final Annotation annotation;
+
+        public VMConfigField(VariableElement field, HotSpotVMField value) {
+            this.field = field;
+            define = archDefines(value.archs());
+            String type = field.asType().toString();
+            String name = value.name();
+            int i = name.lastIndexOf("::");
+            switch (value.get()) {
+                case OFFSET:
+                    setter = String.format("set_%s(\"%s\", offset_of(%s, %s));", type, field.getSimpleName(), name.substring(0, i), name.substring(i + 2));
+                    break;
+                case ADDRESS:
+                    setter = String.format("set_address(\"%s\", &%s);", field.getSimpleName(), name);
+                    break;
+                case VALUE:
+                    setter = String.format("set_%s(\"%s\", (%s) (intptr_t) %s);", type, field.getSimpleName(), type, name);
+                    break;
+                default:
+                    throw new GraalInternalError("unexpected type: " + value.get());
+            }
+        }
+
+        public VMConfigField(VariableElement field, HotSpotVMType value) {
+            this.field = field;
+            define = null; // ((HotSpotVMType) annotation).archs();
+            String type = field.asType().toString();
+            setter = String.format("set_%s(\"%s\", sizeof(%s));", type, field.getSimpleName(), value.name());
+        }
 
-        public VMConfigField(VariableElement field, Annotation value) {
-            super();
+        public VMConfigField(VariableElement field, HotSpotVMValue value) {
             this.field = field;
-            this.annotation = value;
+            String[] defines = value.defines();
+            int length = defines.length;
+            if (length != 0) {
+                for (int i = 0; i < length; i++) {
+                    defines[i] = "defined(" + defines[i] + ")";
+                }
+                define = String.join(" || ", defines);
+            } else {
+                define = null; // ((HotSpotVMValue) annotation).archs();
+            }
+            String type = field.asType().toString();
+            if (value.get() == HotSpotVMValue.Type.ADDRESS) {
+                setter = String.format("set_address(\"%s\", %s);", field.getSimpleName(), value.expression());
+            } else {
+                setter = String.format("set_%s(\"%s\", %s);", type, field.getSimpleName(), value.expression());
+            }
+        }
+
+        public VMConfigField(VariableElement field, HotSpotVMConstant value) {
+            this.field = field;
+            define = archDefines(value.archs());
+            String type = field.asType().toString();
+            setter = String.format("set_%s(\"%s\", %s);", type, field.getSimpleName(), value.name());
+        }
+
+        public VMConfigField(VariableElement field, HotSpotVMFlag value) {
+            this.field = field;
+            define = archDefines(value.archs());
+            optional = value.optional();
+            String type = field.asType().toString();
+            if (value.optional()) {
+                setter = String.format("set_optional_%s_flag(\"%s\",  \"%s\");", type, field.getSimpleName(), value.name());
+            } else {
+                setter = String.format("set_%s(\"%s\", %s);", type, field.getSimpleName(), value.name());
+            }
         }
 
         public String getType() {
             return field.asType().toString();
         }
 
-        private String archDefine(String arch) {
+        private static String archDefine(String arch) {
             switch (arch) {
                 case "amd64":
                     return "defined(AMD64)";
@@ -242,8 +328,8 @@
             }
         }
 
-        private String archDefines(String[] archs) {
-            if (archs.length == 0) {
+        private static String archDefines(String[] archs) {
+            if (archs == null || archs.length == 0) {
                 return null;
             }
             if (archs.length == 1) {
@@ -254,102 +340,16 @@
             for (String arch : archs) {
                 defs[i++] = archDefine(arch);
             }
-            return String.join(" ||", defs);
+            return String.join(" || ", defs);
         }
 
         public void emit(PrintWriter out) {
-            if (annotation instanceof HotSpotVMField) {
-                emitField(out, (HotSpotVMField) annotation);
-            } else if (annotation instanceof HotSpotVMType) {
-                emitType(out, (HotSpotVMType) annotation);
-            } else if (annotation instanceof HotSpotVMFlag) {
-                emitFlag(out, (HotSpotVMFlag) annotation);
-            } else if (annotation instanceof HotSpotVMConstant) {
-                emitConstant(out, (HotSpotVMConstant) annotation);
-            } else if (annotation instanceof HotSpotVMValue) {
-                emitValue(out, (HotSpotVMValue) annotation);
-            } else {
-                throw new InternalError(annotation.toString());
-            }
-
-        }
-
-        private void emitField(PrintWriter out, HotSpotVMField value) {
-            String type = field.asType().toString();
-            String define = archDefines(value.archs());
             if (define != null) {
                 out.printf("#if %s\n", define);
             }
-
-            String name = value.name();
-            int i = name.lastIndexOf("::");
-            switch (value.get()) {
-                case OFFSET:
-                    out.printf("            set_%s(\"%s\", offset_of(%s, %s));\n", type, field.getSimpleName(), name.substring(0, i), name.substring(i + 2));
-                    break;
-                case ADDRESS:
-                    out.printf("            set_address(\"%s\", &%s);\n", field.getSimpleName(), name);
-                    break;
-                case VALUE:
-                    out.printf("            set_%s(\"%s\", (%s) (intptr_t) %s);\n", type, field.getSimpleName(), type, name);
-                    break;
-            }
-            if (define != null) {
-                out.printf("#endif\n");
-            }
-        }
-
-        private void emitType(PrintWriter out, HotSpotVMType value) {
-            String type = field.asType().toString();
-            out.printf("            set_%s(\"%s\", sizeof(%s));\n", type, field.getSimpleName(), value.name());
-        }
-
-        private void emitValue(PrintWriter out, HotSpotVMValue value) {
-            String type = field.asType().toString();
-            int length = value.defines().length;
-            if (length != 0) {
-                out.printf("#if ");
-                for (int i = 0; i < length; i++) {
-                    out.printf("defined(%s)", value.defines()[i]);
-                    if (i + 1 < length) {
-                        out.printf(" || ");
-                    }
-                }
-                out.println();
-            }
-            if (value.get() == HotSpotVMValue.Type.ADDRESS) {
-                out.printf("            set_address(\"%s\", %s);\n", field.getSimpleName(), value.expression());
-            } else {
-                out.printf("            set_%s(\"%s\", %s);\n", type, field.getSimpleName(), value.expression());
-            }
-            if (length != 0) {
-                out.println("#endif");
-            }
-        }
-
-        private void emitConstant(PrintWriter out, HotSpotVMConstant value) {
-            String define = archDefines(value.archs());
-            if (define != null) {
-                out.printf("#if %s\n", define);
-            }
-            String type = field.asType().toString();
-            out.printf("            set_%s(\"%s\", %s);\n", type, field.getSimpleName(), value.name());
-            if (define != null) {
-                out.printf("#endif\n");
-            }
-        }
-
-        private void emitFlag(PrintWriter out, HotSpotVMFlag value) {
-            String type = field.asType().toString();
-
-            String define = archDefines(value.archs());
-            if (define != null) {
-                out.printf("#if %s\n", define);
-            }
-            if (value.optional()) {
-                out.printf("            set_optional_%s_flag(\"%s\",  \"%s\");\n", type, field.getSimpleName(), value.name());
-            } else {
-                out.printf("            set_%s(\"%s\", %s);\n", type, field.getSimpleName(), value.name());
+            out.printf("            %s%n", setter);
+            if (!optional) {
+                out.printf("            assigned++;%n");
             }
             if (define != null) {
                 out.printf("#endif\n");
@@ -358,7 +358,9 @@
 
     }
 
-    private void collectAnnotations(RoundEnvironment roundEnv, Map<String, VMConfigField> annotationMap, Class<? extends Annotation> annotationClass) {
+    @SuppressWarnings("unchecked")
+    private <T extends Annotation> void collectAnnotations(RoundEnvironment roundEnv, Map<String, VMConfigField> annotationMap, Class<T> annotationClass,
+                    BiFunction<VariableElement, T, VMConfigField> builder) {
         for (Element element : roundEnv.getElementsAnnotatedWith(annotationClass)) {
             Annotation constant = element.getAnnotation(annotationClass);
             if (element.getKind() != ElementKind.FIELD) {
@@ -377,7 +379,7 @@
                     errorMessage(element, "Multiple types encountered.  Only HotSpotVMConfig is supported");
                 }
             }
-            annotationMap.put(element.getSimpleName().toString(), new VMConfigField((VariableElement) element, constant));
+            annotationMap.put(element.getSimpleName().toString(), builder.apply((VariableElement) element, (T) constant));
         }
     }
 
@@ -399,11 +401,11 @@
 
             // First collect all the annotations.
             Map<String, VMConfigField> annotationMap = new HashMap<>();
-            collectAnnotations(roundEnv, annotationMap, HotSpotVMConstant.class);
-            collectAnnotations(roundEnv, annotationMap, HotSpotVMFlag.class);
-            collectAnnotations(roundEnv, annotationMap, HotSpotVMField.class);
-            collectAnnotations(roundEnv, annotationMap, HotSpotVMType.class);
-            collectAnnotations(roundEnv, annotationMap, HotSpotVMValue.class);
+            collectAnnotations(roundEnv, annotationMap, HotSpotVMConstant.class, (e, v) -> new VMConfigField(e, v));
+            collectAnnotations(roundEnv, annotationMap, HotSpotVMFlag.class, (e, v) -> new VMConfigField(e, v));
+            collectAnnotations(roundEnv, annotationMap, HotSpotVMField.class, (e, v) -> new VMConfigField(e, v));
+            collectAnnotations(roundEnv, annotationMap, HotSpotVMType.class, (e, v) -> new VMConfigField(e, v));
+            collectAnnotations(roundEnv, annotationMap, HotSpotVMValue.class, (e, v) -> new VMConfigField(e, v));
 
             if (annotationMap.isEmpty()) {
                 return true;
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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.jtt/src/com/oracle/graal/jtt/bytecode/BC_irem.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_irem.java	Mon Aug 11 15:45:18 2014 +0200
@@ -34,6 +34,16 @@
         return a % b;
     }
 
+    // Left as constant
+    public static int test2(int b) {
+        return 13 % b;
+    }
+
+    // Right as constant
+    public static int test3(int a) {
+        return a % 13;
+    }
+
     @Test
     public void run0() throws Throwable {
         runTest("test", 1, 2);
@@ -54,4 +64,33 @@
         runTest("test", 135, 7);
     }
 
+    @Test
+    public void run20() throws Throwable {
+        runTest("test2", 2);
+    }
+
+    @Test
+    public void run21() throws Throwable {
+        runTest("test2", 20000000);
+    }
+
+    @Test
+    public void run22() throws Throwable {
+        runTest("test2", -20000000);
+    }
+
+    @Test
+    public void run30() throws Throwable {
+        runTest("test3", 2);
+    }
+
+    @Test
+    public void run31() throws Throwable {
+        runTest("test3", 200000000);
+    }
+
+    @Test
+    public void run32() throws Throwable {
+        runTest("test3", -200000000);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/BigMixedParams04.java	Mon Aug 11 15:45:18 2014 +0200
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+/*
+ * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ */
+package com.oracle.graal.jtt.micro;
+
+import org.junit.*;
+
+import com.oracle.graal.jtt.*;
+
+/**
+ * Tests different alignment on the stack with extended parameters (index > 5)
+ */
+public class BigMixedParams04 extends JTTTest {
+
+    @SuppressWarnings("unused")
+    public static long test(int choice, int i0, int i1, int i2, int i3, double d1, double d2, boolean bo1, boolean bo2, byte by, short sh, char ch, int in) {
+        switch (choice) {
+            case 0:
+                return bo1 ? 1l : 2l;
+            case 1:
+                return bo2 ? 1l : 2l;
+            case 2:
+                return by;
+            case 3:
+                return sh;
+            case 4:
+                return ch;
+            case 5:
+                return in;
+        }
+        return 42;
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        runTest("test", 0, -1, -1, -1, -1, 1d, 2d, true, false, (byte) -128, (short) -0x7FFF, (char) 0xFFFF, -0x7FFFFFF);
+    }
+
+    @Test
+    public void run1() throws Throwable {
+        runTest("test", 1, -1, -1, -1, -1, 1d, 2d, true, false, (byte) -128, (short) -0x7FFF, (char) 0xFFFF, -0x7FFFFFF);
+    }
+
+    @Test
+    public void run2() throws Throwable {
+        runTest("test", 2, -1, -1, -1, -1, 1d, 2d, true, false, (byte) -128, (short) -0x7FFF, (char) 0xFFFF, -0x7FFFFFF);
+    }
+
+    @Test
+    public void run3() throws Throwable {
+        runTest("test", 3, -1, -1, -1, -1, 1d, 2d, true, false, (byte) -128, (short) -0x7FFF, (char) 0xFFFF, -0x7FFFFFF);
+    }
+
+    @Test
+    public void run4() throws Throwable {
+        runTest("test", 4, -1, -1, -1, -1, 1d, 2d, true, false, (byte) -128, (short) -0x7FFF, (char) 0xFFFF, -0x7FFFFFF);
+    }
+
+    @Test
+    public void run5() throws Throwable {
+        runTest("test", 5, -1, -1, -1, -1, 1d, 2d, true, false, (byte) -128, (short) -0x7FFF, (char) 0xFFFF, -0x7FFFFFF);
+    }
+}
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Mon Aug 11 15:45:18 2014 +0200
@@ -250,8 +250,8 @@
         @Def({REG}) protected Value result;
         @Use({REG, CONST}) protected Value x;
         @Alive({REG, CONST}) protected Value y;
-        @Def({REG}) protected Value scratch1;
-        @Def({REG}) protected Value scratch2;
+        @Temp({REG}) protected Value scratch1;
+        @Temp({REG}) protected Value scratch2;
         @State protected LIRFrameState state;
 
         public RemOp(SPARCArithmetic opcode, Value result, Value x, Value y, LIRFrameState state, LIRGeneratorTool gen) {
@@ -324,6 +324,10 @@
                     assert isSimm13(crb.asIntConst(src2));
                     new Sdivx(asIntReg(src1), crb.asIntConst(src2), asIntReg(dst)).emit(masm);
                     break;
+                case IUDIV:
+                    assert isSimm13(crb.asIntConst(src2));
+                    new Udivx(asIntReg(src1), crb.asIntConst(src2), asIntReg(dst)).emit(masm);
+                    break;
                 case IAND:
                     assert isSimm13(crb.asIntConst(src2)) : src2;
                     new And(asIntReg(src1), crb.asIntConst(src2), asIntReg(dst)).emit(masm);
@@ -360,7 +364,7 @@
                     assert isSimm13(crb.asIntConst(src2));
                     new Mulx(asLongReg(src1), crb.asIntConst(src2), asLongReg(dst)).emit(masm);
                     break;
-                case LDIV:
+                case LDIV: {
                     int c = crb.asIntConst(src2);
                     exceptionOffset = masm.position();
                     if (c == 0) { // Generate div by zero trap
@@ -372,8 +376,14 @@
                         new Sdivx(asLongReg(src1), crb.asIntConst(src2), asLongReg(dst)).emit(masm);
                     }
                     break;
-                case LUDIV:
-                    throw GraalInternalError.unimplemented();
+                }
+                case LUDIV: {
+                    int c = crb.asIntConst(src2);
+                    assert isSimm13(c);
+                    exceptionOffset = masm.position();
+                    new Udivx(asLongReg(src1), c, asLongReg(dst)).emit(masm);
+                    break;
+                }
                 case LAND:
                     assert isSimm13(crb.asIntConst(src2));
                     new And(asLongReg(src1), crb.asIntConst(src2), asLongReg(dst)).emit(masm);
@@ -425,9 +435,15 @@
                     break;
                 case IDIV:
                     new Signx(asIntReg(src1), asIntReg(src1)).emit(masm);
+                    new Signx(asIntReg(src2), asIntReg(src2)).emit(masm);
                     exceptionOffset = masm.position();
                     new Sdivx(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
                     break;
+                case IUDIV:
+                    new Srl(asIntReg(src1), 0, asIntReg(src1)).emit(masm);
+                    exceptionOffset = masm.position();
+                    new Udivx(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
+                    break;
                 case IAND:
                     new And(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
                     break;
@@ -462,7 +478,9 @@
                     new Sdivx(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm);
                     break;
                 case LUDIV:
-                    throw GraalInternalError.unimplemented();
+                    exceptionOffset = masm.position();
+                    new Udivx(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm);
+                    break;
                 case LAND:
                     new And(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm);
                     break;
@@ -532,8 +550,8 @@
                     } else {
                         new Setx(a % b, asIntReg(dst), false).emit(masm);
                     }
+                    break;
                 }
-                    break;
                 case LREM: {
                     long a = crb.asLongConst(src1);
                     long b = crb.asLongConst(src2);
@@ -543,16 +561,11 @@
                     } else {
                         new Setx(a % b, asLongReg(dst), false).emit(masm);
                     }
+                    break;
                 }
-                    break;
                 default:
                     throw GraalInternalError.shouldNotReachHere("not implemented");
             }
-        } else if (isConstant(src1)) {
-            switch (opcode) {
-                default:
-                    throw GraalInternalError.shouldNotReachHere();
-            }
         } else if (isConstant(src2)) {
             switch (opcode) {
                 case IREM:
@@ -563,6 +576,13 @@
                     new Mulx(asIntReg(scratch1), crb.asIntConst(src2), asIntReg(scratch2)).emit(masm);
                     new Sub(asIntReg(src1), asIntReg(scratch2), asIntReg(dst)).emit(masm);
                     break;
+                case IUREM:
+                    new Sra(asIntReg(src1), 0, asIntReg(scratch1)).emit(masm);
+                    exceptionOffset = masm.position();
+                    new Udivx(asIntReg(scratch1), crb.asIntConst(src2), asIntReg(scratch1)).emit(masm);
+                    new Mulx(asIntReg(scratch1), crb.asIntConst(src2), asIntReg(scratch1)).emit(masm);
+                    new Sub(asIntReg(src1), asIntReg(scratch1), asIntReg(dst)).emit(masm);
+                    break;
                 case LREM:
                     assert isSimm13(crb.asIntConst(src2));
                     exceptionOffset = masm.position();
@@ -571,26 +591,55 @@
                     new Sub(asLongReg(src1), asLongReg(scratch2), asLongReg(dst)).emit(masm);
                     break;
                 case LUREM:
-                    throw GraalInternalError.unimplemented();
+                    assert isSimm13(crb.asIntConst(src2));
+                    exceptionOffset = masm.position();
+                    new Udivx(asLongReg(src1), crb.asIntConst(src2), asLongReg(scratch1)).emit(masm);
+                    new Mulx(asLongReg(scratch1), crb.asIntConst(src2), asLongReg(scratch2)).emit(masm);
+                    new Sub(asLongReg(src1), asLongReg(scratch2), asLongReg(dst)).emit(masm);
+                    break;
                 default:
                     throw GraalInternalError.shouldNotReachHere();
             }
         } else {
+            Value srcLeft = src1;
             switch (opcode) {
                 case LREM:
+                    if (isConstant(src1)) {
+                        new Setx(crb.asLongConst(src1), asLongReg(scratch2), false).emit(masm);
+                        srcLeft = scratch2;
+                    }
                     exceptionOffset = masm.position();
-                    new Sdivx(asLongReg(src1), asLongReg(src2), asLongReg(scratch1)).emit(masm);
-                    new Mulx(asLongReg(scratch1), asLongReg(src2), asLongReg(scratch2)).emit(masm);
-                    new Sub(asLongReg(src1), asLongReg(scratch2), asLongReg(dst)).emit(masm);
+                    new Sdivx(asLongReg(srcLeft), asLongReg(src2), asLongReg(scratch1)).emit(masm);
+                    new Mulx(asLongReg(scratch1), asLongReg(src2), asLongReg(scratch1)).emit(masm);
+                    new Sub(asLongReg(srcLeft), asLongReg(scratch1), asLongReg(dst)).emit(masm);
+                    break;
+                case LUREM:
+                    if (isConstant(src1)) {
+                        new Setx(crb.asLongConst(src1), asLongReg(scratch2), false).emit(masm);
+                        srcLeft = scratch2;
+                    }
+                    exceptionOffset = masm.position();
+                    new Udivx(asLongReg(srcLeft), asLongReg(src2), asLongReg(scratch1)).emit(masm);
+                    new Mulx(asLongReg(scratch1), asLongReg(src2), asLongReg(scratch1)).emit(masm);
+                    new Sub(asLongReg(srcLeft), asLongReg(scratch1), asLongReg(dst)).emit(masm);
                     break;
                 case IREM:
+                    if (isConstant(src1)) {
+                        new Setx(crb.asIntConst(src1), asIntReg(scratch2), false).emit(masm);
+                        srcLeft = scratch2;
+                    }
                     exceptionOffset = masm.position();
-                    new Sdivx(asIntReg(src1), asIntReg(src2), asIntReg(scratch1)).emit(masm);
-                    new Mulx(asIntReg(scratch1), asIntReg(src2), asIntReg(scratch2)).emit(masm);
-                    new Sub(asIntReg(src1), asIntReg(scratch2), asIntReg(dst)).emit(masm);
+                    new Sdivx(asIntReg(srcLeft), asIntReg(src2), asIntReg(scratch1)).emit(masm);
+                    new Mulx(asIntReg(scratch1), asIntReg(src2), asIntReg(scratch1)).emit(masm);
+                    new Sub(asIntReg(srcLeft), asIntReg(scratch1), asIntReg(dst)).emit(masm);
                     break;
-                case LUREM:
-                    throw GraalInternalError.unimplemented();
+                case IUREM:
+                    new Sra(asIntReg(src1), 0, asIntReg(scratch1)).emit(masm);
+                    exceptionOffset = masm.position();
+                    new Udivx(asIntReg(scratch1), asIntReg(src2), asIntReg(scratch1)).emit(masm);
+                    new Mulx(asIntReg(scratch1), asIntReg(src2), asIntReg(scratch1)).emit(masm);
+                    new Sub(asIntReg(src1), asIntReg(scratch1), asIntReg(dst)).emit(masm);
+                    break;
                 default:
                     throw GraalInternalError.shouldNotReachHere();
             }
@@ -668,28 +717,40 @@
                     break;
                 case F2L:
                     new Fcmp(CC.Fcc0, Opfs.Fcmps, asFloatReg(dst), asFloatReg(dst)).emit(masm);
-                    new Fbe(false, 4).emit(masm);
+                    new Fbe(false, 4 * 4).emit(masm);
                     new Fstox(asFloatReg(src), asFloatReg(dst)).emit(masm);
                     new Fitos(asFloatReg(dst), asFloatReg(dst)).emit(masm);
                     new Fsubs(asFloatReg(dst), asFloatReg(dst), asFloatReg(dst)).emit(masm);
                     break;
                 case F2I:
                     new Fcmp(CC.Fcc0, Opfs.Fcmps, asFloatReg(dst), asFloatReg(dst)).emit(masm);
-                    new Fbo(false, 4).emit(masm);
+                    new Fbo(false, 4 * 4).emit(masm);
                     new Fstoi(asFloatReg(src), asFloatReg(dst)).emit(masm);
                     new Fitos(asFloatReg(dst), asFloatReg(dst)).emit(masm);
                     new Fsubs(asFloatReg(dst), asFloatReg(dst), asFloatReg(dst)).emit(masm);
                     break;
+                case MOV_D2L:
+                    new Movdtox(asDoubleReg(src), asLongReg(dst)).emit(masm);
+                    break;
+                case MOV_L2D:
+                    new Movxtod(asLongReg(src), asDoubleReg(dst)).emit(masm);
+                    break;
+                case MOV_F2I:
+                    new Movstosw(asFloatReg(src), asIntReg(dst)).emit(masm);
+                    break;
+                case MOV_I2F:
+                    new Movwtos(asIntReg(src), asFloatReg(dst)).emit(masm);
+                    break;
                 case D2L:
                     new Fcmp(CC.Fcc0, Opfs.Fcmpd, asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
-                    new Fbo(false, 4).emit(masm);
+                    new Fbo(false, 4 * 4).emit(masm);
                     new Fdtox(asDoubleReg(src), asDoubleReg(dst)).emit(masm);
                     new Fxtod(asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
                     new Fsubd(asDoubleReg(dst), asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
                     break;
                 case D2I:
                     new Fcmp(CC.Fcc0, Opfs.Fcmpd, asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
-                    new Fbo(false, 4).emit(masm);
+                    new Fbo(false, 4 * 4).emit(masm);
                     new Fdtoi(asDoubleReg(src), asDoubleReg(dst)).emit(masm);
                     new Fitod(asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
                     new Fsubd(asDoubleReg(dst), asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
@@ -740,6 +801,8 @@
             case ISHL:
             case ISHR:
             case IUSHR:
+            case IUDIV:
+            case IUREM:
                 rk = result.getKind();
                 xsk = x.getKind().getStackKind();
                 ysk = y.getKind().getStackKind();
@@ -753,6 +816,8 @@
             case LAND:
             case LOR:
             case LXOR:
+            case LUDIV:
+            case LUREM:
                 rk = result.getKind();
                 xk = x.getKind();
                 yk = y.getKind();
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java	Mon Aug 11 15:45:18 2014 +0200
@@ -160,10 +160,10 @@
         } else {
             new Call(0).emit(masm);
         }
+        new Nop().emit(masm);  // delay slot
         int after = masm.position();
         crb.recordDirectCall(before, after, callTarget, info);
         crb.recordExceptionHandlers(after, info);
-        new Nop().emit(masm);  // delay slot
         masm.ensureUniquePC();
     }
 
@@ -171,19 +171,19 @@
         int before = masm.position();
         new Sethix(0L, dst, true).emit(masm);
         new Jmp(new SPARCAddress(dst, 0)).emit(masm);
+        new Nop().emit(masm);  // delay slot
         int after = masm.position();
         crb.recordIndirectCall(before, after, target, null);
-        new Nop().emit(masm);  // delay slot
         masm.ensureUniquePC();
     }
 
     public static void indirectCall(CompilationResultBuilder crb, SPARCMacroAssembler masm, Register dst, InvokeTarget callTarget, LIRFrameState info) {
         int before = masm.position();
         new Jmpl(dst, 0, o7).emit(masm);
+        new Nop().emit(masm);  // delay slot
         int after = masm.position();
         crb.recordIndirectCall(before, after, callTarget, info);
         crb.recordExceptionHandlers(after, info);
-        new Nop().emit(masm);  // delay slot
         masm.ensureUniquePC();
     }
 }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Mon Aug 11 15:45:18 2014 +0200
@@ -24,8 +24,8 @@
 
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+import static com.oracle.graal.sparc.SPARC.*;
 
-import com.oracle.graal.api.code.CompilationResult.JumpTable;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
@@ -256,9 +256,9 @@
             if (lowKey != 0) {
                 // subtract the low value from the switch value
                 new Sub(value, lowKey, value).emit(masm);
-                // masm.setp_gt_s32(value, highKey - lowKey);
+                new Cmp(value, highKey - lowKey).emit(masm);
             } else {
-                // masm.setp_gt_s32(value, highKey);
+                new Cmp(value, highKey).emit(masm);
             }
 
             // Jump to default target if index is not within the jump table
@@ -268,19 +268,21 @@
             }
 
             // Load jump table entry into scratch and jump to it
-            // masm.movslq(value, new AMD64Address(scratch, value, Scale.Times4, 0));
-            // masm.addq(scratch, value);
-            new Jmp(new SPARCAddress(scratchReg, 0)).emit(masm);
-            new Nop().emit(masm);  // delay slot
+            new Sll(value, 3, value).emit(masm); // Multiply by 8
+            new Rdpc(scratchReg).emit(masm);
+
+            // The jump table follows four instructions after rdpc
+            new Add(scratchReg, 4 * 4, scratchReg).emit(masm);
+            new Jmpl(value, scratchReg, g0).emit(masm);
+            new Sra(value, 3, value).emit(masm); // delay slot, correct the value (division by 8)
 
-            // address of jump table
-            int tablePos = masm.position();
-
-            JumpTable jt = new JumpTable(tablePos, lowKey, highKey, 4);
-            crb.compilationResult.addAnnotation(jt);
-
-            // SPARC: unimp: tableswitch extract
-            throw GraalInternalError.unimplemented();
+            // Emit jump table entries
+            for (LabelRef target : targets) {
+                Label label = target.label();
+                label.addPatchAt(masm.position());
+                new Bpa(0).emit(masm);
+                new Nop().emit(masm); // delay slot
+            }
         }
     }
 
@@ -404,20 +406,24 @@
                 return ConditionFlag.Equal;
             case NE:
                 return ConditionFlag.NotEqual;
+            case BT:
+                return ConditionFlag.LessUnsigned;
             case LT:
                 return ConditionFlag.Less;
+            case BE:
+                return ConditionFlag.LessEqualUnsigned;
             case LE:
                 return ConditionFlag.LessEqual;
+            case AE:
+                return ConditionFlag.GreaterEqualUnsigned;
             case GE:
                 return ConditionFlag.GreaterEqual;
+            case AT:
+                return ConditionFlag.GreaterUnsigned;
             case GT:
                 return ConditionFlag.Greater;
-            case BE:
-            case AE:
-            case AT:
-            case BT:
             default:
-                throw GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere("Unimplemented for: " + cond);
         }
     }
 
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java	Mon Aug 11 15:45:18 2014 +0200
@@ -26,6 +26,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.sparc.*;
 
 /**
  * SPARC specific frame map.
@@ -34,11 +35,15 @@
  *
  * <pre>
  *   Base       Contents
- *
+ * 
  *            :                                :  -----
  *   caller   | incoming overflow argument n   |    ^
  *   frame    :     ...                        :    | positive
  *            | incoming overflow argument 0   |    | offsets
+ *            +--------------------------------+    |
+ *            |                                |    |
+ *            : register save area             :    |
+ *            |                                |    |
  *   ---------+--------------------------------+---------------------------
  *            | spill slot 0                   |    | negative   ^      ^
  *            :     ...                        :    v offsets    |      |
@@ -101,4 +106,29 @@
     protected StackSlot allocateNewSpillSlot(LIRKind kind, int additionalOffset) {
         return StackSlot.get(kind, -spillSize + additionalOffset, true);
     }
+
+    /**
+     * In SPARC we have spill slots word aligned
+     */
+    @Override
+    public int spillSlotSize(LIRKind kind) {
+        return SPARC.spillSlotSize(target, kind.getPlatformKind());
+    }
+
+    /**
+     * We must add the calleSaveAreaSize() when it is a in or out parameter
+     */
+    @Override
+    public int offsetForStackSlot(StackSlot slot) {
+        int offset = super.offsetForStackSlot(slot);
+        if (slot.getRawOffset() >= 0) { // If In or Out parameter
+            offset += calleeSaveAreaSize();
+        }
+        return offset;
+    }
+
+    @Override
+    public boolean frameNeedsAllocating() {
+        return super.frameNeedsAllocating() || spillSize > 0;
+    }
 }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Mon Aug 11 15:45:18 2014 +0200
@@ -387,8 +387,13 @@
         } else if (isConstant(input)) {
             if (isRegister(result)) {
                 const2reg(crb, masm, result, (Constant) input);
+            } else if (isStackSlot(result)) {
+                // Move a Constant to a stack slot (Probably a 7th output parameter)
+                Value scratch = input.getKind() == Kind.Float || input.getKind() == Kind.Double ? f30.asValue(input.getLIRKind()) : g5.asValue(input.getLIRKind());
+                const2reg(crb, masm, scratch, (Constant) input);
+                reg2stack(crb, masm, result, scratch);
             } else {
-                throw GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere("Result is a: " + result);
             }
         } else {
             throw GraalInternalError.shouldNotReachHere();
@@ -405,6 +410,10 @@
             return;
         }
         switch (input.getKind()) {
+            case Boolean:
+            case Byte:
+            case Short:
+            case Char:
             case Int:
             case Long:
             case Object:
@@ -438,7 +447,7 @@
                 }
                 break;
             default:
-                throw GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere("Input is a: " + input.getKind());
         }
     }
 
@@ -446,6 +455,14 @@
         SPARCAddress dst = (SPARCAddress) crb.asAddress(result);
         Register src = asRegister(input);
         switch (input.getKind()) {
+            case Byte:
+            case Boolean:
+                new Stb(src, dst).emit(masm);
+                break;
+            case Char:
+            case Short:
+                new Sth(src, dst).emit(masm);
+                break;
             case Int:
                 new Stw(src, dst).emit(masm);
                 break;
@@ -460,7 +477,7 @@
                 new Stdf(src, dst).emit(masm);
                 break;
             default:
-                throw GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere("Input is a: " + input.getKind() + "(" + input + ")");
         }
     }
 
@@ -468,6 +485,16 @@
         SPARCAddress src = (SPARCAddress) crb.asAddress(input);
         Register dst = asRegister(result);
         switch (input.getKind()) {
+            case Boolean:
+            case Byte:
+                new Ldsb(src, dst).emit(masm);
+                break;
+            case Short:
+                new Ldsh(src, dst).emit(masm);
+                break;
+            case Char:
+                new Lduh(src, dst).emit(masm);
+                break;
             case Int:
                 new Ldsw(src, dst).emit(masm);
                 break;
@@ -476,9 +503,13 @@
                 new Ldx(src, dst).emit(masm);
                 break;
             case Float:
+                new Ldf(src, dst).emit(masm);
+                break;
             case Double:
+                new Lddf(src, dst).emit(masm);
+                break;
             default:
-                throw GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere("Input is a: " + input.getKind());
         }
     }
 
@@ -510,6 +541,7 @@
                 }
                 break;
             case Float:
+                // TODO: Handle it the same way, as in the double case with Movwtos
                 crb.asFloatConstRef(input);
                 // First load the address into the scratch register
                 new Setx(0, scratch, true).emit(masm);
@@ -517,9 +549,8 @@
                 new Ldf(scratch, asFloatReg(result)).emit(masm);
                 break;
             case Double:
-                // before we load this from memory and do the complicated lookup,
+                // instead loading this from memory and do the complicated lookup,
                 // just load it directly into a scratch register
-                scratch = g5;
                 // First load the address into the scratch register
                 new Setx(Double.doubleToLongBits(input.asDouble()), scratch, true).emit(masm);
                 // Now load the float value
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java	Mon Aug 11 15:45:18 2014 +0200
@@ -29,15 +29,13 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsw;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldx;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.asm.*;
 
 public class SPARCTestOp extends SPARCLIRInstruction {
 
     @Use({REG}) protected Value x;
-    @Use({REG, STACK, CONST}) protected Value y;
+    @Use({REG, CONST}) protected Value y;
 
     public SPARCTestOp(Value x, Value y) {
         this.x = x;
@@ -48,6 +46,10 @@
     public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
         if (isRegister(y)) {
             switch (x.getKind()) {
+                case Short:
+                case Byte:
+                case Char:
+                case Boolean:
                 case Int:
                     new Andcc(asIntReg(x), asIntReg(y), g0).emit(masm);
                     break;
@@ -59,6 +61,10 @@
             }
         } else if (isConstant(y)) {
             switch (x.getKind()) {
+                case Short:
+                case Byte:
+                case Char:
+                case Boolean:
                 case Int:
                     new Andcc(asIntReg(x), crb.asIntConst(y), g0).emit(masm);
                     break;
@@ -69,18 +75,7 @@
                     throw GraalInternalError.shouldNotReachHere();
             }
         } else {
-            switch (x.getKind()) {
-                case Int:
-                    new Ldsw((SPARCAddress) crb.asIntAddr(y), asIntReg(y)).emit(masm);
-                    new Andcc(asIntReg(x), asIntReg(y), g0).emit(masm);
-                    break;
-                case Long:
-                    new Ldx((SPARCAddress) crb.asLongAddr(y), asLongReg(y)).emit(masm);
-                    new Andcc(asLongReg(x), asLongReg(y), g0).emit(masm);
-                    break;
-                default:
-                    throw GraalInternalError.shouldNotReachHere();
-            }
+            throw GraalInternalError.shouldNotReachHere();
         }
     }
 
--- /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 11 15:45:18 2014 +0200
@@ -0,0 +1,204 @@
+/*
+ * 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.InstructionValueProcedure;
+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.forEachInput(new InstructionValueProcedure() {
+            @Override
+            public Value doValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue2, value);
+                return value;
+            }
+        });
+
+        op2.forEachInput(new InstructionValueProcedure() {
+            @Override
+            public Value doValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue3, value);
+                return 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.forEachInput(new InstructionValueProcedure() {
+            @Override
+            public Value doValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue2, value);
+                return value;
+            }
+        });
+
+        op2.forEachInput(new InstructionValueProcedure() {
+            @Override
+            public Value doValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue3, value);
+                return 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 11 15:45:18 2014 +0200
@@ -0,0 +1,205 @@
+/*
+ * 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.InstructionValueProcedure;
+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.forEachInput(new InstructionValueProcedure() {
+            @Override
+            public Value doValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue2, value);
+                return value;
+            }
+        });
+
+        op2.forEachInput(new InstructionValueProcedure() {
+            @Override
+            public Value doValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue3, value);
+                return 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.forEachInput(new InstructionValueProcedure() {
+            @Override
+            public Value doValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue2, value);
+                return value;
+            }
+        });
+
+        op2.forEachInput(new InstructionValueProcedure() {
+            @Override
+            public Value doValue(LIRInstruction instruction, Value value) {
+                assertEquals(dummyValue3, value);
+                return value;
+            }
+        });
+    }
+}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java	Mon Aug 11 15:45:18 2014 +0200
@@ -25,6 +25,7 @@
 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;
@@ -34,7 +35,7 @@
 /**
  * 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,8 +56,8 @@
         valueClass = CompositeValueClass.get(getClass());
     }
 
-    public final void forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueProcedure proc) {
-        valueClass.forEachComponent(inst, this, mode, proc);
+    public final CompositeValue forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueProcedure proc) {
+        return valueClass.forEachComponent(inst, this, mode, proc);
     }
 
     public final void forEachComponent(LIRInstruction inst, OperandMode mode, ValuePositionProcedure proc, ValuePosition outerPosition) {
@@ -86,4 +87,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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java	Mon Aug 11 15:45:18 2014 +0200
@@ -141,8 +141,8 @@
         return str.toString();
     }
 
-    public final void forEachComponent(LIRInstruction inst, CompositeValue obj, OperandMode mode, InstructionValueProcedure proc) {
-        forEach(inst, obj, directComponentCount, componentOffsets, mode, componentFlags, proc);
+    public final CompositeValue forEachComponent(LIRInstruction inst, CompositeValue obj, OperandMode mode, InstructionValueProcedure proc) {
+        return forEachComponent(inst, obj, directComponentCount, componentOffsets, mode, componentFlags, proc);
     }
 
     public final void forEachComponent(LIRInstruction inst, CompositeValue obj, OperandMode mode, ValuePositionProcedure proc, ValuePosition outerPosition) {
@@ -172,4 +172,12 @@
     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);
+        }
+    }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Mon Aug 11 15:45:18 2014 +0200
@@ -201,8 +201,11 @@
      * @return the offset of the stack slot
      */
     public int offsetForStackSlot(StackSlot slot) {
-        assert (!slot.getRawAddFrameSize() && slot.getRawOffset() < outgoingSize) || (slot.getRawAddFrameSize() && slot.getRawOffset() < 0 && -slot.getRawOffset() <= spillSize) ||
-                        (slot.getRawAddFrameSize() && slot.getRawOffset() >= 0);
+        // @formatter:off
+        assert (!slot.getRawAddFrameSize() && slot.getRawOffset() <  outgoingSize) ||
+               ( slot.getRawAddFrameSize() && slot.getRawOffset() <  0 && -slot.getRawOffset() <= spillSize) ||
+               ( slot.getRawAddFrameSize() && slot.getRawOffset() >= 0);
+        // @formatter:on
         if (slot.isInCallerFrame()) {
             accessesCallerFrame = true;
         }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Mon Aug 11 15:45:18 2014 +0200
@@ -347,19 +347,19 @@
     }
 
     public final void forEachUse(LIRInstruction obj, InstructionValueProcedure proc) {
-        forEach(obj, obj, directUseCount, useOffsets, OperandMode.USE, useFlags, 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);
+        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);
+        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);
+        forEach(obj, directDefCount, defOffsets, OperandMode.DEF, defFlags, proc);
     }
 
     public final void forEachState(LIRInstruction obj, InstructionValueProcedure proc) {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Mon Aug 11 15:45:18 2014 +0200
@@ -120,31 +120,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, InstructionValueProcedure 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.doValue(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.doValue(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,
+                    InstructionValueProcedure 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.doValue(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.doValue(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 +260,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) {
@@ -258,7 +320,12 @@
             } else if (type == double[].class) {
                 return Arrays.toString((double[]) value);
             } else if (type == byte[].class) {
-                return Arrays.toString((byte[]) value);
+                byte[] byteValue = (byte[]) value;
+                if (isPrintableAsciiString(byteValue)) {
+                    return toString(byteValue);
+                } else {
+                    return Arrays.toString(byteValue);
+                }
             } else if (!type.getComponentType().isPrimitive()) {
                 return Arrays.toString((Object[]) value);
             }
@@ -266,4 +333,39 @@
         assert false : "unhandled field type: " + type;
         return "";
     }
+
+    /**
+     * Tests if all values in this string are printable ASCII characters or value \0 (b in
+     * [0x20,0x7F]) or b == 0
+     *
+     * @param array
+     * @return true if there are only printable ASCII characters and \0, false otherwise
+     */
+    private static boolean isPrintableAsciiString(byte[] array) {
+        for (byte b : array) {
+            char c = (char) b;
+            if (c != 0 && c < 0x20 && c > 0x7F) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static String toString(byte[] bytes) {
+        StringBuilder sb = new StringBuilder();
+        sb.append('"');
+        for (byte b : bytes) {
+            if (b == 0) {
+                sb.append("\\0");
+            } else if (b == '"') {
+                sb.append("\\\"");
+            } else if (b == '\n') {
+                sb.append("\\n");
+            } else {
+                sb.append((char) b);
+            }
+        }
+        sb.append('"');
+        return sb.toString();
+    }
 }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Mon Aug 11 15:45:18 2014 +0200
@@ -24,6 +24,7 @@
 
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 
+import java.util.*;
 import java.util.function.*;
 
 import com.oracle.graal.debug.*;
@@ -63,25 +64,27 @@
         return loop.loopBegin().unswitches() <= LoopMaxUnswitch.getValue();
     }
 
-    public static boolean shouldUnswitch(LoopEx loop, ControlSplitNode controlSplit) {
-        Block postDomBlock = loop.loopsData().controlFlowGraph().blockFor(controlSplit).getPostdominator();
-        BeginNode postDom = postDomBlock != null ? postDomBlock.getBeginNode() : null;
+    public static boolean shouldUnswitch(LoopEx loop, List<ControlSplitNode> controlSplits) {
         int loopTotal = loop.size();
         int inBranchTotal = 0;
         double maxProbability = 0;
-        for (Node successor : controlSplit.successors()) {
-            BeginNode branch = (BeginNode) successor;
-            // this may count twice because of fall-through in switches
-            inBranchTotal += loop.nodesInLoopFrom(branch, postDom).count();
-            double probability = controlSplit.probability(branch);
-            if (probability > maxProbability) {
-                maxProbability = probability;
+        for (ControlSplitNode controlSplit : controlSplits) {
+            Block postDomBlock = loop.loopsData().controlFlowGraph().blockFor(controlSplit).getPostdominator();
+            BeginNode postDom = postDomBlock != null ? postDomBlock.getBeginNode() : null;
+            for (Node successor : controlSplit.successors()) {
+                BeginNode branch = (BeginNode) successor;
+                // this may count twice because of fall-through in switches
+                inBranchTotal += loop.nodesInLoopFrom(branch, postDom).count();
+                double probability = controlSplit.probability(branch);
+                if (probability > maxProbability) {
+                    maxProbability = probability;
+                }
             }
         }
         int netDiff = loopTotal - (inBranchTotal);
         double uncertainty = 1 - maxProbability;
         int maxDiff = LoopUnswitchMaxIncrease.getValue() + (int) (LoopUnswitchUncertaintyBoost.getValue() * loop.loopBegin().loopFrequency() * uncertainty);
-        Debug.log("shouldUnswitch(%s, %s) : delta=%d, max=%d, %.2f%% inside of branches", loop, controlSplit, netDiff, maxDiff, (double) (inBranchTotal) / loopTotal * 100);
+        Debug.log("shouldUnswitch(%s, %s) : delta=%d, max=%d, %.2f%% inside of branches", loop, controlSplits, netDiff, maxDiff, (double) (inBranchTotal) / loopTotal * 100);
         return netDiff <= maxDiff;
     }
 
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Mon Aug 11 15:45:18 2014 +0200
@@ -24,6 +24,8 @@
 
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 
+import java.util.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.graph.*;
@@ -71,36 +73,53 @@
         }
     }
 
-    public static void unswitch(LoopEx loop, ControlSplitNode controlSplitNode) {
+    public static void unswitch(LoopEx loop, List<ControlSplitNode> controlSplitNodeSet) {
+        ControlSplitNode firstNode = controlSplitNodeSet.iterator().next();
         LoopFragmentWhole originalLoop = loop.whole();
+        StructuredGraph graph = firstNode.graph();
+
         // create new control split out of loop
-        ControlSplitNode newControlSplit = (ControlSplitNode) controlSplitNode.copyWithInputs();
+        ControlSplitNode newControlSplit = (ControlSplitNode) firstNode.copyWithInputs();
         originalLoop.entryPoint().replaceAtPredecessor(newControlSplit);
 
-        NodeClassIterator successors = controlSplitNode.successors().iterator();
+        /*
+         * The code below assumes that all of the control split nodes have the same successor
+         * structure, which should have been enforced by findUnswitchable.
+         */
+        NodeClassIterator successors = firstNode.successors().iterator();
         assert successors.hasNext();
         // original loop is used as first successor
         Position firstPosition = successors.nextPosition();
-        NodeClass controlSplitClass = controlSplitNode.getNodeClass();
+        NodeClass controlSplitClass = firstNode.getNodeClass();
         BeginNode originalLoopBegin = BeginNode.begin(originalLoop.entryPoint());
         controlSplitClass.set(newControlSplit, firstPosition, originalLoopBegin);
 
-        StructuredGraph graph = controlSplitNode.graph();
         while (successors.hasNext()) {
             Position position = successors.nextPosition();
-            // create a new loop duplicate, connect it and simplify it
+            // create a new loop duplicate and connect it.
             LoopFragmentWhole duplicateLoop = originalLoop.duplicate();
             BeginNode newBegin = BeginNode.begin(duplicateLoop.entryPoint());
             controlSplitClass.set(newControlSplit, position, newBegin);
-            ControlSplitNode duplicatedControlSplit = duplicateLoop.getDuplicatedNode(controlSplitNode);
-            BeginNode survivingSuccessor = (BeginNode) controlSplitClass.get(duplicatedControlSplit, position);
-            survivingSuccessor.replaceAtUsages(InputType.Guard, newBegin);
-            graph.removeSplitPropagate(duplicatedControlSplit, survivingSuccessor);
+
+            // For each cloned ControlSplitNode, simplify the proper path
+            for (ControlSplitNode controlSplitNode : controlSplitNodeSet) {
+                ControlSplitNode duplicatedControlSplit = duplicateLoop.getDuplicatedNode(controlSplitNode);
+                if (duplicatedControlSplit.isAlive()) {
+                    BeginNode survivingSuccessor = (BeginNode) controlSplitClass.get(duplicatedControlSplit, position);
+                    survivingSuccessor.replaceAtUsages(InputType.Guard, newBegin);
+                    graph.removeSplitPropagate(duplicatedControlSplit, survivingSuccessor);
+                }
+            }
         }
         // original loop is simplified last to avoid deleting controlSplitNode too early
-        BeginNode survivingSuccessor = (BeginNode) controlSplitClass.get(controlSplitNode, firstPosition);
-        survivingSuccessor.replaceAtUsages(InputType.Guard, originalLoopBegin);
-        graph.removeSplitPropagate(controlSplitNode, survivingSuccessor);
+        for (ControlSplitNode controlSplitNode : controlSplitNodeSet) {
+            if (controlSplitNode.isAlive()) {
+                BeginNode survivingSuccessor = (BeginNode) controlSplitClass.get(controlSplitNode, firstPosition);
+                survivingSuccessor.replaceAtUsages(InputType.Guard, originalLoopBegin);
+                graph.removeSplitPropagate(controlSplitNode, survivingSuccessor);
+            }
+        }
+
         // TODO (gd) probabilities need some amount of fixup.. (probably also in other transforms)
     }
 
@@ -125,17 +144,36 @@
         }
     }
 
-    public static ControlSplitNode findUnswitchable(LoopEx loop) {
+    public static List<ControlSplitNode> findUnswitchable(LoopEx loop) {
+        List<ControlSplitNode> controls = null;
+        ValueNode invariantValue = null;
         for (IfNode ifNode : loop.whole().nodes().filter(IfNode.class)) {
             if (loop.isOutsideLoop(ifNode.condition())) {
-                return ifNode;
+                if (controls == null) {
+                    invariantValue = ifNode.condition();
+                    controls = new ArrayList<>();
+                    controls.add(ifNode);
+                } else if (ifNode.condition() == invariantValue) {
+                    controls.add(ifNode);
+                }
             }
         }
-        for (SwitchNode switchNode : loop.whole().nodes().filter(SwitchNode.class)) {
-            if (switchNode.successors().count() > 1 && loop.isOutsideLoop(switchNode.value())) {
-                return switchNode;
+        if (controls == null) {
+            SwitchNode firstSwitch = null;
+            for (SwitchNode switchNode : loop.whole().nodes().filter(SwitchNode.class)) {
+                if (switchNode.successors().count() > 1 && loop.isOutsideLoop(switchNode.value())) {
+                    if (controls == null) {
+                        firstSwitch = switchNode;
+                        invariantValue = switchNode.value();
+                        controls = new ArrayList<>();
+                        controls.add(switchNode);
+                    } else if (switchNode.value() == invariantValue && firstSwitch.structureEquals(switchNode)) {
+                        // Only collect switches which test the same values in the same order
+                        controls.add(switchNode);
+                    }
+                }
             }
         }
-        return null;
+        return controls;
     }
 }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Mon Aug 11 15:45:18 2014 +0200
@@ -24,6 +24,8 @@
 
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 
+import java.util.*;
+
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.graph.NodeClass.NodeClassIterator;
@@ -34,6 +36,7 @@
 public class LoopTransformLowPhase extends Phase {
 
     private static final DebugMetric UNSWITCHED = Debug.metric("Unswitched");
+    private static final DebugMetric UNSWITCH_CANDIDATES = Debug.metric("UnswitchCandidates");
 
     @Override
     protected void run(StructuredGraph graph) {
@@ -56,16 +59,18 @@
                     final LoopsData dataUnswitch = new LoopsData(graph);
                     for (LoopEx loop : dataUnswitch.loops()) {
                         if (LoopPolicies.shouldTryUnswitch(loop)) {
-                            ControlSplitNode controlSplit = LoopTransformations.findUnswitchable(loop);
-                            if (controlSplit != null && LoopPolicies.shouldUnswitch(loop, controlSplit)) {
-                                if (Debug.isLogEnabled()) {
-                                    logUnswitch(loop, controlSplit);
+                            List<ControlSplitNode> controlSplits = LoopTransformations.findUnswitchable(loop);
+                            if (controlSplits != null) {
+                                UNSWITCH_CANDIDATES.increment();
+                                if (LoopPolicies.shouldUnswitch(loop, controlSplits)) {
+                                    if (Debug.isLogEnabled()) {
+                                        logUnswitch(loop, controlSplits);
+                                    }
+                                    LoopTransformations.unswitch(loop, controlSplits);
+                                    UNSWITCHED.increment();
+                                    unswitched = true;
+                                    break;
                                 }
-                                LoopTransformations.unswitch(loop, controlSplit);
-                                UNSWITCHED.increment();
-                                Debug.dump(graph, "After unswitch %s", loop);
-                                unswitched = true;
-                                break;
                             }
                         }
                     }
@@ -74,17 +79,20 @@
         }
     }
 
-    private static void logUnswitch(LoopEx loop, ControlSplitNode controlSplit) {
+    private static void logUnswitch(LoopEx loop, List<ControlSplitNode> controlSplits) {
         StringBuilder sb = new StringBuilder("Unswitching ");
-        sb.append(loop).append(" at ").append(controlSplit).append(" [");
-        NodeClassIterator it = controlSplit.successors().iterator();
-        while (it.hasNext()) {
-            sb.append(controlSplit.probability((BeginNode) it.next()));
-            if (it.hasNext()) {
-                sb.append(", ");
+        sb.append(loop).append(" at ");
+        for (ControlSplitNode controlSplit : controlSplits) {
+            sb.append(controlSplit).append(" [");
+            NodeClassIterator it = controlSplit.successors().iterator();
+            while (it.hasNext()) {
+                sb.append(controlSplit.probability((BeginNode) it.next()));
+                if (it.hasNext()) {
+                    sb.append(", ");
+                }
             }
+            sb.append("]");
         }
-        sb.append("]");
         Debug.log("%s", sb);
     }
 }
--- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/LoopPhiCanonicalizerTest.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/LoopPhiCanonicalizerTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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/src/com/oracle/graal/nodes/ReturnNode.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Mon Aug 11 15:45:18 2014 +0200
@@ -52,11 +52,6 @@
     }
 
     @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/calc/FloatRemNode.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Mon Aug 11 15:45:18 2014 +0200
@@ -50,7 +50,7 @@
     @Override
     public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
         if (forX.isConstant() && forY.isConstant()) {
-            return ConstantNode.forPrimitive(evalConst(getX().asConstant(), getY().asConstant()));
+            return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant()));
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Mon Aug 11 15:45:18 2014 +0200
@@ -42,7 +42,7 @@
     /**
      * Constructs a integer switch instruction. The keyProbabilities and keySuccessors array contain
      * key.length + 1 entries, the last entry describes the default (fall through) case.
-     * 
+     *
      * @param value the instruction producing the value being switched on
      * @param successors the list of successors
      * @param keys the sorted list of keys
@@ -68,7 +68,7 @@
     /**
      * Constructs a integer switch instruction. The keyProbabilities and keySuccessors array contain
      * key.length + 1 entries, the last entry describes the default (fall through) case.
-     * 
+     *
      * @param value the instruction producing the value being switched on
      * @param successorCount the number of successors
      * @param keys the sorted list of keys
@@ -86,7 +86,7 @@
 
     /**
      * Gets the key at the specified index.
-     * 
+     *
      * @param i the index
      * @return the key at that index
      */
@@ -101,6 +101,15 @@
     }
 
     @Override
+    public boolean equalKeys(SwitchNode switchNode) {
+        if (!(switchNode instanceof IntegerSwitchNode)) {
+            return false;
+        }
+        IntegerSwitchNode other = (IntegerSwitchNode) switchNode;
+        return Arrays.equals(keys, other.keys);
+    }
+
+    @Override
     public void generate(NodeLIRBuilderTool gen) {
         gen.emitSwitch(this);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryAccess.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryAccess.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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/SwitchNode.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Mon Aug 11 15:45:18 2014 +0200
@@ -22,6 +22,8 @@
  */
 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.*;
@@ -103,6 +105,15 @@
      */
     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.
+     */
+    public abstract boolean equalKeys(SwitchNode switchNode);
+
     /**
      * Returns the index of the successor belonging to the key at the specified index.
      */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Mon Aug 11 15:45:18 2014 +0200
@@ -44,7 +44,7 @@
     /**
      * Constructs a type switch instruction. The keyProbabilities array contain key.length + 1
      * entries. The last entry in every array describes the default case.
-     * 
+     *
      * @param value the instruction producing the value being switched on, the object hub
      * @param successors the list of successors
      * @param keys the list of types
@@ -57,6 +57,21 @@
         assert keySuccessors.length == keyProbabilities.length;
         this.keys = keys;
         assert assertValues();
+        assert assertKeys();
+    }
+
+    /**
+     * Don't allow duplicate keys
+     */
+    private boolean assertKeys() {
+        for (int i = 0; i < keys.length; i++) {
+            for (int j = 0; j < keys.length; j++) {
+                if (i == j)
+                    continue;
+                assert !keys[i].equals(keys[j]);
+            }
+        }
+        return true;
     }
 
     @Override
@@ -87,6 +102,15 @@
         return keys[index].getEncoding(Representation.ObjectHub);
     }
 
+    @Override
+    public boolean equalKeys(SwitchNode switchNode) {
+        if (!(switchNode instanceof TypeSwitchNode)) {
+            return false;
+        }
+        TypeSwitchNode other = (TypeSwitchNode) switchNode;
+        return Arrays.equals(keys, other.keys);
+    }
+
     public ResolvedJavaType typeAt(int index) {
         return keys[index];
     }
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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.phases.common/src/com/oracle/graal/phases/common/CleanTypeProfileProxyPhase.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CleanTypeProfileProxyPhase.java	Mon Aug 11 15:45:18 2014 +0200
@@ -22,15 +22,30 @@
  */
 package com.oracle.graal.phases.common;
 
+import com.oracle.graal.graph.Graph.NodeEventScope;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.util.*;
+import com.oracle.graal.phases.tiers.*;
 
-public class CleanTypeProfileProxyPhase extends Phase {
+public class CleanTypeProfileProxyPhase extends BasePhase<PhaseContext> {
+
+    private CanonicalizerPhase canonicalizer;
+
+    public CleanTypeProfileProxyPhase(CanonicalizerPhase canonicalizer) {
+        this.canonicalizer = canonicalizer;
+    }
 
     @Override
-    protected void run(StructuredGraph graph) {
-        for (TypeProfileProxyNode proxy : graph.getNodes(TypeProfileProxyNode.class)) {
-            graph.replaceFloating(proxy, proxy.getValue());
+    protected void run(StructuredGraph graph, PhaseContext context) {
+        HashSetNodeEventListener listener = new HashSetNodeEventListener();
+        try (NodeEventScope s = graph.trackNodeEvents(listener)) {
+            for (TypeProfileProxyNode proxy : graph.getNodes(TypeProfileProxyNode.class)) {
+                graph.replaceFloating(proxy, proxy.getValue());
+            }
+        }
+        if (!listener.getNodes().isEmpty()) {
+            canonicalizer.applyIncremental(graph, context, listener.getNodes());
         }
         assert graph.getNodes(TypeProfileProxyNode.class).count() == 0;
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Mon Aug 11 15:45:18 2014 +0200
@@ -385,7 +385,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);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Mon Aug 11 15:45:18 2014 +0200
@@ -78,6 +78,15 @@
         this.methodProbabilities = computeMethodProbabilities();
         this.maximumMethodProbability = maximumMethodProbability();
         assert maximumMethodProbability > 0;
+        assert assertUniqueTypes(ptypes);
+    }
+
+    private static boolean assertUniqueTypes(ArrayList<ProfiledType> ptypes) {
+        Set<ResolvedJavaType> set = new HashSet<>();
+        for (ProfiledType ptype : ptypes) {
+            set.add(ptype.getType());
+        }
+        return set.size() == ptypes.size();
     }
 
     private double[] computeMethodProbabilities() {
@@ -383,15 +392,22 @@
         ResolvedJavaType[] keys = new ResolvedJavaType[ptypes.size()];
         double[] keyProbabilities = new double[ptypes.size() + 1];
         int[] keySuccessors = new int[ptypes.size() + 1];
+        double totalProbability = notRecordedTypeProbability;
         for (int i = 0; i < ptypes.size(); i++) {
             keys[i] = ptypes.get(i).getType();
             keyProbabilities[i] = ptypes.get(i).getProbability();
+            totalProbability += keyProbabilities[i];
             keySuccessors[i] = invokeIsOnlySuccessor ? 0 : typesToConcretes.get(i);
             assert keySuccessors[i] < successors.length - 1 : "last successor is the unknownTypeSux";
         }
         keyProbabilities[keyProbabilities.length - 1] = notRecordedTypeProbability;
         keySuccessors[keySuccessors.length - 1] = successors.length - 1;
 
+        // Normalize the probabilities.
+        for (int i = 0; i < keyProbabilities.length; i++) {
+            keyProbabilities[i] /= totalProbability;
+        }
+
         TypeSwitchNode typeSwitch = graph.add(new TypeSwitchNode(hub, successors, keys, keyProbabilities, keySuccessors));
         FixedWithNextNode pred = (FixedWithNextNode) invoke.asNode().predecessor();
         pred.setNext(typeSwitch);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -187,6 +187,7 @@
 
     @Test
     public void testScanReverseInt() {
+        /* This test isn't valid unless the BitScanReverseNode intrinsic is used. */
         ValueNode result = parseAndInline("scanReverseIntSnippet", BitScanReverseNode.class);
         if (result != null) {
             Assert.assertEquals(StampFactory.forInteger(Kind.Int, 16, 20), result.stamp());
@@ -211,6 +212,7 @@
 
     @Test
     public void testScanReverseLong() {
+        /* This test isn't valid unless the BitScanReverseNode intrinsic is used. */
         ValueNode result = parseAndInline("scanReverseLongSnippet", BitScanReverseNode.class);
         if (result != null) {
             Assert.assertEquals(StampFactory.forInteger(Kind.Int, 48, 64), result.stamp());
@@ -225,6 +227,7 @@
 
     @Test
     public void testScanReverseLongEmpty() {
+        /* This test isn't valid unless the BitScanReverseNode intrinsic is used. */
         ValueNode result = parseAndInline("scanReverseLongEmptySnippet", BitScanReverseNode.class);
         if (result != null) {
             Assert.assertEquals(StampFactory.forInteger(Kind.Int, 24, 64), result.stamp());
@@ -235,16 +238,24 @@
         return parseAndInline(name, null);
     }
 
-    private ValueNode parseAndInline(String name, Class<? extends ValueNode> requiredClass) {
-        StructuredGraph graph = parse(name);
+    /**
+     * Parse and optimize {@code name}. If {@code expectedClass} is non-null and a node of that type
+     * isn't found simply return null. Otherwise return the node returned by the graph.
+     *
+     * @param name
+     * @param expectedClass
+     * @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 = parseEager(name);
         HighTierContext context = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE);
         CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
         canonicalizer.apply(graph, context);
         new InliningPhase(canonicalizer).apply(graph, context);
         canonicalizer.apply(graph, context);
         Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count());
-        if (requiredClass != null) {
-            if (graph.getNodes().filter(requiredClass).count() == 0) {
+        if (expectedClass != null) {
+            if (graph.getNodes().filter(expectedClass).count() == 0) {
                 return null;
             }
         }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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/MethodSubstitutionTest.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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/ObjectAccessTest.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StringSubstitutionsTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/UnsafeSubstitutionsTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java	Mon Aug 11 15:45:18 2014 +0200
@@ -27,13 +27,14 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 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 {
+public class ArrayEqualsNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable, Virtualizable, MemoryAccess {
 
     /** {@link Kind} of the arrays to compare. */
     private final Kind kind;
@@ -132,4 +133,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.sparc/src/com/oracle/graal/sparc/SPARC.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java	Mon Aug 11 15:45:18 2014 +0200
@@ -189,9 +189,19 @@
      * Stack bias for stack and frame pointer loads.
      */
     public static final int STACK_BIAS = 0x7ff;
+    /**
+     * In fact there are 64 single floating point registers, 32 of them could be accessed. TODO:
+     * Improve handling of these float registers
+     */
+    public static final int FLOAT_REGISTER_COUNT = 64;
+
+    /**
+     * Alignment for valid memory access
+     */
+    public static final int MEMORY_ACCESS_ALIGN = 4;
 
     public SPARC() {
-        super("SPARC", 8, ByteOrder.BIG_ENDIAN, false, allRegisters, LOAD_STORE | STORE_STORE, 1, r31.encoding + 1, 8);
+        super("SPARC", 8, ByteOrder.BIG_ENDIAN, false, allRegisters, LOAD_STORE | STORE_STORE, 1, r31.encoding + FLOAT_REGISTER_COUNT + 1, 8);
     }
 
     @Override
@@ -232,4 +242,8 @@
             return Kind.Illegal;
         }
     }
+
+    public static int spillSlotSize(TargetDescription td, PlatformKind kind) {
+        return Math.max(td.getSizeInBytes(kind), MEMORY_ACCESS_ALIGN);
+    }
 }
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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/src/com/oracle/graal/truffle/FrameWithoutBoxing.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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/OptimizedAssumption.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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/OptimizedDirectCallNode.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedDirectCallNode.java	Mon Aug 11 15:45:18 2014 +0200
@@ -66,7 +66,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 +149,7 @@
             getCurrentCallTarget().incrementKnownCallSites();
         }
         splittingStrategy.beforeCall(arguments);
-        propagateInliningInvalidations();
+        // propagateInliningInvalidations();
     }
 
     /** Used by the splitting strategy to install new targets. */
@@ -176,6 +176,7 @@
         }
     }
 
+    @SuppressWarnings("unused")
     private void propagateInliningInvalidations() {
         if (isInlined() && !getCurrentCallTarget().inliningPerformed) {
             replace(this, "Propagate invalid inlining from " + getCurrentCallTarget().toString());
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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/TruffleCompilerOptions.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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
--- /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 11 15:45:18 2014 +0200
@@ -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 11 15:45:18 2014 +0200
@@ -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 11 15:45:18 2014 +0200
@@ -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 11 15:45:18 2014 +0200
@@ -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 11 15:45:18 2014 +0200
@@ -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 11 15:45:18 2014 +0200
@@ -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();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/WrapperTest.java	Mon Aug 11 15:45:18 2014 +0200
@@ -0,0 +1,270 @@
+/*
+ * 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.test.instrument;
+
+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.*;
+
+/**
+ * This test does the following:
+ * <ol>
+ * <li>Creates a simple add AST</li>
+ * <li>Verifies its structure</li>
+ * <li>Instruments the add node</li>
+ * <li>Attaches a simple probe to the instrumented node</li>
+ * <li>Verifies the structure of the instrumented AST</li>
+ * <li>Verifies the execution of the instrumented AST</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 WrapperTest {
+
+    @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);
+
+        // Add a wrapper
+        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);
+
+        // Add an instrument
+        wrapper.getProbe().addInstrument(new TestInstrument());
+
+        // Check instrument and result
+        result = target.call();
+        Assert.assertEquals(Counter.numInstrumentEnter, 1);
+        Assert.assertEquals(Counter.numInstrumentLeave, 1);
+        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;
+        }
+    }
+
+    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.getProbe(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;
+        }
+    }
+
+    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 {
+        @Override
+        public void enter(Node astNode, VirtualFrame frame) {
+            Counter.numInstrumentEnter++;
+        }
+
+        @Override
+        public void leave(Node astNode, VirtualFrame frame, Object result) {
+            Counter.numInstrumentLeave++;
+        }
+    }
+
+    public static class Counter {
+
+        public static int numInstrumentEnter = 0;
+        public static int numInstrumentLeave = 0;
+    }
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultIndirectCallNode.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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();
+        }
     }
-
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Mon Aug 11 15:45:18 2014 +0200
@@ -840,9 +840,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.sl.test/src/com/oracle/truffle/sl/test/instrument/SLCheckVariableEqualityInstrument.java	Mon Aug 11 15:45:18 2014 +0200
@@ -0,0 +1,80 @@
+/*
+ * 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.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.controlflow.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * This sample instrument provides an example of a naive way to check if two numbers in SL are
+ * equivalent using their variable names. This instrument is designed to be attached to an
+ * {@link SLReturnNode}, but provides no guards against this.
+ */
+public class SLCheckVariableEqualityInstrument extends Instrument {
+
+    private final String varName1;
+    private final String varName2;
+    private final PrintStream output;
+
+    /**
+     * Constructor
+     *
+     * @param varName1 The name of the first variable to compare
+     * @param varName2 The name of the second variable to compare
+     * @param output The {@link PrintStream} from the context used to print results. See
+     *            {@link SLContext#getOutput()} for more info.
+     */
+    public SLCheckVariableEqualityInstrument(String varName1, String varName2, PrintStream output) {
+        this.varName1 = varName1;
+        this.varName2 = varName2;
+        this.output = output;
+    }
+
+    /**
+     * In the instrumentation test, this instrument is attached to a return statement. Since returns
+     * are handled via exceptions in Simple, we need to override the leaveExceptional method. This
+     * method does very limited error checking and simply prints "true" if the passed-in variables
+     * match or "false" if they do not.
+     */
+    @Override
+    public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
+        FrameSlot f1 = frame.getFrameDescriptor().findFrameSlot(varName1);
+        FrameSlot f2 = frame.getFrameDescriptor().findFrameSlot(varName2);
+
+        if (f1 == null || f2 == null)
+            output.println("false");
+        else {
+            try {
+                output.println(frame.getLong(f1) == frame.getLong(f2));
+            } catch (FrameSlotTypeException e1) {
+                e1.printStackTrace();
+            }
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestNodeProber.java	Mon Aug 11 15:45:18 2014 +0200
@@ -0,0 +1,119 @@
+/*
+ * 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.sl.test.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.instrument.*;
+import com.oracle.truffle.sl.nodes.local.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * This sample AST Node Prober for simple is used to instrument the nodes that we are interested in
+ * testing. This prober wraps return nodes and assignment nodes. For the purposes of this example,
+ * this is appropriate, but ideally there would be only one node prober responsible for
+ * instrumenting all the nodes of interest instead of a selective one like this one.
+ *
+ */
+public final class SLInstrumentTestNodeProber implements SLNodeProber {
+    private final SLContext slContext;
+
+    public SLInstrumentTestNodeProber(SLContext slContext) {
+        this.slContext = slContext;
+    }
+
+    /**
+     * Not implemented, only returns the astNode that was passed in.
+     */
+    public Node probeAs(Node astNode, SyntaxTag tag, Object... args) {
+        // TODO dp: Currently does nothing in the general case
+        return astNode;
+    }
+
+    /**
+     * If the passed in node is a {@link SLStatementWrapper}, then this simply tags it as a
+     * statement. If the passed in node is a {@link SLReturnNode}, then it is instrumented and
+     * tagged as a statement for testing. Only SLReturnNodes are wrapped.
+     */
+    public SLStatementNode probeAsStatement(SLStatementNode node) {
+        assert node != null;
+
+        SLStatementWrapper wrapper = null;
+        if (node instanceof SLStatementWrapper) {
+            wrapper = (SLStatementWrapper) node;
+            tagStatementNode(wrapper);
+            return wrapper;
+        } else if (node instanceof SLReturnNode) {
+            wrapper = new SLStatementWrapper(slContext, node);
+            tagStatementNode(wrapper);
+            return wrapper;
+        }
+        return node;
+    }
+
+    /**
+     * Not implemented. Returns the passed in node.
+     */
+    public SLExpressionNode probeAsCall(SLExpressionNode node, String callName) {
+        return node;
+    }
+
+    /**
+     * If the passed in node is a {@link SLExpressionWrapper}, then this simply tags it as an
+     * assignment. If the passed in node is a {@link SLWriteLocalVariableNode}, then it is
+     * instrumented and tagged as a assignment for testing. Only SLWriteLocalVariableNode are
+     * wrapped.
+     */
+    public SLExpressionNode probeAsLocalAssignment(SLExpressionNode node, String localName) {
+        assert node != null;
+
+        SLExpressionWrapper wrapper = null;
+        if (node instanceof SLExpressionWrapper) {
+            wrapper = (SLExpressionWrapper) node;
+            tagAssignmentNode(wrapper);
+            return wrapper;
+        } else if (node instanceof SLWriteLocalVariableNode) {
+            wrapper = new SLExpressionWrapper(slContext, node);
+            tagAssignmentNode(wrapper);
+            return wrapper;
+        }
+        return node;
+    }
+
+    private static void tagAssignmentNode(SLExpressionWrapper wrapper) {
+        if (!wrapper.isTaggedAs(ASSIGNMENT)) {
+            wrapper.tagAs(ASSIGNMENT);
+        }
+    }
+
+    private static void tagStatementNode(SLStatementWrapper wrapper) {
+        if (!wrapper.isTaggedAs(STATEMENT)) {
+            wrapper.tagAs(STATEMENT);
+        }
+    }
+
+}
\ No newline at end of file
--- /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 11 15:45:18 2014 +0200
@@ -0,0 +1,302 @@
+/*
+ * 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.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.nodes.*;
+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.*;
+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 VISITOR_ASSIGNMENT_COUNT_SUFFIX = "_assnCount";
+    private static final String VISITOR_VARIABLE_COMPARE_SUFFIX = "_varCompare";
+
+    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'.", SLTestSuite.class.getSimpleName(), c.getName(), SLTestRunner.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(VISITOR_ASSIGNMENT_COUNT_SUFFIX) || testCase.baseName.endsWith(VISITOR_VARIABLE_COMPARE_SUFFIX)) {
+                NodeVisitor nodeVisitor = null;
+                slContext = new SLContext(new BufferedReader(new StringReader(testCase.testInput)), printer);
+                final Source source = Source.fromText(readAllLines(testCase.path), testCase.sourceName);
+                SLASTProber prober = new SLASTProber();
+
+                // Note that the visitor looks for an attachment point via line number
+                if (testCase.baseName.endsWith(VISITOR_ASSIGNMENT_COUNT_SUFFIX)) {
+                    nodeVisitor = new NodeVisitor() {
+
+                        public boolean visit(Node node) {
+                            if (node instanceof SLExpressionWrapper) {
+                                SLExpressionWrapper wrapper = (SLExpressionWrapper) node;
+                                int lineNum = wrapper.getSourceSection().getLineLocation().getLineNumber();
+
+                                if (lineNum == 4) {
+                                    wrapper.getProbe().addInstrument(new SLPrintAssigmentValueInstrument(slContext.getOutput()));
+                                }
+                            }
+                            return true;
+                        }
+                    };
+
+                    // Note that the visitor looks for an attachment point via line number
+                } else if (testCase.baseName.endsWith(VISITOR_VARIABLE_COMPARE_SUFFIX)) {
+                    nodeVisitor = new NodeVisitor() {
+
+                        public boolean visit(Node node) {
+                            if (node instanceof SLStatementWrapper) {
+                                SLStatementWrapper wrapper = (SLStatementWrapper) node;
+                                int lineNum = wrapper.getSourceSection().getLineLocation().getLineNumber();
+
+                                if (lineNum == 6) {
+                                    wrapper.getProbe().addInstrument(new SLCheckVariableEqualityInstrument("i", "count", slContext.getOutput()));
+                                }
+                            }
+                            return true;
+                        }
+                    };
+                }
+
+                prober.addNodeProber(new SLInstrumentTestNodeProber(slContext));
+                Parser.parseSL(slContext, source, prober);
+                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
+                // parsing is what creates our instrumentation points.
+                for (SLFunction function : functionList) {
+                    RootCallTarget rootCallTarget = function.getCallTarget();
+                    rootCallTarget.getRootNode().accept(nodeVisitor);
+                }
+
+                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));
+        SLTestRunner suite = new SLTestRunner(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 11 15:45:18 2014 +0200
@@ -0,0 +1,37 @@
+/*
+ * 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.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 11 15:45:18 2014 +0200
@@ -0,0 +1,50 @@
+/*
+ * 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.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 11 15:45:18 2014 +0200
@@ -0,0 +1,43 @@
+/*
+ * 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.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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.truffle.sl.test/tests/error/TypeError02.output	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.truffle.sl.test/tests/error/TypeError04.output	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:45:18 2014 +0200
@@ -0,0 +1,101 @@
+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 11 15:45:18 2014 +0200
@@ -0,0 +1,12 @@
+function loop(count) {  
+  i = 0;  
+  while (i < count) {  
+    i = i + 1;  
+  }  
+  return i;  
+}
+
+function main() {
+  count = loop(100);
+  println(count);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_varCompare.output	Mon Aug 11 15:45:18 2014 +0200
@@ -0,0 +1,2 @@
+true
+100
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_varCompare.sl	Mon Aug 11 15:45:18 2014 +0200
@@ -0,0 +1,12 @@
+function loop(count) {  
+  i = 0;  
+  while (i < count) {  
+    i = i + 1;  
+  }  
+  return i;  
+}
+
+function main() {
+  count = loop(100);
+  println(count);
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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/nodes/controlflow/SLFunctionBodyNode.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java	Mon Aug 11 15:45:18 2014 +0200
@@ -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;
     }
 
--- /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 11 15:45:18 2014 +0200
@@ -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/parser/Parser.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java	Mon Aug 11 15:45:18 2014 +0200
@@ -53,7 +53,7 @@
     public final Scanner scanner;
     public final Errors errors;
     private final SLNodeFactory factory;
-
+    
     public Parser(SLContext context, Source source, SLNodeProber astProber) {
         this.scanner = new Scanner(source.getInputStream());
         this.factory = new SLNodeFactory(context, source, astProber);
@@ -134,41 +134,43 @@
 	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);
+			factory.addFormalParameter(t); 
 			while (la.kind == 6) {
 				Get();
 				Expect(1);
-				factory.addFormalParameter(t);
+				factory.addFormalParameter(t); 
 			}
 		}
 		Expect(7);
 		SLStatementNode body = Block(false);
-		factory.finishFunction(body);
+		factory.finishFunction(body); 
 	}
 
 	SLStatementNode  Block(boolean inLoop) {
 		SLStatementNode  result;
 		factory.startBlock();
-		List<SLStatementNode> body = new ArrayList<>();
+		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);
+			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;
 	}
 
 	SLStatementNode  Statement(boolean inLoop) {
 		SLStatementNode  result;
-		result = null;
+		result = null; 
 		switch (la.kind) {
 		case 13: {
 			result = WhileStatement();
@@ -176,13 +178,13 @@
 		}
 		case 10: {
 			Get();
-			if (inLoop) { result = factory.createBreak(t); } else { SemErr("break used outside of loop"); }
+			if (inLoop) { result = factory.createBreak(t); } else { SemErr("break used outside of loop"); } 
 			Expect(11);
 			break;
 		}
 		case 12: {
 			Get();
-			if (inLoop) { result = factory.createContinue(t); } else { SemErr("continue used outside of loop"); }
+			if (inLoop) { result = factory.createContinue(t); } else { SemErr("continue used outside of loop"); } 
 			Expect(11);
 			break;
 		}
@@ -207,29 +209,29 @@
 	SLStatementNode  WhileStatement() {
 		SLStatementNode  result;
 		Expect(13);
+		Token whileToken = t; 
 		Expect(5);
-		Token whileToken = t;
 		SLExpressionNode condition = Expression();
 		Expect(7);
 		SLStatementNode body = Block(true);
-		result = factory.createWhile(whileToken, condition, body);
+		result = factory.createWhile(whileToken, condition, body); 
 		return result;
 	}
 
 	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);
-		SLStatementNode elsePart = null;
+		SLStatementNode elsePart = null; 
 		if (la.kind == 15) {
 			Get();
 			elsePart = Block(inLoop);
 		}
-		result = factory.createIf(ifToken, condition, thenPart, elsePart);
+		result = factory.createIf(ifToken, condition, thenPart, elsePart); 
 		return result;
 	}
 
@@ -237,11 +239,11 @@
 		SLStatementNode  result;
 		Expect(16);
 		Token returnToken = t;
-		SLExpressionNode value = null;
+		SLExpressionNode value = null; 
 		if (StartOf(2)) {
 			value = Expression();
 		}
-		result = factory.createReturn(returnToken, value);
+		result = factory.createReturn(returnToken, value); 
 		Expect(11);
 		return result;
 	}
@@ -251,9 +253,9 @@
 		result = LogicTerm();
 		while (la.kind == 17) {
 			Get();
-			Token op = t;
+			Token op = t; 
 			SLExpressionNode right = LogicTerm();
-			result = factory.createBinary(op, result, right);
+			result = factory.createBinary(op, result, right); 
 		}
 		return result;
 	}
@@ -263,9 +265,9 @@
 		result = LogicFactor();
 		while (la.kind == 18) {
 			Get();
-			Token op = t;
+			Token op = t; 
 			SLExpressionNode right = LogicFactor();
-			result = factory.createBinary(op, result, right);
+			result = factory.createBinary(op, result, right); 
 		}
 		return result;
 	}
@@ -300,9 +302,9 @@
 				break;
 			}
 			}
-			Token op = t;
+			Token op = t; 
 			SLExpressionNode right = Arithmetic();
-			result = factory.createBinary(op, result, right);
+			result = factory.createBinary(op, result, right); 
 		}
 		return result;
 	}
@@ -316,9 +318,9 @@
 			} else {
 				Get();
 			}
-			Token op = t;
+			Token op = t; 
 			SLExpressionNode right = Term();
-			result = factory.createBinary(op, result, right);
+			result = factory.createBinary(op, result, right); 
 		}
 		return result;
 	}
@@ -332,52 +334,56 @@
 			} else {
 				Get();
 			}
-			Token op = t;
+			Token op = t; 
 			SLExpressionNode right = Factor();
-			result = factory.createBinary(op, result, right);
+			result = factory.createBinary(op, result, right); 
 		}
 		return result;
 	}
 
 	SLExpressionNode  Factor() {
 		SLExpressionNode  result;
-		result = null;
+		result = null; 
 		if (la.kind == 1) {
 			Get();
-			Token nameToken = t;
+			Token nameToken = t; 
 			if (la.kind == 5) {
 				Get();
 				List<SLExpressionNode> parameters = new ArrayList<>();
-				SLExpressionNode parameter;
+				SLExpressionNode parameter; 
 				if (StartOf(2)) {
 					parameter = Expression();
-					parameters.add(parameter);
+					parameters.add(parameter); 
 					while (la.kind == 6) {
 						Get();
 						parameter = Expression();
-						parameters.add(parameter);
+						parameters.add(parameter); 
 					}
 				}
 				Expect(7);
-				Token finalToken = t;
-				result = factory.createCall(nameToken, parameters, finalToken);
+				Token finalToken = t; 
+				result = factory.createCall(nameToken, parameters, finalToken); 
 			} else if (la.kind == 29) {
 				Get();
 				SLExpressionNode value = Expression();
-				result = factory.createAssignment(nameToken, value);
+				result = factory.createAssignment(nameToken, value); 
 			} else if (StartOf(4)) {
-				result = factory.createRead(nameToken);
+				result = factory.createRead(nameToken); 
 			} else SynErr(32);
 		} else if (la.kind == 2) {
 			Get();
-			result = factory.createStringLiteral(t);
+			result = factory.createStringLiteral(t); 
 		} else if (la.kind == 3) {
 			Get();
-			result = factory.createNumericLiteral(t);
+			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;
 	}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java	Mon Aug 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java	Mon Aug 11 15:45:18 2014 +0200
@@ -65,7 +65,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;
@@ -81,13 +83,17 @@
         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 +105,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 +135,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 +155,127 @@
         }
     }
 
-    public SLStatementNode createBreak(Token t) {
-        return new SLBreakNode(source.createSection(t.val, t.charPos, t.val.length()));
+    /**
+     * Returns a {@link SLBreakNode} for the given token. This node will be instrumented, tagged as
+     * a statement and wrapped in an {@link SLStatementWrapper} if an {@link SLASTProber} was
+     * initialized in this class. ({@link #prober} != null)
+     *
+     * @param breakToken The token containing the break node's info
+     * @return either:
+     *         <ul>
+     *         <li>An un-instrumented SLBreakNode if there is no prober</li>
+     *         <li>An {@link SLStatementWrapper} instrumenting this node.</li>
+     *         </ul>
+     */
+    public SLStatementNode createBreak(Token breakToken) {
+        final SLBreakNode breakNode = new SLBreakNode(srcFromToken(breakToken));
+        if (prober != null) {
+            return prober.probeAsStatement(breakNode);
+        }
+        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 a {@link SLContinueNode} for the given token. This node will be instrumented, tagged
+     * as a statement and wrapped in an {@link SLStatementWrapper} if an {@link SLASTProber} was
+     * initialized in this class. ({@link #prober} != null)
+     *
+     * @param continueToken The token containing the continue node's info
+     * @return either:
+     *         <ul>
+     *         <li>An un-instrumented SLContinueNode if there is no prober</li>
+     *         <li>An {@link SLStatementWrapper} instrumenting this node.</li>
+     *         </ul>
+     */
+    public SLStatementNode createContinue(Token continueToken) {
+        final SLContinueNode continueNode = new SLContinueNode(srcFromToken(continueToken));
+        if (prober != null) {
+            return prober.probeAsStatement(continueNode);
+        }
+        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 a {@link SLWhileNode} for the given token. This node will be instrumented, tagged as
+     * a statement and wrapped in an {@link SLStatementWrapper} if an {@link SLASTProber} was
+     * initialized in this class. ({@link #prober} != null)
+     *
+     * @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 either:
+     *         <ul>
+     *         <li>An un-instrumented SLWhileNode if there is no prober</li>
+     *         <li>An {@link SLStatementWrapper} instrumenting this node.</li>
+     *         </ul>
+     */
+    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);
+        if (prober != null) {
+            return prober.probeAsStatement(whileNode);
+        }
+        return whileNode;
     }
 
+    /**
+     * Returns a {@link SLIfNode} for the given token. This node will be instrumented, tagged as a
+     * statement and wrapped in an {@link SLStatementWrapper} if an {@link SLASTProber} was
+     * initialized in this class. ({@link #prober} != null)
+     *
+     * @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 either:
+     *         <ul>
+     *         <li>An un-instrumented SLIfNode if there is no prober</li>
+     *         <li>An {@link SLStatementWrapper} instrumenting this node.</li>
+     *         </ul>
+     */
+    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);
+        if (prober != null) {
+            return prober.probeAsStatement(ifNode);
+        }
+        return ifNode;
+    }
+
+    /**
+     * Returns a {@link SLReturnNode} for the given token. This node will be instrumented, tagged as
+     * a statement and wrapped in an {@link SLStatementWrapper} if an {@link SLASTProber} was
+     * initialized in this class. ({@link #prober} != null)
+     *
+     * @param t The token containing the return node's info
+     * @param valueNode The value of the return
+     * @return either:
+     *         <ul>
+     *         <li>An un-instrumented SLReturnNode if there is no prober</li>
+     *         <li>An {@link SLStatementWrapper} instrumenting this node.</li>
+     *         </ul>
+     */
     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);
+        if (prober != null) {
+            return prober.probeAsStatement(returnNode);
+        }
+        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 for the operation given by opToken.
+     */
     public SLExpressionNode createBinary(Token opToken, SLExpressionNode leftNode, SLExpressionNode rightNode) {
         int start = leftNode.getSourceSection().getCharIndex();
         int length = rightNode.getSourceSection().getCharEndIndex() - start;
@@ -234,6 +310,20 @@
         }
     }
 
+    /**
+     * Returns a {@link SLInvokeNode} for the given token. This node will be instrumented, tagged as
+     * a call and wrapped in an {@link SLExpressionWrapper} if an {@link SLASTProber} was
+     * initialized in this class. ({@link #prober} != null)
+     *
+     * @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 either:
+     *         <ul>
+     *         <li>An un-instrumented SLInvokeNode if there is no prober</li>
+     *         <li>An {@link SLExpressionWrapper} instrumenting this node.</li>
+     *         </ul>
+     */
     public SLExpressionNode createCall(Token nameToken, List<SLExpressionNode> parameterNodes, Token finalToken) {
         final int startPos = nameToken.charPos;
         final int endPos = finalToken.charPos + finalToken.val.length();
@@ -246,21 +336,47 @@
         return SLInvokeNode.create(src, functionNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()]));
     }
 
+    /**
+     * Returns a {@link SLWriteLocalVariableNode} for the given token. This node will be
+     * instrumented, tagged as an assignment and wrapped in an {@link SLExpressionWrapper} if an
+     * {@link SLASTProber} was initialized in this class. ({@link #prober} != null)
+     *
+     * @param nameToken The name of the variable being assigned
+     * @param valueNode The value to be assigned
+     * @return either:
+     *         <ul>
+     *         <li>An un-instrumented SLWriteLocalVariableNode if there is no prober</li>
+     *         <li>An {@link SLExpressionWrapper} instrumenting this node.</li>
+     *         </ul>
+     */
     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);
+            SLWriteLocalVariableNode writeNode = SLWriteLocalVariableNodeFactory.create(source.createSection("=", start, length), valueNode, frameSlot);
+            final SLExpressionNode wrappedNode = prober.probeAsLocalAssignment(writeNode, nameToken.val);
+            return wrappedNode;
         }
         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 +390,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 +407,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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Mon Aug 11 15:45:18 2014 +0200
@@ -138,6 +138,16 @@
         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) {
@@ -157,8 +167,12 @@
         main.getCallTarget().call();
     }
 
+    /**
+     * Sets the {@link SLASTProber} for the executeMain method.
+     *
+     * @param astProber The prober to use for adding instrumentation for this context.
+     */
     public void setASTNodeProber(SLASTProber astProber) {
-        // TODO Auto-generated method stub
         this.astProber = astProber;
     }
 }
--- a/mx/mx_graal.py	Mon Aug 11 15:44:52 2014 +0200
+++ b/mx/mx_graal.py	Mon Aug 11 15:45:18 2014 +0200
@@ -30,6 +30,7 @@
 from os.path import join, exists, dirname, basename
 from argparse import ArgumentParser, RawDescriptionHelpFormatter, REMAINDER
 from outputparser import OutputParser, ValuesMatcher
+import hashlib
 import mx
 import xml.dom.minidom
 import sanitycheck
@@ -82,7 +83,8 @@
 
 _minVersion = mx.VersionSpec('1.8')
 
-JDK_UNIX_PERMISSIONS = 0755
+JDK_UNIX_PERMISSIONS_DIR = 0755
+JDK_UNIX_PERMISSIONS_FILE = 0644
 
 def isVMSupported(vm):
     if 'client' in vm and len(platform.mac_ver()[0]) != 0:
@@ -138,13 +140,11 @@
         _vm = self.previousVm
         _vmbuild = self.previousBuild
 
-def _chmodDir(chmodFlags, dirname, fnames):
-    os.chmod(dirname, chmodFlags)
-    for name in fnames:
-        os.chmod(os.path.join(dirname, name), chmodFlags)
+def chmodRecursive(dirname, chmodFlagsDir):
+    def _chmodDir(chmodFlags, dirname, fnames):
+        os.chmod(dirname, chmodFlagsDir)
 
-def chmodRecursive(dirname, chmodFlags):
-    os.path.walk(dirname, _chmodDir, chmodFlags)
+    os.path.walk(dirname, _chmodDir, chmodFlagsDir)
 
 def clean(args):
     """clean the GraalVM source tree"""
@@ -380,7 +380,7 @@
             return
     mx.abort('You need to run "mx --vm ' + vm + ' --vmbuild ' + bld + ' build" to build the selected VM')
 
-def _jdk(build='product', vmToCheck=None, create=False, installGraalJar=True):
+def _jdk(build='product', vmToCheck=None, create=False, installJars=True):
     """
     Get the JDK into which Graal is installed, creating it first if necessary.
     """
@@ -416,7 +416,7 @@
 
             assert defaultVM is not None, 'Could not find default VM in ' + jvmCfg
             if mx.get_os() != 'windows':
-                chmodRecursive(jdk, JDK_UNIX_PERMISSIONS)
+                chmodRecursive(jdk, JDK_UNIX_PERMISSIONS_DIR)
             shutil.move(join(_vmLibDirInJdk(jdk), defaultVM), join(_vmLibDirInJdk(jdk), 'original'))
 
 
@@ -457,9 +457,11 @@
                 mx.log("The selected JDK directory does not (yet) exist: " + jdk)
             _handle_missing_VM(build, vmToCheck if vmToCheck else 'graal')
 
-    if installGraalJar:
-        _installGraalJarInJdks(mx.distribution('GRAAL'))
-        _installGraalJarInJdks(mx.distribution('GRAAL_LOADER'))
+    if installJars:
+        _installDistInJdks(mx.distribution('GRAAL'))
+        _installDistInJdks(mx.distribution('GRAAL_LOADER'))
+        _installDistInJdks(mx.distribution('TRUFFLE'))
+        _installDistInJdks(mx.distribution('GRAAL_TRUFFLE'))
 
     if vmToCheck is not None:
         jvmCfg = _vmCfgInJdk(jdk)
@@ -485,37 +487,71 @@
             os.unlink(toDelete)
 
 def _makeHotspotGeneratedSourcesDir():
+    """
+    Gets the directory containing all the HotSpot sources generated from
+    Graal Java sources. This directory will be created if it doesn't yet exist.
+    """
     hsSrcGenDir = join(mx.project('com.oracle.graal.hotspot').source_gen_dir(), 'hotspot')
     if not exists(hsSrcGenDir):
         os.makedirs(hsSrcGenDir)
     return hsSrcGenDir
 
+def _update_graalRuntime_inline_hpp(dist):
+    """
+    (Re)generates graalRuntime.inline.hpp based on a given distribution
+    that transitively represents all the input for the generation process.
 
-def _graalRuntime_inline_hpp_path():
-    return join(_makeHotspotGeneratedSourcesDir(), 'graalRuntime.inline.hpp')
+    A SHA1 digest is computed for all generated content and is written to
+    graalRuntime.inline.hpp as well as stored in a generated class
+    that is appended to the dist.path jar. At runtime, these two digests
+    are checked for consistency.
+    """
 
-def _update_graalRuntime_inline_hpp(graalJar):
     p = mx.project('com.oracle.graal.hotspot.sourcegen')
     mainClass = 'com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp'
     if exists(join(p.output_dir(), mainClass.replace('.', os.sep) + '.class')):
-        graalRuntime_inline_hpp = _graalRuntime_inline_hpp_path()
+        genSrcDir = _makeHotspotGeneratedSourcesDir()
+        graalRuntime_inline_hpp = join(genSrcDir, 'graalRuntime.inline.hpp')
+        cp = os.pathsep.join([mx.distribution(d).path for d in dist.distDependencies] + [dist.path, p.output_dir()])
         tmp = StringIO.StringIO()
-        mx.run_java(['-cp', '{}{}{}'.format(graalJar, os.pathsep, p.output_dir()), mainClass], out=tmp.write)
+        mx.run_java(['-cp', cp, mainClass], out=tmp.write)
+
+        # Compute SHA1 for currently generated graalRuntime.inline.hpp content
+        # and all other generated sources in genSrcDir
+        d = hashlib.sha1()
+        d.update(tmp.getvalue())
+        for e in os.listdir(genSrcDir):
+            if e != 'graalRuntime.inline.hpp':
+                with open(join(genSrcDir, e)) as fp:
+                    d.update(fp.read())
+        sha1 = d.hexdigest()
+
+        # Add SHA1 to end of graalRuntime.inline.hpp
+        print >> tmp, ''
+        print >> tmp, 'const char* GraalRuntime::_generated_sources_sha1 = "' + sha1 + '";'
+
         mx.update_file(graalRuntime_inline_hpp, tmp.getvalue())
 
-def _checkVMIsNewerThanGeneratedSources(jdk, vm, bld):
-    if isGraalEnabled(vm):
-        vmLib = mx.TimeStampFile(join(_vmLibDirInJdk(jdk), vm, mx.add_lib_prefix(mx.add_lib_suffix('jvm'))))
-        for name in ['graalRuntime.inline.hpp', 'HotSpotVMConfig.inline.hpp']:
-            genSrc = join(_makeHotspotGeneratedSourcesDir(), name)
-            if vmLib.isOlderThan(genSrc):
-                mx.log('The VM ' + vmLib.path + ' is older than ' + genSrc)
-                mx.abort('You need to run "mx --vm ' + vm + ' --vmbuild ' + bld + ' build"')
+        # Store SHA1 in generated Java class and append class to specified jar
+        javaSource = join(_graal_home, 'GeneratedSourcesSha1.java')
+        javaClass = join(_graal_home, 'GeneratedSourcesSha1.class')
+        with open(javaSource, 'w') as fp:
+            print >> fp, 'class GeneratedSourcesSha1 { private static final String value = "' + sha1 + '"; }'
+        subprocess.check_call([mx.java().javac, '-d', _graal_home, javaSource], stderr=subprocess.PIPE, stdout=subprocess.PIPE)
+        zf = zipfile.ZipFile(dist.path, 'a')
+        with open(javaClass, 'rb') as fp:
+            zf.writestr(os.path.basename(javaClass), fp.read())
+        zf.close()
+        os.unlink(javaSource)
+        os.unlink(javaClass)
 
-def _installGraalJarInJdks(graalDist):
-    graalJar = graalDist.path
-    if graalJar.endswith('graal.jar'):
-        _update_graalRuntime_inline_hpp(graalJar)
+def _installDistInJdks(dist):
+    """
+    Installs the jar(s) for a given Distribution into all existing Graal JDKs
+    """
+
+    if dist.name == 'GRAAL_TRUFFLE':
+        _update_graalRuntime_inline_hpp(dist)
     jdks = _jdksDir()
 
     if exists(jdks):
@@ -527,7 +563,7 @@
                     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 graal.jar is being updated while
+                        # 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):
@@ -539,11 +575,11 @@
                         shutil.copyfile(srcJar, tmp)
                         os.close(fd)
                         shutil.move(tmp, dstJar)
-                        os.chmod(dstJar, JDK_UNIX_PERMISSIONS)
+                        os.chmod(dstJar, JDK_UNIX_PERMISSIONS_FILE)
 
-                install(graalJar, jreLibDir)
-                if graalDist.sourcesPath:
-                    install(graalDist.sourcesPath, join(jdks, e))
+                install(dist.path, jreLibDir)
+                if dist.sourcesPath:
+                    install(dist.sourcesPath, join(jdks, e))
 
 # run a command in the windows SDK Debug Shell
 def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo=None):
@@ -608,7 +644,7 @@
 def jdkhome(vm=None):
     """return the JDK directory selected for the 'vm' command"""
     build = _vmbuild if _vmSourcesAvailable else 'product'
-    return _jdk(build, installGraalJar=False)
+    return _jdk(build, installJars=False)
 
 def print_jdkhome(args, vm=None):
     """print the JDK directory selected for the 'vm' command"""
@@ -634,6 +670,35 @@
     mx.log('')
     mx.log('Note that these variables can be given persistent values in the file ' + join(_graal_home, 'mx', 'env') + ' (see \'mx about\').')
 
+cached_graal_version = None
+
+def graal_version(dev_suffix='dev'):
+    global cached_graal_version
+
+    if not cached_graal_version:
+        # 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()
+        except:
+            # not a mercurial repository or hg commands are not available.
+            tags = None
+
+        if tags and current_revision:
+            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_version = most_recent_tag_name[len("graal-"):]
+
+            if current_revision == most_recent_tag_revision:
+                cached_graal_version = most_recent_tag_version
+            else:
+                major, minor = map(int, most_recent_tag_version.split('.'))
+                cached_graal_version = str(major) + '.' + str(minor + 1) + '-' + dev_suffix
+        else:
+            cached_graal_version = 'unknown-{}-{}'.format(platform.node(), time.strftime('%Y-%m-%d_%H-%M-%S_%Z'))
+
+    return cached_graal_version
+
 def build(args, vm=None):
     """build the VM binary
 
@@ -700,7 +765,7 @@
             if build is None or len(build) == 0:
                 continue
 
-        jdk = _jdk(build, create=True)
+        jdk = _jdk(build, create=True, installJars=not opts2.java)
 
         if vm == 'original':
             if build != 'product':
@@ -714,7 +779,7 @@
         vmDir = join(_vmLibDirInJdk(jdk), vm)
         if not exists(vmDir):
             if mx.get_os() != 'windows':
-                chmodRecursive(jdk, JDK_UNIX_PERMISSIONS)
+                chmodRecursive(jdk, JDK_UNIX_PERMISSIONS_DIR)
             mx.log('Creating VM directory in JDK: ' + vmDir)
             os.makedirs(vmDir)
 
@@ -794,22 +859,9 @@
                 setMakeVar('INCLUDE_GRAAL', 'false')
                 setMakeVar('ALT_OUTPUTDIR', join(_graal_home, 'build-nograal', mx.get_os()), env=env)
             else:
-                # extract latest release tag for graal
-                try:
-                    tags = [x.split(' ')[0] for x in subprocess.check_output(['hg', '-R', _graal_home, 'tags']).split('\n') if x.startswith("graal-")]
-                except:
-                    # not a mercurial repository or hg commands are not available.
-                    tags = None
-
-                if tags:
-                    # extract the most recent tag
-                    tag = sorted(tags, key=lambda e: [int(x) for x in e[len("graal-"):].split('.')], reverse=True)[0]
-                    setMakeVar('USER_RELEASE_SUFFIX', tag)
-                    setMakeVar('GRAAL_VERSION', tag[len("graal-"):])
-                else:
-                    version = 'unknown-{}-{}'.format(platform.node(), time.strftime('%Y-%m-%d_%H-%M-%S_%Z'))
-                    setMakeVar('USER_RELEASE_SUFFIX', 'graal-' + version)
-                    setMakeVar('GRAAL_VERSION', version)
+                version = graal_version()
+                setMakeVar('USER_RELEASE_SUFFIX', 'graal-' + version)
+                setMakeVar('GRAAL_VERSION', version)
                 setMakeVar('INCLUDE_GRAAL', 'true')
             setMakeVar('INSTALL', 'y', env=env)
             if mx.get_os() == 'solaris':
@@ -861,7 +913,7 @@
         if not found:
             mx.log('Appending "' + prefix + 'KNOWN" to ' + jvmCfg)
             if mx.get_os() != 'windows':
-                os.chmod(jvmCfg, JDK_UNIX_PERMISSIONS)
+                os.chmod(jvmCfg, JDK_UNIX_PERMISSIONS_FILE)
             with open(jvmCfg, 'w') as f:
                 for line in lines:
                     if line.startswith(prefix):
@@ -899,9 +951,8 @@
         mx.abort("conflicting working directories: do not set --vmcwd for this command")
 
     build = vmbuild if vmbuild is not None else _vmbuild if _vmSourcesAvailable else 'product'
-    jdk = _jdk(build, vmToCheck=vm, installGraalJar=False)
+    jdk = _jdk(build, vmToCheck=vm, installJars=False)
     _updateInstalledGraalOptionsFile(jdk)
-    _checkVMIsNewerThanGeneratedSources(jdk, vm, build)
     mx.expand_project_in_args(args)
     if _make_eclipse_launch:
         mx.make_eclipse_launch(args, 'graal-' + build, name=None, deps=mx.project('com.oracle.graal.hotspot').all_deps([], True))
@@ -1071,7 +1122,7 @@
             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])
-            vmArgs = vmArgs + ['-XX:-UseGraalClassLoader']
+            vmArgs = ['-XX:-UseGraalClassLoader'] + vmArgs
 
         if len(testclasses) == 1:
             # Execute Junit directly when one test is being run. This simplifies
@@ -1490,6 +1541,13 @@
             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 maven_install_truffle(args):
+    """install Truffle into your local Maven repository"""
+    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"""
     libpath = join(_graal_home, 'lib')
@@ -2149,6 +2207,7 @@
         'hsdis': [hsdis, '[att]'],
         'hcfdis': [hcfdis, ''],
         'igv' : [igv, ''],
+        '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]'],
@@ -2214,5 +2273,7 @@
     global _vm_prefix
     _vm_prefix = opts.vm_prefix
 
-    mx.distribution('GRAAL').add_update_listener(_installGraalJarInJdks)
-    mx.distribution('GRAAL_LOADER').add_update_listener(_installGraalJarInJdks)
+    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)
--- a/mx/projects	Mon Aug 11 15:44:52 2014 +0200
+++ b/mx/projects	Mon Aug 11 15:45:18 2014 +0200
@@ -77,43 +77,66 @@
 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,\
-com.oracle.graal.truffle,\
-com.oracle.graal.truffle.hotspot.amd64,\
 com.oracle.graal.hotspot.sparc,\
 com.oracle.graal.hotspot,\
 com.oracle.graal.hotspot.jfr,\
 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@TRUFFLE-DSL-PROCESSOR@path=truffle-dsl-processor.jar
+distribution@GRAAL_TRUFFLE@path=build/graal-truffle.jar
+distribution@GRAAL_TRUFFLE@subDir=graal
+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=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.8
+
+# 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.8
+
 # graal.api.collections
 project@com.oracle.graal.api.collections@subDir=graal
 project@com.oracle.graal.api.collections@sourceDirs=src
@@ -212,7 +235,7 @@
 # graal.hotspot
 project@com.oracle.graal.hotspot@subDir=graal
 project@com.oracle.graal.hotspot@sourceDirs=src
-project@com.oracle.graal.hotspot@dependencies=com.oracle.graal.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
@@ -296,18 +319,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
--- a/mxtool/mx.py	Mon Aug 11 15:44:52 2014 +0200
+++ b/mxtool/mx.py	Mon Aug 11 15:45:18 2014 +0200
@@ -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
@@ -497,7 +503,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 +520,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 +564,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 +655,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:
@@ -1006,7 +1015,7 @@
                             logv('[omitting project {} as dependency {} is missing]'.format(d, name))
                             del _projects[d.name]
                             self.projects.remove(d)
-        for dist in _dists.values():
+        for dist in _dists.itervalues():
             for name in list(dist.deps):
                 if not dependency(name, fatalIfMissing=False):
                     logv('[omitting {} from distribution {}]'.format(name, dist))
@@ -1315,6 +1324,23 @@
 
     return sorted_project_deps(projects, includeLibs=includeLibs, includeJreLibs=includeJreLibs, includeAnnotationProcessors=includeAnnotationProcessors)
 
+def sorted_dists():
+    """
+    Gets distributions sorted such that each distribution comes after
+    any distributions it depends upon.
+    """
+    dists = []
+    def add_dist(dist):
+        if not dist in dists:
+            for depDist in [distribution(name) for name in dist.distDependencies]:
+                add_dist(depDist)
+            if not dist in dists:
+                dists.append(dist)
+
+    for d in _dists.itervalues():
+        add_dist(d)
+    return dists
+
 def sorted_project_deps(projects, includeLibs=False, includeJreLibs=False, includeAnnotationProcessors=False):
     deps = []
     for p in projects:
@@ -2217,13 +2243,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 = []
@@ -2392,7 +2417,7 @@
                 log('Compiling {} failed'.format(t.proj.name))
             abort('{} Java compilation tasks failed'.format(len(failed)))
 
-    for dist in _dists.values():
+    for dist in sorted_dists():
         archive(['@' + dist.name])
 
     if suppliedParser:
@@ -2664,6 +2689,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
@@ -3457,12 +3484,6 @@
     if buildProcessorJars:
         files += _processorjars_suite(suite)
 
-    projToDist = dict()
-    for dist in _dists.values():
-        distDeps = dist.sorted_deps()
-        for p in distDeps:
-            projToDist[p.name] = (dist, [dep.name for dep in distDeps])
-
     for p in suite.projects:
         if p.native:
             continue
@@ -3475,7 +3496,8 @@
     _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')
@@ -3483,7 +3505,7 @@
             projectDir = join(suite.dir, dist.name + '.dist')
         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():
@@ -3496,6 +3518,8 @@
         out.open('projects')
         for p in distProjects:
             out.element('project', data=p.name)
+        for d in dist.distDependencies:
+            out.element('project', data=d)
         out.close('projects')
         out.open('buildSpec')
         dist.dir = projectDir
@@ -3909,8 +3933,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}
--- a/src/cpu/sparc/vm/graalCodeInstaller_sparc.cpp	Mon Aug 11 15:44:52 2014 +0200
+++ b/src/cpu/sparc/vm/graalCodeInstaller_sparc.cpp	Mon Aug 11 15:45:18 2014 +0200
@@ -61,9 +61,11 @@
   address pc = _instructions->start() + pc_offset;
   address const_start = _constants->start();
   jint offset = DataSectionReference::offset(data);
+  address dest = _constants->start() + offset;
 
-  NativeMovRegMem* load = nativeMovRegMem_at(pc);
-  load->add_offset_in_bytes((long)const_start+offset);
+  _instructions->relocate(pc + NativeMovConstReg::sethi_offset, internal_word_Relocation::spec((address) dest));
+  _instructions->relocate(pc + NativeMovConstReg::add_offset, internal_word_Relocation::spec((address) dest));
+  TRACE_graal_3("relocating at %p with destination at %p (%d)", pc, dest, offset);
 }
 
 void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Mon Aug 11 15:44:52 2014 +0200
+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Mon Aug 11 15:45:18 2014 +0200
@@ -3561,6 +3561,7 @@
   int exception_in_tls_offset = __ offset() - start;
 
   // No need to update oop_map  as each call to save_live_registers will produce identical oopmap
+  // Opens a new stack frame
   (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_words);
 
   // Restore G2_thread
@@ -3592,7 +3593,10 @@
   // Reexecute entry, similar to c2 uncommon trap
   //
   int reexecute_offset = __ offset() - start;
-
+#if defined(COMPILERGRAAL) && !defined(COMPILER1)
+  // Graal does not use this kind of deoptimization
+  __ should_not_reach_here();
+#endif
   // No need to update oop_map  as each call to save_live_registers will produce identical oopmap
   (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_words);
 
--- a/src/gpu/hsail/vm/gpu_hsail_Tlab.hpp	Mon Aug 11 15:44:52 2014 +0200
+++ b/src/gpu/hsail/vm/gpu_hsail_Tlab.hpp	Mon Aug 11 15:45:18 2014 +0200
@@ -138,6 +138,12 @@
       HSAILTlabInfo* pTlabInfo = &_tlab_infos_pool_start[i];
       _cur_tlab_infos[i] = pTlabInfo;
       pTlabInfo->initialize(tlab->start(), tlab->top(), tlab->end(), donorThread, this);
+
+      // reset the real tlab fields to zero so we are sure the thread doesn't use it
+      tlab->set_start(NULL);
+      tlab->set_top(NULL);
+      tlab->set_pf_top(NULL);
+      tlab->set_end(NULL);
     }
   }
 
@@ -182,6 +188,16 @@
           tlabInfo->_top = tlabInfo->last_good_top();
         }
 
+        // if the donor thread allocated anything while we were running
+        // we will retire its tlab before overwriting with our new one
+        if (tlab->top() != NULL) {
+          if (TraceGPUInteraction) {
+            tty->print("Donor Thread allocated new tlab");
+            printTlabInfoFromThread(tlab);
+          }
+          tlab->make_parsable(true);
+        }
+
         // fill the donor thread 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
--- a/src/os/bsd/vm/os_bsd.cpp	Mon Aug 11 15:44:52 2014 +0200
+++ b/src/os/bsd/vm/os_bsd.cpp	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/src/os/linux/vm/os_linux.cpp	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/src/os/solaris/vm/os_solaris.cpp	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/src/os/windows/vm/os_windows.cpp	Mon Aug 11 15:45:18 2014 +0200
@@ -3672,6 +3672,16 @@
 #endif
 }
 
+address os::get_pc(void* context) {
+  CONTEXT* uc = (CONTEXT*)context;
+#ifdef _M_AMD64
+  return (address) context.Rip;
+#else
+  return (address) context.Eip;
+#endif
+}
+
+
 // GetCurrentThreadId() returns DWORD
 intx os::current_thread_id()          { return GetCurrentThreadId(); }
 
--- a/src/share/vm/code/nmethod.hpp	Mon Aug 11 15:44:52 2014 +0200
+++ b/src/share/vm/code/nmethod.hpp	Mon Aug 11 15:45:18 2014 +0200
@@ -643,7 +643,21 @@
 
   // (thomaswue) When using graal, the address might be off by 5 (because this is the size of the call instruction.
   // (thomaswue) TODO: Replace this by a more general mechanism.
-  bool is_deopt_entry   (address pc) { return pc == deopt_handler_begin() GRAAL_ONLY( || pc == deopt_handler_begin() + 5); }
+  // (sanzinger) SPARC has another offset, looked for some variable existing in HotSpot which describes this offset, but i have not
+  // found anything.
+  bool is_deopt_entry   (address pc) {
+    return pc == deopt_handler_begin()
+#ifdef GRAAL
+      || pc == deopt_handler_begin() +
+#ifdef TARGET_ARCH_sparc
+  8
+#endif // sparc
+#ifdef TARGET_ARCH_x86
+  5
+#endif // x86
+#endif // GRAAL
+      ;
+  }
   bool is_deopt_mh_entry(address pc) { return pc == deopt_mh_handler_begin(); }
   // Accessor/mutator for the original pc of a frame before a frame was deopted.
   address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); }
--- a/src/share/vm/compiler/compileBroker.cpp	Mon Aug 11 15:44:52 2014 +0200
+++ b/src/share/vm/compiler/compileBroker.cpp	Mon Aug 11 15:45:18 2014 +0200
@@ -52,6 +52,7 @@
 #ifdef GRAAL
 #include "graal/graalCompiler.hpp"
 #ifdef COMPILERGRAAL
+#include "graal/graalRuntime.hpp"
 #include "runtime/vframe.hpp"
 #endif
 #endif
@@ -1204,6 +1205,12 @@
           break;
         }
       }
+
+      // Don't allow blocking compilation requests to Graal
+      // if Graal itself is not yet initialized
+      if (!GraalRuntime::is_HotSpotGraalRuntime_initialized() && compiler(comp_level)->is_graal()) {
+        blocking = false;
+      }
     }
     // Don't allow blocking compiles
 #endif
--- a/src/share/vm/compiler/disassembler.cpp	Mon Aug 11 15:44:52 2014 +0200
+++ b/src/share/vm/compiler/disassembler.cpp	Mon Aug 11 15:45:18 2014 +0200
@@ -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/graal/graalCodeInstaller.cpp	Mon Aug 11 15:44:52 2014 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Mon Aug 11 15:45:18 2014 +0200
@@ -68,6 +68,11 @@
       return as_XMMRegister(remainder)->as_VMReg();
     }
 #endif
+#ifdef TARGET_ARCH_sparc
+    if (remainder < FloatRegisterImpl::number_of_registers) {
+      return as_FloatRegister(remainder)->as_VMReg();
+    }
+#endif
     ShouldNotReachHere();
     return NULL;
   }
@@ -129,6 +134,13 @@
       }
     }
 #endif
+#ifdef TARGET_ARCH_sparc
+    for (jint i = 0; i < FloatRegisterImpl::number_of_registers; i++) {
+      VMReg reg = as_FloatRegister(i)->as_VMReg();
+      int idx = RegisterImpl::number_of_registers + i;
+      set_vmreg_oops(map, reg, register_map, idx);
+    }
+#endif
   }
 
   for (jint i = 0; i < bitset_size(frame_map) / 3; i++) {
@@ -214,6 +226,7 @@
 
   if (value->is_a(RegisterValue::klass())) {
     jint number = code_Register::number(RegisterValue::reg(value));
+    jint encoding = code_Register::encoding(RegisterValue::reg(value));
     if (number < RegisterImpl::number_of_registers) {
       Location::Type locationType;
       if (type == T_INT) {
@@ -249,9 +262,9 @@
       return value;
 #else
 #ifdef TARGET_ARCH_sparc
-      ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, as_FloatRegister(number)->as_VMReg()));
+      ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, as_FloatRegister(encoding)->as_VMReg()));
       if (type == T_DOUBLE) {
-        second = value;
+        second = new ConstantIntValue(0);
       }
       return value;
 #else
--- a/src/share/vm/graal/graalGlobals.hpp	Mon Aug 11 15:44:52 2014 +0200
+++ b/src/share/vm/graal/graalGlobals.hpp	Mon Aug 11 15:45:18 2014 +0200
@@ -49,7 +49,7 @@
   product(bool, DebugGraal, true,                                           \
           "Enable JVMTI for the compiler thread")                           \
                                                                             \
-  product(bool, UseGraalClassLoader, false,                                 \
+  product(bool, UseGraalClassLoader, true,                                  \
           "Load Graal classes with separate class loader")                  \
                                                                             \
   COMPILERGRAAL_PRESENT(product(bool, BootstrapGraal, true,                 \
--- a/src/share/vm/graal/graalJavaAccess.hpp	Mon Aug 11 15:44:52 2014 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Mon Aug 11 15:45:18 2014 +0200
@@ -239,6 +239,7 @@
   end_class                                                                                                                                                    \
   start_class(code_Register)                                                                                                                                   \
     int_field(code_Register, number)                                                                                                                           \
+    int_field(code_Register, encoding)                                                                                                                         \
   end_class                                                                                                                                                    \
   start_class(StackSlot)                                                                                                                                       \
     int_field(StackSlot, offset)                                                                                                                               \
--- a/src/share/vm/graal/graalRuntime.cpp	Mon Aug 11 15:44:52 2014 +0200
+++ b/src/share/vm/graal/graalRuntime.cpp	Mon Aug 11 15:45:18 2014 +0200
@@ -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();
@@ -663,9 +664,49 @@
   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);
+  fieldDescriptor fd;
+  if (!InstanceKlass::cast(klass())->find_field(vmSymbols::value_name(), vmSymbols::string_signature(), true, &fd)) {
+    THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), "GeneratedSourcesSha1.value");
+  }
+
+  Symbol* value = java_lang_String::as_symbol(klass->java_mirror()->obj_field(fd.offset()), CHECK);
+  if (!value->equals(_generated_sources_sha1)) {
+    char buf[200];
+    jio_snprintf(buf, sizeof(buf), "Generated sources SHA1 check failed (%s != %s) - need to rebuild the VM", value->as_C_string(), _generated_sources_sha1);
+    THROW_MSG(vmSymbols::java_lang_InternalError(), buf);
+  }
+}
+
 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()));
     KlassHandle klass = load_required_class(name);
     TempNewSymbol runtime = SymbolTable::new_symbol("runtime", CHECK_ABORT_(Handle()));
@@ -673,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));
 }
@@ -973,6 +1015,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 11 15:44:52 2014 +0200
+++ b/src/share/vm/graal/graalRuntime.hpp	Mon Aug 11 15:45:18 2014 +0200
@@ -32,7 +32,9 @@
  private:
 
   static jobject _HotSpotGraalRuntime_instance;
+  static bool _HotSpotGraalRuntime_initialized;
   static address _external_deopt_i2c_entry;
+  static const char* _generated_sources_sha1;
 
   /**
    * Reads the OptionValue object from a specified static field.
@@ -101,11 +103,16 @@
    */
   static Handle create_Service(const char* name, TRAPS);
 
+  /**
+   * Checks that _generated_sources_sha1 equals GeneratedSourcesSha1.value.
+   */
+  static void check_generated_sources_sha1(TRAPS);
+
  public:
 
   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
@@ -173,7 +180,7 @@
   static Klass* load_required_class(Symbol* name);
 
   /**
-   * Creates a separate class loader for classes in graal.jar.
+   * Creates a separate class loader for classes in graal.jar and graal-truffle.jar.
    */
   static oop compute_graal_class_loader(TRAPS);
 
--- a/src/share/vm/memory/threadLocalAllocBuffer.hpp	Mon Aug 11 15:44:52 2014 +0200
+++ b/src/share/vm/memory/threadLocalAllocBuffer.hpp	Mon Aug 11 15:45:18 2014 +0200
@@ -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
--- a/src/share/vm/prims/nativeLookup.cpp	Mon Aug 11 15:44:52 2014 +0200
+++ b/src/share/vm/prims/nativeLookup.cpp	Mon Aug 11 15:45:18 2014 +0200
@@ -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/arguments.cpp	Mon Aug 11 15:44:52 2014 +0200
+++ b/src/share/vm/runtime/arguments.cpp	Mon Aug 11 15:45:18 2014 +0200
@@ -3252,7 +3252,7 @@
   if (!UseGraalClassLoader) {
     // Append graal.jar to boot class path
     const char* home = Arguments::get_java_home();
-    scp_p->add_suffix(os::format_boot_path("%/lib/graal.jar", home, (int)strlen(home), os::file_separator()[0], os::path_separator()[0]));
+    scp_p->add_suffix(os::format_boot_path("%/lib/graal.jar:%/lib/graal-truffle.jar", home, (int)strlen(home), os::file_separator()[0], os::path_separator()[0]));
     scp_assembly_required = true;
   }
 #endif
--- a/src/share/vm/runtime/os.cpp	Mon Aug 11 15:44:52 2014 +0200
+++ b/src/share/vm/runtime/os.cpp	Mon Aug 11 15:45:18 2014 +0200
@@ -1269,6 +1269,7 @@
 #endif
 #ifdef GRAAL
         "%/lib/graal-loader.jar:"
+        "%/lib/truffle.jar:"
 #endif
         "%/classes";
     char* sysclasspath = format_boot_path(classpath_format, home, home_len, fileSep, pathSep);
--- a/src/share/vm/runtime/os.hpp	Mon Aug 11 15:44:52 2014 +0200
+++ b/src/share/vm/runtime/os.hpp	Mon Aug 11 15:45:18 2014 +0200
@@ -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 11 15:44:52 2014 +0200
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Mon Aug 11 15:45:18 2014 +0200
@@ -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/utilities/vmError.cpp	Mon Aug 11 15:44:52 2014 +0200
+++ b/src/share/vm/utilities/vmError.cpp	Mon Aug 11 15:45:18 2014 +0200
@@ -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