# HG changeset patch # User Christian Humer # Date 1407764718 -7200 # Node ID ef3c7944261b8b5c84044d7428714d91309f46a4 # Parent bda327903f969e1b998f9c6d3959868487eb229b# Parent 3507ad1b0c4425a6a36952bcfc434f3c09686bad Merge. diff -r bda327903f96 -r ef3c7944261b .hgignore --- 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 diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionHandle.java --- 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. - *

- * The caller is responsible for ensuring {@code args} comply with the platform ABI (e.g. Unix AMD64 ABI). 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(); -} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionInterface.java --- 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); -} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionPointer.java --- 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. - *

- * 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(); - -} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeLibraryHandle.java --- 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(); -} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaType.java --- 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); - } - } } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ExcludeFromIdentityComparisonVerification.java --- /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 { + +} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java --- 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[] getParameterAnnotations(Class annotationClass, ResolvedJavaMethod method) { - return method.getParameterAnnotations(annotationClass); - } - - @Deprecated - public static T getParameterAnnotation(Class 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); - } } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java --- 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; + } } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/Services.java --- 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[] getServiceImpls(Class service); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java --- 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) { diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java --- 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 { diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/UnsafeAccess.java --- 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) { diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java --- 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) { diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleCosTest.java --- 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(); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleNextAfterTest.java --- 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(); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleNextUpTest.java --- 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(); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleSinTest.java --- 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(); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleTanTest.java --- 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(); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatCosTest.java --- 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(); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatNextAfterTest.java --- 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(); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatNextUpTest.java --- 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(); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatSinTest.java --- 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(); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatTanTest.java --- 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(); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringBuilderTest.java --- 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 diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java --- 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)); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java --- 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); } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java --- 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) { diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java --- 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()); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java --- 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"); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSensitiveReductionTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java --- 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 @@ *

* White box tests for Graal compiler transformations use this pattern: *

    - *
  1. Create a graph by {@linkplain #parse(String) parsing} a method.
  2. + *
  3. Create a graph by {@linkplain #parseEager(String) parsing} a method.
  4. *
  5. Manually modify the graph (e.g. replace a parameter node with a constant).
  6. *
  7. Apply a transformation to the graph.
  8. *
  9. Assert that the transformed graph is equal to an expected graph.
  10. @@ -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 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 getDefaultGraphBuilderSuite() { diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java --- 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); } } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IntegerEqualsCanonicalizerTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java --- 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 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); } } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MergeCanonicalizerTest.java --- 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"); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java --- 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); } } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PhiCreationTests.java --- 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()); } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushThroughIfTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java --- 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 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); } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java --- 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); } } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java --- 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); } } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java --- 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 void testHelper(String snippet, Class 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)); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java --- 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)) { diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java --- 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 { diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/MonitorDeoptTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java --- 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); } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PoorMansEATest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java --- 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 graphBuilderSuite = eagerInfopointMode ? getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault()) : getDefaultGraphBuilderSuite(); Assumptions assumptions = new Assumptions(true); HighTierContext context = new HighTierContext(getProviders(), assumptions, null, graphBuilderSuite, OptimisticOptimizations.ALL); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/nfi/NativeFunctionInterfaceTest.java --- 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 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) { - } - } - -} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/CompilerThread.java --- 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 { diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java --- 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 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 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 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 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 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 Log = new OptionValue<>(null); @Option(help = "Pattern for filtering debug scope output based on method context (see MethodFilter)") public static final OptionValue MethodFilter = new OptionValue<>(null); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java --- 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)); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/HostBackend.java --- 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(); -} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java --- 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 metrics = new HashSet<>(); Set timers = new HashSet<>(); - for (Map.Entry 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 metrics, Set timers) { + do { + try { + for (Map.Entry 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 diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MemUseTrackerImpl.java --- 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; } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/AMD64HotSpotFrameOmissionTest.java --- 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(); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/CompressedNullCheckTest.java --- /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); + } +} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java --- 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); } } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- 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 diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java --- 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; + } + } } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java --- 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; diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.jdk8.test/src/com/oracle/graal/hotspot/jdk8/test/CRC32UpdateByteBufferSubstitutionTest.java --- 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); - } -} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.loader/src/com/oracle/graal/hotspot/loader/Factory.java --- 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); } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java --- 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 { + private final List 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 iterator() { + Stream 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> services = new ArrayList<>(); - for (final Enumeration 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> 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; } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/OptionsVerifier.java --- 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> checked, ZipFile graalJar) throws IOException { + public static void checkClass(Class cls, OptionDescriptor option, Set> 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java --- 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 destroyedRegisters = Collections.emptySet(); - Map calleeSaveInfo = Collections.emptyMap(); - updateStub(stub, destroyedRegisters, calleeSaveInfo, frameMap); + // Even on sparc we need to save floating point registers + Set definedRegisters = gatherDefinedRegisters(lir); + Map 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"); - } - } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallEpilogueOp.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java --- 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))); } } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java --- 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 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 calleeSaveInfo = ((SPARCHotSpotLIRGenerationResult) getResult()).getCalleeSaveInfo(); + assert currentRuntimeCallInfo != null; + assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo); + calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp); return result; } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java --- 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 diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java --- 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); } } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java --- 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; } } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java --- 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); } } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java --- 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); } } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java --- 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)) { diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CRC32SubstitutionsTest.java --- 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); + } + } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java --- 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; } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNmethodTest.java --- 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 { diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/MemoryUsageBenchmark.java --- /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: + * + *
    + *     mx vm -XX:-UseGraalClassLoader -cp @com.oracle.graal.hotspot.test com.oracle.graal.hotspot.test.MemoryUsageBenchmark
    + * 
    + * + * Memory analysis for a {@link CompileTheWorld} execution can also be performed. For example: + * + *
    + *     mx --vm server vm -XX:-UseGraalClassLoader -G:CompileTheWorldClasspath=$HOME/SPECjvm2008/SPECjvm2008.jar -cp @com.oracle.graal.hotspot.test com.oracle.graal.hotspot.test.MemoryUsageBenchmark
    + * 
    + */ +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(); + } + } + } +} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java --- 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 diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java --- 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}. diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptionsLoader.java --- 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 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(); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- 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. diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java --- 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++; diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java --- 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 diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionHandle.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java --- 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 { diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionPointer.java --- 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; } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeLibraryHandle.java --- 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 { diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMConfigProcessor.java --- 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 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 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 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 annotationMap, Class annotationClass) { + @SuppressWarnings("unchecked") + private void collectAnnotations(RoundEnvironment roundEnv, Map annotationMap, Class annotationClass, + BiFunction 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 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; diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java --- 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); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_irem.java --- 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); + } } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/BigMixedParams04.java --- /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); + } +} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java --- 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(); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java --- 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(); } } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java --- 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); } } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java --- 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 @@ * *
      *   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;
    +    }
     }
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java
    --- 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
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java
    --- 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();
             }
         }
     
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest1.java
    --- /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;
    +            }
    +        });
    +    }
    +}
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest2.java
    --- /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;
    +            }
    +        });
    +    }
    +}
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java
    --- 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;
    +    }
    +
     }
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java
    --- 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 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);
    +        }
    +    }
     }
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java
    --- 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;
             }
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java
    --- 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) {
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java
    --- 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[] flags, InstructionValueProcedure proc) {
    +    protected static void forEach(LIRInstruction inst, int directCount, long[] offsets, OperandMode mode, EnumSet[] 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[] 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[] 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();
    +    }
     }
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java
    --- 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 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;
         }
     
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java
    --- 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 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 findUnswitchable(LoopEx loop) {
    +        List 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;
         }
     }
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java
    --- 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 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 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);
         }
     }
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/LoopPhiCanonicalizerTest.java
    --- 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);
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java
    --- 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);
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java
    --- 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;
         }
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java
    --- 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);
         }
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryAccess.java
    --- 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
    +    }
     }
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java
    --- 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.
          */
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java
    --- 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];
         }
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java
    --- 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:
      *
      * 
    - * ServiceLoader<Options> sl = ServiceLoader.loadInstalled(Options.class);
    + * ServiceLoader<Options> sl = ServiceLoader.load(Options.class);
      * for (Options opts : sl) {
      *     for (OptionDescriptor desc : sl) {
      *         // use desc
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CleanTypeProfileProxyPhase.java
    --- 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 {
    +
    +    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;
         }
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java
    --- 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);
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java
    --- 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 ptypes) {
    +        Set 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);
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java
    --- 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);
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java
    --- 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 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 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;
                 }
             }
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java
    --- 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;
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java
    --- 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");
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java
    --- 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 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);
             }
         }
     
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java
    --- 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 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());
         }
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java
    --- 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
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StringSubstitutionsTest.java
    --- 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++) {
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/UnsafeSubstitutionsTest.java
    --- 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
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java
    --- 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 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);
         }
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java
    --- 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);
    +    }
     }
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java
    --- 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);
    +    }
     }
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java
    --- 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);
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java
    --- 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
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java
    --- 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)));
    +    }
     }
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java
    --- 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() {
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedDirectCallNode.java
    --- 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());
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java
    --- 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());
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java
    --- 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 TraceTruffleSplitting = new OptionValue<>(false);
         @Option(help = "Print stack trace on transfer to interpreter")
         public static final OptionValue TraceTruffleTransferToInterpreter = new StableOptionValue<>(false);
    +    @Option(help = "Print stack trace on assumption invalidation")
    +    public static final OptionValue TraceTruffleAssumptions = new StableOptionValue<>(false);
         @Option(help = "")
         public static final OptionValue TruffleCallTargetProfiling = new StableOptionValue<>(false);
         // @formatter:on
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.nfi.test/test/com/oracle/nfi/test/NativeFunctionInterfaceTest.java
    --- /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 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) {
    +        }
    +    }
    +
    +}
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.nfi/src/com/oracle/nfi/NativeFunctionInterfaceRuntime.java
    --- /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;
    +    }
    +}
    diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.nfi/src/com/oracle/nfi/api/NativeFunctionHandle.java
    --- /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.
    +     * 

    + * The caller is responsible for ensuring {@code args} comply with the platform ABI (e.g. Unix AMD64 ABI). 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); + +} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.nfi/src/com/oracle/nfi/api/NativeFunctionInterface.java --- /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); +} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.nfi/src/com/oracle/nfi/api/NativeFunctionPointer.java --- /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. + *

    + * 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(); + +} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.nfi/src/com/oracle/nfi/api/NativeLibraryHandle.java --- /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(); +} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/WrapperTest.java --- /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: + *

      + *
    1. Creates a simple add AST
    2. + *
    3. Verifies its structure
    4. + *
    5. Instruments the add node
    6. + *
    7. Attaches a simple probe to the instrumented node
    8. + *
    9. Verifies the structure of the instrumented AST
    10. + *
    11. Verifies the execution of the instrumented AST
    12. + *
    + * 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 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 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; + } +} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java --- 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(); diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java --- 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; } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultIndirectCallNode.java --- 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(); + } } - } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java --- 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 ""; diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLCheckVariableEqualityInstrument.java --- /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(); + } + } + + } +} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestNodeProber.java --- /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 diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java --- /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 { + + 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 testCases; + + public SLInstrumentTestRunner(Class testClass) throws InitializationError { + super(testClass); + try { + testCases = createTests(testClass); + } catch (IOException e) { + throw new InitializationError(e); + } + } + + @Override + protected List 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 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 testCases = new ArrayList<>(); + + // Scaffolding in place for future automation + Files.walkFileTree(rootPath, new SimpleFileVisitor() { + @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 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; + } + } +} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestSuite.java --- /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(); + +} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLPrintAssigmentValueInstrument.java --- /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); + } +} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLSimpleInstrumentTestSuite.java --- /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() { + } +} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.sl.test/tests/error/TypeError02.output --- 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" diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.sl.test/tests/error/TypeError04.output --- 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 diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.output --- /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 diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.sl --- /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); +} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_varCompare.output --- /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 diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_varCompare.sl --- /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); +} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java --- 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; } /** diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java --- 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; } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLParenExpressionNode.java --- /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); + } +} diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java --- 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 body = new ArrayList<>(); + List 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 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; } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java --- 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 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 bodyNodes, int lBracePos, int length) { + public SLStatementNode finishBlock(List bodyNodes, int startPos, int length) { lexicalScope = lexicalScope.outer; List 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 bodyNodes, List 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: + *
      + *
    • An un-instrumented SLBreakNode if there is no prober
    • + *
    • An {@link SLStatementWrapper} instrumenting this node.
    • + *
    + */ + 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: + *
      + *
    • An un-instrumented SLContinueNode if there is no prober
    • + *
    • An {@link SLStatementWrapper} instrumenting this node.
    • + *
    + */ + 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: + *
      + *
    • An un-instrumented SLWhileNode if there is no prober
    • + *
    • An {@link SLStatementWrapper} instrumenting this node.
    • + *
    + */ + 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: + *
      + *
    • An un-instrumented SLIfNode if there is no prober
    • + *
    • An {@link SLStatementWrapper} instrumenting this node.
    • + *
    + */ + 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: + *
      + *
    • An un-instrumented SLReturnNode if there is no prober
    • + *
    • An {@link SLStatementWrapper} instrumenting this node.
    • + *
    + */ 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. + *
    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: + *
      + *
    • An un-instrumented SLInvokeNode if there is no prober
    • + *
    • An {@link SLExpressionWrapper} instrumenting this node.
    • + *
    + */ public SLExpressionNode createCall(Token nameToken, List 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: + *
      + *
    • An un-instrumented SLWriteLocalVariableNode if there is no prober
    • + *
    • An {@link SLExpressionWrapper} instrumenting this node.
    • + *
    + */ 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.
    There is currently no instrumentation for this node. + * + * @param nameToken The name of the variable/function being read + * @return either: + *
      + *
    • A SLReadLocalVariableNode representing the local variable being read.
    • + *
    • A SLFunctionLiteralNode representing the function definition
    • + *
    + */ 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()); + } + } diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg --- 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 = (. factory.startBlock(); List body = new ArrayList<>(); .) -"{" (. int lBracePos = t.charPos; .) +"{" (. int start = t.charPos; .) { Statement (. 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 = -"while" -"(" (. Token whileToken = t; .) +"while" (. Token whileToken = t; .) +"(" Expression ")" Block (. result = factory.createWhile(whileToken, condition, body); .) @@ -125,8 +126,8 @@ IfStatement = -"if" -"(" (. Token ifToken = t; .) +"if" (. Token ifToken = t; .) +"(" Expression ")" Block (. SLStatementNode elsePart = null; .) @@ -225,7 +226,10 @@ | numericLiteral (. result = factory.createNumericLiteral(t); .) | - "(" Expression ")" + "(" (. int start = t.charPos; .) + Expression (. SLExpressionNode expr = result; .) + ")" (. int length = (t.charPos + t.val.length()) - start; .) + (. result = factory.createParenExpression(expr, start, length); .) ) . diff -r bda327903f96 -r ef3c7944261b graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java --- 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.
    + * 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; } } diff -r bda327903f96 -r ef3c7944261b mx/mx_graal.py --- 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) diff -r bda327903f96 -r ef3c7944261b mx/projects --- 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 diff -r bda327903f96 -r ef3c7944261b mxtool/mx.py --- 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} diff -r bda327903f96 -r ef3c7944261b src/cpu/sparc/vm/graalCodeInstaller_sparc.cpp --- 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) { diff -r bda327903f96 -r ef3c7944261b src/cpu/sparc/vm/sharedRuntime_sparc.cpp --- 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); diff -r bda327903f96 -r ef3c7944261b src/gpu/hsail/vm/gpu_hsail_Tlab.hpp --- 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 diff -r bda327903f96 -r ef3c7944261b src/os/bsd/vm/os_bsd.cpp --- 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); diff -r bda327903f96 -r ef3c7944261b src/os/linux/vm/os_linux.cpp --- 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()) { diff -r bda327903f96 -r ef3c7944261b src/os/solaris/vm/os_solaris.cpp --- 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. diff -r bda327903f96 -r ef3c7944261b src/os/windows/vm/os_windows.cpp --- 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(); } diff -r bda327903f96 -r ef3c7944261b src/share/vm/code/nmethod.hpp --- 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); } diff -r bda327903f96 -r ef3c7944261b src/share/vm/compiler/compileBroker.cpp --- 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 diff -r bda327903f96 -r ef3c7944261b src/share/vm/compiler/disassembler.cpp --- 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*)); diff -r bda327903f96 -r ef3c7944261b src/share/vm/graal/graalCodeInstaller.cpp --- 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 diff -r bda327903f96 -r ef3c7944261b src/share/vm/graal/graalGlobals.hpp --- 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, \ diff -r bda327903f96 -r ef3c7944261b src/share/vm/graal/graalJavaAccess.hpp --- 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) \ diff -r bda327903f96 -r ef3c7944261b src/share/vm/graal/graalRuntime.cpp --- 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); } diff -r bda327903f96 -r ef3c7944261b src/share/vm/graal/graalRuntime.hpp --- 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); diff -r bda327903f96 -r ef3c7944261b src/share/vm/memory/threadLocalAllocBuffer.hpp --- 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 { friend class VMStructs; +#ifdef GRAAL + friend class HSAILAllocationInfo; +#endif private: HeapWord* _start; // address of TLAB HeapWord* _top; // address after last allocation diff -r bda327903f96 -r ef3c7944261b src/share/vm/prims/nativeLookup.cpp --- 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 }; diff -r bda327903f96 -r ef3c7944261b src/share/vm/runtime/arguments.cpp --- 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 diff -r bda327903f96 -r ef3c7944261b src/share/vm/runtime/os.cpp --- 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); diff -r bda327903f96 -r ef3c7944261b src/share/vm/runtime/os.hpp --- 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); diff -r bda327903f96 -r ef3c7944261b src/share/vm/runtime/sharedRuntime.cpp --- 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. diff -r bda327903f96 -r ef3c7944261b src/share/vm/utilities/vmError.cpp --- 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