# HG changeset patch # User Stefan Anzinger # Date 1409026559 25200 # Node ID f8e60d11c0ec5e1f699438f49cc42cd7803b5ae9 # Parent ae0f235469dba9a5b410323194526cf66e2a1286# Parent 87a40fe1ba0c4f23b6e59ee98dca0c22470a4c0c Merge diff -r ae0f235469db -r f8e60d11c0ec .hgignore --- a/.hgignore Mon Aug 25 14:42:42 2014 -0700 +++ b/.hgignore Mon Aug 25 21:15:59 2014 -0700 @@ -71,13 +71,13 @@ .idea/ ^cscope.out ^tags -graal.src.zip* -graal-loader.src.zip* syntax: glob *.bgv core.* *.jar *.jar.* +*.zip +*.zip.* eclipse-build.xml rebuild-launch.out coverage diff -r ae0f235469db -r f8e60d11c0ec .hgtags --- a/.hgtags Mon Aug 25 14:42:42 2014 -0700 +++ b/.hgtags Mon Aug 25 21:15:59 2014 -0700 @@ -406,3 +406,4 @@ b124e22eb772806c13d942cc110de38da0108147 graal-0.1 483d05bf77a7c2a762aca1e06c4191bc06647176 graal-0.2 9535eccd2a115f6c6f0b15efb508b11ff74cc0d3 graal-0.3 +7d4f630172a16e983212d46c0f1ad6cdb826dfce graal-0.4 diff -r ae0f235469db -r f8e60d11c0ec CHANGELOG.md --- a/CHANGELOG.md Mon Aug 25 14:42:42 2014 -0700 +++ b/CHANGELOG.md Mon Aug 25 21:15:59 2014 -0700 @@ -2,26 +2,35 @@ ## `tip` ### Graal +* ... + +### Truffle +* ... + +## Version 0.4 +19-Aug-2014, [Repository Revision](http://hg.openjdk.java.net/graal/graal/rev/graal-0.4) +### Graal * Made initialization of Graal runtime lazy in hosted mode. -* Added supported for new 'jrelibrary' dependency type in mx/projects. -* Java projects with compliance level higher than the JDKs specified by JAVA_HOME and EXTRA_JAVA_HOMES are ignored once mx/projects has been processed. -* ResolvedJavaType.resolveMethod now takes a context type used to perform access checks. It now works correctly regarding default methods. -* Removed Java based compilation queue (CompilationQueue.java). -* Enabled use of separate class loader (via -XX:+UseGraalClassLoader) for classes loaded from graal.jar to hide them from application classes. +* Added supported for new `jrelibrary` dependency type in `mx/projects`. +* Java projects with compliance level higher than the JDKs specified by `JAVA_HOME` and `EXTRA_JAVA_HOMES` are ignored once `mx/projects` has been processed. +* `ResolvedJavaType.resolveMethod` now takes a context type used to perform access checks. It now works correctly regarding default methods. +* Removed Java based compilation queue (`CompilationQueue.java`). +* Enabled use of separate class loader (via `-XX:+UseGraalClassLoader`) for classes loaded from `graal.jar` to hide them from application classes. ### Truffle * Change API for stack walking to a visitor: `TruffleRuntime#iterateFrames` replaces `TruffleRuntime#getStackTrace` -* New flag -G:+TraceTruffleCompilationCallTree to print the tree of inlined calls before compilation. +* New flag `-G:+TraceTruffleCompilationCallTree` to print the tree of inlined calls before compilation. * `truffle.jar`: strip out build-time only dependency into a seperated JAR file (`truffle-dsl-processor.jar`) -* New flag -G:+TraceTruffleCompilationAST to print the AST before compilation. -* New experimental TypedObject interface added. -* Renamed flag -G:+TruffleSplittingEnabled to -G:+TruffleSplitting -* New flag -G:+TruffleSplittingNew to enable the experimental splitting mode based on function arguments. -* New flag -G:+TruffleSplittingTypedInstanceStamps to enable splitting for TypedObject instances. -* New flag -G:+TruffleSplittingClassInstanceStamps to enable splitting for Java object instances except TypedObject. -* New flag -G:TruffleSplittingStartCallCount=3 which sets the number of minimal calls until splitting is performed. -* New flag -G:-TruffleSplittingAggressive if enabled splits every function call. -* ... +* New flag `-G:+TraceTruffleCompilationAST` to print the AST before compilation. +* New experimental `TypedObject` interface added. +* Renamed flag `-G:+TruffleSplittingEnabled` to `-G:+TruffleSplitting` +* New flag `-G:+TruffleSplittingNew` to enable the experimental splitting mode based on function arguments. +* New flag `-G:+TruffleSplittingTypedInstanceStamps` to enable splitting for `TypedObject` instances. +* New flag `-G:+TruffleSplittingClassInstanceStamps` to enable splitting for Java object instances except `TypedObject`. +* New flag `-G:TruffleSplittingStartCallCount=3` which sets the number of minimal calls until splitting is performed. +* New flag `-G:-TruffleSplittingAggressive` if enabled splits every function call. +* Added `isVisited` method for `BranchProfile`. +* Added new `ConditionProfile`, `BinaryConditionProfile` and `CountingConditionProfile` utility classes to profile if conditions. ## Version 0.3 9-May-2014, [Repository Revision](http://hg.openjdk.java.net/graal/graal/rev/graal-0.3) diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java Mon Aug 25 21:15:59 2014 -0700 @@ -161,6 +161,9 @@ * because of Word type rewriting and alternative backends that can't be done. */ public boolean validateFormat() { + if (caller() != null) { + caller().validateFormat(); + } for (int i = 0; i < numLocals + numStack; i++) { if (values[i] != null) { Kind kind = values[i].getKind(); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.api.code; - -/** - * A handle that can be used to {@linkplain #call(Object[]) call} a native function. - */ -public interface NativeFunctionHandle { - - /** - * Calls the native function. - *

- * 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 ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.api.code; - -/** - * Interface to get a {@linkplain NativeFunctionHandle handle} or {@linkplain NativeFunctionPointer - * pointer} to a native function or a {@linkplain NativeLibraryHandle handle} to an open native - * library. - */ -public interface NativeFunctionInterface { - - /** - * Resolves and returns a handle to an open native library. This method will open the library - * only if it is not already open. - * - * @param libPath the absolute path to the library - * @return the resolved library handle - * @throws UnsatisfiedLinkError if the library could not be found or opened - */ - NativeLibraryHandle getLibraryHandle(String libPath); - - /** - * Determines if the underlying platform/runtime supports the notion of a default library search - * path. For example, on *nix systems, this is typically defined by the {@code LD_LIBRARY_PATH} - * environment variable. - */ - boolean isDefaultLibrarySearchSupported(); - - /** - * Resolves the function pointer {@code NativeFunctionPointer} of a native function. - * - * @param libraries the ordered list of libraries to search for the function - * @param name the name of the function to be resolved - * @return a pointer to the native function - * @throws UnsatisfiedLinkError if the function could not be resolved - */ - NativeFunctionPointer getFunctionPointer(NativeLibraryHandle[] libraries, String name); - - /** - * Resolves a function name to a {@linkplain NativeFunctionHandle handle} that can be called - * with a given signature. The signature contains the types of the arguments that will be passed - * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}. - * - * @param library the handle to a resolved library - * @param name the name of the function to be resolved - * @param returnType the type of the return value - * @param argumentTypes the types of the arguments - * @return the function handle of the native function - * @throws UnsatisfiedLinkError if the function handle could not be resolved - */ - NativeFunctionHandle getFunctionHandle(NativeLibraryHandle library, String name, Class returnType, Class... argumentTypes); - - /** - * Resolves a function pointer to a {@linkplain NativeFunctionHandle handle} that can be called - * with a given signature. The signature contains the types of the arguments that will be passed - * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}. - * - * @param functionPointer a function pointer - * @param returnType the type of the return value - * @param argumentTypes the types of the arguments - * @return the function handle of the native function - * @throws UnsatisfiedLinkError the function handle could not be created - */ - NativeFunctionHandle getFunctionHandle(NativeFunctionPointer functionPointer, Class returnType, Class... argumentTypes); - - /** - * Resolves a function name to a {@linkplain NativeFunctionHandle handle} that can be called - * with a given signature. The signature contains the types of the arguments that will be passed - * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}. - * - * @param libraries the ordered list of libraries to search for the function - * @param name the name of the function to be resolved - * @param returnType the type of the return value - * @param argumentTypes the types of the arguments - * @return the function handle of the native function - * @throws UnsatisfiedLinkError if the function handle could not be created - */ - NativeFunctionHandle getFunctionHandle(NativeLibraryHandle[] libraries, String name, Class returnType, Class... argumentTypes); - - /** - * Resolves a function name to a {@linkplain NativeFunctionHandle handle} that can be called - * with a given signature. The signature contains the types of the arguments that will be passed - * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}. - * - * @param name the name of the function to be resolved - * @param returnType the type of the return value - * @param argumentTypes the types of the arguments - * @return the function handle of the native function - * @throws UnsatisfiedLinkError if default library searching is not - * {@linkplain #isDefaultLibrarySearchSupported() supported} or if the function - * could not be resolved - */ - NativeFunctionHandle getFunctionHandle(String name, Class returnType, Class... argumentTypes); - - /** - * Creates a {@link NativeFunctionPointer} from a raw value. - * - * @param rawValue raw function pointer - * @return {@code NativeFunctionPointer} for {@code rawValue} - */ - NativeFunctionPointer getNativeFunctionPointerFromRawValue(long rawValue); -} diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.api.code; - -/** - * An opaque representation of a native function pointer. - *

- * 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 ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.api.code; - -/** - * An opaque representation of a native library handle. A handle is obtained via - * {@link NativeFunctionInterface#getLibraryHandle(String)}. A handle is used to resolve a string to - * a {@linkplain NativeFunctionInterface#getFunctionHandle(String, Class, Class...) handle} or - * {@linkplain NativeFunctionInterface#getFunctionPointer(NativeLibraryHandle[], String) pointer}. - */ -public interface NativeLibraryHandle { - /** - * Gets a name for this library. This may be the path for the file from which the library was - * loaded. - */ - String getName(); -} diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaType.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,11 +24,6 @@ import static org.junit.Assert.*; -import java.io.*; -import java.net.*; -import java.util.*; -import java.util.stream.*; - import org.junit.*; import com.oracle.graal.api.meta.*; @@ -50,91 +45,4 @@ assertEquals(expected, actual); } } - - static class A { - A or(A other) { - return other; - } - } - - @Test - public void testResolve() throws ClassNotFoundException { - String classPath = System.getProperty("java.class.path"); - String[] parts = classPath.split(File.pathSeparator); - URL[] urls = Arrays.asList(parts).stream().map(e -> asURL(e)).collect(Collectors.toList()).toArray(new URL[parts.length]); - URLClassLoader clOne = newClassLoader(urls); - URLClassLoader clTwo = newClassLoader(urls); - - String className = getClass().getName() + "$A"; - Class aClassOne = Class.forName(className, true, clOne); - Class aClassTwo = Class.forName(getClass().getName() + "$A", true, clTwo); - - assertNotEquals(aClassOne, aClassTwo); - assertNotEquals(aClassOne.getClassLoader(), aClassTwo.getClassLoader()); - - ResolvedJavaType aTypeOne = metaAccess.lookupJavaType(aClassOne); - ResolvedJavaType aTypeTwo = metaAccess.lookupJavaType(aClassTwo); - - assertNotEquals(aTypeOne, aTypeTwo); - - checkResolveWithoutAccessingClass(aTypeOne); - checkResolveWithoutAccessingClass(aTypeTwo); - - assertEquals(aTypeOne.resolve(aTypeOne), aTypeOne); - assertNotEquals(aTypeOne.resolve(aTypeTwo), aTypeOne); - assertEquals(aTypeOne.resolve(aTypeTwo), aTypeTwo); - - assertEquals(aTypeTwo.resolve(aTypeTwo), aTypeTwo); - assertNotEquals(aTypeTwo.resolve(aTypeOne), aTypeTwo); - assertEquals(aTypeTwo.resolve(aTypeOne), aTypeOne); - - ResolvedJavaMethod m = ResolvedJavaTypeResolveMethodTest.getMethod(aTypeOne, "or"); - JavaType resolvedTypeOne = m.getSignature().getParameterType(0, aTypeOne); - JavaType resolvedTypeTwo = m.getSignature().getReturnType(aTypeOne); - JavaType unresolvedTypeOne = m.getSignature().getParameterType(0, null); - JavaType unresolvedTypeTwo = m.getSignature().getReturnType(null); - - assertTrue(resolvedTypeOne instanceof ResolvedJavaType); - assertTrue(resolvedTypeTwo instanceof ResolvedJavaType); - assertFalse(unresolvedTypeOne instanceof ResolvedJavaType); - assertFalse(unresolvedTypeTwo instanceof ResolvedJavaType); - - assertEquals(resolvedTypeOne.resolve(aTypeOne), aTypeOne); - assertEquals(resolvedTypeOne.resolve(aTypeTwo), aTypeTwo); - assertEquals(resolvedTypeTwo.resolve(aTypeOne), aTypeOne); - assertEquals(resolvedTypeTwo.resolve(aTypeTwo), aTypeTwo); - - checkResolveWithoutAccessingClass(unresolvedTypeOne); - checkResolveWithoutAccessingClass(unresolvedTypeTwo); - - assertEquals(unresolvedTypeOne.resolve(aTypeOne), aTypeOne); - assertEquals(unresolvedTypeOne.resolve(aTypeTwo), aTypeTwo); - } - - private static void checkResolveWithoutAccessingClass(JavaType type) { - try { - type.resolve(null); - fail(); - } catch (NullPointerException e) { - } - } - - private static URLClassLoader newClassLoader(URL[] urls) { - URLClassLoader cl = new URLClassLoader(urls) { - @Override - protected java.lang.Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - boolean callSuper = name.startsWith("java/") || name.startsWith("java."); - return callSuper ? super.loadClass(name, resolve) : super.findClass(name); - } - }; - return cl; - } - - private static URL asURL(String e) { - try { - return new File(e).toURI().toURL(); - } catch (MalformedURLException e1) { - throw new RuntimeException(e1); - } - } } diff -r ae0f235469db -r f8e60d11c0ec 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 25 21:15:59 2014 -0700 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.api.meta; + +import java.lang.annotation.*; + +/** + * This annotation denotes methods which are allowed to use identity checks (==/!=) on restricted + * types. + * + * @see CheckGraalInvariants + */ +@SuppressWarnings("javadoc") +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface ExcludeFromIdentityComparisonVerification { + +} diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,7 +23,6 @@ package com.oracle.graal.api.meta; import java.io.*; -import java.lang.annotation.*; import java.util.*; /** @@ -289,34 +288,28 @@ base = base.substring(base.length() - 2); } - if (className.equals("boolean")) { - return prefix + "Z"; - } - if (className.equals("byte")) { - return prefix + "B"; - } - if (className.equals("short")) { - return prefix + "S"; - } - if (className.equals("char")) { - return prefix + "C"; + switch (className) { + case "boolean": + return prefix + "Z"; + case "byte": + return prefix + "B"; + case "short": + return prefix + "S"; + case "char": + return prefix + "C"; + case "int": + return prefix + "I"; + case "float": + return prefix + "F"; + case "long": + return prefix + "J"; + case "double": + return prefix + "D"; + case "void": + return prefix + "V"; + default: + return prefix + "L" + className.replace('.', '/') + ";"; } - if (className.equals("int")) { - return prefix + "I"; - } - if (className.equals("float")) { - return prefix + "F"; - } - if (className.equals("long")) { - return prefix + "J"; - } - if (className.equals("double")) { - return prefix + "D"; - } - if (className.equals("void")) { - return prefix + "V"; - } - return prefix + "L" + className.replace('.', '/') + ";"; } /** @@ -333,78 +326,4 @@ } return indentation + lines.replace(newLine, newLine + indentation); } - - // The methods below here will be soon removed. They exist to simplify updating - // clients of the old API to switch to using the default methods that replace - // these utility methods. In Eclipse will show calls to these methods as warnings. - - @Deprecated - public static boolean isJavaLangObject(ResolvedJavaType type) { - return type.isJavaLangObject(); - } - - @Deprecated - public static ResolvedJavaType[] lookupJavaTypes(MetaAccessProvider metaAccess, Class[] classes) { - return metaAccess.lookupJavaTypes(classes); - } - - @Deprecated - public static ResolvedJavaType getElementalType(ResolvedJavaType type) { - return type.getElementalType(); - } - - @Deprecated - public static String toJavaName(JavaType type, boolean qualified) { - return type.toJavaName(qualified); - } - - @Deprecated - public static String toJavaName(JavaType type) { - return type.toJavaName(); - } - - @Deprecated - public static String toClassName(JavaType type) { - return type.toClassName(); - } - - @Deprecated - public static String format(String format, JavaMethod method) throws IllegalFormatException { - return method.format(format); - } - - @Deprecated - public static String format(String format, JavaField field) throws IllegalFormatException { - return field.format(format); - } - - @Deprecated - public static T[] 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 ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java Mon Aug 25 21:15:59 2014 -0700 @@ -96,4 +96,15 @@ } return false; } + + /** + * Checks if this value is identical to {@code other}. + * + * Warning: Use with caution! Usually equivalence {@link #equals(Object)} is sufficient and + * should be used. + */ + @ExcludeFromIdentityComparisonVerification + public final boolean identityEquals(Value other) { + return this == other; + } } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/Services.java Mon Aug 25 21:15:59 2014 -0700 @@ -56,7 +56,7 @@ // Fall back to standard SerivceLoader } } - return ServiceLoader.loadInstalled(service); + return ServiceLoader.load(service, Services.class.getClassLoader()); } private static native S[] getServiceImpls(Class service); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java Mon Aug 25 21:15:59 2014 -0700 @@ -88,12 +88,30 @@ */ public abstract void mov(Register a, Constant src); + private static String getBitTypeFromKind(Kind kind) { + switch (kind) { + case Boolean: + case Byte: + case Short: + case Char: + case Int: + case Float: + return "b32"; + case Long: + case Double: + case Object: + return "b64"; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + public final void emitMov(Kind kind, Value dst, Value src) { if (isRegister(dst) && isConstant(src) && kind.getStackKind() == Kind.Object) { mov(asRegister(dst), asConstant(src)); } else { - String argtype = getArgTypeFromKind(kind).substring(1); - emitString("mov_b" + argtype + " " + mapRegOrConstToString(dst) + ", " + mapRegOrConstToString(src) + ";"); + String argtype = getBitTypeFromKind(kind); + emitString("mov_" + argtype + " " + mapRegOrConstToString(dst) + ", " + mapRegOrConstToString(src) + ";"); } } @@ -324,7 +342,11 @@ } public static String mapAddress(HSAILAddress addr) { - return "[$d" + addr.getBase().encoding() + " + " + addr.getDisplacement() + "]"; + if (addr.getBase().encoding() < 0) { + return "[0x" + Long.toHexString(addr.getDisplacement()) + "]"; + } else { + return "[$d" + addr.getBase().encoding() + " + " + addr.getDisplacement() + "]"; + } } private static String doubleToString(double dval) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java --- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java Mon Aug 25 21:15:59 2014 -0700 @@ -400,20 +400,7 @@ return; } - double probability = profilingInfo.getBranchTakenProbability(bci()); - if (probability < 0) { - assert probability == -1 : "invalid probability"; - Debug.log("missing probability in %s at bci %d", method, bci()); - probability = 0.5; - } - - if (!optimisticOpts.removeNeverExecutedCode()) { - if (probability == 0) { - probability = 0.0000001; - } else if (probability == 1) { - probability = 0.999999; - } - } + double probability = branchProbability(); LabelRef trueDestination = getSuccessor(0); LabelRef falseDestination = getSuccessor(1); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java Mon Aug 25 21:15:59 2014 -0700 @@ -275,63 +275,63 @@ protected AMD64Arithmetic getOp(ValueNode operation, Access access) { Kind memoryKind = getMemoryKind(access); - if (operation.getClass() == IntegerAddNode.class) { + if (operation.getClass() == IntegerAddNode.getGenClass()) { switch (memoryKind) { case Int: return IADD; case Long: return LADD; } - } else if (operation.getClass() == FloatAddNode.class) { + } else if (operation.getClass() == FloatAddNode.getGenClass()) { switch (memoryKind) { case Float: return FADD; case Double: return DADD; } - } else if (operation.getClass() == AndNode.class) { + } else if (operation.getClass() == AndNode.getGenClass()) { switch (memoryKind) { case Int: return IAND; case Long: return LAND; } - } else if (operation.getClass() == OrNode.class) { + } else if (operation.getClass() == OrNode.getGenClass()) { switch (memoryKind) { case Int: return IOR; case Long: return LOR; } - } else if (operation.getClass() == XorNode.class) { + } else if (operation.getClass() == XorNode.getGenClass()) { switch (memoryKind) { case Int: return IXOR; case Long: return LXOR; } - } else if (operation.getClass() == IntegerSubNode.class) { + } else if (operation.getClass() == IntegerSubNode.getGenClass()) { switch (memoryKind) { case Int: return ISUB; case Long: return LSUB; } - } else if (operation.getClass() == FloatSubNode.class) { + } else if (operation.getClass() == FloatSubNode.getGenClass()) { switch (memoryKind) { case Float: return FSUB; case Double: return DSUB; } - } else if (operation.getClass() == IntegerMulNode.class) { + } else if (operation.getClass() == IntegerMulNode.getGenClass()) { switch (memoryKind) { case Int: return IMUL; case Long: return LMUL; } - } else if (operation.getClass() == FloatMulNode.class) { + } else if (operation.getClass() == FloatMulNode.getGenClass()) { switch (memoryKind) { case Float: return FMUL; diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java Mon Aug 25 21:15:59 2014 -0700 @@ -131,6 +131,13 @@ } /** + * Determines if we are running CQE tests (via a -D flag) + */ + public boolean runningCQETests() { + return Boolean.getBoolean("com.amd.CQE"); + } + + /** * Determines if the JVM supports the required typeProfileWidth. */ public boolean typeProfileWidthAtLeast(int val) { diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleCosTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -38,6 +38,12 @@ }); } + // internally allocates a Rempiostruct, escape analysis not catching it + @Override + protected boolean supportsRequiredCapabilities() { + return (canHandleObjectAllocation()); + } + @Test public void testUsingLambdaMethod() { testGeneratedHsailUsingLambdaMethod(); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleNextAfterTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -39,6 +39,11 @@ }); } + @Override + protected boolean supportsRequiredCapabilities() { + return (runningOnSimulator() || runningCQETests()); + } + @Test public void testUsingLambdaMethod() { testGeneratedHsailUsingLambdaMethod(); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleNextUpTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -38,6 +38,11 @@ }); } + @Override + protected boolean supportsRequiredCapabilities() { + return (runningOnSimulator() || runningCQETests()); + } + @Test public void testUsingLambdaMethod() { testGeneratedHsailUsingLambdaMethod(); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleSinTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -38,6 +38,12 @@ }); } + // internally allocates a Rempiostruct, escape analysis not catching it + @Override + protected boolean supportsRequiredCapabilities() { + return (canHandleObjectAllocation()); + } + @Test public void testUsingLambdaMethod() { testGeneratedHsailUsingLambdaMethod(); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleTanTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -38,6 +38,12 @@ }); } + // internally allocates a Rempiostruct, escape analysis not catching it + @Override + protected boolean supportsRequiredCapabilities() { + return (canHandleObjectAllocation()); + } + @Test public void testUsingLambdaMethod() { testGeneratedHsailUsingLambdaMethod(); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatCosTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -38,6 +38,12 @@ }); } + // internally allocates a Rempiostruct, escape analysis not catching it + @Override + protected boolean supportsRequiredCapabilities() { + return (canHandleObjectAllocation()); + } + @Test public void testUsingLambdaMethod() { testGeneratedHsailUsingLambdaMethod(); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatNextAfterTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -39,6 +39,11 @@ }); } + @Override + protected boolean supportsRequiredCapabilities() { + return (runningOnSimulator() || runningCQETests()); + } + @Test public void testUsingLambdaMethod() { testGeneratedHsailUsingLambdaMethod(); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatNextUpTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -38,6 +38,11 @@ }); } + @Override + protected boolean supportsRequiredCapabilities() { + return (runningOnSimulator() || runningCQETests()); + } + @Test public void testUsingLambdaMethod() { testGeneratedHsailUsingLambdaMethod(); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatSinTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -38,6 +38,12 @@ }); } + // internally allocates a Rempiostruct, escape analysis not catching it + @Override + protected boolean supportsRequiredCapabilities() { + return (canHandleObjectAllocation()); + } + @Test public void testUsingLambdaMethod() { testGeneratedHsailUsingLambdaMethod(); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatTanTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -38,6 +38,12 @@ }); } + // internally allocates a Rempiostruct, escape analysis not catching it + @Override + protected boolean supportsRequiredCapabilities() { + return (canHandleObjectAllocation()); + } + @Test public void testUsingLambdaMethod() { testGeneratedHsailUsingLambdaMethod(); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/MoreThanEightArgsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/MoreThanEightArgsTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; + +import org.junit.*; + +public class MoreThanEightArgsTest extends GraalKernelTester { + + int[] makeIntArray(int size) { + int[] out = new int[size]; + + for (int i = 0; i < size; i++) { + out[i] = 1; + } + return out; + } + + final int rows = 4096; + final int cols = 4096; + final int loops = 2; + + @Result int[] result; + + void innerTest(int[] res, int[] a, int[] b, int[] c, int[] d, int base, int stride) { + final int resCols = a.length; + final int resRows = res.length; + final int limit = resCols - stride; + + dispatchLambdaKernel(resRows, (row) -> { + res[row] = 0; + if (a != null) { + for (int col = base; col < limit; col += 4) { + int p0 = 0; + int p1 = 0; + int p2 = 0; + int p3 = 0; + p0 = a[col] + b[col] + c[col] + d[col] + stride; + p1 = a[col + 1] + b[col + 1] + c[col + 1] + d[col + 1]; + p2 = a[col + 2] + b[col + 2] + c[col + 2] + d[col + 2]; + p3 = a[col + 3] + b[col + 3] + c[col + 3] + d[col + 3]; + res[row] += p0 + p1 + p2 + p3; + } + } + }); + } + + @Override + public void runTest() { + int[] a; + int[] b; + int[] c; + int[] d; + + result = makeIntArray(rows); + a = makeIntArray(cols); + b = makeIntArray(cols); + c = makeIntArray(cols); + d = makeIntArray(cols); + for (int i = 0; i < loops; i++) { + innerTest(result, a, b, c, d, 0, 4); + } + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } +} diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringBuilderTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -47,7 +47,7 @@ @Override protected boolean supportsRequiredCapabilities() { - return (canHandleObjectAllocation()); + return (canHandleObjectAllocation() && (runningOnSimulator() || runningCQETests())); } @Test diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Mon Aug 25 21:15:59 2014 -0700 @@ -243,8 +243,6 @@ @Override public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability) { append(new BranchOp(ConditionFlag.CarrySet, overflow, noOverflow, Kind.Long)); - // append(new BranchOp(negated ? ConditionFlag.NoOverflow : ConditionFlag.Overflow, label)); -// throw GraalInternalError.unimplemented(); } @Override diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/AllocSpy.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/AllocSpy.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/AllocSpy.java Mon Aug 25 21:15:59 2014 -0700 @@ -51,7 +51,7 @@ * @see #BarSize * @see #NumberSize */ -final class AllocSpy implements AutoCloseable { +public final class AllocSpy implements AutoCloseable { static ThreadLocal current = new ThreadLocal<>(); @@ -70,6 +70,10 @@ } } + public static boolean isEnabled() { + return ENABLED; + } + static String prop(String sfx) { return AllocSpy.class.getSimpleName() + "." + sfx; } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -305,7 +305,7 @@ } private void processMethod(final String snippet) { - graph = parse(snippet); + graph = parseEager(snippet); Assumptions assumptions = new Assumptions(false); HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); @@ -317,7 +317,7 @@ } private void compareGraphs(final String snippet, final String referenceSnippet, final boolean loopPeeling, final boolean excludeVirtual) { - graph = parse(snippet); + graph = parseEager(snippet); Assumptions assumptions = new Assumptions(false); HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); @@ -334,7 +334,7 @@ new DeadCodeEliminationPhase().apply(graph); canonicalizer.apply(graph, context); - StructuredGraph referenceGraph = parse(referenceSnippet); + StructuredGraph referenceGraph = parseEager(referenceSnippet); new InliningPhase(new CanonicalizerPhase(true)).apply(referenceGraph, context); new DeadCodeEliminationPhase().apply(referenceGraph); new CanonicalizerPhase(true).apply(referenceGraph, context); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java Mon Aug 25 21:15:59 2014 -0700 @@ -38,7 +38,9 @@ import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.CompilerThreadFactory.DebugConfigAccess; import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; import com.oracle.graal.java.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.VerifyPhase.VerificationError; @@ -113,17 +115,28 @@ for (String className : classNames) { try { Class c = Class.forName(className, false, CheckGraalInvariants.class.getClassLoader()); + executor.execute(() -> { + try { + checkClass(c, metaAccess); + } catch (Throwable e) { + errors.add(String.format("Error while checking %s:%n%s", className, printStackTraceToString(e))); + } + }); + for (Method m : c.getDeclaredMethods()) { if (Modifier.isNative(m.getModifiers()) || Modifier.isAbstract(m.getModifiers())) { // ignore } else { String methodName = className + "." + m.getName(); + boolean verifyEquals = !m.isAnnotationPresent(ExcludeFromIdentityComparisonVerification.class); if (matches(filters, methodName)) { executor.execute(() -> { StructuredGraph graph = new StructuredGraph(metaAccess.lookupJavaMethod(m)); try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) { graphBuilderSuite.apply(graph, context); - checkGraph(context, graph); + // update phi stamps + graph.getNodes().filter(PhiNode.class).forEach(PhiNode::inferStamp); + checkGraph(context, graph, verifyEquals); } catch (VerificationError e) { errors.add(e.getMessage()); } catch (LinkageError e) { @@ -132,9 +145,7 @@ // Graal bail outs on certain patterns in Java bytecode (e.g., // unbalanced monitors introduced by jacoco). } catch (Throwable e) { - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); - errors.add(String.format("Error while checking %s:%n%s", methodName, sw)); + errors.add(String.format("Error while checking %s:%n%s", methodName, printStackTraceToString(e))); } }); } @@ -166,15 +177,41 @@ } /** + * @param metaAccess + */ + private static void checkClass(Class c, MetaAccessProvider metaAccess) { + if (Node.class.isAssignableFrom(c)) { + if (c.getAnnotation(GeneratedNode.class) == null) { + if (Modifier.isFinal(c.getModifiers())) { + throw new AssertionError(String.format("Node subclass %s must not be final", c.getName())); + } + if (c.getAnnotation(NodeInfo.class) == null) { + throw new AssertionError(String.format("Node subclass %s requires %s annotation", c.getName(), NodeClass.class.getSimpleName())); + } + if (!Modifier.isAbstract(c.getModifiers())) { + try { + Class.forName(c.getName().replace('$', '_') + "Gen"); + } catch (ClassNotFoundException e) { + throw new AssertionError(String.format("Missing generated Node class %s", c.getName() + "Gen")); + } + } + } + } + } + + /** * Checks the invariants for a single graph. */ - private static void checkGraph(HighTierContext context, StructuredGraph graph) { - new VerifyUsageWithEquals(Value.class).apply(graph, context); - new VerifyUsageWithEquals(Register.class).apply(graph, context); - new VerifyUsageWithEquals(JavaType.class).apply(graph, context); - new VerifyUsageWithEquals(JavaMethod.class).apply(graph, context); - new VerifyUsageWithEquals(JavaField.class).apply(graph, context); - new VerifyUsageWithEquals(LIRKind.class).apply(graph, context); + private static void checkGraph(HighTierContext context, StructuredGraph graph, boolean verifyEquals) { + if (verifyEquals) { + new VerifyNoNodeClassLiteralIdentityTests().apply(graph, context); + new VerifyUsageWithEquals(Value.class).apply(graph, context); + new VerifyUsageWithEquals(Register.class).apply(graph, context); + new VerifyUsageWithEquals(JavaType.class).apply(graph, context); + new VerifyUsageWithEquals(JavaMethod.class).apply(graph, context); + new VerifyUsageWithEquals(JavaField.class).apply(graph, context); + new VerifyUsageWithEquals(LIRKind.class).apply(graph, context); + } new VerifyDebugUsage().apply(graph, context); } @@ -189,4 +226,10 @@ } return false; } + + private static String printStackTraceToString(Throwable t) { + StringWriter sw = new StringWriter(); + t.printStackTrace(new PrintWriter(sw)); + return sw.toString(); + } } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -35,7 +35,7 @@ public class CompareCanonicalizerTest extends GraalCompilerTest { private StructuredGraph getCanonicalizedGraph(String name) { - StructuredGraph graph = parse(name); + StructuredGraph graph = parseEager(name); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); return graph; } @@ -48,9 +48,9 @@ @Test public void testCanonicalComparison() { - StructuredGraph referenceGraph = parse("referenceCanonicalComparison"); + StructuredGraph referenceGraph = parseEager("referenceCanonicalComparison"); for (int i = 1; i < 4; i++) { - StructuredGraph graph = parse("canonicalCompare" + i); + StructuredGraph graph = parseEager("canonicalCompare" + i); assertEquals(referenceGraph, graph); } Assumptions assumptions = new Assumptions(false); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -90,7 +90,7 @@ @Test public void testRedundantCompares() { - StructuredGraph graph = parse("testRedundantComparesSnippet"); + StructuredGraph graph = parseEager("testRedundantComparesSnippet"); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); PhaseContext context = new PhaseContext(getProviders(), null); @@ -113,7 +113,7 @@ @Test @Ignore public void testInstanceOfCheckCastLowered() { - StructuredGraph graph = parse("testInstanceOfCheckCastSnippet"); + StructuredGraph graph = parseEager("testInstanceOfCheckCastSnippet"); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); PhaseContext context = new PhaseContext(getProviders(), null); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -81,12 +81,12 @@ private void test(final String snippet) { try (Scope s = Debug.scope("DegeneratedLoopsTest", new DebugDumpScope(snippet))) { - StructuredGraph graph = parse(snippet); + StructuredGraph graph = parseEager(snippet); HighTierContext context = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); Debug.dump(graph, "Graph"); - StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); + StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET); Debug.dump(referenceGraph, "ReferenceGraph"); assertEquals(referenceGraph, graph); } catch (Throwable e) { diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -106,7 +106,7 @@ } private StructuredGraph compileSnippet(final String snippet, final int checkcasts, final int afterCanon) { - final StructuredGraph graph = parse(snippet); + final StructuredGraph graph = parseEager(snippet); try (Scope s = Debug.scope("NestedCheckCastsTest", graph)) { Debug.dump(graph, "After parsing: " + snippet); Assert.assertEquals(checkcasts, graph.getNodes().filter(CheckCastNode.class).count()); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -58,7 +58,7 @@ private void test(final String snippet) { try (Scope s = Debug.scope("FloatingReadTest", new DebugDumpScope(snippet))) { - StructuredGraph graph = parse(snippet); + StructuredGraph graph = parseEager(snippet); PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false)); new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new FloatingReadPhase().apply(graph); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,25 +22,21 @@ */ package com.oracle.graal.compiler.test; -import com.oracle.graal.debug.Debug; -import com.oracle.graal.debug.DebugConfig; -import com.oracle.graal.debug.DebugConfigScope; -import com.oracle.graal.debug.internal.DebugScope; -import com.oracle.graal.graph.Node; -import com.oracle.graal.nodes.calc.ObjectEqualsNode; -import com.oracle.graal.nodes.util.GraphUtil; -import com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase; +import java.util.*; import org.junit.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.internal.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.common.cfs.*; import com.oracle.graal.phases.tiers.*; -import java.util.Iterator; -import java.util.List; - /** * Tests whether {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase} actually * performs some graph rewritings that it's supposed to perform. @@ -376,7 +372,7 @@ } public StructuredGraph afterFlowSensitiveReduce(String snippet) { - StructuredGraph before = canonicalize(parse(snippet)); + StructuredGraph before = canonicalize(parseEager(snippet)); // visualize(before, snippet + "-before"); StructuredGraph result = flowSensitiveReduce(before); // visualize(result, snippet + "-after"); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSensitiveReductionTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,16 +26,15 @@ import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; import static org.junit.Assert.*; -import com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase; - import org.junit.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.common.cfs.*; import com.oracle.graal.phases.tiers.*; /** @@ -144,7 +143,7 @@ test("testNullnessSnippet", new Object(), null); test("testNullnessSnippet", new Object(), new Object()); - StructuredGraph graph = parse("testNullnessSnippet"); + StructuredGraph graph = parseEager("testNullnessSnippet"); PhaseContext context = new PhaseContext(getProviders(), null); new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); @@ -172,14 +171,14 @@ @Test public void testDisjunction() { - StructuredGraph graph = parse("testDisjunctionSnippet"); + StructuredGraph graph = parseEager("testDisjunctionSnippet"); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); IfNode ifNode = (IfNode) graph.start().next(); InstanceOfNode instanceOf = (InstanceOfNode) ifNode.condition(); - IsNullNode x = graph.unique(new IsNullNode(graph.getParameter(0))); + IsNullNode x = graph.unique(IsNullNode.create(graph.getParameter(0))); InstanceOfNode y = instanceOf; - ShortCircuitOrNode disjunction = graph.unique(new ShortCircuitOrNode(x, false, y, false, NOT_FREQUENT_PROBABILITY)); - LogicNegationNode negation = graph.unique(new LogicNegationNode(disjunction)); + ShortCircuitOrNode disjunction = graph.unique(ShortCircuitOrNode.create(x, false, y, false, NOT_FREQUENT_PROBABILITY)); + LogicNegationNode negation = graph.unique(LogicNegationNode.create(disjunction)); ifNode.setCondition(negation); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, new PhaseContext(getProviders(), null)); @@ -200,7 +199,7 @@ @Test public void testInvoke() { test("testInvokeSnippet", new Integer(16)); - StructuredGraph graph = parse("testInvokeSnippet"); + StructuredGraph graph = parseEager("testInvokeSnippet"); PhaseContext context = new PhaseContext(getProviders(), null); new CanonicalizerPhase(true).apply(graph, context); new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context); @@ -231,7 +230,7 @@ @Test public void testTypeMerging() { - StructuredGraph graph = parse("testTypeMergingSnippet"); + StructuredGraph graph = parseEager("testTypeMergingSnippet"); PhaseContext context = new PhaseContext(getProviders(), null); new CanonicalizerPhase(true).apply(graph, context); new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context); @@ -249,7 +248,7 @@ @Test public void testInstanceOfCheckCast() { - StructuredGraph graph = parse("testInstanceOfCheckCastSnippet"); + StructuredGraph graph = parseEager("testInstanceOfCheckCastSnippet"); PhaseContext context = new PhaseContext(getProviders(), null); new CanonicalizerPhase(true).apply(graph, context); new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context); @@ -274,7 +273,7 @@ public void testDuplicateNullChecks() { // This tests whether explicit null checks properly eliminate later null guards. Currently // it's failing. - StructuredGraph graph = parse("testDuplicateNullChecksSnippet"); + StructuredGraph graph = parseEager("testDuplicateNullChecksSnippet"); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); PhaseContext context = new PhaseContext(getProviders(), null); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -45,9 +45,9 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Node.Verbosity; import com.oracle.graal.java.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.spi.*; @@ -67,7 +67,7 @@ *

* 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 ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -180,7 +180,7 @@ } private void testCombinedIf(String snippet, int count) { - StructuredGraph graph = parse(snippet); + StructuredGraph graph = parseEager(snippet); PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false)); new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new FloatingReadPhase().apply(graph); @@ -193,7 +193,7 @@ } private void test(String snippet) { - StructuredGraph graph = parse(snippet); + StructuredGraph graph = parseEager(snippet); ParameterNode param = graph.getNodes(ParameterNode.class).iterator().next(); ConstantNode constant = ConstantNode.forInt(0, graph); for (Node n : param.usages().filter(isNotA(FrameState.class)).snapshot()) { @@ -205,7 +205,7 @@ fs.replaceFirstInput(param, null); param.safeDelete(); } - StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); + StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET); assertEquals(referenceGraph, graph); } } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -59,7 +59,7 @@ @Test public void callInfopoints() { final Method method = getMethod("testMethod"); - final StructuredGraph graph = parse(method); + final StructuredGraph graph = parseEager(method); CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false); final CompilationResult cr = compileGraph(graph, null, cc, graph.method(), getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, getProfilingInfo(graph), null, getSuites(), new CompilationResult(), CompilationResultBuilderFactory.Default); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IntegerEqualsCanonicalizerTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -112,7 +112,7 @@ } private StructuredGraph getCanonicalizedGraph(String snippet) { - StructuredGraph graph = parse(snippet); + StructuredGraph graph = parseEager(snippet); new CanonicalizerPhase(false).apply(graph, new PhaseContext(getProviders(), null)); for (FrameState state : graph.getNodes(FrameState.class).snapshot()) { state.replaceAtUsages(null); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -71,7 +71,7 @@ } private void test(String snippet) { - StructuredGraph graph = parse(snippet); + StructuredGraph graph = parseEager(snippet); Map 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 ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -89,7 +89,7 @@ private StructuredGraph getGraph(String snippet) { Method method = getMethod(snippet); - StructuredGraph graph = parse(method); + StructuredGraph graph = parseEager(method); Assumptions assumptions = new Assumptions(true); HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new CanonicalizerPhase(true).apply(graph, context); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -121,8 +121,8 @@ } private void test(String snippet, String referenceSnippet) { - final StructuredGraph graph = parse(snippet); - final StructuredGraph referenceGraph = parse(referenceSnippet); + final StructuredGraph graph = parseEager(snippet); + final StructuredGraph referenceGraph = parseEager(referenceSnippet); new LoopTransformLowPhase().apply(graph); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,6 +24,7 @@ import static com.oracle.graal.compiler.common.GraalOptions.*; import static org.junit.Assert.*; + import java.util.*; import org.junit.*; @@ -600,7 +601,7 @@ } private SchedulePhase getFinalSchedule(final String snippet, final TestMode mode, final MemoryScheduling memsched, final SchedulingStrategy schedulingStrategy) { - final StructuredGraph graph = parse(snippet); + final StructuredGraph graph = parseEager(snippet); try (Scope d = Debug.scope("FloatingReadTest", graph)) { try (OverrideScope s = OptionValue.override(OptScheduleOutOfLoops, schedulingStrategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS, OptImplicitNullChecks, false)) { Assumptions assumptions = new Assumptions(false); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MergeCanonicalizerTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -57,7 +57,7 @@ } private void testReturnCount(String snippet, int returnCount) { - StructuredGraph graph = parse(snippet); + StructuredGraph graph = parseEager(snippet); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); Debug.dump(graph, "Graph"); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,6 +23,7 @@ package com.oracle.graal.compiler.test; import static com.oracle.graal.graph.iterators.NodePredicates.*; + import java.util.*; import org.junit.*; @@ -83,7 +84,7 @@ } private StructuredGraph parseAndProcess(String snippet) { - StructuredGraph graph = parse(snippet); + StructuredGraph graph = parseEager(snippet); ParameterNode param = graph.getNodes(ParameterNode.class).first(); if (param != null) { ConstantNode constant = ConstantNode.forInt(0, graph); @@ -105,7 +106,7 @@ private void test(String snippet) { StructuredGraph graph = parseAndProcess(snippet); - StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); + StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET); assertEquals(referenceGraph, graph); } } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -145,7 +145,7 @@ } private void test(String snippet, int rootExits, int nestedExits, int innerExits) { - StructuredGraph graph = parse(snippet); + StructuredGraph graph = parseEager(snippet); Debug.dump(graph, "Graph"); ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PhiCreationTests.java Mon Aug 25 21:15:59 2014 -0700 @@ -40,7 +40,7 @@ @Test public void test1() { - StructuredGraph graph = parse("test1Snippet"); + StructuredGraph graph = parseEager("test1Snippet"); Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext()); } @@ -53,7 +53,7 @@ @Test public void test2() { - StructuredGraph graph = parse("test2Snippet"); + StructuredGraph graph = parseEager("test2Snippet"); Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext()); } @@ -66,7 +66,7 @@ @Test public void test3() { - StructuredGraph graph = parse("test3Snippet"); + StructuredGraph graph = parseEager("test3Snippet"); Debug.dump(graph, "Graph"); Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext()); } @@ -82,7 +82,7 @@ @Test public void test4() { - StructuredGraph graph = parse("test4Snippet"); + StructuredGraph graph = parseEager("test4Snippet"); Debug.dump(graph, "Graph"); Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext()); } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -91,7 +91,7 @@ } private StructuredGraph compileTestSnippet(final String snippet) { - StructuredGraph graph = parse(snippet); + StructuredGraph graph = parseEager(snippet); PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false)); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushThroughIfTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -57,7 +57,7 @@ } private void test(String snippet, String reference) { - StructuredGraph graph = parse(snippet); + StructuredGraph graph = parseEager(snippet); Debug.dump(graph, "Graph"); for (FrameState fs : graph.getNodes(FrameState.class).snapshot()) { fs.replaceAtUsages(null); @@ -66,7 +66,7 @@ new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); - StructuredGraph referenceGraph = parse(reference); + StructuredGraph referenceGraph = parseEager(reference); for (FrameState fs : referenceGraph.getNodes(FrameState.class).snapshot()) { fs.replaceAtUsages(null); GraphUtil.killWithUnusedFloatingInputs(fs); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -82,7 +82,7 @@ try (Scope s = Debug.scope("ReadAfterCheckCastTest", new DebugDumpScope(snippet))) { // check shape of graph, with lots of assumptions. will probably fail if graph // structure changes significantly - StructuredGraph graph = parse(snippet); + StructuredGraph graph = parseEager(snippet); PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false)); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -243,10 +243,10 @@ } private 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 ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,13 +22,13 @@ */ package com.oracle.graal.compiler.test; -import com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase; import org.junit.*; import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.common.cfs.*; import com.oracle.graal.phases.tiers.*; /** @@ -165,13 +165,13 @@ private void test(final String snippet, final String referenceSnippet) { // No debug scope to reduce console noise for @Test(expected = ...) tests - StructuredGraph graph = parse(snippet); + StructuredGraph graph = parseEager(snippet); Debug.dump(graph, "Graph"); Assumptions assumptions = new Assumptions(false); PhaseContext context = new PhaseContext(getProviders(), assumptions); new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); - StructuredGraph referenceGraph = parse(referenceSnippet); + StructuredGraph referenceGraph = parseEager(referenceSnippet); assertEquals(referenceGraph, graph); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,7 +22,7 @@ */ package com.oracle.graal.compiler.test; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import java.util.*; @@ -42,21 +42,21 @@ public void testImplies() { StructuredGraph graph = new StructuredGraph(); - AbstractEndNode trueEnd = graph.add(new EndNode()); - AbstractEndNode falseEnd = graph.add(new EndNode()); + AbstractEndNode trueEnd = graph.add(EndNode.create()); + AbstractEndNode falseEnd = graph.add(EndNode.create()); - BeginNode trueBegin = graph.add(new BeginNode()); + BeginNode trueBegin = graph.add(BeginNode.create()); trueBegin.setNext(trueEnd); - BeginNode falseBegin = graph.add(new BeginNode()); + BeginNode falseBegin = graph.add(BeginNode.create()); falseBegin.setNext(falseEnd); - IfNode ifNode = graph.add(new IfNode(null, trueBegin, falseBegin, 0.5)); + IfNode ifNode = graph.add(IfNode.create(null, trueBegin, falseBegin, 0.5)); graph.start().setNext(ifNode); - MergeNode merge = graph.add(new MergeNode()); + MergeNode merge = graph.add(MergeNode.create()); merge.addForwardEnd(trueEnd); merge.addForwardEnd(falseEnd); - ReturnNode returnNode = graph.add(new ReturnNode(null)); + ReturnNode returnNode = graph.add(ReturnNode.create(null)); merge.setNext(returnNode); dumpGraph(graph); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -109,7 +109,7 @@ } private void testZeroReturn(String methodName) { - StructuredGraph graph = parse(methodName); + StructuredGraph graph = parseEager(methodName); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); new DeadCodeEliminationPhase().apply(graph); assertConstantReturn(graph, 0); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -87,10 +87,10 @@ private void test(final String snippet) { // No debug scope to reduce console noise for @Test(expected = ...) tests - StructuredGraph graph = parse(snippet); + StructuredGraph graph = parseEager(snippet); Debug.dump(graph, "Graph"); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); - StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); + StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET); assertEquals(referenceGraph, graph); } } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,18 +24,17 @@ import java.io.*; -import com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase; - import org.junit.*; import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Node.Verbosity; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.common.cfs.*; import com.oracle.graal.phases.schedule.*; import com.oracle.graal.phases.tiers.*; @@ -196,7 +195,7 @@ } private void test(String snippet, String referenceSnippet) { - StructuredGraph graph = parse(snippet); + StructuredGraph graph = parseEager(snippet); Debug.dump(graph, "Graph"); Assumptions assumptions = new Assumptions(false); /* @@ -208,7 +207,7 @@ new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); // a second canonicalizer is needed to process nested MaterializeNodes new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); - StructuredGraph referenceGraph = parse(referenceSnippet); + StructuredGraph referenceGraph = parseEager(referenceSnippet); new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(getProviders(), assumptions)); assertEquals(referenceGraph, graph); } @@ -256,7 +255,7 @@ } private 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 ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -38,7 +38,6 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.LIRInstruction.ValueProcedure; import com.oracle.graal.lir.StandardOp.MoveOp; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; @@ -48,7 +47,7 @@ public class AllocatorTest extends GraalCompilerTest { protected void test(String snippet, final int expectedRegisters, final int expectedRegRegMoves, final int expectedSpillMoves) { - final StructuredGraph graph = parse(snippet); + final StructuredGraph graph = parseEager(snippet); try (Scope s = Debug.scope("AllocatorTest", graph, graph.method(), getCodeCache())) { final RegisterStats stats = getRegisterStats(graph); try (Scope s2 = Debug.scope("Assertions", stats.lir)) { diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -53,7 +53,7 @@ @Test public void test1() { Method method = getMethod("testMethod"); - final StructuredGraph graph = parse(method); + final StructuredGraph graph = parseEager(method); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); new DeadCodeEliminationPhase().apply(graph); @@ -76,7 +76,7 @@ @Test public void test3() { Method method = getMethod("testMethod"); - final StructuredGraph graph = parse(method); + final StructuredGraph graph = parseEager(method); final ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(method); InstalledCode compiledMethod = getCode(javaMethod, graph); try { @@ -90,7 +90,7 @@ @Test public void test4() { Method method = getMethod("testMethodVirtual"); - final StructuredGraph graph = parse(method); + final StructuredGraph graph = parseEager(method); final ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(method); InstalledCode compiledMethod = getCode(javaMethod, graph); try { diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/MonitorDeoptTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -136,7 +136,7 @@ public void run0() throws Throwable { Method method = getMethod("test"); - StructuredGraph graph = parse(method); + StructuredGraph graph = parseEager(method); removeLoopSafepoint(graph); ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(method); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -40,7 +40,7 @@ @Override protected void processMethod(final String snippet) { - graph = parse(snippet); + graph = parseEager(snippet); Assumptions assumptions = new Assumptions(false); HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -276,9 +276,8 @@ return obj2.x instanceof TestClassObject; } - @SuppressWarnings("unused") public static void testNewNodeSnippet() { - new ValueAnchorNode(null); + ValueAnchorNode.create(null); } /** diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -84,7 +84,7 @@ } private void processMethod(final String snippet) { - graph = parse(snippet); + graph = parseEager(snippet); HighTierContext context = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new IterativeInliningPhase(new CanonicalizerPhase(true)).apply(graph, context); } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,6 +23,7 @@ package com.oracle.graal.compiler.test.ea; import static org.junit.Assert.*; + import java.util.*; import org.junit.*; @@ -243,7 +244,7 @@ } protected void processMethod(final String snippet) { - graph = parse(snippet); + graph = parseEager(snippet); Assumptions assumptions = new Assumptions(false); HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PoorMansEATest.java Mon Aug 25 21:15:59 2014 -0700 @@ -59,7 +59,7 @@ private void test(final String snippet) { try (Scope s = Debug.scope("PoorMansEATest", new DebugDumpScope(snippet))) { - StructuredGraph graph = parse(snippet); + StructuredGraph graph = parseEager(snippet); Assumptions assumptions = new Assumptions(false); HighTierContext highTierContext = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,6 +23,7 @@ package com.oracle.graal.compiler.test.inlining; import static org.junit.Assert.*; + import java.lang.reflect.*; import org.junit.*; @@ -231,7 +232,7 @@ private StructuredGraph getGraph(final String snippet, final boolean eagerInfopointMode) { try (Scope s = Debug.scope("InliningTest", new DebugDumpScope(snippet))) { Method method = getMethod(snippet); - StructuredGraph graph = eagerInfopointMode ? parseDebug(method) : parse(method); + StructuredGraph graph = eagerInfopointMode ? parseDebug(method) : parseEager(method); PhaseSuite graphBuilderSuite = eagerInfopointMode ? getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault()) : getDefaultGraphBuilderSuite(); Assumptions assumptions = new Assumptions(true); HighTierContext context = new HighTierContext(getProviders(), assumptions, null, graphBuilderSuite, OptimisticOptimizations.ALL); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,401 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.compiler.test.nfi; - -import static com.oracle.graal.compiler.common.UnsafeAccess.*; -import static java.io.File.*; -import static java.lang.System.*; -import static org.junit.Assert.*; -import static org.junit.Assume.*; - -import java.io.*; -import java.util.*; - -import org.junit.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.compiler.target.*; -import com.oracle.graal.runtime.*; - -@Ignore -public class NativeFunctionInterfaceTest { - - public final NativeFunctionInterface nfi; - - public NativeFunctionInterfaceTest() { - RuntimeProvider runtimeProvider = Graal.getRequiredCapability(RuntimeProvider.class); - Assume.assumeTrue(runtimeProvider.getHostBackend() instanceof HostBackend); - nfi = ((HostBackend) runtimeProvider.getHostBackend()).getNativeFunctionInterface(); - } - - private List 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 ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/CompilerThread.java Mon Aug 25 21:15:59 2014 -0700 @@ -44,6 +44,7 @@ @Override public void run() { GraalDebugConfig debugConfig = debugConfigAccess.getDebugConfig(); + setContextClassLoader(getClass().getClassLoader()); try { super.run(); } finally { diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java Mon Aug 25 21:15:59 2014 -0700 @@ -29,8 +29,8 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Node.Verbosity; import com.oracle.graal.lir.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.options.*; @@ -38,17 +38,17 @@ public class GraalDebugConfig implements DebugConfig { // @formatter:off - @Option(help = "Pattern for scope(s) to in which dumping is enabled (see DebugFilter and Debug.dump)") + @Option(help = "Pattern for scope(s) in which dumping is enabled (see DebugFilter and Debug.dump)") public static final OptionValue 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); @@ -259,14 +259,14 @@ if (o instanceof Graph) { Debug.log("Context obj %s", o); if (DumpOnError.getValue()) { - Debug.dump(o, "Exception graph"); + Debug.dump(o, "Exception graph: " + e); } else { Debug.log("Use -G:+DumpOnError to enable dumping of graphs on this error"); } } else if (o instanceof LIR) { Debug.log("Context obj %s", o); if (DumpOnError.getValue()) { - Debug.dump(o, "LIR"); + Debug.dump(o, "Exception LIR: " + e); } else { Debug.log("Use -G:+DumpOnError to enable dumping of graphs on this error"); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Mon Aug 25 21:15:59 2014 -0700 @@ -42,11 +42,8 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.LIRInstruction.InstructionStateProcedure; -import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure; import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; -import com.oracle.graal.lir.LIRInstruction.ValueProcedure; import com.oracle.graal.lir.StandardOp.MoveOp; import com.oracle.graal.nodes.*; import com.oracle.graal.options.*; @@ -615,14 +612,13 @@ intervalsSize = operandSize(); intervals = new Interval[intervalsSize + (intervalsSize >> SPLIT_INTERVALS_CAPACITY_RIGHT_SHIFT)]; - ValueProcedure setVariableProc = new ValueProcedure() { + ValueConsumer setVariableConsumer = new ValueConsumer() { @Override - public Value doValue(Value value) { + public void visitValue(Value value) { if (isVariable(value)) { getOrCreateInterval(asVariable(value)); } - return value; } }; @@ -652,8 +648,8 @@ opIdToBlockMap[index] = block; assert instructionForId(opId) == op : "must match"; - op.forEachTemp(setVariableProc); - op.forEachOutput(setVariableProc); + op.visitEachTemp(setVariableConsumer); + op.visitEachOutput(setVariableConsumer); index++; opId += 2; // numbering of lirOps by two @@ -682,10 +678,10 @@ List instructions = ir.getLIRforBlock(block); int numInst = instructions.size(); - ValueProcedure useProc = new ValueProcedure() { + ValueConsumer useConsumer = new ValueConsumer() { @Override - protected Value doValue(Value operand) { + protected void visitValue(Value operand) { if (isVariable(operand)) { int operandNum = operandNumber(operand); if (!liveKill.get(operandNum)) { @@ -700,25 +696,23 @@ if (DetailedAsserts.getValue()) { verifyInput(block, liveKill, operand); } - return operand; } }; - ValueProcedure stateProc = new ValueProcedure() { + ValueConsumer stateConsumer = new ValueConsumer() { @Override - public Value doValue(Value operand) { + public void visitValue(Value operand) { int operandNum = operandNumber(operand); if (!liveKill.get(operandNum)) { liveGen.set(operandNum); Debug.log("liveGen in state for operand %d", operandNum); } - return operand; } }; - ValueProcedure defProc = new ValueProcedure() { + ValueConsumer defConsumer = new ValueConsumer() { @Override - public Value doValue(Value operand) { + public void visitValue(Value operand) { if (isVariable(operand)) { int varNum = operandNumber(operand); liveKill.set(varNum); @@ -734,7 +728,6 @@ // process them only in debug mode so that this can be checked verifyTemp(liveKill, operand); } - return operand; } }; @@ -743,13 +736,13 @@ final LIRInstruction op = instructions.get(j); try (Indent indent2 = Debug.logAndIndent("handle op %d", op.id())) { - op.forEachInput(useProc); - op.forEachAlive(useProc); + op.visitEachInput(useConsumer); + op.visitEachAlive(useConsumer); // Add uses of live locals from interpreter's point of view for proper debug // information generation - op.forEachState(stateProc); - op.forEachTemp(defProc); - op.forEachOutput(defProc); + op.visitEachState(stateConsumer); + op.visitEachTemp(defConsumer); + op.visitEachOutput(defConsumer); } } // end of instruction iteration @@ -1145,34 +1138,32 @@ void buildIntervals() { try (Indent indent = Debug.logAndIndent("build intervals")) { - InstructionValueProcedure outputProc = new InstructionValueProcedure() { + InstructionValueConsumer outputConsumer = new InstructionValueConsumer() { @Override - public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet flags) { + public void visitValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet flags) { if (isVariableOrRegister(operand)) { addDef((AllocatableValue) operand, op, registerPriorityOfOutputOperand(op), operand.getLIRKind()); addRegisterHint(op, operand, mode, flags, true); } - return operand; } }; - InstructionValueProcedure tempProc = new InstructionValueProcedure() { + InstructionValueConsumer tempConsumer = new InstructionValueConsumer() { @Override - public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet flags) { + public void visitValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet flags) { if (isVariableOrRegister(operand)) { addTemp((AllocatableValue) operand, op.id(), RegisterPriority.MustHaveRegister, operand.getLIRKind()); addRegisterHint(op, operand, mode, flags, false); } - return operand; } }; - InstructionValueProcedure aliveProc = new InstructionValueProcedure() { + InstructionValueConsumer aliveConsumer = new InstructionValueConsumer() { @Override - public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet flags) { + public void visitValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet flags) { if (isVariableOrRegister(operand)) { RegisterPriority p = registerPriorityOfInputOperand(flags); final int opId = op.id(); @@ -1180,14 +1171,13 @@ addUse((AllocatableValue) operand, blockFrom, opId + 1, p, operand.getLIRKind()); addRegisterHint(op, operand, mode, flags, false); } - return operand; } }; - InstructionValueProcedure inputProc = new InstructionValueProcedure() { + InstructionValueConsumer inputConsumer = new InstructionValueConsumer() { @Override - public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet flags) { + public void visitValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet flags) { if (isVariableOrRegister(operand)) { final int opId = op.id(); final int blockFrom = getFirstLirInstructionId((blockForId(opId))); @@ -1195,18 +1185,16 @@ addUse((AllocatableValue) operand, blockFrom, opId, p, operand.getLIRKind()); addRegisterHint(op, operand, mode, flags, false); } - return operand; } }; - InstructionValueProcedure stateProc = new InstructionValueProcedure() { + InstructionValueConsumer stateProc = new InstructionValueConsumer() { @Override - public Value doValue(LIRInstruction op, Value operand) { + public void visitValue(LIRInstruction op, Value operand) { final int opId = op.id(); final int blockFrom = getFirstLirInstructionId((blockForId(opId))); addUse((AllocatableValue) operand, blockFrom, opId + 1, RegisterPriority.None, operand.getLIRKind()); - return operand; } }; @@ -1263,17 +1251,17 @@ Debug.log("operation destroys all caller-save registers"); } - op.forEachOutput(outputProc); - op.forEachTemp(tempProc); - op.forEachAlive(aliveProc); - op.forEachInput(inputProc); + op.visitEachOutput(outputConsumer); + op.visitEachTemp(tempConsumer); + op.visitEachAlive(aliveConsumer); + op.visitEachInput(inputConsumer); // Add uses of live locals from interpreter's point of view for proper // debug information generation // Treat these operands as temp values (if the live range is extended // to a call site, the value would be in a register at // the call otherwise) - op.forEachState(stateProc); + op.visitEachState(stateProc); // special steps for some instructions (especially moves) handleMethodArguments(op); @@ -2202,25 +2190,24 @@ } } - class CheckProcedure extends ValueProcedure { + class CheckConsumer extends ValueConsumer { boolean ok; Interval curInterval; @Override - protected Value doValue(Value operand) { + protected void visitValue(Value operand) { if (isRegister(operand)) { if (intervalFor(operand) == curInterval) { ok = true; } } - return operand; } } void verifyNoOopsInFixedIntervals() { try (Indent indent = Debug.logAndIndent("verifying that no oops are in fixed intervals *")) { - CheckProcedure checkProc = new CheckProcedure(); + CheckConsumer checkConsumer = new CheckConsumer(); Interval fixedIntervals; Interval otherIntervals; @@ -2249,15 +2236,15 @@ // This interval is live out of this op so make sure // that this interval represents some value that's // referenced by this op either as an input or output. - checkProc.curInterval = interval; - checkProc.ok = false; + checkConsumer.curInterval = interval; + checkConsumer.ok = false; - op.forEachInput(checkProc); - op.forEachAlive(checkProc); - op.forEachTemp(checkProc); - op.forEachOutput(checkProc); + op.visitEachInput(checkConsumer); + op.visitEachAlive(checkConsumer); + op.visitEachTemp(checkConsumer); + op.visitEachOutput(checkConsumer); - assert checkProc.ok : "fixed intervals should never be live across an oopmap point"; + assert checkConsumer.ok : "fixed intervals should never be live across an oopmap point"; } } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java Mon Aug 25 21:15:59 2014 -0700 @@ -32,7 +32,6 @@ import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure; import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; import com.oracle.graal.phases.util.*; @@ -187,10 +186,10 @@ } void processOperations(List ops, final Interval[] inputState) { - InstructionValueProcedure useProc = new InstructionValueProcedure() { + InstructionValueConsumer useConsumer = new InstructionValueConsumer() { @Override - public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet flags) { + public void visitValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet flags) { // we skip spill moves inserted by the spill position optimization if (LinearScan.isVariableOrRegister(operand) && allocator.isProcessed(operand) && op.id() != LinearScan.DOMINATOR_SPILL_MOVE_ID) { Interval interval = intervalAt(operand); @@ -200,14 +199,13 @@ assert checkState(inputState, interval.location(), interval.splitParent()); } - return operand; } }; - InstructionValueProcedure defProc = new InstructionValueProcedure() { + InstructionValueConsumer defConsumer = new InstructionValueConsumer() { @Override - public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet flags) { + public void visitValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet flags) { if (LinearScan.isVariableOrRegister(operand) && allocator.isProcessed(operand)) { Interval interval = intervalAt(operand); if (op.id() != -1) { @@ -216,7 +214,6 @@ statePut(inputState, interval.location(), interval.splitParent()); } - return operand; } }; @@ -229,19 +226,19 @@ } // check if input operands are correct - op.forEachInput(useProc); + op.visitEachInput(useConsumer); // invalidate all caller save registers at calls if (op.destroysCallerSavedRegisters()) { for (Register r : allocator.frameMap.registerConfig.getCallerSaveRegisters()) { statePut(inputState, r.asValue(), null); } } - op.forEachAlive(useProc); + op.visitEachAlive(useConsumer); // set temp operands (some operations use temp operands also as output operands, so // can't set them null) - op.forEachTemp(defProc); + op.visitEachTemp(defConsumer); // set output operands - op.forEachOutput(defProc); + op.visitEachOutput(defConsumer); } } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchPattern.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchPattern.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchPattern.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,8 +23,8 @@ package com.oracle.graal.compiler.match; import com.oracle.graal.debug.*; -import com.oracle.graal.graph.Node.Verbosity; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; /** @@ -137,7 +137,7 @@ /** * The inputs to match the patterns against. */ - private final NodeClass.Position[] inputs; + private final Position[] inputs; /** * Can there only be one user of the node. Constant nodes can be matched even if there are other @@ -159,7 +159,7 @@ this.inputs = null; } - private MatchPattern(Class nodeClass, String name, boolean singleUser, MatchPattern[] patterns, NodeClass.Position[] inputs) { + private MatchPattern(Class nodeClass, String name, boolean singleUser, MatchPattern[] patterns, Position[] inputs) { assert inputs == null || inputs.length == patterns.length; this.nodeClass = nodeClass; this.name = name; @@ -168,15 +168,15 @@ this.inputs = inputs; } - public MatchPattern(Class nodeClass, String name, MatchPattern first, NodeClass.Position[] inputs, boolean singleUser) { + public MatchPattern(Class nodeClass, String name, MatchPattern first, Position[] inputs, boolean singleUser) { this(nodeClass, name, singleUser, new MatchPattern[]{first}, inputs); } - public MatchPattern(Class nodeClass, String name, MatchPattern first, MatchPattern second, NodeClass.Position[] inputs, boolean singleUser) { + public MatchPattern(Class nodeClass, String name, MatchPattern first, MatchPattern second, Position[] inputs, boolean singleUser) { this(nodeClass, name, singleUser, new MatchPattern[]{first, second}, inputs); } - public MatchPattern(Class nodeClass, String name, MatchPattern first, MatchPattern second, MatchPattern third, NodeClass.Position[] inputs, boolean singleUser) { + public MatchPattern(Class nodeClass, String name, MatchPattern first, MatchPattern second, MatchPattern third, Position[] inputs, boolean singleUser) { this(nodeClass, name, singleUser, new MatchPattern[]{first, second, third}, inputs); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java Mon Aug 25 21:15:59 2014 -0700 @@ -193,7 +193,7 @@ } /** - * Recursively accumulate any required NodeClass.Position declarations. + * Recursively accumulate any required Position declarations. */ void generatePositionDeclarations(Set declarations) { matchDescriptor.generatePositionDeclarations(declarations); @@ -460,7 +460,7 @@ } String generatePositionDeclaration() { - return String.format("NodeClass.Position[] %s_positions = MatchRuleRegistry.findPositions(lookup, %s.class, new String[]{\"%s\"});", nodeType.nodeClass, nodeType.nodeClass, + return String.format("Position[] %s_positions = MatchRuleRegistry.findPositions(lookup, %s.class, new String[]{\"%s\"});", nodeType.nodeClass, nodeType.nodeClass, String.join("\", \"", nodeType.inputs)); } } @@ -493,7 +493,7 @@ out.println("import java.util.*;"); out.println("import " + MatchStatementSet.class.getPackage().getName() + ".*;"); out.println("import " + NodeLIRBuilder.class.getName() + ";"); - out.println("import " + NodeClass.class.getName() + ";"); + out.println("import " + Position.class.getName() + ";"); for (String p : requiredPackages) { out.println("import " + p + ".*;"); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java Mon Aug 25 21:15:59 2014 -0700 @@ -44,7 +44,6 @@ */ public static interface NodeClassLookup { NodeClass get(Class theClass); - } static class DefaultNodeClassLookup implements NodeClassLookup { @@ -54,19 +53,19 @@ } /** - * Convert a list of field names into {@link com.oracle.graal.graph.NodeClass.Position} objects - * that can be used to read them during a match. The names should already have been confirmed to - * exist in the type. + * Convert a list of field names into {@link com.oracle.graal.graph.Position} objects that can + * be used to read them during a match. The names should already have been confirmed to exist in + * the type. * * @param theClass * @param names * @return an array of Position objects corresponding to the named fields. */ - public static NodeClass.Position[] findPositions(NodeClassLookup lookup, Class theClass, String[] names) { - NodeClass.Position[] result = new NodeClass.Position[names.length]; + public static Position[] findPositions(NodeClassLookup lookup, Class theClass, String[] names) { + Position[] result = new Position[names.length]; NodeClass nodeClass = lookup.get(theClass); for (int i = 0; i < names.length; i++) { - for (NodeClass.Position position : nodeClass.getFirstLevelInputPositions()) { + for (Position position : nodeClass.getFirstLevelInputPositions()) { String name = nodeClass.getName(position); if (name.equals(names[i])) { result[i] = position; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatement.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatement.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatement.java Mon Aug 25 21:15:59 2014 -0700 @@ -32,7 +32,7 @@ import com.oracle.graal.compiler.match.MatchPattern.Result; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Node.Verbosity; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; /** diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.compiler.target; - -import com.oracle.graal.api.code.*; - -/** - * Common functionality of host backends. - */ -public interface HostBackend { - NativeFunctionInterface getNativeFunctionInterface(); -} diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Mon Aug 25 21:15:59 2014 -0700 @@ -929,6 +929,9 @@ private static DebugMetric createMetric(String format, Object arg1, Object arg2) { String name = formatDebugName(format, arg1, arg2); boolean conditional = enabledMetrics == null || !enabledMetrics.contains(name); + if (!ENABLED && conditional) { + return VOID_METRIC; + } return new MetricImpl(name, conditional); } @@ -1082,19 +1085,39 @@ static { Set 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; } + public static boolean areUnconditionalTimersEnabled() { + return enabledTimers != null && !enabledTimers.isEmpty(); + } + + public static boolean areUnconditionalMetricsEnabled() { + return enabledMetrics != null && !enabledMetrics.isEmpty(); + } + + 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 @@ -1183,6 +1206,9 @@ private static DebugTimer createTimer(String format, Object arg1, Object arg2) { String name = formatDebugName(format, arg1, arg2); boolean conditional = enabledTimers == null || !enabledTimers.contains(name); + if (!ENABLED && conditional) { + return VOID_TIMER; + } return new TimerImpl(name, conditional); } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MemUseTrackerImpl.java Mon Aug 25 21:15:59 2014 -0700 @@ -38,7 +38,7 @@ */ private static final long threadMXBeanOverhead = -getCurrentThreadAllocatedBytes() + getCurrentThreadAllocatedBytes(); - private static long getCurrentThreadAllocatedBytes() { + public static long getCurrentThreadAllocatedBytes() { return threadMXBean.getThreadAllocatedBytes(currentThread().getId()) - threadMXBeanOverhead; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeMapTest.java --- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeMapTest.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeMapTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,10 +27,18 @@ import org.junit.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; public class NodeMapTest { - private static class TestNode extends Node { + @NodeInfo + static class TestNode extends Node { + TestNode() { + } + + public static TestNode create() { + return USE_GENERATED_NODES ? new NodeMapTest_TestNodeGen() : new TestNode(); + } } private Graph graph; @@ -41,7 +49,7 @@ public void before() { graph = new Graph(); for (int i = 0; i < nodes.length; i++) { - nodes[i] = graph.add(new TestNode()); + nodes[i] = graph.add(TestNode.create()); } map = new NodeMap<>(graph); for (int i = 0; i < nodes.length; i += 2) { @@ -95,7 +103,7 @@ * Failing here is not required, but if this behavior changes, usages of get need to be * checked for compatibility. */ - TestNode newNode = graph.add(new TestNode()); + TestNode newNode = graph.add(TestNode.create()); map.get(newNode); } @@ -105,19 +113,19 @@ * Failing here is not required, but if this behavior changes, usages of set need to be * checked for compatibility. */ - TestNode newNode = graph.add(new TestNode()); + TestNode newNode = graph.add(TestNode.create()); map.set(newNode, 1); } @Test public void testNewGetAndGrow() { - TestNode newNode = graph.add(new TestNode()); + TestNode newNode = graph.add(TestNode.create()); assertEquals(null, map.getAndGrow(newNode)); } @Test public void testNewSetAndGrow() { - TestNode newNode = graph.add(new TestNode()); + TestNode newNode = graph.add(TestNode.create()); map.setAndGrow(newNode, 1); assertEquals((Integer) 1, map.get(newNode)); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeUsagesTests.java --- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeUsagesTests.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeUsagesTests.java Mon Aug 25 21:15:59 2014 -0700 @@ -29,19 +29,28 @@ import org.junit.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; public class NodeUsagesTests { - private static class Def extends Node { - + @NodeInfo + static class Def extends Node { + public static Def create() { + return USE_GENERATED_NODES ? new NodeUsagesTests_DefGen() : new Def(); + } } - private static class Use extends Node { - private @Input Def in0; - private @Input Def in1; - private @Input Def in2; + @NodeInfo + static class Use extends Node { + @Input Def in0; + @Input Def in1; + @Input Def in2; - public Use(Def in0, Def in1, Def in2) { + public static Use create(Def in0, Def in1, Def in2) { + return USE_GENERATED_NODES ? new NodeUsagesTests_UseGen(in0, in1, in2) : new Use(in0, in1, in2); + } + + Use(Def in0, Def in1, Def in2) { this.in0 = in0; this.in1 = in1; this.in2 = in2; @@ -51,11 +60,11 @@ @Test public void testReplaceAtUsages() { Graph graph = new Graph(); - Def def0 = graph.add(new Def()); - Def def1 = graph.add(new Def()); - Use use0 = graph.add(new Use(def0, null, null)); - Use use1 = graph.add(new Use(null, def0, null)); - Use use2 = graph.add(new Use(null, null, def0)); + Def def0 = graph.add(Def.create()); + Def def1 = graph.add(Def.create()); + Use use0 = graph.add(Use.create(def0, null, null)); + Use use1 = graph.add(Use.create(null, def0, null)); + Use use2 = graph.add(Use.create(null, null, def0)); assertEquals(3, def0.usages().count()); assertThat(def0.usages(), contains(use0)); @@ -80,11 +89,11 @@ @Test public void testReplaceAtUsagesWithPredicateAll() { Graph graph = new Graph(); - Def def0 = graph.add(new Def()); - Def def1 = graph.add(new Def()); - Use use0 = graph.add(new Use(def0, null, null)); - Use use1 = graph.add(new Use(null, def0, null)); - Use use2 = graph.add(new Use(null, null, def0)); + Def def0 = graph.add(Def.create()); + Def def1 = graph.add(Def.create()); + Use use0 = graph.add(Use.create(def0, null, null)); + Use use1 = graph.add(Use.create(null, def0, null)); + Use use2 = graph.add(Use.create(null, null, def0)); assertEquals(3, def0.usages().count()); assertThat(def0.usages(), contains(use0)); @@ -109,11 +118,11 @@ @Test public void testReplaceAtUsagesWithPredicateNone() { Graph graph = new Graph(); - Def def0 = graph.add(new Def()); - Def def1 = graph.add(new Def()); - Use use0 = graph.add(new Use(def0, null, null)); - Use use1 = graph.add(new Use(null, def0, null)); - Use use2 = graph.add(new Use(null, null, def0)); + Def def0 = graph.add(Def.create()); + Def def1 = graph.add(Def.create()); + Use use0 = graph.add(Use.create(def0, null, null)); + Use use1 = graph.add(Use.create(null, def0, null)); + Use use2 = graph.add(Use.create(null, null, def0)); assertEquals(3, def0.usages().count()); assertThat(def0.usages(), contains(use0)); @@ -138,11 +147,11 @@ @Test public void testReplaceAtUsagesWithPredicate1() { Graph graph = new Graph(); - Def def0 = graph.add(new Def()); - Def def1 = graph.add(new Def()); - Use use0 = graph.add(new Use(def0, null, null)); - Use use1 = graph.add(new Use(null, def0, null)); - Use use2 = graph.add(new Use(null, null, def0)); + Def def0 = graph.add(Def.create()); + Def def1 = graph.add(Def.create()); + Use use0 = graph.add(Use.create(def0, null, null)); + Use use1 = graph.add(Use.create(null, def0, null)); + Use use2 = graph.add(Use.create(null, null, def0)); assertEquals(3, def0.usages().count()); assertThat(def0.usages(), contains(use0)); @@ -169,11 +178,11 @@ @Test public void testReplaceAtUsagesWithPredicate2() { Graph graph = new Graph(); - Def def0 = graph.add(new Def()); - Def def1 = graph.add(new Def()); - Use use0 = graph.add(new Use(def0, null, null)); - Use use1 = graph.add(new Use(null, def0, null)); - Use use2 = graph.add(new Use(null, null, def0)); + Def def0 = graph.add(Def.create()); + Def def1 = graph.add(Def.create()); + Use use0 = graph.add(Use.create(def0, null, null)); + Use use1 = graph.add(Use.create(null, def0, null)); + Use use2 = graph.add(Use.create(null, null, def0)); assertEquals(3, def0.usages().count()); assertThat(def0.usages(), contains(use0)); @@ -200,11 +209,11 @@ @Test public void testReplaceAtUsagesWithPredicate0() { Graph graph = new Graph(); - Def def0 = graph.add(new Def()); - Def def1 = graph.add(new Def()); - Use use0 = graph.add(new Use(def0, null, null)); - Use use1 = graph.add(new Use(null, def0, null)); - Use use2 = graph.add(new Use(null, null, def0)); + Def def0 = graph.add(Def.create()); + Def def1 = graph.add(Def.create()); + Use use0 = graph.add(Use.create(def0, null, null)); + Use use1 = graph.add(Use.create(null, def0, null)); + Use use2 = graph.add(Use.create(null, null, def0)); assertEquals(3, def0.usages().count()); assertThat(def0.usages(), contains(use0)); @@ -231,11 +240,11 @@ @Test public void testReplaceAtUsagesWithPredicate02() { Graph graph = new Graph(); - Def def0 = graph.add(new Def()); - Def def1 = graph.add(new Def()); - Use use0 = graph.add(new Use(def0, null, null)); - Use use1 = graph.add(new Use(null, def0, null)); - Use use2 = graph.add(new Use(null, null, def0)); + Def def0 = graph.add(Def.create()); + Def def1 = graph.add(Def.create()); + Use use0 = graph.add(Use.create(def0, null, null)); + Use use1 = graph.add(Use.create(null, def0, null)); + Use use2 = graph.add(Use.create(null, null, def0)); assertEquals(3, def0.usages().count()); assertThat(def0.usages(), contains(use0)); @@ -262,12 +271,12 @@ @Test public void testReplaceAtUsagesWithPredicate023() { Graph graph = new Graph(); - Def def0 = graph.add(new Def()); - Def def1 = graph.add(new Def()); - Use use0 = graph.add(new Use(def0, null, null)); - Use use1 = graph.add(new Use(null, def0, null)); - Use use2 = graph.add(new Use(null, null, def0)); - Use use3 = graph.add(new Use(null, null, def0)); + Def def0 = graph.add(Def.create()); + Def def1 = graph.add(Def.create()); + Use use0 = graph.add(Use.create(def0, null, null)); + Use use1 = graph.add(Use.create(null, def0, null)); + Use use2 = graph.add(Use.create(null, null, def0)); + Use use3 = graph.add(Use.create(null, null, def0)); assertEquals(4, def0.usages().count()); assertThat(def0.usages(), contains(use0)); @@ -296,12 +305,12 @@ @Test public void testReplaceAtUsagesWithPredicate013() { Graph graph = new Graph(); - Def def0 = graph.add(new Def()); - Def def1 = graph.add(new Def()); - Use use0 = graph.add(new Use(def0, null, null)); - Use use1 = graph.add(new Use(null, def0, null)); - Use use2 = graph.add(new Use(null, null, def0)); - Use use3 = graph.add(new Use(null, null, def0)); + Def def0 = graph.add(Def.create()); + Def def1 = graph.add(Def.create()); + Use use0 = graph.add(Use.create(def0, null, null)); + Use use1 = graph.add(Use.create(null, def0, null)); + Use use2 = graph.add(Use.create(null, null, def0)); + Use use3 = graph.add(Use.create(null, null, def0)); assertEquals(4, def0.usages().count()); assertThat(def0.usages(), contains(use0)); @@ -330,12 +339,12 @@ @Test public void testReplaceAtUsagesWithPredicate2_3() { Graph graph = new Graph(); - Def def0 = graph.add(new Def()); - Def def1 = graph.add(new Def()); - Use use0 = graph.add(new Use(def0, null, null)); - Use use1 = graph.add(new Use(null, def0, null)); - Use use2 = graph.add(new Use(null, null, def0)); - Use use3 = graph.add(new Use(null, null, def0)); + Def def0 = graph.add(Def.create()); + Def def1 = graph.add(Def.create()); + Use use0 = graph.add(Use.create(def0, null, null)); + Use use1 = graph.add(Use.create(null, def0, null)); + Use use2 = graph.add(Use.create(null, null, def0)); + Use use3 = graph.add(Use.create(null, null, def0)); assertEquals(4, def0.usages().count()); assertThat(def0.usages(), contains(use0)); @@ -364,11 +373,11 @@ @Test public void testReplaceAtUsagesWithPredicate01() { Graph graph = new Graph(); - Def def0 = graph.add(new Def()); - Def def1 = graph.add(new Def()); - Use use0 = graph.add(new Use(def0, null, null)); - Use use1 = graph.add(new Use(null, def0, null)); - Use use2 = graph.add(new Use(null, null, def0)); + Def def0 = graph.add(Def.create()); + Def def1 = graph.add(Def.create()); + Use use0 = graph.add(Use.create(def0, null, null)); + Use use1 = graph.add(Use.create(null, def0, null)); + Use use2 = graph.add(Use.create(null, null, def0)); assertEquals(3, def0.usages().count()); assertThat(def0.usages(), contains(use0)); @@ -395,11 +404,11 @@ @Test public void testReplaceAtUsagesWithPredicate12() { Graph graph = new Graph(); - Def def0 = graph.add(new Def()); - Def def1 = graph.add(new Def()); - Use use0 = graph.add(new Use(def0, null, null)); - Use use1 = graph.add(new Use(null, def0, null)); - Use use2 = graph.add(new Use(null, null, def0)); + Def def0 = graph.add(Def.create()); + Def def1 = graph.add(Def.create()); + Use use0 = graph.add(Use.create(def0, null, null)); + Use use1 = graph.add(Use.create(null, def0, null)); + Use use2 = graph.add(Use.create(null, null, def0)); assertEquals(3, def0.usages().count()); assertThat(def0.usages(), contains(use0)); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest.java --- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -29,14 +29,20 @@ import org.junit.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; public class TypedNodeIteratorTest { - private static class TestNode extends Node implements IterableNodeType, TestNodeInterface { + @NodeInfo + static class TestNode extends Node implements IterableNodeType, TestNodeInterface { private final String name; - public TestNode(String name) { + public static TestNode create(String name) { + return USE_GENERATED_NODES ? new TypedNodeIteratorTest_TestNodeGen(name) : new TestNode(name); + } + + TestNode(String name) { this.name = name; } @@ -48,14 +54,14 @@ @Test public void singleNodeTest() { Graph graph = new Graph(); - graph.add(new TestNode("a")); + graph.add(TestNode.create("a")); assertTrue(graph.hasNode(TestNode.class)); assertEquals("a", toString(graph.getNodes(TestNode.class))); } @Test public void deletingNodeTest() { - TestNode testNode = new TestNode("a"); + TestNode testNode = TestNode.create("a"); Graph graph = new Graph(); graph.add(testNode); testNode.safeDelete(); @@ -64,29 +70,29 @@ @Test public void deleteAndAddTest() { - TestNode testNode = new TestNode("b"); + TestNode testNode = TestNode.create("b"); Graph graph = new Graph(); - graph.add(new TestNode("a")); + graph.add(TestNode.create("a")); graph.add(testNode); testNode.safeDelete(); assertEquals("a", toString(graph.getNodes(TestNode.class))); - graph.add(new TestNode("c")); + graph.add(TestNode.create("c")); assertEquals("ac", toString(graph.getNodes(TestNode.class))); } @Test public void iteratorBehaviorTest() { Graph graph = new Graph(); - graph.add(new TestNode("a")); + graph.add(TestNode.create("a")); Iterator iterator = graph.getNodes(TestNode.class).iterator(); assertTrue(iterator.hasNext()); assertEquals("a", iterator.next().getName()); assertFalse(iterator.hasNext()); - graph.add(new TestNode("b")); + graph.add(TestNode.create("b")); assertTrue(iterator.hasNext()); assertEquals("b", iterator.next().getName()); assertFalse(iterator.hasNext()); - TestNode c = new TestNode("c"); + TestNode c = TestNode.create("c"); graph.add(c); assertTrue(iterator.hasNext()); c.safeDelete(); @@ -96,26 +102,26 @@ @Test public void complicatedIterationTest() { Graph graph = new Graph(); - graph.add(new TestNode("a")); + graph.add(TestNode.create("a")); for (TestNode tn : graph.getNodes(TestNode.class)) { String name = tn.getName(); for (int i = 0; i < name.length(); ++i) { char c = name.charAt(i); if (c == 'a') { tn.safeDelete(); - graph.add(new TestNode("b")); - graph.add(new TestNode("c")); + graph.add(TestNode.create("b")); + graph.add(TestNode.create("c")); } else if (c == 'b') { tn.safeDelete(); } else if (c == 'c') { - graph.add(new TestNode("d")); - graph.add(new TestNode("e")); - graph.add(new TestNode("d")); - graph.add(new TestNode("e")); - graph.add(new TestNode("e")); - graph.add(new TestNode("d")); - graph.add(new TestNode("e")); - graph.add(new TestNode("d")); + graph.add(TestNode.create("d")); + graph.add(TestNode.create("e")); + graph.add(TestNode.create("d")); + graph.add(TestNode.create("e")); + graph.add(TestNode.create("e")); + graph.add(TestNode.create("d")); + graph.add(TestNode.create("e")); + graph.add(TestNode.create("d")); } else if (c == 'd') { for (TestNode tn2 : graph.getNodes(TestNode.class)) { if (tn2.getName().equals("e")) { @@ -135,12 +141,12 @@ @Test public void addingNodeDuringIterationTest() { Graph graph = new Graph(); - graph.add(new TestNode("a")); + graph.add(TestNode.create("a")); StringBuilder sb = new StringBuilder(); int z = 0; for (TestNode tn : graph.getNodes(TestNode.class)) { if (z == 0) { - graph.add(new TestNode("b")); + graph.add(TestNode.create("b")); } sb.append(tn.getName()); z++; @@ -150,7 +156,7 @@ z = 0; for (TestNode tn : graph.getNodes(TestNode.class)) { if (z == 0) { - graph.add(new TestNode("c")); + graph.add(TestNode.create("c")); } assertNotNull(tn); z++; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest2.java --- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest2.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest2.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,14 +27,20 @@ import org.junit.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; public class TypedNodeIteratorTest2 { - private static class NodeA extends Node implements TestNodeInterface { + @NodeInfo + static class NodeA extends Node implements TestNodeInterface { private final String name; - public NodeA(String name) { + public static NodeA create(String name) { + return USE_GENERATED_NODES ? new TypedNodeIteratorTest2_NodeAGen(name) : new NodeA(name); + } + + NodeA(String name) { this.name = name; } @@ -43,23 +49,36 @@ } } - private static class NodeB extends NodeA implements IterableNodeType { + @NodeInfo + static class NodeB extends NodeA implements IterableNodeType { - public NodeB(String name) { + public static NodeB create(String name) { + return USE_GENERATED_NODES ? new TypedNodeIteratorTest2_NodeBGen(name) : new NodeB(name); + } + + NodeB(String name) { super(name); } } - private static class NodeC extends NodeB { + @NodeInfo + static class NodeC extends NodeB { + public static NodeC create(String name) { + return USE_GENERATED_NODES ? new TypedNodeIteratorTest2_NodeCGen(name) : new NodeC(name); + } - public NodeC(String name) { + NodeC(String name) { super(name); } } - private static class NodeD extends NodeC { + @NodeInfo + static class NodeD extends NodeC { + public static NodeD create(String name) { + return USE_GENERATED_NODES ? new TypedNodeIteratorTest2_NodeDGen(name) : new NodeD(name); + } - public NodeD(String name) { + NodeD(String name) { super(name); } } @@ -67,8 +86,8 @@ @Test public void simpleSubclassTest() { Graph graph = new Graph(); - graph.add(new NodeB("b")); - graph.add(new NodeD("d")); + graph.add(NodeB.create("b")); + graph.add(NodeD.create("d")); Assert.assertEquals("bd", TypedNodeIteratorTest.toString(graph.getNodes(NodeB.class))); Assert.assertEquals("d", TypedNodeIteratorTest.toString(graph.getNodes(NodeD.class))); @@ -77,19 +96,19 @@ @Test public void addingNodeDuringIterationTest() { Graph graph = new Graph(); - graph.add(new NodeB("b1")); - NodeD d1 = graph.add(new NodeD("d1")); + graph.add(NodeB.create("b1")); + NodeD d1 = graph.add(NodeD.create("d1")); StringBuilder sb = new StringBuilder(); for (NodeB tn : graph.getNodes(NodeB.class)) { if (tn == d1) { - graph.add(new NodeB("b2")); + graph.add(NodeB.create("b2")); } sb.append(tn.getName()); } assertEquals("b1d1b2", sb.toString()); for (NodeB tn : graph.getNodes(NodeB.class)) { if (tn == d1) { - graph.add(new NodeB("b3")); + graph.add(NodeB.create("b3")); } assertNotNull(tn); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.graph/src/com/oracle/graal/graph/FirstLevelPositionCollection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/FirstLevelPositionCollection.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.graph; + +import static com.oracle.graal.graph.Node.*; + +import java.util.*; + +import com.oracle.graal.graph.Node.Input; +import com.oracle.graal.graph.Node.Successor; + +/** + * A collection of the positions of the {@link Node} and {@link NodeList} fields in a node. + */ +public final class FirstLevelPositionCollection extends AbstractCollection implements Collection { + + public static final FirstLevelPositionCollection Empty = new FirstLevelPositionCollection(0, 0, false); + + /** + * The total number of {@link Node} and {@link NodeList} fields. + */ + protected final int allNodeRefFields; + + /** + * The number of {@link Node} fields. + */ + protected final int nodeFields; + + /** + * Specifies if this iterator iterates over {@linkplain Input inputs} or {@linkplain Successor + * successors}. + */ + private final boolean isInputs; + + /** + * Creates a collection of the positions of the {@link Node} and {@link NodeList} fields in a + * node. + */ + public FirstLevelPositionCollection(int nodeFields, int nodeListFields, boolean isInputs) { + this.allNodeRefFields = nodeListFields + nodeFields; + this.nodeFields = nodeFields; + this.isInputs = isInputs; + } + + @Override + public int size() { + return allNodeRefFields; + } + + @Override + public Iterator iterator() { + return new FirstLevelPositionIterator(nodeFields, allNodeRefFields - nodeFields, isInputs); + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.graph/src/com/oracle/graal/graph/FirstLevelPositionIterator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/FirstLevelPositionIterator.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.graph; + +import static com.oracle.graal.graph.Node.*; + +import java.util.*; + +import com.oracle.graal.graph.Node.Input; +import com.oracle.graal.graph.Node.Successor; + +/** + * An iterator over the {@link Node} and {@link NodeList} fields in a node. + */ +public class FirstLevelPositionIterator implements Iterator { + + public static final FirstLevelPositionIterator Empty = new FirstLevelPositionIterator(0, 0, false); + + /** + * The total number of {@link Node} and {@link NodeList} fields. + */ + protected final int allNodeRefFields; + + /** + * The number of {@link Node} fields. + */ + protected final int nodeFields; + + /** + * Specifies if this iterator iterates over {@linkplain Input inputs} or {@linkplain Successor + * successors}. + */ + private final boolean isInputs; + + /** + * Current field iteration index. + */ + protected int index; + + /** + * Creates an iterator over the {@link Node} and {@link NodeList} fields in a node. + * + * @param nodeFields the number of {@link Node} fields in the class hierarchy of the node being + * iterated + * @param nodeListFields the number of {@link NodeList} fields in the class hierarchy of the + * node being iterated + */ + protected FirstLevelPositionIterator(int nodeFields, int nodeListFields, boolean isInputs) { + this.allNodeRefFields = nodeListFields + nodeFields; + this.nodeFields = nodeFields; + this.isInputs = isInputs; + index = Node.NOT_ITERABLE; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + public Position next() { + Position pos = new Position(isInputs, index, index >= nodeFields ? NODE_LIST : NOT_ITERABLE); + index++; + return pos; + } + + public boolean hasNext() { + return index < allNodeRefFields; + } + + public int size() { + return allNodeRefFields; + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,13 +22,14 @@ */ package com.oracle.graal.graph; +import static com.oracle.graal.graph.Node.*; + import java.util.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.Node.ValueNumberable; import com.oracle.graal.graph.NodeClass.NodeClassIterator; -import com.oracle.graal.graph.NodeClass.Position; import com.oracle.graal.graph.iterators.*; /** @@ -85,7 +86,7 @@ public CacheEntry(Node node) { assert node.getNodeClass().valueNumberable(); - assert node.getNodeClass().isLeafNode(); + assert node.isLeafNode(); this.node = node; } @@ -117,7 +118,7 @@ this(null); } - static final boolean MODIFICATION_COUNTS_ENABLED = assertionsEnabled(); + public static final boolean MODIFICATION_COUNTS_ENABLED = assertionsEnabled(); /** * Determines if assertions are enabled for the {@link Graph} class. @@ -440,7 +441,7 @@ return (T) other; } else { Node result = addIfMissing ? addHelper(node) : node; - if (node.getNodeClass().isLeafNode()) { + if (node.isLeafNode()) { putNodeIntoCache(result); } return (T) result; @@ -450,7 +451,7 @@ void putNodeIntoCache(Node node) { assert node.graph() == this || node.graph() == null; assert node.getNodeClass().valueNumberable(); - assert node.getNodeClass().isLeafNode() : node.getClass(); + assert node.isLeafNode() : node.getClass(); cachedNodes.put(new CacheEntry(node), node); } @@ -467,7 +468,7 @@ public Node findDuplicate(Node node) { NodeClass nodeClass = node.getNodeClass(); assert nodeClass.valueNumberable(); - if (nodeClass.isLeafNode()) { + if (node.isLeafNode()) { Node cachedNode = findNodeInCache(node); if (cachedNode != null) { return cachedNode; @@ -646,8 +647,18 @@ }; } - private static final Node PLACE_HOLDER = new Node() { - }; + // Fully qualified annotation name is required to satisfy javac + @com.oracle.graal.nodeinfo.NodeInfo + static class PlaceHolderNode extends Node { + public static PlaceHolderNode create() { + return new PlaceHolderNode(); + } + + PlaceHolderNode() { + } + } + + private static final Node PLACE_HOLDER = USE_GENERATED_NODES ? new Graph_PlaceHolderNodeGen() : new PlaceHolderNode(); /** * When the percent of live nodes in {@link #nodes} fall below this number, a call to @@ -698,15 +709,17 @@ return true; } - private class TypedNodeIterator implements Iterator { + private static class TypedNodeIterator implements Iterator { + private final Graph graph; private final int[] ids; private final Node[] current; private int currentIdIndex; private boolean needsForward; - public TypedNodeIterator(NodeClass clazz) { + public TypedNodeIterator(NodeClass clazz, Graph graph) { + this.graph = graph; ids = clazz.iterableIds(); currentIdIndex = 0; current = new Node[ids.length]; @@ -732,7 +745,7 @@ return current(); } - private Node skipDeleted(Node node) { + private static Node skipDeleted(Node node) { Node n = node; while (n != null && n.isDeleted()) { n = n.typeCacheNext; @@ -746,7 +759,7 @@ while (true) { Node next; if (current() == PLACE_HOLDER) { - next = getStartNode(ids[currentIdIndex]); + next = graph.getStartNode(ids[currentIdIndex]); } else { next = current().typeCacheNext; } @@ -810,7 +823,7 @@ @Override public Iterator iterator() { - return new TypedNodeIterator<>(nodeClass); + return new TypedNodeIterator<>(nodeClass, Graph.this); } }; } @@ -861,7 +874,7 @@ nodesSize++; int nodeClassId = node.getNodeClass().iterableId(); - if (nodeClassId != NodeClass.NOT_ITERABLE) { + if (nodeClassId != Node.NOT_ITERABLE) { while (nodeCacheFirst.size() <= nodeClassId) { nodeCacheFirst.add(null); nodeCacheLast.add(null); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.graph/src/com/oracle/graal/graph/InputType.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/InputType.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.graph; - -public enum InputType { - /** - * Inputs that consume an actual value generated by the referenced node. - */ - Value, - /** - * Inputs that consume the memory state of the referenced node. - */ - Memory, - /** - * Inputs that reference a condition. - */ - Condition, - /** - * Inputs that reference a frame state. - */ - State, - /** - * Inputs that reference a guard (guards, begin nodes). - */ - Guard, - /** - * Inputs that reference an anchor (begin nodes, value anchors). - */ - Anchor, - /** - * Inputs that represent an association between nodes, e.g., a phi and the merge or a loop begin - * and loop exits and ends. - */ - Association, - /** - * Inputs that connect tightly coupled nodes, e.g., an InvokeNode and its CallTargetNode. - */ - Extension, - /** - * Inputs of this type are temporarily exempt from type checking. This should only be used in - * exceptional cases and should never survive to later stages of compilation. - */ - Unchecked -} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,10 +27,11 @@ import java.lang.annotation.*; import java.util.*; +import com.oracle.graal.graph.Graph.NodeEventListener; import com.oracle.graal.graph.NodeClass.NodeClassIterator; -import com.oracle.graal.graph.NodeClass.Position; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; /** * This class is the base class for all nodes, it represent a node which can be inserted in a @@ -52,20 +53,26 @@ * exception or return true. They can thus be used within an assert statement, so that the check is * only performed if assertions are enabled. */ +@NodeInfo public abstract class Node implements Cloneable, Formattable { + public final static boolean USE_GENERATED_NODES = Boolean.getBoolean("graal.useGeneratedNodes"); + static final int DELETED_ID_START = -1000000000; static final int INITIAL_ID = -1; static final int ALIVE_ID_START = 0; + // The use of fully qualified class names here and in the rest + // of this file works around a problem javac has resolving symbols + /** * Denotes a non-optional (non-null) node input. This should be applied to exactly the fields of * a node that are of type {@link Node} or {@link NodeInputList}. Nodes that update fields of * type {@link Node} outside of their constructor should call * {@link Node#updateUsages(Node, Node)} just prior to doing the update of the input. */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) + @java.lang.annotation.Retention(RetentionPolicy.RUNTIME) + @java.lang.annotation.Target(ElementType.FIELD) public static @interface Input { InputType value() default InputType.Value; } @@ -76,14 +83,14 @@ * {@link Node} outside of their constructor should call {@link Node#updateUsages(Node, Node)} * just prior to doing the update of the input. */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) + @java.lang.annotation.Retention(RetentionPolicy.RUNTIME) + @java.lang.annotation.Target(ElementType.FIELD) public static @interface OptionalInput { InputType value() default InputType.Value; } - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) + @java.lang.annotation.Retention(RetentionPolicy.RUNTIME) + @java.lang.annotation.Target(ElementType.FIELD) public static @interface Successor { } @@ -91,8 +98,8 @@ * Denotes that a parameter of an {@linkplain NodeIntrinsic intrinsic} method must be a compile * time constant at all call sites to the intrinsic method. */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.PARAMETER) + @java.lang.annotation.Retention(RetentionPolicy.RUNTIME) + @java.lang.annotation.Target(ElementType.PARAMETER) public static @interface ConstantNodeParameter { } @@ -102,8 +109,8 @@ * an argument for the annotated parameter. Injected parameters must precede all non-injected * parameters in a constructor. */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.PARAMETER) + @java.lang.annotation.Retention(RetentionPolicy.RUNTIME) + @java.lang.annotation.Target(ElementType.PARAMETER) public static @interface InjectedNodeParameter { } @@ -112,10 +119,10 @@ * annotated method can be replaced with an instance of the node class denoted by * {@link #value()}. For this reason, the signature of the annotated method must match the * signature (excluding a prefix of {@linkplain InjectedNodeParameter injected} parameters) of a - * constructor in the node class. + * factory method named {@code "create"} in the node class. */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.METHOD) + @java.lang.annotation.Retention(RetentionPolicy.RUNTIME) + @java.lang.annotation.Target(ElementType.METHOD) public static @interface NodeIntrinsic { /** @@ -145,20 +152,25 @@ // therefore points to the next Node of the same type. Node typeCacheNext; - private static final int INLINE_USAGE_COUNT = 2; + static final int INLINE_USAGE_COUNT = 2; private static final Node[] NO_NODES = {}; /** * Head of usage list. The elements of the usage list in order are {@link #usage0}, * {@link #usage1} and {@link #extraUsages}. The first null entry terminates the list. */ - private Node usage0; - private Node usage1; - private Node[] extraUsages; + Node usage0; + Node usage1; + Node[] extraUsages; private Node predecessor; + public static final int NODE_LIST = -2; + public static final int NOT_ITERABLE = -1; + public Node() { + assert USE_GENERATED_NODES == (getClass().getAnnotation(GeneratedNode.class) != null) : getClass() + " is not a generated Node class - forgot @" + NodeInfo.class.getSimpleName() + + " on class declaration?"; init(); } @@ -198,95 +210,6 @@ return getNodeClass().getSuccessorIterable(this); } - class NodeUsageIterator implements Iterator { - - int index = -1; - Node current; - - private void advance() { - current = null; - index++; - if (index == 0) { - current = usage0; - } else if (index == 1) { - current = usage1; - } else { - if (index - INLINE_USAGE_COUNT < extraUsages.length) { - current = extraUsages[index - INLINE_USAGE_COUNT]; - } - } - } - - public NodeUsageIterator() { - advance(); - } - - public boolean hasNext() { - return current != null; - } - - public Node next() { - Node result = current; - if (result == null) { - throw new NoSuchElementException(); - } - advance(); - return result; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - - class NodeUsageWithModCountIterator extends NodeUsageIterator { - - private final int expectedModCount = usageModCount(); - - @Override - public boolean hasNext() { - if (expectedModCount != usageModCount()) { - throw new ConcurrentModificationException(); - } - return super.hasNext(); - } - - @Override - public Node next() { - if (expectedModCount != usageModCount()) { - throw new ConcurrentModificationException(); - } - return super.next(); - } - } - - class NodeUsageIterable implements NodeIterable { - - public NodeUsageIterator iterator() { - if (MODIFICATION_COUNTS_ENABLED) { - return new NodeUsageWithModCountIterator(); - } else { - return new NodeUsageIterator(); - } - } - - @Override - public boolean isEmpty() { - return usage0 == null; - } - - @Override - public boolean isNotEmpty() { - return usage0 != null; - } - - @Override - public int count() { - return usageCount(); - } - } - int getUsageCountUpperBound() { assert recordsUsages(); if (usage0 == null) { @@ -303,7 +226,7 @@ */ public final NodeIterable usages() { assert recordsUsages() : this; - return new NodeUsageIterable(); + return new NodeUsageIterable(this); } /** @@ -380,7 +303,7 @@ } } - private int usageCount() { + int usageCount() { if (usage0 == null) { return 0; } @@ -524,7 +447,7 @@ return predecessor; } - final int modCount() { + public final int modCount() { if (MODIFICATION_COUNTS_ENABLED && graph != null) { return graph.modCount(this); } @@ -840,7 +763,7 @@ final Node clone(Graph into, boolean clearInputsAndSuccessors) { NodeClass nodeClass = getNodeClass(); - if (into != null && nodeClass.valueNumberable() && nodeClass.isLeafNode()) { + if (into != null && nodeClass.valueNumberable() && isLeafNode()) { Node otherNode = into.findNodeInCache(this); if (otherNode != null) { return otherNode; @@ -868,13 +791,20 @@ newNode.extraUsages = NO_NODES; newNode.predecessor = null; - if (into != null && nodeClass.valueNumberable() && nodeClass.isLeafNode()) { + if (into != null && nodeClass.valueNumberable() && isLeafNode()) { into.putNodeIntoCache(newNode); } newNode.afterClone(this); return newNode; } + /** + * @returns true if this node has no inputs and no successors + */ + public boolean isLeafNode() { + return USE_GENERATED_NODES || getNodeClass().isLeafNode(); + } + protected void afterClone(@SuppressWarnings("unused") Node other) { } @@ -996,34 +926,6 @@ return toString(Verbosity.Short); } - public enum Verbosity { - /** - * Only the id of the node. - */ - Id, - /** - * Only the name of the node, which may contain some more information for certain node types - * (constants, ...). - */ - Name, - /** - * {@link #Id} + {@link #Name}. - */ - Short, - /** - * Defaults to {@link #Short} and may be enhanced by subclasses. - */ - Long, - /** - * For use by a custom formatting facility in an IDE. - */ - Debugger, - /** - * All the other information plus all debug properties of the node. - */ - All - } - /** * Creates a String representation for this node with a given {@link Verbosity}. */ @@ -1120,4 +1022,39 @@ } } } + + // NEW API IMPLEMENTED BY GENERATED METHODS - NOT YET USED + + public NodeRefIterable inputsV2() { + return NodeRefIterable.Empty; + } + + public Collection getFirstLevelInputs() { + return Collections.emptyList(); + } + + public Collection getFirstLevelSuccessors() { + return Collections.emptyList(); + } + + /** + * @param pos + */ + public InputType getInputTypeAt(Position pos) { + throw new NoSuchElementException(); + } + + /** + * @param pos + */ + public String getNameOf(Position pos) { + throw new NoSuchElementException(); + } + + /** + * @param pos + */ + public boolean isOptionalInputAt(Position pos) { + throw new NoSuchElementException(); + } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,6 +23,7 @@ package com.oracle.graal.graph; import static com.oracle.graal.graph.Graph.*; +import static com.oracle.graal.graph.Node.*; import static com.oracle.graal.graph.util.CollectionsAccess.*; import java.lang.reflect.*; @@ -33,8 +34,8 @@ import com.oracle.graal.graph.Graph.DuplicationReplacement; import com.oracle.graal.graph.Node.Input; import com.oracle.graal.graph.Node.Successor; -import com.oracle.graal.graph.Node.Verbosity; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; /** * Metadata for every {@link Node} type. The metadata includes: @@ -53,7 +54,9 @@ */ @SuppressWarnings("unchecked") public static NodeClass get(Class c) { - Class key = (Class) c; + GeneratedNode gen = c.getAnnotation(GeneratedNode.class); + Class key = gen == null ? (Class) c : (Class) gen.value(); + NodeClass value = (NodeClass) allClasses.get(key); // The fact that {@link ConcurrentHashMap#put} and {@link ConcurrentHashMap#get} // are used makes the double-checked locking idiom work. @@ -72,9 +75,6 @@ return value; } - public static final int NOT_ITERABLE = -1; - public static final int NODE_LIST = -2; - private static final Class NODE_CLASS = Node.class; private static final Class INPUT_LIST_CLASS = NodeInputList.class; private static final Class SUCCESSOR_LIST_CLASS = NodeSuccessorList.class; @@ -89,7 +89,6 @@ private final long[] successorOffsets; private final Class[] dataTypes; private final boolean canGVN; - private final boolean isLeafNode; private final int startGVNNumber; private final String shortName; private final String nameTemplate; @@ -109,6 +108,7 @@ * Determines if this node type implements {@link Simplifiable}. */ private final boolean isSimplifiable; + private final boolean isLeafNode; public NodeClass(Class clazz) { this(clazz, new DefaultCalcOffset(), null, 0); @@ -165,6 +165,8 @@ if (!info.nameTemplate().isEmpty()) { newNameTemplate = info.nameTemplate(); } + } else { + System.out.println("No NodeInfo for " + clazz); } EnumSet newAllowedUsageTypes = EnumSet.noneOf(InputType.class); Class current = clazz; @@ -205,10 +207,9 @@ } this.iterableIds = ids; } else { - this.iterableId = NOT_ITERABLE; + this.iterableId = Node.NOT_ITERABLE; this.iterableIds = null; } - isLeafNode = (this.inputOffsets.length == 0 && this.successorOffsets.length == 0); nodeIterableCount = Debug.metric("NodeIterable_%s", shortName); } @@ -233,6 +234,16 @@ fieldTypes.putAll(scanner.fieldTypes); } + private boolean isNodeClassFor(Node n) { + if (Node.USE_GENERATED_NODES) { + GeneratedNode gen = n.getClass().getAnnotation(GeneratedNode.class); + assert gen != null; + return gen.value() == getClazz(); + } else { + return n.getNodeClass().getClazz() == n.getClass(); + } + } + public String shortName() { return shortName; } @@ -250,10 +261,6 @@ return canGVN; } - public boolean isLeafNode() { - return isLeafNode; - } - /** * Determines if this node type implements {@link Canonicalizable}. */ @@ -296,13 +303,14 @@ assert !field.isAnnotationPresent(Node.Successor.class) : "field cannot be both input and successor"; assert field.isAnnotationPresent(Node.Input.class) ^ field.isAnnotationPresent(Node.OptionalInput.class) : "inputs can either be optional or non-optional"; if (INPUT_LIST_CLASS.isAssignableFrom(type)) { - GraalInternalError.guarantee(Modifier.isFinal(field.getModifiers()), "NodeInputList input field %s should be final", field); + // NodeInputList fields should not be final since they are + // written (via Unsafe) in clearInputs() + GraalInternalError.guarantee(!Modifier.isFinal(field.getModifiers()), "NodeInputList input field %s should not be final", field); GraalInternalError.guarantee(!Modifier.isPublic(field.getModifiers()), "NodeInputList input field %s should not be public", field); inputListOffsets.add(offset); } else { GraalInternalError.guarantee(NODE_CLASS.isAssignableFrom(type) || type.isInterface(), "invalid input type: %s", type); GraalInternalError.guarantee(!Modifier.isFinal(field.getModifiers()), "Node input field %s should not be final", field); - GraalInternalError.guarantee(Modifier.isPrivate(field.getModifiers()), "Node input field %s should be private", field); inputOffsets.add(offset); } if (field.isAnnotationPresent(Node.Input.class)) { @@ -316,13 +324,14 @@ } } else if (field.isAnnotationPresent(Node.Successor.class)) { if (SUCCESSOR_LIST_CLASS.isAssignableFrom(type)) { - GraalInternalError.guarantee(Modifier.isFinal(field.getModifiers()), "NodeSuccessorList successor field % should be final", field); + // NodeSuccessorList fields should not be final since they are + // written (via Unsafe) in clearSuccessors() + GraalInternalError.guarantee(!Modifier.isFinal(field.getModifiers()), "NodeSuccessorList successor field % should not be final", field); GraalInternalError.guarantee(!Modifier.isPublic(field.getModifiers()), "NodeSuccessorList successor field %s should not be public", field); successorListOffsets.add(offset); } else { GraalInternalError.guarantee(NODE_CLASS.isAssignableFrom(type), "invalid successor type: %s", type); GraalInternalError.guarantee(!Modifier.isFinal(field.getModifiers()), "Node successor field %s should not be final", field); - GraalInternalError.guarantee(Modifier.isPrivate(field.getModifiers()), "Node successor field %s should be private", field); successorOffsets.add(offset); } names.put(offset, field.getName()); @@ -354,104 +363,6 @@ return str.toString(); } - /** - * Describes an edge slot for a {@link NodeClass}. - * - * @see NodeClass#get(Node, Position) - * @see NodeClass#getName(Position) - */ - public static final class Position { - - private final boolean input; - private final int index; - private final int subIndex; - - public Position(boolean input, int index, int subIndex) { - this.input = input; - this.index = index; - this.subIndex = subIndex; - } - - @Override - public String toString() { - return (input ? "input " : "successor ") + index + "/" + subIndex; - } - - public Node get(Node node) { - return node.getNodeClass().get(node, this); - } - - public InputType getInputType(Node node) { - return node.getNodeClass().getInputType(this); - } - - public String getInputName(Node node) { - return node.getNodeClass().getName(this); - } - - public boolean isInputOptional(Node node) { - return node.getNodeClass().isInputOptional(this); - } - - public void set(Node node, Node value) { - node.getNodeClass().set(node, this, value); - } - - public void initialize(Node node, Node value) { - node.getNodeClass().initializePosition(node, this, value); - } - - public boolean isValidFor(Node node, Node from) { - return node.getNodeClass().isValid(this, from.getNodeClass()); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + index; - result = prime * result + (input ? 1231 : 1237); - result = prime * result + subIndex; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - Position other = (Position) obj; - if (index != other.index) { - return false; - } - if (input != other.input) { - return false; - } - if (subIndex != other.subIndex) { - return false; - } - return true; - } - - public int getSubIndex() { - return subIndex; - } - - public int getIndex() { - return index; - } - - public boolean isInput() { - return input; - } - } - private static Node getNode(Node node, long offset) { return (Node) unsafe.getObject(node, offset); } @@ -966,7 +877,7 @@ public NodeList getNodeList(Node node, Position pos) { long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()]; - assert pos.getSubIndex() == NODE_LIST; + assert pos.getSubIndex() == Node.NODE_LIST; return getNodeList(node, offset); } @@ -1303,7 +1214,7 @@ * @param newNode the node to which the inputs should be copied. */ public void copyInputs(Node node, Node newNode) { - assert node.getClass() == getClazz() && newNode.getClass() == getClazz(); + assert isNodeClassFor(node) && isNodeClassFor(newNode); int index = 0; while (index < directInputCount) { @@ -1325,7 +1236,7 @@ * @param newNode the node to which the successors should be copied. */ public void copySuccessors(Node node, Node newNode) { - assert node.getClass() == getClazz() && newNode.getClass() == getClazz(); + assert isNodeClassFor(node) && isNodeClassFor(newNode); int index = 0; while (index < directSuccessorCount) { @@ -1344,7 +1255,7 @@ } public boolean inputsEqual(Node node, Node other) { - assert node.getClass() == getClazz() && other.getClass() == getClazz(); + assert isNodeClassFor(node) && isNodeClassFor(other); int index = 0; while (index < directInputCount) { if (getNode(other, inputOffsets[index]) != getNode(node, inputOffsets[index])) { @@ -1363,7 +1274,7 @@ } public boolean successorsEqual(Node node, Node other) { - assert node.getClass() == getClazz() && other.getClass() == getClazz(); + assert isNodeClassFor(node) && isNodeClassFor(other); int index = 0; while (index < directSuccessorCount) { if (getNode(other, successorOffsets[index]) != getNode(node, successorOffsets[index])) { @@ -1382,7 +1293,7 @@ } public boolean inputContains(Node node, Node other) { - assert node.getClass() == getClazz(); + assert isNodeClassFor(node); int index = 0; while (index < directInputCount) { @@ -1402,7 +1313,7 @@ } public boolean successorContains(Node node, Node other) { - assert node.getClass() == getClazz(); + assert isNodeClassFor(node); int index = 0; while (index < directSuccessorCount) { @@ -1425,7 +1336,7 @@ return new AbstractCollection() { @Override public Iterator iterator() { - return new Iterator() { + return new Iterator() { int i = 0; @Override @@ -1434,7 +1345,7 @@ } public Position next() { - Position pos = new Position(true, i, i >= directInputCount ? NODE_LIST : NOT_ITERABLE); + Position pos = new Position(true, i, i >= directInputCount ? Node.NODE_LIST : Node.NOT_ITERABLE); i++; return pos; } @@ -1456,7 +1367,7 @@ return new AbstractCollection() { @Override public Iterator iterator() { - return new Iterator() { + return new Iterator() { int i = 0; @Override @@ -1465,7 +1376,7 @@ } public Position next() { - Position pos = new Position(false, i, i >= directSuccessorCount ? NODE_LIST : NOT_ITERABLE); + Position pos = new Position(false, i, i >= directSuccessorCount ? Node.NODE_LIST : Node.NOT_ITERABLE); i++; return pos; } @@ -1663,4 +1574,8 @@ private static boolean isAssignable(Class fieldType, Node replacement) { return replacement == null || !NODE_CLASS.isAssignableFrom(fieldType) || fieldType.isAssignableFrom(replacement.getClass()); } + + public boolean isLeafNode() { + return isLeafNode; + } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClassIterable.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClassIterable.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClassIterable.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,7 +23,6 @@ package com.oracle.graal.graph; import com.oracle.graal.graph.NodeClass.NodeClassIterator; -import com.oracle.graal.graph.NodeClass.Position; import com.oracle.graal.graph.iterators.*; /** diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInfo.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInfo.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.graph; - -import java.lang.annotation.*; - -import com.oracle.graal.graph.Node.Verbosity; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface NodeInfo { - - String shortName() default ""; - - /** - * The template used to build the {@link Verbosity#Name} version. Variable part are specified - * using {i#inputName} or {p#propertyName}. - */ - String nameTemplate() default ""; - - InputType[] allowedUsageTypes() default {}; -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputList.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputList.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputList.java Mon Aug 25 21:15:59 2014 -0700 @@ -61,7 +61,7 @@ } @Override - public boolean add(T node) { + public boolean add(Node node) { assert node == null || !node.isDeleted(); self.incModCount(); return super.add(node); @@ -86,7 +86,7 @@ } @Override - void copy(NodeList other) { + void copy(NodeList other) { self.incModCount(); super.copy(other); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java Mon Aug 25 21:15:59 2014 -0700 @@ -121,14 +121,15 @@ modCount++; } + @SuppressWarnings("unchecked") @Override - public boolean add(T node) { + public boolean add(Node node) { incModCount(); if (size == nodes.length) { nodes = Arrays.copyOf(nodes, nodes.length * 2 + 1); } nodes[size++] = node; - update(null, node); + update(null, (T) node); return true; } @@ -145,22 +146,22 @@ @Override @SuppressWarnings("unchecked") - public T set(int index, T node) { + public T set(int index, Node node) { incModCount(); T oldValue = (T) nodes[index]; assert index < size(); - update((T) nodes[index], node); + update((T) nodes[index], (T) node); nodes[index] = node; return oldValue; } - void initialize(int index, T node) { + public void initialize(int index, Node node) { incModCount(); assert index < size(); nodes[index] = node; } - void copy(NodeList other) { + void copy(NodeList other) { incModCount(); nodes = Arrays.copyOf(other.nodes, other.size); size = other.size; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeRefIterable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeRefIterable.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.graph; + +import com.oracle.graal.graph.iterators.*; + +/** + * The iterator returned by this iterable can be used to access {@link Position Positions} during + * iteration using {@link NodeRefIterator#nextPosition()}. + */ +public interface NodeRefIterable extends NodeIterable { + /** + * Returns an iterator that produces all non-null values. + */ + @Override + NodeRefIterator iterator(); + + /** + * Returns an iterator that produces all values, including null values. + */ + NodeRefIterator withNullIterator(); + + NodeRefIterable Empty = new NodeRefIterable() { + + public NodeRefIterator withNullIterator() { + return NodeRefIterator.Empty; + } + + public NodeRefIterator iterator() { + return NodeRefIterator.Empty; + } + }; +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeRefIterator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeRefIterator.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.graph; + +import java.util.*; + +import com.oracle.graal.graph.Node.Input; +import com.oracle.graal.graph.Node.Successor; + +/** + * An iterator over the references to a {@link Node}'s {@linkplain Input inputs} and + * {@linkplain Successor successors}. + * + * An iterator of this type will not return null values, unless the field values are modified + * concurrently. Concurrent modifications are detected by an assertion on a best-effort basis. + */ +public class NodeRefIterator implements Iterator { + + public static final NodeRefIterator Empty = new NodeRefIterator(0, 0, false); + + /** + * The total number of {@link Node} and {@link NodeList} fields. + */ + protected final int allNodeRefFields; + + /** + * The number of {@link Node} fields. + */ + protected final int nodeFields; + + /** + * Specifies if this iterator iterates over {@linkplain Input inputs} or {@linkplain Successor + * successors}. + */ + private final boolean isInputs; + + /** + * Current field iteration index. + */ + protected int index; + + /** + * Current iteration index within a {@link NodeList} if {@link #index} denotes a + * {@link NodeList} field. + */ + protected int subIndex; + + /** + * Creates an iterator over a node's references (i.e., {@linkplain Input inputs} or + * {@linkplain Successor successors}) to other nodes. The {@link Node} fields are iterated + * before the {@link NodeList} fields. All elements of these NodeLists will be visited by the + * iterator as well. + * + * @param nodeFields the number of {@link Node} fields in the class hierarchy of the node being + * iterated + * @param nodeListFields the number of {@link NodeList} fields in the class hierarchy of the + * node being iterated + */ + protected NodeRefIterator(int nodeFields, int nodeListFields, boolean isInputs) { + this.allNodeRefFields = nodeListFields + nodeFields; + this.nodeFields = nodeFields; + this.isInputs = isInputs; + index = Node.NOT_ITERABLE; + subIndex = 0; + } + + /** + * Gets the value of a {@link Node} field in the node. + * + * @param at the index of the Node field whose value is being requested. This is guaranteed to + * be between 0 and the {@code nodeFields} value this iterator was constructed with + */ + protected Node getNode(int at) { + throw new NoSuchElementException(); + } + + /** + * Gets the value of a {@link NodeList} field in the node. + * + * @param at the index of the {@link NodeList} field whose value is being requested. This is + * guaranteed to be between 0 and the {@code nodeListFields} value this iterator was + * constructed with + */ + protected NodeList getNodeList(int at) { + throw new NoSuchElementException(); + } + + protected void forward() { + if (index < nodeFields) { + index++; + while (index < nodeFields) { + Node element = getNode(index); + if (element != null) { + return; + } + index++; + } + } else { + subIndex++; + } + while (index < allNodeRefFields) { + NodeList list = getNodeList(index - nodeFields); + while (subIndex < list.size()) { + if (list.get(subIndex) != null) { + return; + } + subIndex++; + } + subIndex = 0; + index++; + } + return; + } + + private Node nextElement() { + if (index < nodeFields) { + return getNode(index); + } else if (index < allNodeRefFields) { + NodeList list = getNodeList(index - nodeFields); + return list.get(subIndex); + } + throw new NoSuchElementException(); + } + + @Override + public boolean hasNext() { + return index >= 0 && index < allNodeRefFields; + } + + @Override + public Node next() { + try { + return nextElement(); + } finally { + forward(); + } + } + + public Position nextPosition() { + try { + if (index < nodeFields) { + return new Position(isInputs, index, Node.NOT_ITERABLE); + } else { + return new Position(isInputs, index, subIndex); + } + } finally { + forward(); + } + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeSuccessorList.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeSuccessorList.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeSuccessorList.java Mon Aug 25 21:15:59 2014 -0700 @@ -47,7 +47,7 @@ } @Override - public boolean add(T node) { + public boolean add(Node node) { self.incModCount(); return super.add(node); } @@ -71,7 +71,7 @@ } @Override - void copy(NodeList other) { + void copy(NodeList other) { self.incModCount(); super.copy(other); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsageIterable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsageIterable.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.graph; + +import static com.oracle.graal.graph.Graph.*; + +import com.oracle.graal.graph.iterators.*; + +class NodeUsageIterable implements NodeIterable { + + final Node node; + + NodeUsageIterable(Node node) { + this.node = node; + } + + public NodeUsageIterator iterator() { + if (MODIFICATION_COUNTS_ENABLED) { + return new NodeUsageWithModCountIterator(node); + } else { + return new NodeUsageIterator(node); + } + } + + @Override + public boolean isEmpty() { + return node.usage0 == null; + } + + @Override + public boolean isNotEmpty() { + return node.usage0 != null; + } + + @Override + public int count() { + return node.usageCount(); + } +} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsageIterator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsageIterator.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.graph; + +import java.util.*; + +class NodeUsageIterator implements Iterator { + + final Node node; + int index = -1; + Node current; + + void advance() { + current = null; + index++; + if (index == 0) { + current = node.usage0; + } else if (index == 1) { + current = node.usage1; + } else { + if (index - Node.INLINE_USAGE_COUNT < node.extraUsages.length) { + current = node.extraUsages[index - Node.INLINE_USAGE_COUNT]; + } + } + } + + public NodeUsageIterator(Node node) { + this.node = node; + advance(); + } + + public boolean hasNext() { + return current != null; + } + + public Node next() { + Node result = current; + if (result == null) { + throw new NoSuchElementException(); + } + advance(); + return result; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } +} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsageWithModCountIterator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsageWithModCountIterator.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.graph; + +import java.util.*; + +class NodeUsageWithModCountIterator extends NodeUsageIterator { + + public NodeUsageWithModCountIterator(Node n) { + super(n); + } + + private final int expectedModCount = node.usageModCount(); + + @Override + public boolean hasNext() { + if (expectedModCount != node.usageModCount()) { + throw new ConcurrentModificationException(); + } + return super.hasNext(); + } + + @Override + public Node next() { + if (expectedModCount != node.usageModCount()) { + throw new ConcurrentModificationException(); + } + return super.next(); + } +} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Position.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Position.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.graph; + +import com.oracle.graal.graph.Node.Input; +import com.oracle.graal.graph.Node.OptionalInput; +import com.oracle.graal.nodeinfo.*; + +/** + * Describes an edge slot for a {@link NodeClass}. + * + * @see NodeClass#getName(Position) + */ +public final class Position { + + /** + * Specifies if this position denotes an {@link Input} or {@link OptionalInput} field. + */ + private final boolean input; + + /** + * Index of the {@link Node} or {@link NodeList} field denoted by this position. + */ + private final int index; + + /** + * Index within a {@link NodeList} if {@link #index} denotes a {@link NodeList} field otherwise + * {@link Node#NOT_ITERABLE}. + */ + private final int subIndex; + + public Position(boolean input, int index, int subIndex) { + this.input = input; + this.index = index; + this.subIndex = subIndex; + } + + public Node get(Node node) { + return node.getNodeClass().get(node, this); + } + + public InputType getInputType(Node node) { + return node.getNodeClass().getInputType(this); + } + + public String getInputName(Node node) { + return node.getNodeClass().getName(this); + } + + public boolean isInputOptional(Node node) { + return node.getNodeClass().isInputOptional(this); + } + + public void set(Node node, Node value) { + node.getNodeClass().set(node, this, value); + } + + public void initialize(Node node, Node value) { + node.getNodeClass().initializePosition(node, this, value); + } + + @Override + public String toString() { + return (input ? "input " : "successor ") + index + "/" + subIndex; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + index; + result = prime * result + (input ? 1231 : 1237); + result = prime * result + subIndex; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Position other = (Position) obj; + if (index != other.index) { + return false; + } + if (input != other.input) { + return false; + } + if (subIndex != other.subIndex) { + return false; + } + return true; + } + + /** + * Gets the index within a {@link NodeList} if {@link #getIndex()} denotes a {@link NodeList} + * field otherwise {@link Node#NOT_ITERABLE}. + */ + public int getSubIndex() { + return subIndex; + } + + /** + * Gets the index of the {@link Node} or {@link NodeList} field denoted by this position. + */ + public int getIndex() { + return index; + } + + /** + * Returns true if this position denotes an {@link Input} or {@link OptionalInput} field, false + * otherwise. + */ + public boolean isInput() { + return input; + } +} diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/AMD64HotSpotFrameOmissionTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -104,7 +104,7 @@ private void testHelper(String name, CodeGenerator gen) { Method method = getMethod(name); ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(method); - InstalledCode installedCode = getCode(javaMethod, parse(method)); + InstalledCode installedCode = getCode(javaMethod, parseEager(method)); TargetDescription target = getCodeCache().getTarget(); RegisterConfig registerConfig = getCodeCache().getRegisterConfig(); diff -r ae0f235469db -r f8e60d11c0ec 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 25 21:15:59 2014 -0700 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.amd64.test; + +import org.junit.*; + +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; + +/** + * Ensures that frame omission works in cases where it is expected to. + */ +public class CompressedNullCheckTest extends GraalCompilerTest { + + private static final class Container { + Integer i = new Integer(1); + } + + public static void testSnippet(Container c) { + c.i.intValue(); + } + + @Test + public void test() { + test("testSnippet", new Container()); + } + + @Override + protected boolean checkMidTierGraph(StructuredGraph graph) { + int count = 0; + for (IsNullNode isNull : graph.getNodes().filter(IsNullNode.class).snapshot()) { + ValueNode value = isNull.getValue(); + if (value instanceof CompressionNode) { + count++; + isNull.replaceFirstInput(value, ((CompressionNode) value).getValue()); + } + } + Assert.assertEquals("graph should contain exactly one IsNullNode", 1, count); + return super.checkMidTierGraph(graph); + } +} diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Mon Aug 25 21:15:59 2014 -0700 @@ -49,6 +49,7 @@ import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.nfi.api.*; /** * HotSpot AMD64 specific backend. @@ -321,15 +322,18 @@ } } - @Override - public NativeFunctionInterface getNativeFunctionInterface() { - HotSpotVMConfig config = getRuntime().getConfig(); + /** + * Called from the VM. + */ + public static NativeFunctionInterface createNativeFunctionInterface() { + HotSpotVMConfig config = HotSpotGraalRuntime.runtime().getConfig(); RawNativeCallNodeFactory factory = new RawNativeCallNodeFactory() { public FixedWithNextNode createRawCallNode(Kind returnType, Constant functionPointer, ValueNode... args) { - return new AMD64RawNativeCallNode(returnType, functionPointer, args); + return AMD64RawNativeCallNode.create(returnType, functionPointer, args); } }; - return new HotSpotNativeFunctionInterface(getProviders(), factory, this, config.dllLoad, config.dllLookup, config.rtldDefault); + Backend backend = HotSpotGraalRuntime.runtime().getBackend(AMD64.class); + return new HotSpotNativeFunctionInterface(HotSpotGraalRuntime.runtime().getHostProviders(), factory, backend, config.dllLoad, config.dllLookup, config.rtldDefault); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,7 +26,7 @@ import com.oracle.graal.asm.amd64.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.StandardOp.*; +import com.oracle.graal.lir.StandardOp.BlockEndOp; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java Mon Aug 25 21:15:59 2014 -0700 @@ -31,7 +31,7 @@ import com.oracle.graal.asm.amd64.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.StandardOp.*; +import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java Mon Aug 25 21:15:59 2014 -0700 @@ -31,7 +31,7 @@ import com.oracle.graal.asm.amd64.*; import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.StandardOp.*; +import com.oracle.graal.lir.StandardOp.BlockEndOp; import com.oracle.graal.lir.asm.*; /** diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Mon Aug 25 21:15:59 2014 -0700 @@ -559,8 +559,19 @@ } public void emitNullCheck(Value address, LIRFrameState state) { - assert address.getKind() == Kind.Object : address + " - " + address.getKind() + " not an object!"; - append(new AMD64Move.NullCheckOp(load(address), state)); + if (address.getLIRKind().getPlatformKind() == Kind.Int) { + CompressEncoding encoding = config.getOopEncoding(); + if (encoding.shift <= 3) { + AMD64AddressValue uncompressionAddress = emitAddress(getProviders().getRegisters().getHeapBaseRegister().asValue(), 0, load(address), 1 << encoding.shift); + append(new AMD64HotSpotMove.CompressedNullCheckOp(uncompressionAddress, state)); + } else { + Value uncompress = emitUncompress(address, encoding, false); + append(new AMD64Move.NullCheckOp(load(uncompress), state)); + } + } else { + assert address.getKind() == Kind.Object : address + " - " + address.getKind() + " not an object!"; + append(new AMD64Move.NullCheckOp(load(address), state)); + } } @Override diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveDeoptimizedStackFrameOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveDeoptimizedStackFrameOp.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveDeoptimizedStackFrameOp.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,8 +22,8 @@ */ package com.oracle.graal.hotspot.amd64; +import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.api.code.ValueUtil.*; -import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import com.oracle.graal.api.code.*; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,7 +27,7 @@ import com.oracle.graal.asm.amd64.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.StandardOp.*; +import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; +import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; @@ -254,4 +255,24 @@ } } + public static class CompressedNullCheckOp extends AMD64LIRInstruction { + + @Use({COMPOSITE}) protected AMD64AddressValue address; + @State protected LIRFrameState state; + + public CompressedNullCheckOp(AMD64AddressValue address, LIRFrameState state) { + this.address = address; + this.state = state; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + crb.recordImplicitException(masm.position(), state); + masm.testl(AMD64.rax, address.toAddress()); + } + + public LIRFrameState getState() { + return state; + } + } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Mon Aug 25 21:15:59 2014 -0700 @@ -47,8 +47,8 @@ import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java Mon Aug 25 21:15:59 2014 -0700 @@ -29,7 +29,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.StandardOp.*; +import com.oracle.graal.lir.StandardOp.BlockEndOp; import com.oracle.graal.lir.asm.*; /** diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java Mon Aug 25 21:15:59 2014 -0700 @@ -31,7 +31,7 @@ import com.oracle.graal.asm.amd64.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.StandardOp.*; +import com.oracle.graal.lir.StandardOp.BlockEndOp; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -28,15 +28,21 @@ import com.oracle.graal.compiler.amd64.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public class AMD64RawNativeCallNode extends FixedWithNextNode implements LIRLowerable { private final Constant functionPointer; - @Input private final NodeInputList args; + @Input NodeInputList args; - public AMD64RawNativeCallNode(Kind returnType, Constant functionPointer, ValueNode[] args) { + public static AMD64RawNativeCallNode create(Kind returnType, Constant functionPointer, ValueNode[] args) { + return USE_GENERATED_NODES ? new AMD64RawNativeCallNodeGen(returnType, functionPointer, args) : new AMD64RawNativeCallNode(returnType, functionPointer, args); + } + + protected AMD64RawNativeCallNode(Kind returnType, Constant functionPointer, ValueNode[] args) { super(StampFactory.forKind(returnType)); this.functionPointer = functionPointer; this.args = new NodeInputList<>(this, args); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/DonorThreadPool.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/DonorThreadPool.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.hsail; - -import static com.oracle.graal.hotspot.hsail.HSAILHotSpotBackend.Options.*; - -import java.util.concurrent.*; - -import com.oracle.graal.hotspot.hsail.HSAILHotSpotBackend.Options; - -/** - * Thread pool for HSAIL allocation support. - */ -public class DonorThreadPool { - - private final Thread[] threads; - - void waitAt(CyclicBarrier barrier) { - try { - barrier.await(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * Creates a pool of threads whose size is given by {@link Options#HsailDonorThreads}. - */ - DonorThreadPool() { - int size = HsailDonorThreads.getValue(); - this.threads = new Thread[size]; - CyclicBarrier barrier = new CyclicBarrier(size + 1); - - // fill in threads - for (int i = 0; i < size; i++) { - threads[i] = new Thread(new Runnable() { - @Override - public void run() { - while (true) { - waitAt(barrier); - } - } - }, "HsailDonorThread-" + i); - threads[i].setDaemon(true); - threads[i].start(); - } - // creating thread waits at barrier to make sure others have started - waitAt(barrier); - } - - public Thread[] getThreads() { - return threads; - } -} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/ForEachToGraal.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/ForEachToGraal.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/ForEachToGraal.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,12 +27,12 @@ import java.lang.reflect.*; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.*; import java.util.function.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.GraalInternalError; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.hsail.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Mon Aug 25 21:15:59 2014 -0700 @@ -85,8 +85,8 @@ public static class Options { // @formatter:off - @Option(help = "Number of donor threads for HSAIL kernel dispatch") - static public final OptionValue HsailDonorThreads = new OptionValue<>(4); + @Option(help = "Number of TLABs used for HSAIL kernels which allocate") + static public final OptionValue HsailKernelTlabs = new OptionValue<>(4); // @formatter:on } @@ -369,25 +369,18 @@ return result; } - private static final ThreadLocal donorThreadPool = new ThreadLocal() { - @Override - protected DonorThreadPool initialValue() { - return new DonorThreadPool(); - } - }; - public boolean executeKernel(HotSpotInstalledCode kernel, int jobSize, Object[] args) throws InvalidInstalledCodeException { if (!deviceInitialized) { throw new GraalInternalError("Cannot execute GPU kernel if device is not initialized"); } int[] oopMapArray = ((HSAILHotSpotNmethod) kernel).getOopMapArray(); - // Pass donorThreadPoolArray if this kernel uses allocation, otherwise null - Thread[] donorThreadArray = ((HSAILHotSpotNmethod) kernel).getUsesAllocationFlag() ? donorThreadPool.get().getThreads() : null; - return executeKernel0(kernel, jobSize, args, donorThreadArray, HsailAllocBytesPerWorkitem.getValue(), oopMapArray); + // Pass HsailKernelTlabs number if this kernel uses allocation, otherwise 0 + int numTlabs = ((HSAILHotSpotNmethod) kernel).getUsesAllocationFlag() ? HsailKernelTlabs.getValue() : 0; + return executeKernel0(kernel, jobSize, args, numTlabs, HsailAllocBytesPerWorkitem.getValue(), oopMapArray); } - private static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args, Thread[] donorThreads, int allocBytesPerWorkitem, int[] oopMapArray) + private static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args, int numTlabs, int allocBytesPerWorkitem, int[] oopMapArray) throws InvalidInstalledCodeException; /** @@ -633,12 +626,12 @@ RegisterValue d16_deoptInfo = HSAIL.d16.asValue(wordLIRKind); // Aliases for d17 - RegisterValue d17_donorThreadIndex = HSAIL.d17.asValue(wordLIRKind); - RegisterValue d17_safepointFlagAddrIndex = d17_donorThreadIndex; + RegisterValue d17_tlabIndex = HSAIL.d17.asValue(wordLIRKind); + RegisterValue d17_safepointFlagAddrIndex = d17_tlabIndex; // Aliases for s34 RegisterValue s34_deoptOccurred = HSAIL.s34.asValue(LIRKind.value(Kind.Int)); - RegisterValue s34_donorThreadIndex = s34_deoptOccurred; + RegisterValue s34_tlabIndex = s34_deoptOccurred; asm.emitLoadKernelArg(d16_deoptInfo, asm.getDeoptInfoName(), "u64"); asm.emitComment("// Check if a deopt or safepoint has occurred and abort if true before doing any work"); @@ -657,15 +650,15 @@ // load thread register if this kernel performs allocation if (usesAllocation) { RegisterValue threadReg = getProviders().getRegisters().getThreadRegister().asValue(wordLIRKind); - assert HsailDonorThreads.getValue() > 0; + assert HsailKernelTlabs.getValue() > 0; asm.emitLoad(wordKind, threadReg, new HSAILAddressValue(wordLIRKind, d16_deoptInfo, config.hsailCurTlabInfoOffset).toAddress()); - if (HsailDonorThreads.getValue() != 1) { - asm.emitComment("// map workitem to a donor thread"); - asm.emitString(String.format("rem_u32 $%s, %s, %d;", s34_donorThreadIndex.getRegister(), workItemReg, HsailDonorThreads.getValue())); - asm.emitConvert(d17_donorThreadIndex, s34_donorThreadIndex, wordKind, Kind.Int); - asm.emit("mad", threadReg, d17_donorThreadIndex, Constant.forInt(8), threadReg); + if (HsailKernelTlabs.getValue() != 1) { + asm.emitComment("// map workitem to a tlab"); + asm.emitString(String.format("rem_u32 $%s, %s, %d;", s34_tlabIndex.getRegister(), workItemReg, HsailKernelTlabs.getValue())); + asm.emitConvert(d17_tlabIndex, s34_tlabIndex, wordKind, Kind.Int); + asm.emit("mad", threadReg, d17_tlabIndex, Constant.forInt(8), threadReg); } else { - // workitem is already mapped to solitary donor thread + // workitem is already mapped to solitary tlab } asm.emitComment("// $" + getProviders().getRegisters().getThreadRegister() + " will point to holder of tlab thread info for this workitem"); } @@ -686,7 +679,9 @@ String iterationObjArgReg = HSAIL.mapRegister(cc.getArgument(nonConstantParamCount - 1)); /* * iterationObjArgReg will be the highest $d register in use (it is the last parameter) - * so tempReg can be the next higher $d register + * so tempReg can be the next higher $d register. As of 1.0 spec, we cannot use + * ld_global_u32 $dxx, [addr]; so we need a temporary $s register. We can use + * workItemReg+1; */ String tmpReg = "$d" + (asRegister(cc.getArgument(nonConstantParamCount - 1)).encoding() + 1); // Convert gid to long. @@ -699,9 +694,13 @@ asm.emitString("add_u64 " + tmpReg + ", " + tmpReg + ", " + iterationObjArgReg + "; // Add to array ref ptr"); // Load the object into the parameter reg. if (useCompressedOops) { + int workItemRegEncoding = asRegister(cc.getArgument(nonConstantParamCount)).encoding(); + String tmpReg32 = "$s" + Integer.toString(workItemRegEncoding + 1); - // Load u32 into the d 64 reg since it will become an object address - asm.emitString("ld_global_u32 " + tmpReg + ", " + "[" + tmpReg + "]" + "; // Load compressed ptr from array"); + // Load u32 into the temporary $s reg since it will become an object address + + asm.emitString("ld_global_u32 " + tmpReg32 + ", " + "[" + tmpReg + "]" + "; // Load compressed ptr from array"); + asm.emitString("cvt_u64_u32 " + tmpReg + ", " + tmpReg32 + "; // cvt to 64 bits"); long narrowOopBase = config.narrowOopBase; long narrowOopShift = config.narrowOopShift; @@ -1069,10 +1068,10 @@ return null; } StructuredGraph hostGraph = new StructuredGraph(method, -2); - ParameterNode deoptId = hostGraph.unique(new ParameterNode(0, StampFactory.intValue())); - ParameterNode hsailFrame = hostGraph.unique(new ParameterNode(1, StampFactory.forKind(providers.getCodeCache().getTarget().wordKind))); - ParameterNode reasonAndAction = hostGraph.unique(new ParameterNode(2, StampFactory.intValue())); - ParameterNode speculation = hostGraph.unique(new ParameterNode(3, StampFactory.object())); + ParameterNode deoptId = hostGraph.unique(ParameterNode.create(0, StampFactory.intValue())); + ParameterNode hsailFrame = hostGraph.unique(ParameterNode.create(1, StampFactory.forKind(providers.getCodeCache().getTarget().wordKind))); + ParameterNode reasonAndAction = hostGraph.unique(ParameterNode.create(2, StampFactory.intValue())); + ParameterNode speculation = hostGraph.unique(ParameterNode.create(3, StampFactory.object())); BeginNode[] branches = new BeginNode[deopts.size() + 1]; int[] keys = new int[deopts.size()]; int[] keySuccessors = new int[deopts.size() + 1]; @@ -1095,7 +1094,7 @@ keyProbabilities[deopts.size()] = 0; // default keySuccessors[deopts.size()] = deopts.size(); branches[deopts.size()] = createHostCrashBranch(hostGraph, deoptId); - IntegerSwitchNode switchNode = hostGraph.add(new IntegerSwitchNode(deoptId, branches, keys, keyProbabilities, keySuccessors)); + IntegerSwitchNode switchNode = hostGraph.add(IntegerSwitchNode.create(deoptId, branches, keys, keyProbabilities, keySuccessors)); StartNode start = hostGraph.start(); start.setNext(switchNode); /* @@ -1106,16 +1105,16 @@ } private static BeginNode createHostCrashBranch(StructuredGraph hostGraph, ValueNode deoptId) { - VMErrorNode vmError = hostGraph.add(new VMErrorNode("Error in HSAIL deopt. DeoptId=%d", deoptId)); + VMErrorNode vmError = hostGraph.add(VMErrorNode.create("Error in HSAIL deopt. DeoptId=%d", deoptId)); // ConvertNode.convert(hostGraph, Kind.Long, deoptId))); - vmError.setNext(hostGraph.add(new ReturnNode(ConstantNode.defaultForKind(hostGraph.method().getSignature().getReturnKind(), hostGraph)))); + vmError.setNext(hostGraph.add(ReturnNode.create(ConstantNode.defaultForKind(hostGraph.method().getSignature().getReturnKind(), hostGraph)))); return BeginNode.begin(vmError); } private static BeginNode createHostDeoptBranch(DeoptimizingOp deopt, ParameterNode hsailFrame, ValueNode reasonAndAction, ValueNode speculation, HotSpotProviders providers, HotSpotVMConfig config, int numSRegs, int numDRegs) { - BeginNode branch = hsailFrame.graph().add(new BeginNode()); - DynamicDeoptimizeNode deoptimization = hsailFrame.graph().add(new DynamicDeoptimizeNode(reasonAndAction, speculation)); + BeginNode branch = hsailFrame.graph().add(BeginNode.create()); + DynamicDeoptimizeNode deoptimization = hsailFrame.graph().add(DynamicDeoptimizeNode.create(reasonAndAction, speculation)); deoptimization.setStateBefore(createFrameState(deopt.getFrameState().topFrame, hsailFrame, providers, config, numSRegs, numDRegs)); branch.setNext(deoptimization); return branch; @@ -1148,7 +1147,7 @@ locks[i] = lirValueToHirNode.apply(lockValue); monitorIds[i] = getMonitorIdForHotSpotMonitorValueFromFrame(lockValue, hsailFrame, hostGraph); } - FrameState frameState = hostGraph.add(new FrameState(lowLevelFrame.getMethod(), lowLevelFrame.getBCI(), locals, stack, locks, monitorIds, lowLevelFrame.rethrowException, false)); + FrameState frameState = hostGraph.add(FrameState.create(lowLevelFrame.getMethod(), lowLevelFrame.getBCI(), locals, stack, locks, monitorIds, lowLevelFrame.rethrowException, false)); if (outterFrameState != null) { frameState.setOuterFrameState(outterFrameState); } @@ -1163,7 +1162,7 @@ VirtualObject virtualObject = entry.getKey(); VirtualObjectNode virtualObjectNode = entry.getValue(); List fieldValues = Arrays.stream(virtualObject.getValues()).map(lirValueToHirNode).collect(Collectors.toList()); - virtualStates.add(new VirtualObjectState(virtualObjectNode, fieldValues)); + virtualStates.add(VirtualObjectState.create(virtualObjectNode, fieldValues)); } // New virtual objects may have been discovered while processing the previous set. // Wait until a fixed point is reached @@ -1208,9 +1207,9 @@ private static ValueNode getNodeForVirtualObjectFromFrame(VirtualObject virtualObject, Map virtualObjects, StructuredGraph hostGraph) { return virtualObjects.computeIfAbsent(virtualObject, vo -> { if (vo.getType().isArray()) { - return hostGraph.add(new VirtualArrayNode(vo.getType().getComponentType(), vo.getValues().length)); + return hostGraph.add(VirtualArrayNode.create(vo.getType().getComponentType(), vo.getValues().length)); } else { - return hostGraph.add(new VirtualInstanceNode(vo.getType(), true)); + return hostGraph.add(VirtualInstanceNode.create(vo.getType(), true)); } }); } @@ -1230,7 +1229,7 @@ } else { throw GraalInternalError.shouldNotReachHere("unknown hsail register: " + regNumber); } - valueNode = hostGraph.unique(new FloatingReadNode(hsailFrame, location, null, StampFactory.forKind(valueKind))); + valueNode = hostGraph.unique(FloatingReadNode.create(hsailFrame, location, null, StampFactory.forKind(valueKind))); return valueNode; } @@ -1242,7 +1241,7 @@ int intSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Int); long offset = config.hsailFrameHeaderSize + (intSize * numSRegs) + (longSize * numDRegs) + HSAIL.getStackOffsetStart(slot, slotSizeInBits); LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, valueKind, offset, hostGraph); - ValueNode valueNode = hostGraph.unique(new FloatingReadNode(hsailFrame, location, null, StampFactory.forKind(valueKind))); + ValueNode valueNode = hostGraph.unique(FloatingReadNode.create(hsailFrame, location, null, StampFactory.forKind(valueKind))); return valueNode; } else { throw GraalInternalError.shouldNotReachHere("unsupported stack slot kind: " + valueKind); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,12 +26,12 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.hsail.replacements.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hsail.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; -import com.oracle.graal.hotspot.hsail.replacements.*; @ServiceProvider(HotSpotBackendFactory.class) public class HSAILHotSpotBackendFactory implements HotSpotBackendFactory { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,20 +22,20 @@ */ package com.oracle.graal.hotspot.hsail; +import java.util.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.hsail.replacements.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.hotspot.hsail.replacements.*; - -import java.util.HashMap; +import com.oracle.graal.nodes.spi.*; public class HSAILHotSpotLoweringProvider extends DefaultHotSpotLoweringProvider { @@ -94,7 +94,7 @@ default: reason = DeoptimizationReason.None; } - unwind.replaceAtPredecessor(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, reason))); + unwind.replaceAtPredecessor(graph.add(DeoptimizeNode.create(DeoptimizationAction.InvalidateReprofile, reason))); unwind.safeDelete(); } else { // unwind whose exception is not an instance of ForeignCallNode @@ -103,22 +103,22 @@ } }; - private HashMap, LoweringStrategy> strategyMap = new HashMap<>(); + private HashMap strategyMap = new HashMap<>(); void initStrategyMap() { - strategyMap.put(ConvertNode.class, PassThruStrategy); - strategyMap.put(FloatConvertNode.class, PassThruStrategy); - strategyMap.put(NewInstanceNode.class, NewObjectStrategy); - strategyMap.put(NewArrayNode.class, NewObjectStrategy); - strategyMap.put(NewMultiArrayNode.class, RejectStrategy); - strategyMap.put(DynamicNewArrayNode.class, RejectStrategy); - strategyMap.put(MonitorEnterNode.class, RejectStrategy); - strategyMap.put(MonitorExitNode.class, RejectStrategy); - strategyMap.put(UnwindNode.class, UnwindNodeStrategy); + strategyMap.put(NodeClass.get(ConvertNode.class), PassThruStrategy); + strategyMap.put(NodeClass.get(FloatConvertNode.class), PassThruStrategy); + strategyMap.put(NodeClass.get(NewInstanceNode.class), NewObjectStrategy); + strategyMap.put(NodeClass.get(NewArrayNode.class), NewObjectStrategy); + strategyMap.put(NodeClass.get(NewMultiArrayNode.class), RejectStrategy); + strategyMap.put(NodeClass.get(DynamicNewArrayNode.class), RejectStrategy); + strategyMap.put(NodeClass.get(MonitorEnterNode.class), RejectStrategy); + strategyMap.put(NodeClass.get(MonitorExitNode.class), RejectStrategy); + strategyMap.put(NodeClass.get(UnwindNode.class), UnwindNodeStrategy); } private LoweringStrategy getStrategy(Node n) { - return strategyMap.get(n.getClass()); + return strategyMap.get(n.getNodeClass()); } public HSAILHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, TargetDescription target) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILDirectLoadAcquireNode.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILDirectLoadAcquireNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILDirectLoadAcquireNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,15 +23,21 @@ package com.oracle.graal.hotspot.hsail.replacements; import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.hsail.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.nodes.*; -import com.oracle.graal.hotspot.hsail.*; import com.oracle.graal.word.*; +@NodeInfo public class HSAILDirectLoadAcquireNode extends DirectReadNode { - public HSAILDirectLoadAcquireNode(ValueNode address, Kind readKind) { + public static HSAILDirectLoadAcquireNode create(ValueNode address, Kind readKind) { + return USE_GENERATED_NODES ? new HSAILDirectLoadAcquireNodeGen(address, readKind) : new HSAILDirectLoadAcquireNode(address, readKind); + } + + protected HSAILDirectLoadAcquireNode(ValueNode address, Kind readKind) { super(address, readKind); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILDirectStoreReleaseNode.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILDirectStoreReleaseNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILDirectStoreReleaseNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,15 +23,21 @@ package com.oracle.graal.hotspot.hsail.replacements; import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.hsail.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.nodes.*; -import com.oracle.graal.hotspot.hsail.*; import com.oracle.graal.word.*; +@NodeInfo public class HSAILDirectStoreReleaseNode extends DirectStoreNode { - public HSAILDirectStoreReleaseNode(ValueNode address, ValueNode value, Kind kind) { + public static HSAILDirectStoreReleaseNode create(ValueNode address, ValueNode value, Kind kind) { + return USE_GENERATED_NODES ? new HSAILDirectStoreReleaseNodeGen(address, value, kind) : new HSAILDirectStoreReleaseNode(address, value, kind); + } + + protected HSAILDirectStoreReleaseNode(ValueNode address, ValueNode value, Kind kind) { super(address, value, kind); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILHotSpotReplacementsUtil.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILHotSpotReplacementsUtil.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILHotSpotReplacementsUtil.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,11 +24,11 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.replacements.Snippet.Fold; import com.oracle.graal.word.*; -import com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil; -import com.oracle.graal.hotspot.meta.*; //JaCoCo Exclude @@ -50,7 +50,7 @@ public static final LocationIdentity TLABINFO_START_LOCATION = new NamedLocationIdentity("TlabInfoStart"); public static final LocationIdentity TLABINFO_ALLOCINFO_LOCATION = new NamedLocationIdentity("TlabInfoAllocInfo"); public static final LocationIdentity TLABINFO_ORIGINALTOP_LOCATION = new NamedLocationIdentity("TlabInfoOriginalTop"); - public static final LocationIdentity TLABINFO_DONORTHREAD_LOCATION = new NamedLocationIdentity("TlabInfoDonorThread"); + public static final LocationIdentity TLABINFO_TLAB_LOCATION = new NamedLocationIdentity("TlabInfoTlab"); public static final LocationIdentity ALLOCINFO_TLABINFOSPOOLNEXT_LOCATION = new NamedLocationIdentity("AllocInfoTlabInfosPoolNext"); public static final LocationIdentity ALLOCINFO_TLABINFOSPOOLEND_LOCATION = new NamedLocationIdentity("AllocInfoTlabInfosPoolEnd"); @@ -121,12 +121,12 @@ tlabInfo.writeWord(config().hsailTlabInfoOriginalTopOffset, val, TLABINFO_ORIGINALTOP_LOCATION); } - public static void writeTlabInfoDonorThread(Word tlabInfo, Word val) { - tlabInfo.writeWord(config().hsailTlabInfoDonorThreadOffset, val, TLABINFO_DONORTHREAD_LOCATION); + public static void writeTlabInfoTlab(Word tlabInfo, Word val) { + tlabInfo.writeWord(config().hsailTlabInfoTlabOffset, val, TLABINFO_TLAB_LOCATION); } - public static Word readTlabInfoDonorThread(Word tlabInfo) { - return tlabInfo.readWord(config().hsailTlabInfoDonorThreadOffset, TLABINFO_DONORTHREAD_LOCATION); + public static Word readTlabInfoTlab(Word tlabInfo) { + return tlabInfo.readWord(config().hsailTlabInfoTlabOffset, TLABINFO_TLAB_LOCATION); } public static Word readAllocInfoTlabInfosPoolEnd(Word allocInfo) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java Mon Aug 25 21:15:59 2014 -0700 @@ -97,7 +97,7 @@ Word alignReserveBytes = readAllocInfoTlabAlignReserveBytes(allocInfo); writeTlabInfoEnd(newTlabInfo, tlabStart.add(newTlabSize.subtract(alignReserveBytes))); writeTlabInfoAllocInfo(newTlabInfo, allocInfo); - writeTlabInfoDonorThread(newTlabInfo, readTlabInfoDonorThread(oldTlabInfo)); + writeTlabInfoTlab(newTlabInfo, readTlabInfoTlab(oldTlabInfo)); return (newTlabInfo); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILWorkItemAbsIdNode.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILWorkItemAbsIdNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILWorkItemAbsIdNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,13 +24,19 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.hotspot.hsail.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.hotspot.hsail.*; +@NodeInfo public class HSAILWorkItemAbsIdNode extends FixedWithNextNode implements LIRLowerable { - public HSAILWorkItemAbsIdNode() { + public static HSAILWorkItemAbsIdNode create() { + return USE_GENERATED_NODES ? new HSAILWorkItemAbsIdNodeGen() : new HSAILWorkItemAbsIdNode(); + } + + protected HSAILWorkItemAbsIdNode() { super(StampFactory.forKind(Kind.Int)); } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.jdk8.test; - -import java.io.*; -import java.nio.*; -import java.util.zip.*; - -import org.junit.*; - -import com.oracle.graal.compiler.test.*; - -/** - * Tests compiled call to {@link CRC32#updateByteBuffer(int, long, int, int)}. - */ -@SuppressWarnings("javadoc") -public class CRC32UpdateByteBufferSubstitutionTest extends GraalCompilerTest { - - public static long updateByteBuffer(ByteBuffer buffer) { - CRC32 crc = new CRC32(); - buffer.rewind(); - crc.update(buffer); - return crc.getValue(); - } - - @Test - public void test1() throws Throwable { - String classfileName = CRC32UpdateByteBufferSubstitutionTest.class.getSimpleName().replace('.', '/') + ".class"; - InputStream s = CRC32UpdateByteBufferSubstitutionTest.class.getResourceAsStream(classfileName); - byte[] buf = new byte[s.available()]; - new DataInputStream(s).readFully(buf); - - ByteBuffer directBuf = ByteBuffer.allocateDirect(buf.length); - directBuf.put(buf); - ByteBuffer heapBuf = ByteBuffer.wrap(buf); - - test("updateByteBuffer", directBuf); - test("updateByteBuffer", heapBuf); - } -} diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.loader/src/com/oracle/graal/hotspot/loader/Factory.java Mon Aug 25 21:15:59 2014 -0700 @@ -40,7 +40,8 @@ @SuppressWarnings("unused") private static ClassLoader newClassLoader() throws MalformedURLException { URL[] urls = {getGraalJarUrl("graal"), getGraalJarUrl("graal-truffle")}; - return URLClassLoader.newInstance(urls); + ClassLoader parent = null; + return URLClassLoader.newInstance(urls, parent); } /** diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java Mon Aug 25 21:15:59 2014 -0700 @@ -46,7 +46,6 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; -import com.oracle.graal.lir.LIRInstruction.ValueProcedure; import com.oracle.graal.lir.StandardOp.LabelOp; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.gen.*; @@ -225,7 +224,7 @@ return kernel; } - static final class RegisterAnalysis extends ValueProcedure { + static final class RegisterAnalysis extends ValueConsumer { private final SortedSet signed32 = new TreeSet<>(); private final SortedSet signed64 = new TreeSet<>(); @@ -261,7 +260,7 @@ } @Override - public Value doValue(Value value, OperandMode mode, EnumSet flags) { + public void visitValue(Value value, OperandMode mode, EnumSet flags) { if (isVariable(value)) { Variable regVal = (Variable) value; Kind regKind = regVal.getKind(); @@ -310,7 +309,6 @@ } } } - return value; } } @@ -426,8 +424,8 @@ } // Record registers used in the kernel registerAnalysis.op = op; - op.forEachTemp(registerAnalysis); - op.forEachOutput(registerAnalysis); + op.visitEachTemp(registerAnalysis); + op.visitEachOutput(registerAnalysis); } } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotNodeLIRBuilder.java diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java Mon Aug 25 21:15:59 2014 -0700 @@ -192,7 +192,7 @@ InvokeNode kernelStart = createInvoke(getClass(), "getKernelStart", ConstantNode.forConstant(HotSpotObjectConstant.forObject(kernel), providers.getMetaAccess(), getGraph())); - AllocaNode buf = append(new AllocaNode(bufSize / wordSize, new BitSet())); + AllocaNode buf = append(AllocaNode.create(bufSize / wordSize, new BitSet())); ValueNode objectParametersOffsets; ValueNode pinnedObjects; ConstantNode nullWord = ConstantNode.forIntegerKind(wordKind, 0L, getGraph()); @@ -202,22 +202,22 @@ } else { int intsPerWord = wordSize / intSize; int slots = roundUp(objectSlots.size(), intsPerWord); - objectParametersOffsets = append(new AllocaNode(slots, new BitSet())); + objectParametersOffsets = append(AllocaNode.create(slots, new BitSet())); // No refmap for pinned objects list since kernel execution is (currently) GC unsafe - pinnedObjects = append(new AllocaNode(objectSlots.size(), new BitSet())); + pinnedObjects = append(AllocaNode.create(objectSlots.size(), new BitSet())); // Initialize the object parameter offsets array int index = 0; for (int slot : objectSlots) { int offset = slot * wordSize; LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, index * intSize, getGraph()); - append(new WriteNode(objectParametersOffsets, ConstantNode.forInt(offset, getGraph()), location, BarrierType.NONE, false)); + append(WriteNode.create(objectParametersOffsets, ConstantNode.forInt(offset, getGraph()), location, BarrierType.NONE, false)); index++; } } Map args = new EnumMap<>(LaunchArg.class); - args.put(Thread, append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), true, false))); + args.put(Thread, append(ReadRegisterNode.create(providers.getRegisters().getThreadRegister(), true, false))); args.put(Kernel, kernelStart); args.put(DimX, forInt(1, getGraph())); args.put(DimY, forInt(1, getGraph())); @@ -234,12 +234,12 @@ ParameterNode javaParameter = javaParameters[javaParametersIndex]; int javaParameterOffset = javaParameterOffsetsInKernelParametersBuffer[javaParametersIndex]; LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, javaParameter.getKind(), javaParameterOffset, getGraph()); - append(new WriteNode(buf, javaParameter, location, BarrierType.NONE, false)); + append(WriteNode.create(buf, javaParameter, location, BarrierType.NONE, false)); updateDimArg(method, sig, sigIndex++, args, javaParameter); } if (returnKind != Kind.Void) { LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, bufSize - wordSize, getGraph()); - append(new WriteNode(buf, nullWord, location, BarrierType.NONE, false)); + append(WriteNode.create(buf, nullWord, location, BarrierType.NONE, false)); } HIRFrameStateBuilder fsb = new HIRFrameStateBuilder(method, getGraph(), true); @@ -247,7 +247,7 @@ getGraph().start().setStateAfter(fs); ValueNode[] launchArgsArray = args.values().toArray(new ValueNode[args.size()]); - ForeignCallNode result = append(new ForeignCallNode(providers.getForeignCalls(), CALL_KERNEL, launchArgsArray)); + ForeignCallNode result = append(ForeignCallNode.create(providers.getForeignCalls(), CALL_KERNEL, launchArgsArray)); result.setStateAfter(fs); InvokeNode getObjectResult = null; @@ -261,13 +261,13 @@ case Short: case Char: case Int: - returnValue = unique(new NarrowNode(result, 32)); + returnValue = unique(NarrowNode.create(result, 32)); break; case Long: returnValue = result; break; case Float: { - ValueNode asInt = unique(new NarrowNode(result, 32)); + ValueNode asInt = unique(NarrowNode.create(result, 32)); returnValue = ReinterpretNode.reinterpret(Kind.Float, asInt); break; } @@ -282,7 +282,7 @@ throw new GraalInternalError("%s return kind not supported", returnKind); } - append(new ReturnNode(returnValue)); + append(ReturnNode.create(returnValue)); if (Debug.isDumpEnabled()) { Debug.dump(getGraph(), "Initial kernel launch graph"); @@ -314,7 +314,7 @@ } else { stamp = StampFactory.forKind(kind); } - javaParameters[javaParametersIndex] = unique(new ParameterNode(javaParametersIndex, stamp)); + javaParameters[javaParametersIndex] = unique(ParameterNode.create(javaParametersIndex, stamp)); bufSize += kindByteSize; } @@ -326,7 +326,7 @@ if (sigIndex >= 0) { ParallelOver parallelOver = method.getParameterAnnotation(ParallelOver.class, sigIndex); if (parallelOver != null && sig.getParameterType(sigIndex, method.getDeclaringClass()).equals(providers.getMetaAccess().lookupJavaType(int[].class))) { - ArrayLengthNode dimension = append(new ArrayLengthNode(javaParameter)); + ArrayLengthNode dimension = append(ArrayLengthNode.create(javaParameter)); LaunchArg argKey = LaunchArg.valueOf(LaunchArg.class, "Dim" + parallelOver.dimension()); ValueNode existing = launchArgs.put(argKey, dimension); if (existing != null && existing instanceof ArrayLengthNode) { diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import java.io.*; import java.lang.reflect.*; import java.util.*; +import java.util.stream.*; import java.util.zip.*; import com.oracle.graal.api.runtime.*; @@ -57,10 +58,7 @@ } public Iterator iterator() { - List entries = new ArrayList<>(); - for (ZipFile jar : jars) { - entries.addAll(Collections.list(jar.entries())); - } + Stream entries = jars.stream().flatMap(ZipFile::stream); return entries.iterator(); } @@ -148,7 +146,8 @@ } /** - * Generates code for {@code GraalRuntime::set_option()}. + * Generates code for {@code GraalRuntime::set_option()} and + * {@code GraalRuntime::set_option_bool()}. */ private static void genSetOption(PrintStream out) throws Exception { SortedMap options = getOptions(); @@ -159,21 +158,20 @@ } lengths.add("PrintFlags".length()); - out.println("bool GraalRuntime::set_option(KlassHandle hotSpotOptionsClass, char* name, int name_len, const char* value, TRAPS) {"); + out.println("bool GraalRuntime::set_option_bool(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, char value, TRAPS) {"); out.println(" bool check_only = hotSpotOptionsClass.is_null();"); - out.println(" if (value != NULL && (value[0] == '+' || value[0] == '-')) {"); - out.println(" // boolean options"); genMatchers(out, lengths, options, true); - out.println(" } else {"); - out.println(" // non-boolean options"); + out.println(" return false;"); + out.println("}"); + out.println("bool GraalRuntime::set_option(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, const char* value, TRAPS) {"); + out.println(" bool check_only = hotSpotOptionsClass.is_null();"); genMatchers(out, lengths, options, false); - out.println(" }"); out.println(" return false;"); out.println("}"); } protected static void genMatchers(PrintStream out, Set lengths, SortedMap options, boolean isBoolean) throws Exception { - out.println(" switch (name_len) {"); + out.println(" switch (name_len) {"); for (int len : lengths) { boolean printedCase = false; @@ -181,56 +179,56 @@ // null terminated for = style options. if (len == "PrintFlags".length() && isBoolean) { printedCase = true; - out.println(" case " + len + ":"); - out.printf(" if (strncmp(name, \"PrintFlags\", %d) == 0) {%n", len); - out.println(" if (value[0] == '+') {"); - out.println(" if (check_only) {"); - out.println(" TempNewSymbol name = SymbolTable::new_symbol(\"Lcom/oracle/graal/hotspot/HotSpotOptions;\", CHECK_(true));"); - out.println(" hotSpotOptionsClass = SystemDictionary::resolve_or_fail(name, true, CHECK_(true));"); - out.println(" }"); - out.println(" set_option_helper(hotSpotOptionsClass, name, name_len, Handle(), '?', Handle(), 0L);"); + out.println(" case " + len + ":"); + out.printf(" if (strncmp(name, \"PrintFlags\", %d) == 0) {%n", len); + out.println(" if (value == '+') {"); + out.println(" if (check_only) {"); + out.println(" TempNewSymbol name = SymbolTable::new_symbol(\"Lcom/oracle/graal/hotspot/HotSpotOptions;\", CHECK_(true));"); + out.println(" hotSpotOptionsClass = SystemDictionary::resolve_or_fail(name, true, CHECK_(true));"); out.println(" }"); - out.println(" return true;"); + out.println(" set_option_helper(hotSpotOptionsClass, name, name_len, Handle(), '?', Handle(), 0L);"); out.println(" }"); + out.println(" return true;"); + out.println(" }"); } for (Map.Entry e : options.entrySet()) { OptionDescriptor desc = e.getValue(); if (e.getKey().length() == len && ((desc.getType() == Boolean.class) == isBoolean)) { if (!printedCase) { printedCase = true; - out.println(" case " + len + ":"); + out.println(" case " + len + ":"); } - out.printf(" if (strncmp(name, \"%s\", %d) == 0) {%n", e.getKey(), len); + out.printf(" if (strncmp(name, \"%s\", %d) == 0) {%n", e.getKey(), len); Class declaringClass = desc.getDeclaringClass(); if (isBoolean) { - out.printf(" Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(), + out.printf(" Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(), + toInternalName(getFieldType(desc))); + out.println(" if (!check_only) {"); + out.println(" set_option_helper(hotSpotOptionsClass, name, name_len, option, value, Handle(), 0L);"); + out.println(" }"); + } else if (desc.getType() == String.class) { + out.println(" check_required_value(name, name_len, value, CHECK_(true));"); + out.printf(" Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(), toInternalName(getFieldType(desc))); - out.println(" if (!check_only) {"); - out.println(" set_option_helper(hotSpotOptionsClass, name, name_len, option, value[0], Handle(), 0L);"); - out.println(" }"); - } else if (desc.getType() == String.class) { - out.println(" check_required_value(name, name_len, value, CHECK_(true));"); + out.println(" if (!check_only) {"); + out.println(" Handle stringValue = java_lang_String::create_from_str(value, CHECK_(true));"); + out.println(" set_option_helper(hotSpotOptionsClass, name, name_len, option, 's', stringValue, 0L);"); + out.println(" }"); + } else { + char spec = getPrimitiveSpecChar(desc); + out.println(" jlong primitiveValue = parse_primitive_option_value('" + spec + "', name, name_len, value, CHECK_(true));"); + out.println(" if (!check_only) {"); out.printf(" Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(), toInternalName(getFieldType(desc))); - out.println(" if (!check_only) {"); - out.println(" Handle stringValue = java_lang_String::create_from_str(value, CHECK_(true));"); - out.println(" set_option_helper(hotSpotOptionsClass, name, name_len, option, 's', stringValue, 0L);"); - out.println(" }"); - } else { - char spec = getPrimitiveSpecChar(desc); - out.println(" jlong primitiveValue = parse_primitive_option_value('" + spec + "', name, name_len, value, CHECK_(true));"); - out.println(" if (!check_only) {"); - out.printf(" Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(), - toInternalName(getFieldType(desc))); - out.println(" set_option_helper(hotSpotOptionsClass, name, name_len, option, '" + spec + "', Handle(), primitiveValue);"); - out.println(" }"); + out.println(" set_option_helper(hotSpotOptionsClass, name, name_len, option, '" + spec + "', Handle(), primitiveValue);"); + out.println(" }"); } - out.println(" return true;"); - out.println(" }"); + out.println(" return true;"); + out.println(" }"); } } } - out.println(" }"); + out.println(" }"); } @SuppressWarnings("unchecked") diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Mon Aug 25 21:15:59 2014 -0700 @@ -43,7 +43,6 @@ import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Nop; import com.oracle.graal.asm.sparc.SPARCMacroAssembler.RestoreWindow; import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx; -import com.oracle.graal.compiler.common.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; import com.oracle.graal.hotspot.meta.*; @@ -250,9 +249,4 @@ } } - @Override - public NativeFunctionInterface getNativeFunctionInterface() { - throw GraalInternalError.unimplemented("No NativeFunctionInterface of SPARC"); - } - } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java Mon Aug 25 21:15:59 2014 -0700 @@ -30,11 +30,9 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.sparc.*; -import com.oracle.graal.asm.sparc.SPARCAssembler.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.sparc.*; -import com.oracle.graal.lir.StandardOp.*; import com.oracle.graal.lir.asm.*; /** @@ -50,17 +48,14 @@ @Alive(REG) AllocatableValue framePc; @Alive(REG) AllocatableValue senderSp; @Temp(REG) AllocatableValue scratch; - private SaveRegistersOp saveRegisterOp; - SPARCHotSpotEnterUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue scratch, - SaveRegistersOp saveRegisterOp) { + SPARCHotSpotEnterUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue scratch) { this.thread = thread; this.threadLastJavaSpOffset = threadLastJavaSpOffset; this.threadLastJavaPcOffset = threadLastJavaPcOffset; this.framePc = framePc; this.senderSp = senderSp; this.scratch = scratch; - this.saveRegisterOp = saveRegisterOp; } @Override diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Mon Aug 25 21:15:59 2014 -0700 @@ -268,7 +268,7 @@ } public void emitLeaveCurrentStackFrame(SaveRegistersOp saveRegisterOp) { - append(new SPARCHotSpotLeaveCurrentStackFrameOp(saveRegisterOp)); + append(new SPARCHotSpotLeaveCurrentStackFrameOp()); } public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) { @@ -280,13 +280,12 @@ Variable framePcVariable = load(framePc); Variable senderSpVariable = load(senderSp); Variable scratchVariable = newVariable(LIRKind.value(getHostWordKind())); - append(new SPARCHotSpotEnterUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), framePcVariable, senderSpVariable, scratchVariable, - saveRegisterOp)); + append(new SPARCHotSpotEnterUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), framePcVariable, senderSpVariable, scratchVariable)); } public void emitLeaveUnpackFramesStackFrame(SaveRegistersOp saveRegisterOp) { Register thread = getProviders().getRegisters().getThreadRegister(); - append(new SPARCHotSpotLeaveUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), saveRegisterOp)); + append(new SPARCHotSpotLeaveUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset())); } public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveCurrentStackFrameOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveCurrentStackFrameOp.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveCurrentStackFrameOp.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,16 +24,11 @@ import static com.oracle.graal.sparc.SPARC.*; -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.sparc.*; -import com.oracle.graal.asm.sparc.SPARCAssembler.Lddf; -import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.sparc.*; -import com.oracle.graal.sparc.*; /** * Pops the current frame off the stack. @@ -41,10 +36,7 @@ @Opcode("LEAVE_CURRENT_STACK_FRAME") final class SPARCHotSpotLeaveCurrentStackFrameOp extends SPARCLIRInstruction { - private final SaveRegistersOp saveRegisterOp; - - public SPARCHotSpotLeaveCurrentStackFrameOp(SaveRegistersOp saveRegisterOp) { - this.saveRegisterOp = saveRegisterOp; + public SPARCHotSpotLeaveCurrentStackFrameOp() { } @Override diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,18 +24,13 @@ import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; import static com.oracle.graal.sparc.SPARC.*; -import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.sparc.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.sparc.*; -import com.oracle.graal.lir.StandardOp.*; import com.oracle.graal.lir.asm.*; -import com.oracle.graal.sparc.*; /** * Emits code that leaves a stack frame which is tailored to call the C++ method @@ -49,14 +44,11 @@ private final int threadLastJavaPcOffset; private final int threadJavaFrameAnchorFlagsOffset; - private final SaveRegistersOp saveRegisterOp; - - SPARCHotSpotLeaveUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadJavaFrameAnchorFlagsOffset, SaveRegistersOp saveRegisterOp) { + SPARCHotSpotLeaveUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadJavaFrameAnchorFlagsOffset) { this.thread = thread; this.threadLastJavaSpOffset = threadLastJavaSpOffset; this.threadLastJavaPcOffset = threadLastJavaPcOffset; this.threadJavaFrameAnchorFlagsOffset = threadJavaFrameAnchorFlagsOffset; - this.saveRegisterOp = saveRegisterOp; } @Override diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -197,7 +197,7 @@ } private StructuredGraph compile(String test, boolean compileAOT) { - StructuredGraph graph = parse(test); + StructuredGraph graph = parseEager(test); ResolvedJavaMethod method = graph.method(); try (OverrideScope s = OptionValue.override(ImmutableCode, compileAOT)) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/BytecodeVerificationTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/BytecodeVerificationTest.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.test; - -import java.io.*; - -import jdk.internal.org.objectweb.asm.*; - -import org.junit.*; - -import com.oracle.graal.compiler.test.*; - -/** - * Tests that the Graal API can only be used to access verified bytecode. - */ -public class BytecodeVerificationTest extends GraalCompilerTest { - - @Test(expected = VerifyError.class) - public void test() throws Exception { - BadClassLoader loader = new BadClassLoader(); - String className = BytecodeVerificationTest.class.getName() + "$BadClass"; - Class c = loader.findClass(className); - - // Should fail with a verification error as long as -XX:-BytecodeVerificationRemote is not - // specified on the command line - getMetaAccess().lookupJavaMethod(c.getDeclaredMethod("getValue")).getCode(); - } - - /** - * Class that will be rewritten during loading to be unverifiable. - */ - public static class BadClass { - - public static String value; - - public static String getValue() { - // Re-written to "return 5;" - return value; - } - } - - /** - * Rewrites {@link BadClass#getValue()} to: - * - *
    -     * public static String getValue() {
    -     *     return 5;
    -     * }
    -     * 
    - */ - private static class BadClassRewriter extends ClassVisitor { - - public BadClassRewriter(ClassWriter cw) { - super(Opcodes.ASM5, cw); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String d, String signature, String[] exceptions) { - MethodVisitor mv = super.visitMethod(access, name, d, signature, exceptions); - if (name.equals("getValue")) { - return new MethodVisitor(Opcodes.ASM5, mv) { - @Override - public void visitFieldInsn(int opcode, String owner, String fieldName, String fieldDesc) { - if (opcode == Opcodes.GETSTATIC) { - visitInsn(Opcodes.ICONST_5); - } else { - super.visitFieldInsn(opcode, owner, name, fieldDesc); - } - } - }; - } - return mv; - } - } - - /** - * Class loader used for loading {@link BadClass}. Using a separate class loader ensure the - * class is treated as "remote" so that it will be subject to verification by default. - */ - private static class BadClassLoader extends ClassLoader { - - @Override - protected Class findClass(final String name) throws ClassNotFoundException { - byte[] classData = null; - try { - InputStream is = BytecodeVerificationTest.class.getResourceAsStream("/" + name.replace('.', '/') + ".class"); - classData = new byte[is.available()]; - new DataInputStream(is).readFully(classData); - } catch (IOException e) { - Assert.fail("can't access class: " + name); - } - - ClassReader cr = new ClassReader(classData); - ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES); - - BadClassRewriter rewriter = new BadClassRewriter(cw); - cr.accept(rewriter, ClassReader.SKIP_FRAMES); - classData = cw.toByteArray(); - return defineClass(null, classData, 0, classData.length); - } - } -} diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CRC32SubstitutionsTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.test; import java.io.*; +import java.nio.*; import java.util.zip.*; import org.junit.*; @@ -74,4 +75,26 @@ } } + public static long updateByteBuffer(ByteBuffer buffer) { + CRC32 crc = new CRC32(); + buffer.rewind(); + crc.update(buffer); + return crc.getValue(); + } + + @Test + public void test4() throws Throwable { + String classfileName = CRC32SubstitutionsTest.class.getSimpleName().replace('.', '/') + ".class"; + InputStream s = CRC32SubstitutionsTest.class.getResourceAsStream(classfileName); + byte[] buf = new byte[s.available()]; + new DataInputStream(s).readFully(buf); + + ByteBuffer directBuf = ByteBuffer.allocateDirect(buf.length); + directBuf.put(buf); + ByteBuffer heapBuf = ByteBuffer.wrap(buf); + + test("updateByteBuffer", directBuf); + test("updateByteBuffer", heapBuf); + } + } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -50,7 +50,7 @@ private HotSpotInstalledCode getInstalledCode(String name, Class... parameterTypes) throws Exception { final Method method = CompressedOopTest.class.getMethod(name, parameterTypes); final HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(method); - final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(javaMethod, parse(method)); + final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(javaMethod, parseEager(method)); return installedBenchmarkCode; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/GraalClassLoaderTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/GraalClassLoaderTest.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.test; - -import org.junit.*; - -import sun.management.*; - -import com.oracle.graal.api.runtime.*; -import com.sun.management.*; - -/** - * Tests that the Graal API is inaccessible when -XX:+UseGraalClassLoader is specified. Execute as - * follows to show class loader based isolation: - * - *
    - * mx unittest -XX:+UseGraalClassLoader GraalClassLoaderTest
    - * 
    - */ -public class GraalClassLoaderTest { - - @Test - public void test() throws Exception { - if (System.getProperty("java.vm.version").contains("graal")) { - HotSpotDiagnosticMXBean diag = ManagementFactoryHelper.getDiagnosticMXBean(); - VMOption option = diag.getVMOption("UseGraalClassLoader"); - if (option.getValue().equals("true")) { - try { - Graal.getRuntime(); - Assert.fail(); - } catch (NoClassDefFoundError e) { - // expected - } - } - } - } - -} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNmethodTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -37,7 +37,7 @@ @Test public void testInstallCodeInvalidation() { final ResolvedJavaMethod testJavaMethod = getMetaAccess().lookupJavaMethod(getMethod("foo")); - final StructuredGraph graph = parse("otherFoo"); + final StructuredGraph graph = parseEager("otherFoo"); final HotSpotNmethod nmethod = (HotSpotNmethod) getCode(testJavaMethod, graph); Assert.assertTrue(nmethod.isValid()); Object result; @@ -61,7 +61,7 @@ @Test public void testInstallCodeInvalidationWhileRunning() { final ResolvedJavaMethod testJavaMethod = getMetaAccess().lookupJavaMethod(getMethod("foo")); - final StructuredGraph graph = parse("otherFoo"); + final StructuredGraph graph = parseEager("otherFoo"); final HotSpotNmethod nmethod = (HotSpotNmethod) getCode(testJavaMethod, graph); Object result; try { @@ -76,7 +76,7 @@ @Test public void testInstalledCodeCalledFromCompiledCode() { final ResolvedJavaMethod testJavaMethod = getMetaAccess().lookupJavaMethod(getMethod("foo")); - final StructuredGraph graph = parse("otherFoo"); + final StructuredGraph graph = parseEager("otherFoo"); final HotSpotNmethod nmethod = (HotSpotNmethod) getCode(testJavaMethod, graph); Assert.assertTrue(nmethod.isValid()); try { diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -50,13 +50,13 @@ public void test1() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException { final Method fooMethod = InstalledCodeExecuteHelperTest.class.getMethod("foo"); final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(fooMethod); - final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod)); + final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parseEager(fooMethod)); argsToBind = new Object[]{fooCode}; final Method benchmarkMethod = InstalledCodeExecuteHelperTest.class.getMethod("benchmark", HotSpotInstalledCode.class); final ResolvedJavaMethod benchmarkJavaMethod = metaAccess.lookupJavaMethod(benchmarkMethod); - final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(benchmarkJavaMethod, parse(benchmarkMethod)); + final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(benchmarkJavaMethod, parseEager(benchmarkMethod)); Assert.assertEquals(Integer.valueOf(42), benchmark(fooCode)); @@ -79,8 +79,8 @@ } @Override - protected StructuredGraph parse(Method m) { - StructuredGraph graph = super.parse(m); + protected StructuredGraph parseEager(Method m) { + StructuredGraph graph = super.parseEager(m); if (argsToBind != null) { Object receiver = isStatic(m.getModifiers()) ? null : this; Object[] args = argsWithReceiver(receiver, argsToBind); diff -r ae0f235469db -r f8e60d11c0ec 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 25 21:15:59 2014 -0700 @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.test; + +import static com.oracle.graal.debug.internal.MemUseTrackerImpl.*; +import static com.oracle.graal.hotspot.CompileTheWorld.*; +import static com.oracle.graal.hotspot.CompileTheWorld.Options.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +import static com.oracle.graal.nodes.StructuredGraph.*; + +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.internal.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.CompileTheWorld.Config; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.printer.*; + +/** + * Used to benchmark memory usage during Graal compilation. + * + * To benchmark: + * + *
    + *     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, String label) { + HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) getMetaAccess().lookupJavaMethod(getMethod(methodName)); + HotSpotBackend backend = runtime().getHostBackend(); + + // invalidate any existing compiled code + method.reprofile(); + + int id = method.allocateCompileId(INVOCATION_ENTRY_BCI); + long ctask = 0L; + + try (MemoryUsageCloseable c = label == null ? null : new MemoryUsageCloseable(label)) { + CompilationTask task = new CompilationTask(backend, method, INVOCATION_ENTRY_BCI, ctask, id); + task.runCompilation(); + } + } + + private void allocSpyCompilation(String methodName) { + if (AllocSpy.isEnabled()) { + HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) getMetaAccess().lookupJavaMethod(getMethod(methodName)); + HotSpotBackend backend = runtime().getHostBackend(); + + // invalidate any existing compiled code + method.reprofile(); + + int id = method.allocateCompileId(INVOCATION_ENTRY_BCI); + long ctask = 0L; + try (AllocSpy as = AllocSpy.open(methodName)) { + CompilationTask task = new CompilationTask(backend, method, INVOCATION_ENTRY_BCI, ctask, id); + task.runCompilation(); + } + } + } + + private static final boolean verbose = Boolean.getBoolean("verbose"); + + private void compileAndTime(String methodName) { + + // Parse in eager mode to resolve methods/fields/classes + parseEager(methodName); + + // Warm up and initialize compiler phases used by this compilation + for (int i = 0; i < 10; i++) { + doCompilation(methodName, verbose ? methodName + "[warmup-" + i + "]" : null); + } + + doCompilation(methodName, methodName); + } + + public void run() { + compileAndTime("simple"); + compileAndTime("complex"); + if (CompileTheWorldClasspath.getValue() != SUN_BOOT_CLASS_PATH) { + CompileTheWorld ctw = new CompileTheWorld(CompileTheWorldClasspath.getValue(), new Config(CompileTheWorldConfig.getValue()), CompileTheWorldStartAt.getValue(), + CompileTheWorldStopAt.getValue(), CompileTheWorldVerbose.getValue()); + try { + ctw.compile(); + } catch (Throwable e) { + e.printStackTrace(); + } + } + allocSpyCompilation("simple"); + allocSpyCompilation("complex"); + } +} diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -244,13 +244,13 @@ private HotSpotInstalledCode getInstalledCode(String name) throws Exception { final Method method = WriteBarrierAdditionTest.class.getMethod(name, Object.class, Object.class, Object.class); final HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(method); - final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(javaMethod, parse(method)); + final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(javaMethod, parseEager(method)); return installedBenchmarkCode; } private void test(final String snippet, final int expectedBarriers) throws Exception, SecurityException { try (Scope s = Debug.scope("WriteBarrierAdditionTest", new DebugDumpScope(snippet))) { - StructuredGraph graph = parse(snippet); + StructuredGraph graph = parseEager(snippet); HighTierContext highContext = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); MidTierContext midContext = new MidTierContext(getProviders(), new Assumptions(false), getCodeCache().getTarget(), OptimisticOptimizations.ALL, graph.method().getProfilingInfo(), null); new InliningPhase(new InlineEverythingPolicy(), new CanonicalizerPhase(true)).apply(graph, highContext); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -613,7 +613,7 @@ private void test(final String snippet, final int expectedBarriers, final int... removedBarrierIndices) { try (Scope d = Debug.scope("WriteBarrierVerificationTest", new DebugDumpScope(snippet))) { - final StructuredGraph graph = parse(snippet); + final StructuredGraph graph = parseEager(snippet); HighTierContext highTierContext = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Mon Aug 25 21:15:59 2014 -0700 @@ -52,7 +52,7 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.java.*; -import com.oracle.graal.java.GraphBuilderConfiguration.*; +import com.oracle.graal.java.GraphBuilderConfiguration.DebugInfoMode; import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot; import static com.oracle.graal.compiler.common.GraalOptions.*; +import static com.oracle.graal.debug.internal.MemUseTrackerImpl.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.nodes.StructuredGraph.*; @@ -41,7 +42,6 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.options.*; import com.oracle.graal.options.OptionValue.OverrideScope; -import com.oracle.graal.phases.tiers.*; import com.oracle.graal.replacements.*; /** @@ -158,6 +158,7 @@ private int classFileCounter = 0; private int compiledMethodsCounter = 0; private long compileTime = 0; + private long memoryUsed = 0; private boolean verbose; private final Config config; @@ -235,83 +236,85 @@ private void compile(String fileList) throws Throwable { final String[] entries = fileList.split(File.pathSeparator); - for (int i = 0; i < entries.length; i++) { - final String entry = entries[i]; - - // For now we only compile all methods in all classes in zip/jar files. - if (!entry.endsWith(".zip") && !entry.endsWith(".jar")) { - println("CompileTheWorld : Skipped classes in " + entry); - println(); - continue; - } + try (AutoCloseable s = config.apply()) { + for (int i = 0; i < entries.length; i++) { + final String entry = entries[i]; - println("CompileTheWorld : Compiling all classes in " + entry); - println(); - - URL url = new URL("jar", "", "file:" + entry + "!/"); - ClassLoader loader = new URLClassLoader(new URL[]{url}); - - JarFile jarFile = new JarFile(entry); - Enumeration e = jarFile.entries(); - - while (e.hasMoreElements()) { - JarEntry je = e.nextElement(); - if (je.isDirectory() || !je.getName().endsWith(".class")) { + // For now we only compile all methods in all classes in zip/jar files. + if (!entry.endsWith(".zip") && !entry.endsWith(".jar")) { + println("CompileTheWorld : Skipped classes in " + entry); + println(); continue; } - // Are we done? - if (classFileCounter >= stopAt) { - break; - } + println("CompileTheWorld : Compiling all classes in " + entry); + println(); - String className = je.getName().substring(0, je.getName().length() - ".class".length()); - classFileCounter++; + URL url = new URL("jar", "", "file:" + entry + "!/"); + ClassLoader loader = new URLClassLoader(new URL[]{url}); + + JarFile jarFile = new JarFile(entry); + Enumeration e = jarFile.entries(); - try (AutoCloseable s = config.apply()) { - // Load and initialize class - Class javaClass = Class.forName(className.replace('/', '.'), true, loader); + while (e.hasMoreElements()) { + JarEntry je = e.nextElement(); + if (je.isDirectory() || !je.getName().endsWith(".class")) { + continue; + } - // Pre-load all classes in the constant pool. - try { - HotSpotResolvedObjectType objectType = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(javaClass); - ConstantPool constantPool = objectType.constantPool(); - for (int cpi = 1; cpi < constantPool.length(); cpi++) { - constantPool.loadReferencedType(cpi, Bytecodes.LDC); - } - } catch (Throwable t) { - // If something went wrong during pre-loading we just ignore it. - println("Preloading failed for (%d) %s", classFileCounter, className); + // Are we done? + if (classFileCounter >= stopAt) { + break; } - // Are we compiling this class? - HotSpotMetaAccessProvider metaAccess = runtime.getHostProviders().getMetaAccess(); - if (classFileCounter >= startAt) { - println("CompileTheWorld (%d) : %s", classFileCounter, className); + String className = je.getName().substring(0, je.getName().length() - ".class".length()); + classFileCounter++; + + try { + // Load and initialize class + Class javaClass = Class.forName(className.replace('/', '.'), true, loader); - // Compile each constructor/method in the class. - for (Constructor constructor : javaClass.getDeclaredConstructors()) { - HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaConstructor(constructor); - if (canBeCompiled(javaMethod, constructor.getModifiers())) { - compileMethod(javaMethod); + // Pre-load all classes in the constant pool. + try { + HotSpotResolvedObjectType objectType = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(javaClass); + ConstantPool constantPool = objectType.constantPool(); + for (int cpi = 1; cpi < constantPool.length(); cpi++) { + constantPool.loadReferencedType(cpi, Bytecodes.LDC); + } + } catch (Throwable t) { + // If something went wrong during pre-loading we just ignore it. + println("Preloading failed for (%d) %s", classFileCounter, className); + } + + // Are we compiling this class? + HotSpotMetaAccessProvider metaAccess = runtime.getHostProviders().getMetaAccess(); + if (classFileCounter >= startAt) { + println("CompileTheWorld (%d) : %s", classFileCounter, className); + + // Compile each constructor/method in the class. + for (Constructor constructor : javaClass.getDeclaredConstructors()) { + HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaConstructor(constructor); + if (canBeCompiled(javaMethod, constructor.getModifiers())) { + compileMethod(javaMethod); + } + } + for (Method method : javaClass.getDeclaredMethods()) { + HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(method); + if (canBeCompiled(javaMethod, method.getModifiers())) { + compileMethod(javaMethod); + } } } - for (Method method : javaClass.getDeclaredMethods()) { - HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(method); - if (canBeCompiled(javaMethod, method.getModifiers())) { - compileMethod(javaMethod); - } - } + } catch (Throwable t) { + println("CompileTheWorld (%d) : Skipping %s", classFileCounter, className); } - } catch (Throwable t) { - println("CompileTheWorld (%d) : Skipping %s", classFileCounter, className); } + jarFile.close(); } - jarFile.close(); } println(); - println("CompileTheWorld : Done (%d classes, %d methods, %d ms)", classFileCounter, compiledMethodsCounter, compileTime); + println("CompileTheWorld : Done (%d classes, %d methods, %d ms, %d bytes of memory used)", classFileCounter, compiledMethodsCounter, compileTime, memoryUsed); } class CTWCompilationTask extends CompilationTask { @@ -321,16 +324,6 @@ } /** - * Returns a fresh compilation suite for its compilation so that the CTW option value - * overriding configuration has effect. - */ - @Override - protected Suites getSuites(HotSpotProviders providers) { - assert config.scope != null : "not inside a CTW option value overriding scope"; - return providers.getSuites().createSuites(); - } - - /** * Returns empty profiling info to be as close to the CTW behavior of C1 and C2 as possible. */ @Override @@ -346,11 +339,13 @@ private void compileMethod(HotSpotResolvedJavaMethod method) { try { long start = System.currentTimeMillis(); + long allocatedAtStart = getCurrentThreadAllocatedBytes(); HotSpotBackend backend = runtime.getHostBackend(); CompilationTask task = new CTWCompilationTask(backend, method); task.runCompilation(); + memoryUsed += getCurrentThreadAllocatedBytes() - allocatedAtStart; compileTime += (System.currentTimeMillis() - start); compiledMethodsCounter++; method.reprofile(); // makes the method also not-entrant @@ -374,6 +369,10 @@ if (c.dontCompileHugeMethods && javaMethod.getCodeSize() > c.hugeMethodLimit) { return false; } + // Allow use of -XX:CompileCommand=dontinline to exclude problematic methods + if (!javaMethod.canBeInlined()) { + return false; + } // Skip @Snippets for now if (javaMethod.getAnnotation(Snippet.class) != null) { return false; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/DebugValuesPrinter.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/DebugValuesPrinter.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/DebugValuesPrinter.java Mon Aug 25 21:15:59 2014 -0700 @@ -38,7 +38,7 @@ public class DebugValuesPrinter { public void printDebugValues(String phase, boolean reset) throws GraalInternalError { - if (Debug.isEnabled() && areMetricsOrTimersEnabled()) { + if (Debug.areUnconditionalMetricsEnabled() || Debug.areUnconditionalTimersEnabled() || (Debug.isEnabled() && areMetricsOrTimersEnabled())) { TTY.println(); if (phase != null) { TTY.println(""); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Mon Aug 25 21:15:59 2014 -0700 @@ -36,7 +36,6 @@ import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.LIRInstruction.ValueProcedure; import com.oracle.graal.lir.StandardOp.LabelOp; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.nodes.*; @@ -152,15 +151,14 @@ */ protected static Set gatherDefinedRegisters(LIR lir) { final Set definedRegisters = new HashSet<>(); - ValueProcedure defProc = new ValueProcedure() { + ValueConsumer defConsumer = new ValueConsumer() { @Override - public Value doValue(Value value) { + public void visitValue(Value value) { if (ValueUtil.isRegister(value)) { final Register reg = ValueUtil.asRegister(value); definedRegisters.add(reg); } - return value; } }; for (AbstractBlock block : lir.codeEmittingOrder()) { @@ -168,8 +166,8 @@ if (op instanceof LabelOp) { // Don't consider this as a definition } else { - op.forEachTemp(defProc); - op.forEachOutput(defProc); + op.visitEachTemp(defConsumer); + op.visitEachOutput(defConsumer); } } } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,7 +27,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; -import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.hotspot.meta.*; @@ -37,7 +36,7 @@ /** * Common functionality of HotSpot host backends. */ -public abstract class HotSpotHostBackend extends HotSpotBackend implements HostBackend { +public abstract class HotSpotHostBackend extends HotSpotBackend { /** * Descriptor for {@link DeoptimizationStub#deoptimizationHandler}. diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,7 +26,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure; import com.oracle.graal.lir.LIRInstruction.OperandMode; /** @@ -39,11 +38,11 @@ } @Override - protected Value processValue(LIRInstruction inst, InstructionValueProcedure proc, Value value) { + protected Value processValue(LIRInstruction inst, InstructionValueProcedureBase proc, Value value) { if (value instanceof HotSpotMonitorValue) { HotSpotMonitorValue monitor = (HotSpotMonitorValue) value; if (processed(monitor.getOwner())) { - monitor.setOwner(proc.doValue(inst, monitor.getOwner(), OperandMode.ALIVE, STATE_FLAGS)); + monitor.setOwner(proc.processValue(inst, monitor.getOwner(), OperandMode.ALIVE, STATE_FLAGS)); } return value; } else { diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptionsLoader.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,6 +24,7 @@ import java.util.*; +import com.oracle.graal.api.runtime.*; import com.oracle.graal.options.*; /** @@ -36,8 +37,7 @@ * Initializes {@link #options} from {@link Options} services. */ static { - ServiceLoader 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 ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Mon Aug 25 21:15:59 2014 -0700 @@ -1052,8 +1052,8 @@ @HotSpotVMField(name = "HSAILTlabInfo::_end", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailTlabInfoEndOffset; @HotSpotVMField(name = "HSAILTlabInfo::_last_good_top", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailTlabInfoLastGoodTopOffset; @HotSpotVMField(name = "HSAILTlabInfo::_original_top", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailTlabInfoOriginalTopOffset; - @HotSpotVMField(name = "HSAILTlabInfo::_donor_thread", type = "JavaThread*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailTlabInfoDonorThreadOffset; @HotSpotVMField(name = "HSAILTlabInfo::_alloc_info", type = "HSAILAllocationInfo*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailTlabInfoAllocInfoOffset; + @HotSpotVMField(name = "HSAILTlabInfo::_tlab", type = "ThreadLocalAllocBuffer*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailTlabInfoTlabOffset; @HotSpotVMType(name = "HSAILTlabInfo", get = HotSpotVMType.Type.SIZE) @Stable public int hsailTlabInfoSize; /** diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Mon Aug 25 21:15:59 2014 -0700 @@ -377,18 +377,18 @@ public static void lower(DynamicCounterNode counter, HotSpotRegistersProvider registers, HotSpotVMConfig config, Kind wordKind) { StructuredGraph graph = counter.graph(); - ReadRegisterNode thread = graph.add(new ReadRegisterNode(registers.getThreadRegister(), wordKind, true, false)); + ReadRegisterNode thread = graph.add(ReadRegisterNode.create(registers.getThreadRegister(), wordKind, true, false)); int index = BenchmarkCounters.getIndex(counter); if (index >= config.graalCountersSize) { throw new GraalInternalError("too many counters, reduce number of counters or increase -XX:GraalCounterSize=... (current value: " + config.graalCountersSize + ")"); } ConstantLocationNode arrayLocation = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, wordKind, config.graalCountersThreadOffset, graph); - ReadNode readArray = graph.add(new ReadNode(thread, arrayLocation, StampFactory.forKind(wordKind), BarrierType.NONE)); + ReadNode readArray = graph.add(ReadNode.create(thread, arrayLocation, StampFactory.forKind(wordKind), BarrierType.NONE)); ConstantLocationNode location = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, Kind.Long, Unsafe.ARRAY_LONG_INDEX_SCALE * index, graph); - ReadNode read = graph.add(new ReadNode(readArray, location, StampFactory.forKind(Kind.Long), BarrierType.NONE)); - IntegerAddNode add = graph.unique(new IntegerAddNode(read, counter.getIncrement())); - WriteNode write = graph.add(new WriteNode(readArray, add, location, BarrierType.NONE)); + ReadNode read = graph.add(ReadNode.create(readArray, location, StampFactory.forKind(Kind.Long), BarrierType.NONE)); + IntegerAddNode add = graph.unique(IntegerAddNode.create(read, counter.getIncrement())); + WriteNode write = graph.add(WriteNode.create(readArray, add, location, BarrierType.NONE)); graph.addBeforeFixed(counter, thread); graph.addBeforeFixed(counter, readArray); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java Mon Aug 25 21:15:59 2014 -0700 @@ -198,10 +198,10 @@ // We use LocationNode.ANY_LOCATION for the reads that access the // compiled code entry as HotSpot does not guarantee they are final // values. - ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, ConstantLocationNode.create(ANY_LOCATION, wordKind, runtime.getConfig().methodCompiledEntryOffset, graph), + ReadNode compiledEntry = graph.add(ReadNode.create(metaspaceMethod, ConstantLocationNode.create(ANY_LOCATION, wordKind, runtime.getConfig().methodCompiledEntryOffset, graph), StampFactory.forKind(wordKind), BarrierType.NONE)); - loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), + loweredCallTarget = graph.add(HotSpotIndirectCallTargetNode.create(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall, callTarget.invokeKind())); graph.addBeforeFixed(invoke.asNode(), metaspaceMethod); @@ -210,7 +210,7 @@ } if (loweredCallTarget == null) { - loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall, + loweredCallTarget = graph.add(HotSpotDirectCallTargetNode.create(parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall, callTarget.invokeKind())); } callTarget.replaceAndDelete(loweredCallTarget); @@ -255,7 +255,7 @@ * Anchor the read of the element klass to the cfg, because it is only valid when arrayClass * is an object class, which might not be the case in other parts of the compiled method. */ - return graph.unique(new FloatingReadNode(arrayHub, location, null, StampFactory.forKind(wordKind), BeginNode.prevBegin(anchor))); + return graph.unique(FloatingReadNode.create(arrayHub, location, null, StampFactory.forKind(wordKind), BeginNode.prevBegin(anchor))); } @Override @@ -293,9 +293,9 @@ private void lowerOSRStartNode(OSRStartNode osrStart) { StructuredGraph graph = osrStart.graph(); if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { - StartNode newStart = graph.add(new StartNode()); - ParameterNode buffer = graph.unique(new ParameterNode(0, StampFactory.forKind(runtime.getTarget().wordKind))); - ForeignCallNode migrationEnd = graph.add(new ForeignCallNode(foreignCalls, OSR_MIGRATION_END, buffer)); + StartNode newStart = graph.add(StartNode.create()); + ParameterNode buffer = graph.unique(ParameterNode.create(0, StampFactory.forKind(runtime.getTarget().wordKind))); + ForeignCallNode migrationEnd = graph.add(ForeignCallNode.create(foreignCalls, OSR_MIGRATION_END, buffer)); migrationEnd.setStateAfter(osrStart.stateAfter()); newStart.setNext(migrationEnd); @@ -310,7 +310,7 @@ int size = HIRFrameStateBuilder.stackSlots(osrLocal.getKind()); int offset = localsOffset - (osrLocal.index() + size - 1) * 8; IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, osrLocal.getKind(), offset, ConstantNode.forLong(0, graph), graph, 1); - ReadNode load = graph.add(new ReadNode(buffer, location, osrLocal.stamp(), BarrierType.NONE)); + ReadNode load = graph.add(ReadNode.create(buffer, location, osrLocal.stamp(), BarrierType.NONE)); osrLocal.replaceAndDelete(load); graph.addBeforeFixed(migrationEnd, load); } @@ -368,7 +368,7 @@ throw GraalInternalError.shouldNotReachHere(); } - ForeignCallNode foreignCallNode = graph.add(new ForeignCallNode(foreignCalls, descriptor, node.stamp(), node.getArguments())); + ForeignCallNode foreignCallNode = graph.add(ForeignCallNode.create(foreignCalls, descriptor, node.stamp(), node.getArguments())); graph.replaceFixedWithFixed(node, foreignCallNode); } } @@ -393,7 +393,7 @@ assert vtableEntryOffset > 0; // We use LocationNode.ANY_LOCATION for the reads that access the vtable // entry as HotSpot does not guarantee that this is a final value. - ReadNode metaspaceMethod = graph.add(new ReadNode(hub, ConstantLocationNode.create(ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind), BarrierType.NONE)); + ReadNode metaspaceMethod = graph.add(ReadNode.create(hub, ConstantLocationNode.create(ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind), BarrierType.NONE)); return metaspaceMethod; } @@ -411,7 +411,7 @@ hubStamp = StampFactory.forKind(wordKind); } - FloatingReadNode memoryRead = graph.unique(new FloatingReadNode(object, location, null, hubStamp, guard, BarrierType.NONE)); + FloatingReadNode memoryRead = graph.unique(FloatingReadNode.create(object, location, null, hubStamp, guard, BarrierType.NONE)); if (config.useCompressedClassPointers) { return CompressionNode.uncompress(memoryRead, config.getKlassEncoding()); } else { @@ -429,7 +429,7 @@ writeValue = CompressionNode.compress(value, config.getKlassEncoding()); } - return graph.add(new WriteNode(object, writeValue, location, BarrierType.NONE)); + return graph.add(WriteNode.create(object, writeValue, location, BarrierType.NONE)); } @Override diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Mon Aug 25 21:15:59 2014 -0700 @@ -159,8 +159,8 @@ linkForeignCall(providers, DYNAMIC_NEW_ARRAY, c.dynamicNewArrayAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, INIT_LOCATION); linkForeignCall(providers, DYNAMIC_NEW_INSTANCE, c.dynamicNewInstanceAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, INIT_LOCATION); linkForeignCall(providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); linkForeignCall(providers, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); linkForeignCall(providers, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); linkForeignCall(providers, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF_NOFP, NOT_REEXECUTABLE, NO_LOCATIONS); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,6 +27,7 @@ import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.java.*; +import com.oracle.graal.options.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; @@ -35,18 +36,18 @@ */ public class HotSpotSuitesProvider implements SuitesProvider { - protected final Suites defaultSuites; + protected final DerivedOptionValue defaultSuites; protected final PhaseSuite defaultGraphBuilderSuite; protected final HotSpotGraalRuntime runtime; public HotSpotSuitesProvider(HotSpotGraalRuntime runtime) { this.runtime = runtime; this.defaultGraphBuilderSuite = createGraphBuilderSuite(); - defaultSuites = createSuites(); + this.defaultSuites = new DerivedOptionValue<>(this::createSuites); } public Suites getDefaultSuites() { - return defaultSuites; + return defaultSuites.getValue(); } public PhaseSuite getDefaultGraphBuilderSuite() { diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionHandle.java Mon Aug 25 21:15:59 2014 -0700 @@ -29,6 +29,7 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; +import com.oracle.nfi.api.*; public class HotSpotNativeFunctionHandle implements NativeFunctionHandle { @@ -87,10 +88,6 @@ return true; } - public InstalledCode getCallStub() { - return code; - } - @Override public String toString() { return name + Arrays.toString(argumentTypes); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java Mon Aug 25 21:15:59 2014 -0700 @@ -40,6 +40,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; +import com.oracle.nfi.api.*; public class HotSpotNativeFunctionInterface implements NativeFunctionInterface { @@ -87,7 +88,7 @@ @Override public HotSpotNativeFunctionHandle getFunctionHandle(NativeLibraryHandle library, String name, Class returnType, Class... argumentTypes) { - HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(name, library, true); + HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(name, library, false); return createHandle(functionPointer, returnType, argumentTypes); } @@ -178,7 +179,7 @@ if (rtldDefault == null) { throw new UnsatisfiedLinkError(name); } - return lookupFunctionPointer(name, rtldDefault, true); + return lookupFunctionPointer(name, rtldDefault, false); } public boolean isDefaultLibrarySearchSupported() { diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionPointer.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.nfi; -import com.oracle.graal.api.code.*; +import com.oracle.nfi.api.*; public class HotSpotNativeFunctionPointer implements NativeFunctionPointer { @@ -41,7 +41,7 @@ return name; } - public long getValue() { + public long getRawValue() { return value; } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeLibraryHandle.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.nfi; -import com.oracle.graal.api.code.*; +import com.oracle.nfi.api.*; public class HotSpotNativeLibraryHandle implements NativeLibraryHandle { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java Mon Aug 25 21:15:59 2014 -0700 @@ -53,10 +53,10 @@ try { ResolvedJavaMethod method = providers.getMetaAccess().lookupJavaMethod(NativeCallStubGraphBuilder.class.getMethod("libCall", Object.class, Object.class, Object.class)); StructuredGraph g = new StructuredGraph(method); - ParameterNode arg0 = g.unique(new ParameterNode(0, StampFactory.forKind(Kind.Object))); - ParameterNode arg1 = g.unique(new ParameterNode(1, StampFactory.forKind(Kind.Object))); - ParameterNode arg2 = g.unique(new ParameterNode(2, StampFactory.forKind(Kind.Object))); - FrameState frameState = g.add(new FrameState(null, method, 0, Arrays.asList(new ValueNode[]{arg0, arg1, arg2}), 3, 0, false, false, new ArrayList(), + ParameterNode arg0 = g.unique(ParameterNode.create(0, StampFactory.forKind(Kind.Object))); + ParameterNode arg1 = g.unique(ParameterNode.create(1, StampFactory.forKind(Kind.Object))); + ParameterNode arg2 = g.unique(ParameterNode.create(2, StampFactory.forKind(Kind.Object))); + FrameState frameState = g.add(FrameState.create(null, method, 0, Arrays.asList(new ValueNode[]{arg0, arg1, arg2}), 3, 0, false, false, new ArrayList(), new ArrayList())); g.start().setStateAfter(frameState); List parameters = new ArrayList<>(); @@ -84,12 +84,12 @@ throw new IllegalArgumentException("Return type not supported: " + returnType.getName()); } ResolvedJavaType type = providers.getMetaAccess().lookupJavaType(callNode.getKind().toBoxedJavaClass()); - boxedResult = g.unique(new BoxNode(callNode, type, callNode.getKind())); + boxedResult = g.unique(BoxNode.create(callNode, type, callNode.getKind())); } else { - boxedResult = g.unique(new BoxNode(ConstantNode.forLong(0, g), providers.getMetaAccess().lookupJavaType(Long.class), Kind.Long)); + boxedResult = g.unique(BoxNode.create(ConstantNode.forLong(0, g), providers.getMetaAccess().lookupJavaType(Long.class), Kind.Long)); } - ReturnNode returnNode = g.add(new ReturnNode(boxedResult)); + ReturnNode returnNode = g.add(ReturnNode.create(boxedResult)); callNode.setNext(returnNode); (new WordTypeRewriterPhase(providers.getMetaAccess(), providers.getSnippetReflection(), Kind.Long)).apply(g); return g; @@ -103,7 +103,7 @@ FixedWithNextNode last = null; for (int i = 0; i < numArgs; i++) { // load boxed array element: - LoadIndexedNode boxedElement = g.add(new LoadIndexedNode(argumentsArray, ConstantNode.forInt(i, g), Kind.Object)); + LoadIndexedNode boxedElement = g.add(LoadIndexedNode.create(argumentsArray, ConstantNode.forInt(i, g), Kind.Object)); if (i == 0) { g.start().setNext(boxedElement); last = boxedElement; @@ -122,13 +122,13 @@ int indexScaling = getArrayIndexScale(arrayElementKind); IndexedLocationNode locationNode = IndexedLocationNode.create(locationIdentity, arrayElementKind, displacement, index, g, indexScaling); Stamp wordStamp = StampFactory.forKind(providers.getCodeCache().getTarget().wordKind); - ComputeAddressNode arrayAddress = g.unique(new ComputeAddressNode(boxedElement, locationNode, wordStamp)); + ComputeAddressNode arrayAddress = g.unique(ComputeAddressNode.create(boxedElement, locationNode, wordStamp)); args.add(arrayAddress); } else { // boxed primitive value try { ResolvedJavaField field = providers.getMetaAccess().lookupJavaField(kind.toBoxedJavaClass().getDeclaredField("value")); - LoadFieldNode loadFieldNode = g.add(new LoadFieldNode(boxedElement, field)); + LoadFieldNode loadFieldNode = g.add(LoadFieldNode.create(boxedElement, field)); last.setNext(loadFieldNode); last = loadFieldNode; args.add(loadFieldNode); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -28,6 +28,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -35,7 +36,8 @@ * Reserves a block of memory in the stack frame of a method. The block is reserved in the frame for * the entire execution of the associated method. */ -public final class AllocaNode extends FixedWithNextNode implements LIRLowerable { +@NodeInfo +public class AllocaNode extends FixedWithNextNode implements LIRLowerable { /** * The number of slots in block. @@ -49,7 +51,11 @@ */ private final BitSet objects; - public AllocaNode(int slots, BitSet objects) { + public static AllocaNode create(int slots, BitSet objects) { + return USE_GENERATED_NODES ? new AllocaNodeGen(slots, objects) : new AllocaNode(slots, objects); + } + + protected AllocaNode(int slots, BitSet objects) { super(StampFactory.forKind(HotSpotGraalRuntime.getHostWordKind())); this.slots = slots; this.objects = objects; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayRangeWriteBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayRangeWriteBarrier.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayRangeWriteBarrier.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,12 +22,14 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +@NodeInfo public abstract class ArrayRangeWriteBarrier extends WriteBarrier { - @Input private ValueNode startIndex; - @Input private ValueNode length; + @Input ValueNode startIndex; + @Input ValueNode length; public ArrayRangeWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { super(object, null, null, true); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,8 +24,8 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -38,11 +38,15 @@ * check on the object. */ @NodeInfo(allowedUsageTypes = {InputType.Memory}) -public final class BeginLockScopeNode extends AbstractMemoryCheckpoint implements LIRLowerable, MonitorEnter, MemoryCheckpoint.Single { +public class BeginLockScopeNode extends AbstractMemoryCheckpoint implements LIRLowerable, MonitorEnter, MemoryCheckpoint.Single { private int lockDepth; - private BeginLockScopeNode(int lockDepth) { + public static BeginLockScopeNode create(int lockDepth) { + return USE_GENERATED_NODES ? new BeginLockScopeNodeGen(lockDepth) : new BeginLockScopeNode(lockDepth); + } + + BeginLockScopeNode(int lockDepth) { super(null); this.lockDepth = lockDepth; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; @@ -30,11 +31,16 @@ /** * Converts a compile-time constant Java string into a C string installed with the generated code. */ -public final class CStringNode extends FloatingNode implements LIRLowerable { +@NodeInfo +public class CStringNode extends FloatingNode implements LIRLowerable { private final String string; - private CStringNode(String string) { + public static CStringNode create(String string) { + return USE_GENERATED_NODES ? new CStringNodeGen(string) : new CStringNode(string); + } + + CStringNode(String string) { super(null); this.string = string; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.replacements.nodes.*; @@ -34,9 +35,14 @@ * * @see ClassSubstitutions#cast(Class, Object) */ +@NodeInfo public class ClassCastNode extends MacroStateSplitNode implements Canonicalizable.Binary { - public ClassCastNode(Invoke invoke) { + public static ClassCastNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new ClassCastNodeGen(invoke) : new ClassCastNode(invoke); + } + + protected ClassCastNode(Invoke invoke) { super(invoke); } @@ -62,7 +68,7 @@ Class c = (Class) HotSpotObjectConstant.asObject(forJavaClass.asConstant()); if (c != null && !c.isPrimitive()) { HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(c); - return new CheckCastNode(type, forObject, null, false); + return CheckCastNode.create(type, forObject, null, false); } } return this; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.replacements.nodes.*; @@ -35,9 +36,14 @@ * @see ClassSubstitutions#getClassLoader0(Class) */ @SuppressWarnings("javadoc") +@NodeInfo public class ClassGetClassLoader0Node extends MacroStateSplitNode implements Canonicalizable { - public ClassGetClassLoader0Node(Invoke invoke) { + public static ClassGetClassLoader0Node create(Invoke invoke) { + return USE_GENERATED_NODES ? new ClassGetClassLoader0NodeGen(invoke) : new ClassGetClassLoader0Node(invoke); + } + + protected ClassGetClassLoader0Node(Invoke invoke) { super(invoke); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetComponentTypeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetComponentTypeNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetComponentTypeNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.replacements.nodes.*; @@ -34,9 +35,14 @@ * * @see ClassSubstitutions#getComponentType(Class) */ +@NodeInfo public class ClassGetComponentTypeNode extends MacroNode implements Canonicalizable { - public ClassGetComponentTypeNode(Invoke invoke) { + public static ClassGetComponentTypeNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new ClassGetComponentTypeNodeGen(invoke) : new ClassGetComponentTypeNode(invoke); + } + + protected ClassGetComponentTypeNode(Invoke invoke) { super(invoke); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetModifiersNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetModifiersNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetModifiersNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.replacements.nodes.*; @@ -34,9 +35,14 @@ * * @see ClassSubstitutions#getModifiers(Class) */ +@NodeInfo public class ClassGetModifiersNode extends MacroNode implements Canonicalizable { - public ClassGetModifiersNode(Invoke invoke) { + public static ClassGetModifiersNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new ClassGetModifiersNodeGen(invoke) : new ClassGetModifiersNode(invoke); + } + + protected ClassGetModifiersNode(Invoke invoke) { super(invoke); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetSuperclassNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetSuperclassNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetSuperclassNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.replacements.nodes.*; @@ -34,9 +35,14 @@ * * @see ClassSubstitutions#getSuperclass(Class) */ +@NodeInfo public class ClassGetSuperclassNode extends MacroNode implements Canonicalizable { - public ClassGetSuperclassNode(Invoke invoke) { + public static ClassGetSuperclassNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new ClassGetSuperclassNodeGen(invoke) : new ClassGetSuperclassNode(invoke); + } + + protected ClassGetSuperclassNode(Invoke invoke) { super(invoke); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsArrayNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsArrayNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsArrayNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.replacements.nodes.*; @@ -34,9 +35,14 @@ * * @see ClassSubstitutions#isArray(Class) */ +@NodeInfo public class ClassIsArrayNode extends MacroNode implements Canonicalizable { - public ClassIsArrayNode(Invoke invoke) { + public static ClassIsArrayNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new ClassIsArrayNodeGen(invoke) : new ClassIsArrayNode(invoke); + } + + protected ClassIsArrayNode(Invoke invoke) { super(invoke); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInstanceNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInstanceNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInstanceNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; @@ -36,9 +37,14 @@ * * @see ClassSubstitutions#isInstance(Class, Object) */ +@NodeInfo public class ClassIsInstanceNode extends MacroNode implements Canonicalizable { - public ClassIsInstanceNode(Invoke invoke) { + public static ClassIsInstanceNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new ClassIsInstanceNodeGen(invoke) : new ClassIsInstanceNode(invoke); + } + + protected ClassIsInstanceNode(Invoke invoke) { super(invoke); } @@ -65,8 +71,8 @@ return ConstantNode.forBoolean(o != null && c.isInstance(o)); } HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(c); - InstanceOfNode instanceOf = new InstanceOfNode(type, object, null); - return new ConditionalNode(instanceOf, ConstantNode.forBoolean(true), ConstantNode.forBoolean(false)); + InstanceOfNode instanceOf = InstanceOfNode.create(type, object, null); + return ConditionalNode.create(instanceOf, ConstantNode.forBoolean(true), ConstantNode.forBoolean(false)); } } return this; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInterfaceNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInterfaceNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInterfaceNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.replacements.nodes.*; @@ -34,9 +35,14 @@ * * @see ClassSubstitutions#isInterface(Class) */ +@NodeInfo public class ClassIsInterfaceNode extends MacroNode implements Canonicalizable { - public ClassIsInterfaceNode(Invoke invoke) { + public static ClassIsInterfaceNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new ClassIsInterfaceNodeGen(invoke) : new ClassIsInterfaceNode(invoke); + } + + protected ClassIsInterfaceNode(Invoke invoke) { super(invoke); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsPrimitiveNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsPrimitiveNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsPrimitiveNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.replacements.nodes.*; @@ -34,9 +35,14 @@ * * @see ClassSubstitutions#isPrimitive(Class) */ +@NodeInfo public class ClassIsPrimitiveNode extends MacroNode implements Canonicalizable { - public ClassIsPrimitiveNode(Invoke invoke) { + public static ClassIsPrimitiveNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new ClassIsPrimitiveNodeGen(invoke) : new ClassIsPrimitiveNode(invoke); + } + + protected ClassIsPrimitiveNode(Invoke invoke) { super(invoke); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,12 +25,12 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -40,9 +40,9 @@ * Compress or uncompress an oop or metaspace pointer. */ @NodeInfo(nameTemplate = "{p#op/s}") -public final class CompressionNode extends ConvertNode implements LIRLowerable { +public class CompressionNode extends ConvertNode implements LIRLowerable { - private enum CompressionOp { + enum CompressionOp { Compress, Uncompress } @@ -50,7 +50,11 @@ private final CompressionOp op; private final CompressEncoding encoding; - private CompressionNode(CompressionOp op, ValueNode input, CompressEncoding encoding) { + public static CompressionNode create(CompressionOp op, ValueNode input, CompressEncoding encoding) { + return USE_GENERATED_NODES ? new CompressionNodeGen(op, input, encoding) : new CompressionNode(op, input, encoding); + } + + CompressionNode(CompressionOp op, ValueNode input, CompressEncoding encoding) { super(mkStamp(op, input.stamp(), encoding), input); this.op = op; this.encoding = encoding; @@ -62,11 +66,11 @@ } public static CompressionNode compress(ValueNode input, CompressEncoding encoding) { - return input.graph().unique(new CompressionNode(CompressionOp.Compress, input, encoding)); + return input.graph().unique(CompressionNode.create(CompressionOp.Compress, input, encoding)); } public static CompressionNode uncompress(ValueNode input, CompressEncoding encoding) { - return input.graph().unique(new CompressionNode(CompressionOp.Uncompress, input, encoding)); + return input.graph().unique(CompressionNode.create(CompressionOp.Uncompress, input, encoding)); } private static Constant compress(Constant c, CompressEncoding encoding) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -29,6 +29,7 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; @@ -36,11 +37,16 @@ /** * Gets the address of the C++ JavaThread object for the current thread. */ -public final class CurrentJavaThreadNode extends FloatingNode implements LIRLowerable { +@NodeInfo +public class CurrentJavaThreadNode extends FloatingNode implements LIRLowerable { private LIRKind wordKind; - private CurrentJavaThreadNode(Kind kind) { + public static CurrentJavaThreadNode create(Kind kind) { + return USE_GENERATED_NODES ? new CurrentJavaThreadNodeGen(kind) : new CurrentJavaThreadNode(kind); + } + + CurrentJavaThreadNode(Kind kind) { super(StampFactory.forKind(kind)); this.wordKind = LIRKind.value(kind); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; @@ -32,11 +33,16 @@ /** * Intrinsic for getting the lock in the current {@linkplain BeginLockScopeNode lock scope}. */ -public final class CurrentLockNode extends FixedWithNextNode implements LIRLowerable { +@NodeInfo +public class CurrentLockNode extends FixedWithNextNode implements LIRLowerable { private int lockDepth; - private CurrentLockNode(int lockDepth) { + public static CurrentLockNode create(int lockDepth) { + return USE_GENERATED_NODES ? new CurrentLockNodeGen(lockDepth) : new CurrentLockNode(lockDepth); + } + + CurrentLockNode(int lockDepth) { super(null); this.lockDepth = lockDepth; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,9 +27,9 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -41,10 +41,14 @@ @NodeInfo(allowedUsageTypes = {InputType.Memory}) public class DeoptimizationFetchUnrollInfoCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Multi { - @Input private SaveAllRegistersNode registerSaver; + @Input SaveAllRegistersNode registerSaver; private final ForeignCallsProvider foreignCalls; - public DeoptimizationFetchUnrollInfoCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver) { + public static DeoptimizationFetchUnrollInfoCallNode create(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver) { + return USE_GENERATED_NODES ? new DeoptimizationFetchUnrollInfoCallNodeGen(foreignCalls, registerSaver) : new DeoptimizationFetchUnrollInfoCallNode(foreignCalls, registerSaver); + } + + protected DeoptimizationFetchUnrollInfoCallNode(ForeignCallsProvider foreignCalls, ValueNode registerSaver) { super(StampFactory.forKind(Kind.fromJavaClass(FETCH_UNROLL_INFO.getResultType()))); this.registerSaver = (SaveAllRegistersNode) registerSaver; this.foreignCalls = foreignCalls; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,8 +24,8 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -38,7 +38,11 @@ private final DeoptimizationAction action; private final DeoptimizationReason reason; - public DeoptimizeCallerNode(DeoptimizationAction action, DeoptimizationReason reason) { + public static DeoptimizeCallerNode create(DeoptimizationAction action, DeoptimizationReason reason) { + return USE_GENERATED_NODES ? new DeoptimizeCallerNodeGen(action, reason) : new DeoptimizeCallerNode(action, reason); + } + + protected DeoptimizeCallerNode(DeoptimizationAction action, DeoptimizationReason reason) { super(StampFactory.forVoid()); this.action = action; this.reason = reason; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,11 +23,17 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +@NodeInfo public class DeoptimizingStubCall extends DeoptimizingFixedWithNextNode { - public DeoptimizingStubCall(Stamp stamp) { + public static DeoptimizingStubCall create(Stamp stamp) { + return USE_GENERATED_NODES ? new DeoptimizingStubCallGen(stamp) : new DeoptimizingStubCall(stamp); + } + + protected DeoptimizingStubCall(Stamp stamp) { super(stamp); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -29,6 +29,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; @@ -37,11 +38,16 @@ * Intrinsic for allocating an on-stack array of integers to hold the dimensions of a multianewarray * instruction. */ -public final class DimensionsNode extends FixedWithNextNode implements LIRLowerable { +@NodeInfo +public class DimensionsNode extends FixedWithNextNode implements LIRLowerable { private final int rank; - private DimensionsNode(int rank) { + public static DimensionsNode create(int rank) { + return USE_GENERATED_NODES ? new DimensionsNodeGen(rank) : new DimensionsNode(rank); + } + + DimensionsNode(int rank) { super(null); this.rank = rank; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,8 +23,8 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; @@ -40,14 +40,19 @@ @NodeInfo(allowedUsageTypes = {InputType.Memory}) public class DirectCompareAndSwapNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single { - @Input private ValueNode object; - @Input private ValueNode offset; - @Input private ValueNode expectedValue; - @Input private ValueNode newValue; + @Input ValueNode object; + @Input ValueNode offset; + @Input ValueNode expectedValue; + @Input ValueNode newValue; private final LocationIdentity locationIdentity; - public DirectCompareAndSwapNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, LocationIdentity locationIdentity) { + public static DirectCompareAndSwapNode create(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, LocationIdentity locationIdentity) { + return USE_GENERATED_NODES ? new DirectCompareAndSwapNodeGen(object, offset, expected, newValue, locationIdentity) : new DirectCompareAndSwapNode(object, offset, expected, newValue, + locationIdentity); + } + + protected DirectCompareAndSwapNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, LocationIdentity locationIdentity) { super(expected.stamp()); this.object = object; this.offset = offset; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,7 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -34,9 +34,13 @@ * object. */ @NodeInfo(allowedUsageTypes = {InputType.Memory}) -public final class EndLockScopeNode extends AbstractMemoryCheckpoint implements LIRLowerable, MonitorExit, MemoryCheckpoint.Single { +public class EndLockScopeNode extends AbstractMemoryCheckpoint implements LIRLowerable, MonitorExit, MemoryCheckpoint.Single { - public EndLockScopeNode() { + public static EndLockScopeNode create() { + return USE_GENERATED_NODES ? new EndLockScopeNodeGen() : new EndLockScopeNode(); + } + + protected EndLockScopeNode() { super(StampFactory.forVoid()); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EnterUnpackFramesStackFrameNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EnterUnpackFramesStackFrameNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EnterUnpackFramesStackFrameNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,7 +25,8 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.lir.StandardOp.*; +import com.oracle.graal.lir.StandardOp.SaveRegistersOp; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; @@ -34,14 +35,20 @@ * Emits code to enter a low-level stack frame specifically to call out to the C++ method * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. */ +@NodeInfo public class EnterUnpackFramesStackFrameNode extends FixedWithNextNode implements LIRLowerable { - @Input private ValueNode framePc; - @Input private ValueNode senderSp; - @Input private ValueNode senderFp; - @Input private SaveAllRegistersNode registerSaver; + @Input ValueNode framePc; + @Input ValueNode senderSp; + @Input ValueNode senderFp; + @Input SaveAllRegistersNode registerSaver; - public EnterUnpackFramesStackFrameNode(ValueNode framePc, ValueNode senderSp, ValueNode senderFp, ValueNode registerSaver) { + public static EnterUnpackFramesStackFrameNode create(ValueNode framePc, ValueNode senderSp, ValueNode senderFp, ValueNode registerSaver) { + return USE_GENERATED_NODES ? new EnterUnpackFramesStackFrameNodeGen(framePc, senderSp, senderFp, registerSaver) : new EnterUnpackFramesStackFrameNode(framePc, senderSp, senderFp, + registerSaver); + } + + protected EnterUnpackFramesStackFrameNode(ValueNode framePc, ValueNode senderSp, ValueNode senderFp, ValueNode registerSaver) { super(StampFactory.forVoid()); this.framePc = framePc; this.senderSp = senderSp; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePostWriteBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePostWriteBarrier.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePostWriteBarrier.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,11 +22,17 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; -public final class G1ArrayRangePostWriteBarrier extends ArrayRangeWriteBarrier { +@NodeInfo +public class G1ArrayRangePostWriteBarrier extends ArrayRangeWriteBarrier { - public G1ArrayRangePostWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { + public static G1ArrayRangePostWriteBarrier create(ValueNode object, ValueNode startIndex, ValueNode length) { + return USE_GENERATED_NODES ? new G1ArrayRangePostWriteBarrierGen(object, startIndex, length) : new G1ArrayRangePostWriteBarrier(object, startIndex, length); + } + + protected G1ArrayRangePostWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { super(object, startIndex, length); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePreWriteBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePreWriteBarrier.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePreWriteBarrier.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,11 +22,17 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; -public final class G1ArrayRangePreWriteBarrier extends ArrayRangeWriteBarrier { +@NodeInfo +public class G1ArrayRangePreWriteBarrier extends ArrayRangeWriteBarrier { - public G1ArrayRangePreWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { + public static G1ArrayRangePreWriteBarrier create(ValueNode object, ValueNode startIndex, ValueNode length) { + return USE_GENERATED_NODES ? new G1ArrayRangePreWriteBarrierGen(object, startIndex, length) : new G1ArrayRangePreWriteBarrier(object, startIndex, length); + } + + protected G1ArrayRangePreWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { super(object, startIndex, length); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrier.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrier.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,14 +22,20 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; +@NodeInfo public class G1PostWriteBarrier extends WriteBarrier { private final boolean alwaysNull; - public G1PostWriteBarrier(ValueNode object, ValueNode value, LocationNode location, boolean precise, boolean alwaysNull) { + public static G1PostWriteBarrier create(ValueNode object, ValueNode value, LocationNode location, boolean precise, boolean alwaysNull) { + return USE_GENERATED_NODES ? new G1PostWriteBarrierGen(object, value, location, precise, alwaysNull) : new G1PostWriteBarrier(object, value, location, precise, alwaysNull); + } + + protected G1PostWriteBarrier(ValueNode object, ValueNode value, LocationNode location, boolean precise, boolean alwaysNull) { super(object, value, location, precise); this.alwaysNull = alwaysNull; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,17 +22,22 @@ */ package com.oracle.graal.hotspot.nodes; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; +@NodeInfo public class G1PreWriteBarrier extends WriteBarrier implements DeoptimizingNode.DeoptBefore { - @OptionalInput(InputType.State) private FrameState stateBefore; + @OptionalInput(InputType.State) FrameState stateBefore; private final boolean nullCheck; private final boolean doLoad; - public G1PreWriteBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad, boolean nullCheck) { + public static G1PreWriteBarrier create(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad, boolean nullCheck) { + return USE_GENERATED_NODES ? new G1PreWriteBarrierGen(object, expectedObject, location, doLoad, nullCheck) : new G1PreWriteBarrier(object, expectedObject, location, doLoad, nullCheck); + } + + protected G1PreWriteBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad, boolean nullCheck) { super(object, expectedObject, location, true); this.doLoad = doLoad; this.nullCheck = nullCheck; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ReferentFieldReadBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ReferentFieldReadBarrier.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ReferentFieldReadBarrier.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -31,11 +32,16 @@ * {@code UnsafeLoadNode}). The return value of the read is passed to the snippet implementing the * read barrier and consequently is added to the SATB queue if the concurrent marker is enabled. */ +@NodeInfo public class G1ReferentFieldReadBarrier extends WriteBarrier { private final boolean doLoad; - public G1ReferentFieldReadBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad) { + public static G1ReferentFieldReadBarrier create(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad) { + return USE_GENERATED_NODES ? new G1ReferentFieldReadBarrierGen(object, expectedObject, location, doLoad) : new G1ReferentFieldReadBarrier(object, expectedObject, location, doLoad); + } + + protected G1ReferentFieldReadBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad) { super(object, expectedObject, location, true); this.doLoad = doLoad; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -32,11 +33,16 @@ * {@link #get(Object)} and all uses of the returned value must be atomic. The only exception to * this is if the usage is not an attempt to dereference the value. */ +@NodeInfo public class GetObjectAddressNode extends FixedWithNextNode implements LIRLowerable { - @Input private ValueNode object; + @Input ValueNode object; - public GetObjectAddressNode(ValueNode obj) { + public static GetObjectAddressNode create(ValueNode obj) { + return USE_GENERATED_NODES ? new GetObjectAddressNodeGen(obj) : new GetObjectAddressNode(obj); + } + + protected GetObjectAddressNode(ValueNode obj) { super(StampFactory.forKind(Kind.Long)); this.object = obj; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,10 +27,17 @@ import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +@NodeInfo public class HotSpotDirectCallTargetNode extends DirectCallTargetNode { - public HotSpotDirectCallTargetNode(List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, Type callType, InvokeKind invokeKind) { + public static HotSpotDirectCallTargetNode create(List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, Type callType, InvokeKind invokeKind) { + return USE_GENERATED_NODES ? new HotSpotDirectCallTargetNodeGen(arguments, returnStamp, signature, target, callType, invokeKind) : new HotSpotDirectCallTargetNode(arguments, returnStamp, + signature, target, callType, invokeKind); + } + + protected HotSpotDirectCallTargetNode(List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, Type callType, InvokeKind invokeKind) { super(arguments, returnStamp, signature, target, callType, invokeKind); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,13 +27,21 @@ import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +@NodeInfo public class HotSpotIndirectCallTargetNode extends IndirectCallTargetNode { - @Input private ValueNode metaspaceMethod; + @Input ValueNode metaspaceMethod; - public HotSpotIndirectCallTargetNode(ValueNode metaspaceMethod, ValueNode computedAddress, List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, + public static HotSpotIndirectCallTargetNode create(ValueNode metaspaceMethod, ValueNode computedAddress, List arguments, Stamp returnStamp, JavaType[] signature, + ResolvedJavaMethod target, Type callType, InvokeKind invokeKind) { + return USE_GENERATED_NODES ? new HotSpotIndirectCallTargetNodeGen(metaspaceMethod, computedAddress, arguments, returnStamp, signature, target, callType, invokeKind) + : new HotSpotIndirectCallTargetNode(metaspaceMethod, computedAddress, arguments, returnStamp, signature, target, callType, invokeKind); + } + + protected HotSpotIndirectCallTargetNode(ValueNode metaspaceMethod, ValueNode computedAddress, List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, Type callType, InvokeKind invokeKind) { super(computedAddress, arguments, returnStamp, signature, target, callType, invokeKind); this.metaspaceMethod = metaspaceMethod; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,6 +24,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; @@ -32,13 +33,19 @@ * Sets up the {@linkplain HotSpotBackend#EXCEPTION_HANDLER_IN_CALLER arguments} expected by an * exception handler in the caller's frame, removes the current frame and jumps to said handler. */ +@NodeInfo public class JumpToExceptionHandlerInCallerNode extends ControlSinkNode implements LIRLowerable { - @Input private ValueNode handlerInCallerPc; - @Input private ValueNode exception; - @Input private ValueNode exceptionPc; + @Input ValueNode handlerInCallerPc; + @Input ValueNode exception; + @Input ValueNode exceptionPc; - public JumpToExceptionHandlerInCallerNode(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) { + public static JumpToExceptionHandlerInCallerNode create(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) { + return USE_GENERATED_NODES ? new JumpToExceptionHandlerInCallerNodeGen(handlerInCallerPc, exception, exceptionPc) : new JumpToExceptionHandlerInCallerNode(handlerInCallerPc, exception, + exceptionPc); + } + + protected JumpToExceptionHandlerInCallerNode(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) { super(StampFactory.forVoid()); this.handlerInCallerPc = handlerInCallerPc; this.exception = exception; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveCurrentStackFrameNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveCurrentStackFrameNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveCurrentStackFrameNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,7 +24,8 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.lir.StandardOp.*; +import com.oracle.graal.lir.StandardOp.SaveRegistersOp; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -32,11 +33,16 @@ * Emits code to leave (pop) the current low-level stack frame. This operation also removes the * return address if its location is on the stack. */ +@NodeInfo public class LeaveCurrentStackFrameNode extends FixedWithNextNode implements LIRLowerable { - @Input private SaveAllRegistersNode registerSaver; + @Input SaveAllRegistersNode registerSaver; - public LeaveCurrentStackFrameNode(ValueNode registerSaver) { + public static LeaveCurrentStackFrameNode create(ValueNode registerSaver) { + return USE_GENERATED_NODES ? new LeaveCurrentStackFrameNodeGen(registerSaver) : new LeaveCurrentStackFrameNode(registerSaver); + } + + protected LeaveCurrentStackFrameNode(ValueNode registerSaver) { super(StampFactory.forVoid()); this.registerSaver = (SaveAllRegistersNode) registerSaver; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; @@ -34,12 +35,17 @@ * Emits code to leave (pop) the current low-level stack frame which is being deoptimized. This node * is only used in {@link DeoptimizationStub}. */ +@NodeInfo public class LeaveDeoptimizedStackFrameNode extends FixedWithNextNode implements LIRLowerable { - @Input private ValueNode frameSize; - @Input private ValueNode initialInfo; + @Input ValueNode frameSize; + @Input ValueNode initialInfo; - public LeaveDeoptimizedStackFrameNode(ValueNode frameSize, ValueNode initialInfo) { + public static LeaveDeoptimizedStackFrameNode create(ValueNode frameSize, ValueNode initialInfo) { + return USE_GENERATED_NODES ? new LeaveDeoptimizedStackFrameNodeGen(frameSize, initialInfo) : new LeaveDeoptimizedStackFrameNode(frameSize, initialInfo); + } + + protected LeaveDeoptimizedStackFrameNode(ValueNode frameSize, ValueNode initialInfo) { super(StampFactory.forVoid()); this.frameSize = frameSize; this.initialInfo = initialInfo; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,7 +24,8 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.lir.StandardOp.*; +import com.oracle.graal.lir.StandardOp.SaveRegistersOp; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -32,11 +33,16 @@ * Emits code to leave a low-level stack frame specifically to call out to the C++ method * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. */ +@NodeInfo public class LeaveUnpackFramesStackFrameNode extends FixedWithNextNode implements LIRLowerable { - @Input private SaveAllRegistersNode registerSaver; + @Input SaveAllRegistersNode registerSaver; - public LeaveUnpackFramesStackFrameNode(ValueNode registerSaver) { + public static LeaveUnpackFramesStackFrameNode create(ValueNode registerSaver) { + return USE_GENERATED_NODES ? new LeaveUnpackFramesStackFrameNodeGen(registerSaver) : new LeaveUnpackFramesStackFrameNode(registerSaver); + } + + protected LeaveUnpackFramesStackFrameNode(ValueNode registerSaver) { super(StampFactory.forVoid()); this.registerSaver = (SaveAllRegistersNode) registerSaver; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; @@ -33,9 +34,14 @@ /** * Node that is used to maintain a stack based counter of how many locks are currently held. */ -public final class MonitorCounterNode extends FloatingNode implements LIRLowerable { +@NodeInfo +public class MonitorCounterNode extends FloatingNode implements LIRLowerable { - private MonitorCounterNode() { + public static MonitorCounterNode create() { + return USE_GENERATED_NODES ? new MonitorCounterNodeGen() : new MonitorCounterNode(); + } + + MonitorCounterNode() { super(null); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java Mon Aug 25 21:15:59 2014 -0700 @@ -29,6 +29,7 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; @@ -36,14 +37,19 @@ /** * A call to the {@link NewArrayStub}. */ +@NodeInfo public class NewArrayStubCall extends DeoptimizingStubCall implements LIRLowerable { private static final Stamp defaultStamp = StampFactory.objectNonNull(); - @Input private ValueNode hub; - @Input private ValueNode length; + @Input ValueNode hub; + @Input ValueNode length; - public NewArrayStubCall(ValueNode hub, ValueNode length) { + public static NewArrayStubCall create(ValueNode hub, ValueNode length) { + return USE_GENERATED_NODES ? new NewArrayStubCallGen(hub, length) : new NewArrayStubCall(hub, length); + } + + protected NewArrayStubCall(ValueNode hub, ValueNode length) { super(defaultStamp); this.hub = hub; this.length = length; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Mon Aug 25 21:15:59 2014 -0700 @@ -29,6 +29,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; @@ -36,13 +37,18 @@ /** * A call to the {@link NewInstanceStub}. */ +@NodeInfo public class NewInstanceStubCall extends DeoptimizingStubCall implements LIRLowerable { private static final Stamp defaultStamp = StampFactory.objectNonNull(); - @Input private ValueNode hub; + @Input ValueNode hub; - public NewInstanceStubCall(ValueNode hub) { + public static NewInstanceStubCall create(ValueNode hub) { + return USE_GENERATED_NODES ? new NewInstanceStubCallGen(hub) : new NewInstanceStubCall(hub); + } + + protected NewInstanceStubCall(ValueNode hub) { super(defaultStamp); this.hub = hub; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java Mon Aug 25 21:15:59 2014 -0700 @@ -28,6 +28,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -36,15 +37,20 @@ /** * Node implementing a call to {@code GraalRuntime::new_multi_array}. */ +@NodeInfo public class NewMultiArrayStubCall extends ForeignCallNode { private static final Stamp defaultStamp = StampFactory.objectNonNull(); - @Input private ValueNode hub; - @Input private ValueNode dims; + @Input ValueNode hub; + @Input ValueNode dims; private final int rank; - public NewMultiArrayStubCall(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode hub, int rank, ValueNode dims) { + public static NewMultiArrayStubCall create(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode hub, int rank, ValueNode dims) { + return USE_GENERATED_NODES ? new NewMultiArrayStubCallGen(foreignCalls, hub, rank, dims) : new NewMultiArrayStubCall(foreignCalls, hub, rank, dims); + } + + protected NewMultiArrayStubCall(ForeignCallsProvider foreignCalls, ValueNode hub, int rank, ValueNode dims) { super(foreignCalls, NEW_MULTI_ARRAY, defaultStamp); this.hub = hub; this.rank = rank; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PatchReturnAddressNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PatchReturnAddressNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PatchReturnAddressNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,6 +24,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; @@ -31,11 +32,16 @@ /** * Modifies the return address of the current frame. */ +@NodeInfo public class PatchReturnAddressNode extends FixedWithNextNode implements LIRLowerable { - @Input private ValueNode address; + @Input ValueNode address; - public PatchReturnAddressNode(ValueNode address) { + public static PatchReturnAddressNode create(ValueNode address) { + return USE_GENERATED_NODES ? new PatchReturnAddressNodeGen(address) : new PatchReturnAddressNode(address); + } + + protected PatchReturnAddressNode(ValueNode address) { super(StampFactory.forVoid()); this.address = address; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,16 +25,22 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; +@NodeInfo public class PrefetchAllocateNode extends FixedWithNextNode implements LIRLowerable { - @Input private ValueNode distance; - @Input private ValueNode address; + @Input ValueNode distance; + @Input ValueNode address; - public PrefetchAllocateNode(ValueNode address, ValueNode distance) { + public static PrefetchAllocateNode create(ValueNode address, ValueNode distance) { + return USE_GENERATED_NODES ? new PrefetchAllocateNodeGen(address, distance) : new PrefetchAllocateNode(address, distance); + } + + protected PrefetchAllocateNode(ValueNode address, ValueNode distance) { super(StampFactory.forVoid()); this.address = address; this.distance = distance; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PushInterpreterFrameNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PushInterpreterFrameNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PushInterpreterFrameNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; @@ -32,14 +33,19 @@ /** * A call to the runtime code implementing the uncommon trap logic. */ +@NodeInfo public class PushInterpreterFrameNode extends FixedWithNextNode implements LIRLowerable { - @Input private ValueNode framePc; - @Input private ValueNode frameSize; - @Input private ValueNode senderSp; - @Input private ValueNode initialInfo; + @Input ValueNode framePc; + @Input ValueNode frameSize; + @Input ValueNode senderSp; + @Input ValueNode initialInfo; - public PushInterpreterFrameNode(ValueNode frameSize, ValueNode framePc, ValueNode senderSp, ValueNode initialInfo) { + public static PushInterpreterFrameNode create(ValueNode frameSize, ValueNode framePc, ValueNode senderSp, ValueNode initialInfo) { + return USE_GENERATED_NODES ? new PushInterpreterFrameNodeGen(frameSize, framePc, senderSp, initialInfo) : new PushInterpreterFrameNode(frameSize, framePc, senderSp, initialInfo); + } + + protected PushInterpreterFrameNode(ValueNode frameSize, ValueNode framePc, ValueNode senderSp, ValueNode initialInfo) { super(StampFactory.forVoid()); this.frameSize = frameSize; this.framePc = framePc; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SaveAllRegistersNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SaveAllRegistersNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SaveAllRegistersNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,9 +24,9 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.lir.StandardOp.*; +import com.oracle.graal.lir.StandardOp.SaveRegistersOp; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -39,7 +39,11 @@ private SaveRegistersOp saveRegistersOp; - public SaveAllRegistersNode() { + public static SaveAllRegistersNode create() { + return USE_GENERATED_NODES ? new SaveAllRegistersNodeGen() : new SaveAllRegistersNode(); + } + + protected SaveAllRegistersNode() { super(StampFactory.forKind(Kind.Long)); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialArrayRangeWriteBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialArrayRangeWriteBarrier.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialArrayRangeWriteBarrier.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,11 +22,17 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; -public final class SerialArrayRangeWriteBarrier extends ArrayRangeWriteBarrier { +@NodeInfo +public class SerialArrayRangeWriteBarrier extends ArrayRangeWriteBarrier { - public SerialArrayRangeWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { + public static SerialArrayRangeWriteBarrier create(ValueNode object, ValueNode startIndex, ValueNode length) { + return USE_GENERATED_NODES ? new SerialArrayRangeWriteBarrierGen(object, startIndex, length) : new SerialArrayRangeWriteBarrier(object, startIndex, length); + } + + protected SerialArrayRangeWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { super(object, startIndex, length); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialWriteBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialWriteBarrier.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialWriteBarrier.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,14 +22,20 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; +@NodeInfo public class SerialWriteBarrier extends WriteBarrier { private final boolean alwaysNull; - public SerialWriteBarrier(ValueNode object, LocationNode location, boolean precise, boolean alwaysNull) { + public static SerialWriteBarrier create(ValueNode object, LocationNode location, boolean precise, boolean alwaysNull) { + return USE_GENERATED_NODES ? new SerialWriteBarrierGen(object, location, precise, alwaysNull) : new SerialWriteBarrier(object, location, precise, alwaysNull); + } + + protected SerialWriteBarrier(ValueNode object, LocationNode location, boolean precise, boolean alwaysNull) { super(object, null, location, precise); this.alwaysNull = alwaysNull; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetAnchorNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetAnchorNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetAnchorNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,15 +23,19 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @NodeInfo(allowedUsageTypes = {InputType.Value, InputType.Anchor, InputType.Guard}) -public final class SnippetAnchorNode extends FixedWithNextNode implements Simplifiable, GuardingNode { +public class SnippetAnchorNode extends FixedWithNextNode implements Simplifiable, GuardingNode { - public SnippetAnchorNode() { + public static SnippetAnchorNode create() { + return USE_GENERATED_NODES ? new SnippetAnchorNodeGen() : new SnippetAnchorNode(); + } + + protected SnippetAnchorNode() { super(StampFactory.object()); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetLocationProxyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetLocationProxyNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetLocationProxyNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,16 +25,21 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; @NodeInfo(allowedUsageTypes = {InputType.Association, InputType.Value}) -public final class SnippetLocationProxyNode extends FloatingNode implements Canonicalizable { +public class SnippetLocationProxyNode extends FloatingNode implements Canonicalizable { + + @Input(InputType.Unchecked) ValueNode location; - @Input(InputType.Unchecked) private ValueNode location; + public static SnippetLocationProxyNode create(ValueNode location) { + return USE_GENERATED_NODES ? new SnippetLocationProxyNodeGen(location) : new SnippetLocationProxyNode(location); + } - public SnippetLocationProxyNode(ValueNode location) { + protected SnippetLocationProxyNode(ValueNode location) { super(StampFactory.object()); this.location = location; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -29,6 +29,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -39,12 +40,16 @@ @NodeInfo(nameTemplate = "StubForeignCall#{p#descriptor/s}", allowedUsageTypes = {InputType.Memory}) public class StubForeignCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Multi { - @Input private final NodeInputList arguments; + @Input NodeInputList arguments; private final ForeignCallsProvider foreignCalls; private final ForeignCallDescriptor descriptor; - public StubForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) { + public static StubForeignCallNode create(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) { + return USE_GENERATED_NODES ? new StubForeignCallNodeGen(foreignCalls, descriptor, arguments) : new StubForeignCallNode(foreignCalls, descriptor, arguments); + } + + protected StubForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) { super(StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType()))); this.arguments = new NodeInputList<>(this, arguments); this.descriptor = descriptor; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubStartNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubStartNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubStartNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,16 +23,22 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; /** * Start node for a {@link Stub}'s graph. */ +@NodeInfo public class StubStartNode extends StartNode { private final Stub stub; - public StubStartNode(Stub stub) { + public static StubStartNode create(Stub stub) { + return USE_GENERATED_NODES ? new StubStartNodeGen(stub) : new StubStartNode(stub); + } + + protected StubStartNode(Stub stub) { this.stub = stub; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -29,10 +29,10 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.java.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -40,10 +40,11 @@ * Performs a tail call to the specified target compiled method, with the parameter taken from the * supplied FrameState. */ +@NodeInfo public class TailcallNode extends FixedWithNextNode implements LIRLowerable { - @Input(InputType.State) private FrameState frameState; - @Input private ValueNode target; + @Input(InputType.State) FrameState frameState; + @Input ValueNode target; /** * Creates a TailcallNode. @@ -51,7 +52,11 @@ * @param target points to the start of an nmethod * @param frameState the parameters will be taken from this FrameState */ - public TailcallNode(ValueNode target, FrameState frameState) { + public static TailcallNode create(ValueNode target, FrameState frameState) { + return USE_GENERATED_NODES ? new TailcallNodeGen(target, frameState) : new TailcallNode(target, frameState); + } + + protected TailcallNode(ValueNode target, FrameState frameState) { super(StampFactory.forVoid()); this.target = target; this.frameState = frameState; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,9 +27,9 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -41,11 +41,15 @@ @NodeInfo(allowedUsageTypes = {InputType.Memory}) public class UncommonTrapCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Multi { - @Input private ValueNode trapRequest; - @Input private SaveAllRegistersNode registerSaver; + @Input ValueNode trapRequest; + @Input SaveAllRegistersNode registerSaver; private final ForeignCallsProvider foreignCalls; - public UncommonTrapCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver, ValueNode trapRequest) { + public static UncommonTrapCallNode create(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver, ValueNode trapRequest) { + return USE_GENERATED_NODES ? new UncommonTrapCallNodeGen(foreignCalls, registerSaver, trapRequest) : new UncommonTrapCallNode(foreignCalls, registerSaver, trapRequest); + } + + protected UncommonTrapCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver, ValueNode trapRequest) { super(StampFactory.forKind(Kind.fromJavaClass(UNCOMMON_TRAP.getResultType()))); this.trapRequest = trapRequest; this.registerSaver = (SaveAllRegistersNode) registerSaver; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -28,6 +28,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; @@ -36,12 +37,17 @@ * Causes the VM to exit with a description of the current Java location and an optional * {@linkplain Log#printf(String, long) formatted} error message specified. */ -public final class VMErrorNode extends DeoptimizingStubCall implements LIRLowerable { +@NodeInfo +public class VMErrorNode extends DeoptimizingStubCall implements LIRLowerable { private final String format; - @Input private ValueNode value; + @Input ValueNode value; - public VMErrorNode(String format, ValueNode value) { + public static VMErrorNode create(String format, ValueNode value) { + return USE_GENERATED_NODES ? new VMErrorNodeGen(format, value) : new VMErrorNode(format, value); + } + + protected VMErrorNode(String format, ValueNode value) { super(StampFactory.forVoid()); this.format = format; this.value = value; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,16 +23,17 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public abstract class WriteBarrier extends FixedWithNextNode implements Lowerable { - @Input private ValueNode object; - @OptionalInput private ValueNode value; - @OptionalInput(InputType.Association) private LocationNode location; + @Input ValueNode object; + @OptionalInput ValueNode value; + @OptionalInput(InputType.Association) LocationNode location; private final boolean precise; public WriteBarrier(ValueNode object, ValueNode value, LocationNode location, boolean precise) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Mon Aug 25 21:15:59 2014 -0700 @@ -28,7 +28,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.hotspot.HotSpotVMConfig.*; +import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.*; @@ -91,7 +91,7 @@ ConstantNode klassNode = ConstantNode.forConstant(klass, metaAccess, graph); Stamp stamp = StampFactory.exactNonNull(metaAccess.lookupJavaType(Class.class)); - FloatingReadNode freadNode = graph.unique(new FloatingReadNode(klassNode, location, null, stamp)); + FloatingReadNode freadNode = graph.unique(FloatingReadNode.create(klassNode, location, null, stamp)); if (HotSpotObjectConstant.isCompressed(constant)) { return CompressionNode.compress(freadNode, oopEncoding); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,9 +26,9 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Node.Verbosity; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.loop.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.util.*; @@ -84,7 +84,7 @@ FrameState osrState = osr.stateAfter(); osr.setStateAfter(null); - OSRStartNode osrStart = graph.add(new OSRStartNode()); + OSRStartNode osrStart = graph.add(OSRStartNode.create()); StartNode start = graph.start(); FixedNode next = osr.next(); osr.setNext(null); @@ -100,7 +100,7 @@ * we need to drop the stamp since the types we see during OSR may be too precise * (if a branch was not parsed for example). */ - proxy.replaceAndDelete(graph.unique(new OSRLocalNode(i, proxy.stamp().unrestricted()))); + proxy.replaceAndDelete(graph.unique(OSRLocalNode.create(i, proxy.stamp().unrestricted()))); } else { assert value == null || value instanceof OSRLocalNode; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java Mon Aug 25 21:15:59 2014 -0700 @@ -63,7 +63,7 @@ private static void addReadNodeBarriers(ReadNode node, StructuredGraph graph) { if (node.getBarrierType() == BarrierType.PRECISE) { assert useG1GC(); - G1ReferentFieldReadBarrier barrier = graph.add(new G1ReferentFieldReadBarrier(node.object(), node, node.location(), false)); + G1ReferentFieldReadBarrier barrier = graph.add(G1ReferentFieldReadBarrier.create(node.object(), node, node.location(), false)); graph.addAfterFixed(node, barrier); } else { assert node.getBarrierType() == BarrierType.NONE : "Non precise read barrier has been attached to read node."; @@ -71,7 +71,7 @@ } protected static void addG1PreWriteBarrier(FixedAccessNode node, ValueNode object, ValueNode value, LocationNode location, boolean doLoad, boolean nullCheck, StructuredGraph graph) { - G1PreWriteBarrier preBarrier = graph.add(new G1PreWriteBarrier(object, value, location, doLoad, nullCheck)); + G1PreWriteBarrier preBarrier = graph.add(G1PreWriteBarrier.create(object, value, location, doLoad, nullCheck)); preBarrier.setStateBefore(node.stateBefore()); node.setNullCheck(false); node.setStateBefore(null); @@ -80,13 +80,13 @@ protected void addG1PostWriteBarrier(FixedAccessNode node, ValueNode object, ValueNode value, LocationNode location, boolean precise, StructuredGraph graph) { final boolean alwaysNull = StampTool.isObjectAlwaysNull(value); - graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(object, value, location, precise, alwaysNull))); + graph.addAfterFixed(node, graph.add(G1PostWriteBarrier.create(object, value, location, precise, alwaysNull))); } protected void addSerialPostWriteBarrier(FixedAccessNode node, ValueNode object, ValueNode value, LocationNode location, boolean precise, StructuredGraph graph) { final boolean alwaysNull = StampTool.isObjectAlwaysNull(value); final LocationNode loc = (precise ? location : null); - graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(object, loc, precise, alwaysNull))); + graph.addAfterFixed(node, graph.add(SerialWriteBarrier.create(object, loc, precise, alwaysNull))); } private void addWriteNodeBarriers(WriteNode node, StructuredGraph graph) { @@ -157,13 +157,13 @@ private static void addArrayRangeBarriers(ArrayRangeWriteNode node, StructuredGraph graph) { if (useG1GC()) { if (!node.isInitialization()) { - G1ArrayRangePreWriteBarrier g1ArrayRangePreWriteBarrier = graph.add(new G1ArrayRangePreWriteBarrier(node.getArray(), node.getIndex(), node.getLength())); + G1ArrayRangePreWriteBarrier g1ArrayRangePreWriteBarrier = graph.add(G1ArrayRangePreWriteBarrier.create(node.getArray(), node.getIndex(), node.getLength())); graph.addBeforeFixed(node, g1ArrayRangePreWriteBarrier); } - G1ArrayRangePostWriteBarrier g1ArrayRangePostWriteBarrier = graph.add(new G1ArrayRangePostWriteBarrier(node.getArray(), node.getIndex(), node.getLength())); + G1ArrayRangePostWriteBarrier g1ArrayRangePostWriteBarrier = graph.add(G1ArrayRangePostWriteBarrier.create(node.getArray(), node.getIndex(), node.getLength())); graph.addAfterFixed(node, g1ArrayRangePostWriteBarrier); } else { - SerialArrayRangeWriteBarrier serialArrayRangeWriteBarrier = graph.add(new SerialArrayRangeWriteBarrier(node.getArray(), node.getIndex(), node.getLength())); + SerialArrayRangeWriteBarrier serialArrayRangeWriteBarrier = graph.add(SerialArrayRangeWriteBarrier.create(node.getArray(), node.getIndex(), node.getLength())); graph.addAfterFixed(node, serialArrayRangeWriteBarrier); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java Mon Aug 25 21:15:59 2014 -0700 @@ -128,7 +128,7 @@ } private static boolean validateBarrier(FixedAccessNode write, WriteBarrier barrier) { - assert write instanceof WriteNode || write instanceof LoweredCompareAndSwapNode : "Node must be of type requiring a write barrier"; + assert write instanceof WriteNode || write instanceof LoweredCompareAndSwapNode || write instanceof LoweredAtomicReadAndWriteNode : "Node must be of type requiring a write barrier " + write; if ((barrier.getObject() == write.object()) && (!barrier.usePrecise() || (barrier.usePrecise() && barrier.getLocation() == write.location()))) { return true; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -30,9 +30,9 @@ import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; @@ -41,13 +41,13 @@ import com.oracle.graal.runtime.*; @NodeInfo(allowedUsageTypes = {InputType.Memory}) -public final class ArrayCopyCallNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single { +public class ArrayCopyCallNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single { - @Input private ValueNode src; - @Input private ValueNode srcPos; - @Input private ValueNode dest; - @Input private ValueNode destPos; - @Input private ValueNode length; + @Input ValueNode src; + @Input ValueNode srcPos; + @Input ValueNode dest; + @Input ValueNode destPos; + @Input ValueNode length; private Kind elementKind; @@ -58,7 +58,13 @@ private boolean disjoint; private boolean uninitialized; - private ArrayCopyCallNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind, boolean aligned, boolean disjoint, boolean uninitialized) { + public static ArrayCopyCallNode create(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind, boolean aligned, boolean disjoint, + boolean uninitialized) { + return USE_GENERATED_NODES ? new ArrayCopyCallNodeGen(src, srcPos, dest, destPos, length, elementKind, aligned, disjoint, uninitialized) : new ArrayCopyCallNode(src, srcPos, dest, destPos, + length, elementKind, aligned, disjoint, uninitialized); + } + + ArrayCopyCallNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind, boolean aligned, boolean disjoint, boolean uninitialized) { super(StampFactory.forVoid()); assert elementKind != null; this.src = src; @@ -72,7 +78,12 @@ this.uninitialized = uninitialized; } - private ArrayCopyCallNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind, boolean disjoint) { + public static ArrayCopyCallNode create(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind, boolean disjoint) { + return USE_GENERATED_NODES ? new ArrayCopyCallNodeGen(src, srcPos, dest, destPos, length, elementKind, disjoint) : new ArrayCopyCallNode(src, srcPos, dest, destPos, length, elementKind, + disjoint); + } + + ArrayCopyCallNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind, boolean disjoint) { this(src, srcPos, dest, destPos, length, elementKind, false, disjoint, false); } @@ -113,10 +124,10 @@ } private ValueNode computeBase(ValueNode base, ValueNode pos) { - FixedWithNextNode basePtr = graph().add(new GetObjectAddressNode(base)); + FixedWithNextNode basePtr = graph().add(GetObjectAddressNode.create(base)); graph().addBeforeFixed(this, basePtr); ValueNode loc = IndexedLocationNode.create(getLocationIdentity(), elementKind, arrayBaseOffset(elementKind), pos, graph(), arrayIndexScale(elementKind)); - return graph().unique(new ComputeAddressNode(basePtr, loc, StampFactory.forKind(Kind.Long))); + return graph().unique(ComputeAddressNode.create(basePtr, loc, StampFactory.forKind(Kind.Long))); } @Override @@ -131,7 +142,7 @@ if (len.stamp().getStackKind() != Kind.Long) { len = IntegerConvertNode.convert(len, StampFactory.forKind(Kind.Long), graph()); } - ForeignCallNode call = graph.add(new ForeignCallNode(Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getForeignCalls(), desc, srcAddr, destAddr, len)); + ForeignCallNode call = graph.add(ForeignCallNode.create(Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getForeignCalls(), desc, srcAddr, destAddr, len)); call.setStateAfter(stateAfter()); graph.replaceFixedWithFixed(this, call); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -30,6 +30,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.loop.phases.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -38,9 +39,14 @@ import com.oracle.graal.phases.tiers.*; import com.oracle.graal.replacements.nodes.*; +@NodeInfo public class ArrayCopyNode extends MacroStateSplitNode implements Virtualizable, Lowerable { - public ArrayCopyNode(Invoke invoke) { + public static ArrayCopyNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new ArrayCopyNodeGen(invoke) : new ArrayCopyNode(invoke); + } + + protected ArrayCopyNode(Invoke invoke) { super(invoke); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -29,13 +29,19 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.nodes.*; +@NodeInfo public class CallSiteTargetNode extends MacroStateSplitNode implements Canonicalizable, Lowerable { - public CallSiteTargetNode(Invoke invoke) { + public static CallSiteTargetNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new CallSiteTargetNodeGen(invoke) : new CallSiteTargetNode(invoke); + } + + protected CallSiteTargetNode(Invoke invoke) { super(invoke); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompositeValueClassSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompositeValueClassSubstitutions.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompositeValueClassSubstitutions.java Mon Aug 25 21:15:59 2014 -0700 @@ -28,6 +28,7 @@ import com.oracle.graal.api.replacements.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.lir.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.nodes.*; @@ -43,9 +44,14 @@ * knowledge about node classes to replace itself with a constant value for a constant * {@link Class} parameter. */ + @NodeInfo public static class CompositeValueClassGetNode extends PureFunctionMacroNode { - public CompositeValueClassGetNode(Invoke invoke) { + public static CompositeValueClassGetNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new CompositeValueClassSubstitutions_CompositeValueClassGetNodeGen(invoke) : new CompositeValueClassGetNode(invoke); + } + + protected CompositeValueClassGetNode(Invoke invoke) { super(invoke); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeClassSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeClassSubstitutions.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeClassSubstitutions.java Mon Aug 25 21:15:59 2014 -0700 @@ -28,6 +28,7 @@ import com.oracle.graal.api.replacements.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.nodes.*; @@ -43,9 +44,14 @@ * about node classes to replace itself with a constant value for a constant {@link Class} * parameter. */ + @NodeInfo public static class NodeClassGetNode extends PureFunctionMacroNode { - public NodeClassGetNode(Invoke invoke) { + public static NodeClassGetNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new HotSpotNodeClassSubstitutions_NodeClassGetNodeGen(invoke) : new NodeClassGetNode(invoke); + } + + protected NodeClassGetNode(Invoke invoke) { super(invoke); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Mon Aug 25 21:15:59 2014 -0700 @@ -78,9 +78,9 @@ public void lower(LoadExceptionObjectNode loadExceptionObject, HotSpotRegistersProvider registers, LoweringTool tool) { if (USE_C_RUNTIME) { StructuredGraph graph = loadExceptionObject.graph(); - ReadRegisterNode thread = graph.add(new ReadRegisterNode(registers.getThreadRegister(), true, false)); + ReadRegisterNode thread = graph.add(ReadRegisterNode.create(registers.getThreadRegister(), true, false)); graph.addBeforeFixed(loadExceptionObject, thread); - ForeignCallNode loadExceptionC = graph.add(new ForeignCallNode(providers.getForeignCalls(), LOAD_AND_CLEAR_EXCEPTION, thread)); + ForeignCallNode loadExceptionC = graph.add(ForeignCallNode.create(providers.getForeignCalls(), LOAD_AND_CLEAR_EXCEPTION, thread)); loadExceptionC.setStateAfter(loadExceptionObject.stateAfter()); graph.replaceFixedWithFixed(loadExceptionObject, loadExceptionC); } else { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -34,6 +34,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.java.*; @@ -44,6 +45,7 @@ /** * Node for invocation methods defined on the class {@link MethodHandle}. */ +@NodeInfo public class MethodHandleNode extends MacroStateSplitNode implements Simplifiable { /** The method that this node is representing. */ @@ -52,9 +54,13 @@ // Replacement method data private ResolvedJavaMethod replacementTargetMethod; private JavaType replacementReturnType; - @Input private final NodeInputList replacementArguments; + @Input NodeInputList replacementArguments; - public MethodHandleNode(Invoke invoke) { + public static MethodHandleNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new MethodHandleNodeGen(invoke) : new MethodHandleNode(invoke); + } + + protected MethodHandleNode(Invoke invoke) { super(invoke); MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); @@ -98,10 +104,10 @@ throw GraalInternalError.shouldNotReachHere(); } if (invoke != null) { - FixedNode next = next(); + FixedNode currentNext = next(); replaceAtUsages(invoke); GraphUtil.removeFixedWithUnusedInputs(this); - graph().addBeforeFixed(next, invoke); + graph().addBeforeFixed(currentNext, invoke); } } @@ -230,7 +236,7 @@ ValueNode argument = arguments.get(index); ResolvedJavaType argumentType = StampTool.typeOrNull(argument.stamp()); if (argumentType == null || (argumentType.isAssignableFrom(targetType) && !argumentType.equals(targetType))) { - PiNode piNode = graph().unique(new PiNode(argument, StampFactory.declared(targetType))); + PiNode piNode = graph().unique(PiNode.create(argument, StampFactory.declared(targetType))); arguments.set(index, piNode); } } @@ -269,10 +275,10 @@ // If there is already replacement information, use that instead. MethodCallTargetNode callTarget; if (replacementTargetMethod == null) { - callTarget = new SelfReplacingMethodCallTargetNode(invokeKind, targetMethod, targetArguments, returnType, getTargetMethod(), originalArguments, getReturnType()); + callTarget = SelfReplacingMethodCallTargetNode.create(invokeKind, targetMethod, targetArguments, returnType, getTargetMethod(), originalArguments, getReturnType()); } else { ValueNode[] args = replacementArguments.toArray(new ValueNode[replacementArguments.size()]); - callTarget = new SelfReplacingMethodCallTargetNode(invokeKind, targetMethod, targetArguments, returnType, replacementTargetMethod, args, replacementReturnType); + callTarget = SelfReplacingMethodCallTargetNode.create(invokeKind, targetMethod, targetArguments, returnType, replacementTargetMethod, args, replacementReturnType); } graph().add(callTarget); @@ -283,9 +289,9 @@ // (usually java.lang.Object). InvokeNode invoke; if (stamp() == StampFactory.forVoid()) { - invoke = new InvokeNode(callTarget, getBci(), stamp()); + invoke = InvokeNode.create(callTarget, getBci(), stamp()); } else { - invoke = new InvokeNode(callTarget, getBci()); + invoke = InvokeNode.create(callTarget, getBci()); } graph().add(invoke); invoke.setStateAfter(stateAfter()); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Mon Aug 25 21:15:59 2014 -0700 @@ -495,8 +495,8 @@ if (nodes.isEmpty()) { // Only insert the nodes if this is the first monitorenter being lowered. JavaType returnType = initCounter.getMethod().getSignature().getReturnType(initCounter.getMethod().getDeclaringClass()); - MethodCallTargetNode callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, initCounter.getMethod(), new ValueNode[0], returnType)); - InvokeNode invoke = graph.add(new InvokeNode(callTarget, 0)); + MethodCallTargetNode callTarget = graph.add(MethodCallTargetNode.create(InvokeKind.Static, initCounter.getMethod(), new ValueNode[0], returnType)); + InvokeNode invoke = graph.add(InvokeNode.create(callTarget, 0)); invoke.setStateAfter(graph.start().stateAfter()); graph.addAfterFixed(graph.start(), invoke); @@ -508,10 +508,10 @@ returnType = checkCounter.getMethod().getSignature().getReturnType(checkCounter.getMethod().getDeclaringClass()); String msg = "unbalanced monitors in " + graph.method().format("%H.%n(%p)") + ", count = %d"; ConstantNode errMsg = ConstantNode.forConstant(HotSpotObjectConstant.forObject(msg), providers.getMetaAccess(), graph); - callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter.getMethod(), new ValueNode[]{errMsg}, returnType)); - invoke = graph.add(new InvokeNode(callTarget, 0)); + callTarget = graph.add(MethodCallTargetNode.create(InvokeKind.Static, checkCounter.getMethod(), new ValueNode[]{errMsg}, returnType)); + invoke = graph.add(InvokeNode.create(callTarget, 0)); List stack = Collections.emptyList(); - FrameState stateAfter = new FrameState(graph.method(), BytecodeFrame.AFTER_BCI, new ValueNode[0], stack, new ValueNode[0], new MonitorIdNode[0], false, false); + FrameState stateAfter = FrameState.create(graph.method(), BytecodeFrame.AFTER_BCI, new ValueNode[0], stack, new ValueNode[0], new MonitorIdNode[0], false, false); invoke.setStateAfter(graph.add(stateAfter)); graph.addBeforeFixed(ret, invoke); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -32,6 +32,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; @@ -39,9 +40,14 @@ import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.replacements.nodes.*; +@NodeInfo public class ObjectCloneNode extends MacroStateSplitNode implements VirtualizableAllocation, ArrayLengthProvider { - public ObjectCloneNode(Invoke invoke) { + public static ObjectCloneNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new ObjectCloneNodeGen(invoke) : new ObjectCloneNode(invoke); + } + + protected ObjectCloneNode(Invoke invoke) { super(invoke); } @@ -82,16 +88,16 @@ type = getConcreteType(getObject().stamp(), tool.assumptions(), tool.getMetaAccess()); if (type != null) { StructuredGraph newGraph = new StructuredGraph(); - ParameterNode param = newGraph.unique(new ParameterNode(0, getObject().stamp())); - NewInstanceNode newInstance = newGraph.add(new NewInstanceNode(type, true)); + ParameterNode param = newGraph.unique(ParameterNode.create(0, getObject().stamp())); + NewInstanceNode newInstance = newGraph.add(NewInstanceNode.create(type, true)); newGraph.addAfterFixed(newGraph.start(), newInstance); - ReturnNode returnNode = newGraph.add(new ReturnNode(newInstance)); + ReturnNode returnNode = newGraph.add(ReturnNode.create(newInstance)); newGraph.addAfterFixed(newInstance, returnNode); for (ResolvedJavaField field : type.getInstanceFields(true)) { - LoadFieldNode load = newGraph.add(new LoadFieldNode(param, field)); + LoadFieldNode load = newGraph.add(LoadFieldNode.create(param, field)); newGraph.addBeforeFixed(returnNode, load); - newGraph.addBeforeFixed(returnNode, newGraph.add(new StoreFieldNode(newInstance, field, load))); + newGraph.addBeforeFixed(returnNode, newGraph.add(StoreFieldNode.create(newInstance, field, load))); } return lowerReplacement(newGraph, tool); } @@ -107,7 +113,7 @@ /* * Looks at the given stamp and determines if it is an exact type (or can be assumed to be an * exact type) and if it is a cloneable type. - * + * * If yes, then the exact type is returned, otherwise it returns null. */ private static ResolvedJavaType getConcreteType(Stamp stamp, Assumptions assumptions, MetaAccessProvider metaAccess) { @@ -153,13 +159,13 @@ } ResolvedJavaType type = getConcreteType(obj.stamp(), tool.getAssumptions(), tool.getMetaAccessProvider()); if (type != null && !type.isArray()) { - VirtualInstanceNode newVirtual = new VirtualInstanceNode(type, true); + VirtualInstanceNode newVirtual = VirtualInstanceNode.create(type, true); ResolvedJavaField[] fields = newVirtual.getFields(); ValueNode[] state = new ValueNode[fields.length]; final LoadFieldNode[] loads = new LoadFieldNode[fields.length]; for (int i = 0; i < fields.length; i++) { - state[i] = loads[i] = new LoadFieldNode(obj, fields[i]); + state[i] = loads[i] = LoadFieldNode.create(obj, fields[i]); tool.addNode(loads[i]); } tool.createVirtualObject(newVirtual, state, Collections. emptyList()); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectGetClassNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectGetClassNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectGetClassNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -28,6 +28,7 @@ import com.oracle.graal.api.meta.ResolvedJavaType.Representation; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -37,9 +38,14 @@ * This macro node will replace itself with the correct Java {@link Class} as soon as the object's * type is known (exact). */ +@NodeInfo public class ObjectGetClassNode extends MacroNode implements Virtualizable, Canonicalizable { - public ObjectGetClassNode(Invoke invoke) { + public static ObjectGetClassNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new ObjectGetClassNodeGen(invoke) : new ObjectGetClassNode(invoke); + } + + protected ObjectGetClassNode(Invoke invoke) { super(invoke); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -29,13 +29,19 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.nodes.*; +@NodeInfo public class ReflectionGetCallerClassNode extends MacroStateSplitNode implements Canonicalizable, Lowerable { - public ReflectionGetCallerClassNode(Invoke invoke) { + public static ReflectionGetCallerClassNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new ReflectionGetCallerClassNodeGen(invoke) : new ReflectionGetCallerClassNode(invoke); + } + + protected ReflectionGetCallerClassNode(Invoke invoke) { super(invoke); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,12 +26,18 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.replacements.nodes.*; +@NodeInfo public class SystemIdentityHashCodeNode extends PureFunctionMacroNode { - public SystemIdentityHashCodeNode(Invoke invoke) { + public static SystemIdentityHashCodeNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new SystemIdentityHashCodeNodeGen(invoke) : new SystemIdentityHashCodeNode(invoke); + } + + protected SystemIdentityHashCodeNode(Invoke invoke) { super(invoke); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,25 +26,30 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.SnippetTemplate.Arguments; @NodeInfo(allowedUsageTypes = {InputType.Memory}) -public final class UnsafeArrayCopyNode extends ArrayRangeWriteNode implements Lowerable, MemoryCheckpoint.Single { +public class UnsafeArrayCopyNode extends ArrayRangeWriteNode implements Lowerable, MemoryCheckpoint.Single { - @Input private ValueNode src; - @Input private ValueNode srcPos; - @Input private ValueNode dest; - @Input private ValueNode destPos; - @Input private ValueNode length; - @OptionalInput private ValueNode layoutHelper; + @Input ValueNode src; + @Input ValueNode srcPos; + @Input ValueNode dest; + @Input ValueNode destPos; + @Input ValueNode length; + @OptionalInput ValueNode layoutHelper; private Kind elementKind; - private UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode layoutHelper, Kind elementKind) { + public static UnsafeArrayCopyNode create(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode layoutHelper, Kind elementKind) { + return USE_GENERATED_NODES ? new UnsafeArrayCopyNodeGen(src, srcPos, dest, destPos, length, layoutHelper, elementKind) : new UnsafeArrayCopyNode(src, srcPos, dest, destPos, length, + layoutHelper, elementKind); + } + + UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode layoutHelper, Kind elementKind) { super(StampFactory.forVoid()); assert layoutHelper == null || elementKind == null; this.src = src; @@ -56,11 +61,19 @@ this.elementKind = elementKind; } - private UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind) { + public static UnsafeArrayCopyNode create(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind) { + return USE_GENERATED_NODES ? new UnsafeArrayCopyNodeGen(src, srcPos, dest, destPos, length, elementKind) : new UnsafeArrayCopyNode(src, srcPos, dest, destPos, length, elementKind); + } + + UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind) { this(src, srcPos, dest, destPos, length, null, elementKind); } - private UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode layoutHelper) { + public static UnsafeArrayCopyNode create(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode layoutHelper) { + return USE_GENERATED_NODES ? new UnsafeArrayCopyNodeGen(src, srcPos, dest, destPos, length, layoutHelper) : new UnsafeArrayCopyNode(src, srcPos, dest, destPos, length, layoutHelper); + } + + UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode layoutHelper) { this(src, srcPos, dest, destPos, length, layoutHelper, null); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Mon Aug 25 21:15:59 2014 -0700 @@ -189,14 +189,14 @@ GraphKit kit = new GraphKit(graph, providers); ParameterNode[] params = createParameters(kit, args); - ReadRegisterNode thread = kit.append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), true, false)); + ReadRegisterNode thread = kit.append(ReadRegisterNode.create(providers.getRegisters().getThreadRegister(), true, false)); ValueNode result = createTargetCall(kit, params, thread); kit.createInvoke(StubUtil.class, "handlePendingException", thread, ConstantNode.forBoolean(isObjectResult, graph)); if (isObjectResult) { InvokeNode object = kit.createInvoke(HotSpotReplacementsUtil.class, "getAndClearObjectResult", thread); result = kit.createInvoke(StubUtil.class, "verifyObject", object); } - kit.append(new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result)); + kit.append(ReturnNode.create(linkage.getDescriptor().getResultType() == void.class ? null : result)); if (Debug.isDumpEnabled()) { Debug.dump(graph, "Initial stub graph"); @@ -224,7 +224,7 @@ } else { stamp = StampFactory.forKind(type.getKind()); } - ParameterNode param = kit.unique(new ParameterNode(i, stamp)); + ParameterNode param = kit.unique(ParameterNode.create(i, stamp)); params[i] = param; } return params; @@ -235,9 +235,9 @@ ValueNode[] targetArguments = new ValueNode[1 + params.length]; targetArguments[0] = thread; System.arraycopy(params, 0, targetArguments, 1, params.length); - return kit.append(new StubForeignCallNode(providers.getForeignCalls(), target.getDescriptor(), targetArguments)); + return kit.append(StubForeignCallNode.create(providers.getForeignCalls(), target.getDescriptor(), targetArguments)); } else { - return kit.append(new StubForeignCallNode(providers.getForeignCalls(), target.getDescriptor(), params)); + return kit.append(StubForeignCallNode.create(providers.getForeignCalls(), target.getDescriptor(), params)); } } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Mon Aug 25 21:15:59 2014 -0700 @@ -148,7 +148,7 @@ try (Scope d = Debug.sandbox("CompilingStub", DebugScope.getConfig(), providers.getCodeCache(), debugScopeContext())) { final StructuredGraph graph = getGraph(); if (!(graph.start() instanceof StubStartNode)) { - StubStartNode newStart = graph.add(new StubStartNode(Stub.this)); + StubStartNode newStart = graph.add(StubStartNode.create(Stub.this)); newStart.setStateAfter(graph.start().stateAfter()); graph.replaceFixed(graph.start(), newStart); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java Mon Aug 25 21:15:59 2014 -0700 @@ -64,7 +64,7 @@ Method found = null; for (Method method : stubClass.getDeclaredMethods()) { if (Modifier.isStatic(method.getModifiers()) && method.getAnnotation(NodeIntrinsic.class) != null && method.getName().equals(name)) { - if (method.getAnnotation(NodeIntrinsic.class).value() == StubForeignCallNode.class) { + if (method.getAnnotation(NodeIntrinsic.class).value().equals(StubForeignCallNode.class)) { assert found == null : "found more than one foreign call named " + name + " in " + stubClass; assert method.getParameterTypes().length != 0 && method.getParameterTypes()[0] == ForeignCallDescriptor.class : "first parameter of foreign call '" + name + "' in " + stubClass + " must be of type " + ForeignCallDescriptor.class.getSimpleName(); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java Mon Aug 25 21:15:59 2014 -0700 @@ -35,7 +35,8 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.Snippet.Fold; import com.oracle.graal.word.*; /** diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerBlock.java --- a/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerBlock.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerBlock.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,9 +25,9 @@ import java.io.*; import java.util.*; -import com.oracle.graal.graph.Node.Verbosity; import com.oracle.graal.java.decompiler.*; import com.oracle.graal.java.decompiler.lines.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.phases.schedule.*; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerAssignmentLine.java --- a/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerAssignmentLine.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerAssignmentLine.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,8 +23,8 @@ package com.oracle.graal.java.decompiler.lines; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Node.Verbosity; import com.oracle.graal.java.decompiler.block.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; public class DecompilerAssignmentLine extends DecompilerSyntaxLine { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerControlSplitLine.java --- a/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerControlSplitLine.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerControlSplitLine.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,8 +23,8 @@ package com.oracle.graal.java.decompiler.lines; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Node.Verbosity; import com.oracle.graal.java.decompiler.block.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.cfg.*; public class DecompilerControlSplitLine extends DecompilerSyntaxLine { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import static com.oracle.graal.api.code.TypeCheckHints.*; import static com.oracle.graal.bytecode.Bytecodes.*; + import java.util.*; import com.oracle.graal.api.code.*; @@ -895,6 +896,28 @@ return probability == 0 && optimisticOpts.removeNeverExecutedCode() && entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI; } + protected double branchProbability() { + double probability = profilingInfo.getBranchTakenProbability(bci()); + if (probability < 0) { + assert probability == -1 : "invalid probability"; + Debug.log("missing probability in %s at bci %d", method, bci()); + probability = 0.5; + } + + if (!removeNeverExecutedCode()) { + if (probability == 0) { + probability = 0.0000001; + } else if (probability == 1) { + probability = 0.999999; + } + } + return probability; + } + + protected boolean removeNeverExecutedCode() { + return optimisticOpts.removeNeverExecutedCode() && entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI; + } + protected abstract void processBlock(BciBlock block); protected abstract void iterateBytecodesForBlock(BciBlock block); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.java/src/com/oracle/graal/java/ComputeLoopFrequenciesClosure.java diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,21 +22,22 @@ */ package com.oracle.graal.java; +import com.oracle.graal.options.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; public class DefaultSuitesProvider implements SuitesProvider { - private final Suites defaultSuites; + private final DerivedOptionValue defaultSuites; private final PhaseSuite defaultGraphBuilderSuite; public DefaultSuitesProvider() { this.defaultGraphBuilderSuite = createGraphBuilderSuite(); - this.defaultSuites = createSuites(); + this.defaultSuites = new DerivedOptionValue<>(this::createSuites); } public Suites getDefaultSuites() { - return defaultSuites; + return defaultSuites.getValue(); } public Suites createSuites() { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Aug 25 21:15:59 2014 -0700 @@ -43,6 +43,7 @@ import com.oracle.graal.java.BciBlockMapping.BciBlock; import com.oracle.graal.java.BciBlockMapping.ExceptionDispatchBlock; import com.oracle.graal.java.BciBlockMapping.LocalLiveness; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.calc.*; @@ -99,6 +100,7 @@ * the jump. When the block is seen the second time, a {@link MergeNode} is created to * correctly merge the now two different predecessor states. */ + @NodeInfo protected static class BlockPlaceholderNode extends FixedWithNextNode { /* @@ -108,7 +110,11 @@ */ private final Object nextPlaceholder; - public BlockPlaceholderNode(BytecodeParser builder) { + public static BlockPlaceholderNode create(BytecodeParser builder) { + return USE_GENERATED_NODES ? new GraphBuilderPhase_Instance_BlockPlaceholderNodeGen(builder) : new BlockPlaceholderNode(builder); + } + + protected BlockPlaceholderNode(BytecodeParser builder) { super(StampFactory.forVoid()); nextPlaceholder = builder.placeholders; builder.placeholders = this; @@ -320,7 +326,7 @@ @Override protected void handleUnresolvedLoadConstant(JavaType type) { assert !graphBuilderConfig.eagerResolving(); - append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); + append(DeoptimizeNode.create(InvalidateRecompile, Unresolved)); } /** @@ -330,7 +336,7 @@ @Override protected void handleUnresolvedCheckCast(JavaType type, ValueNode object) { assert !graphBuilderConfig.eagerResolving(); - append(new FixedGuardNode(currentGraph.unique(new IsNullNode(object)), Unresolved, InvalidateRecompile)); + append(FixedGuardNode.create(currentGraph.unique(IsNullNode.create(object)), Unresolved, InvalidateRecompile)); frameState.apush(appendConstant(Constant.NULL_OBJECT)); } @@ -341,9 +347,9 @@ @Override protected void handleUnresolvedInstanceOf(JavaType type, ValueNode object) { assert !graphBuilderConfig.eagerResolving(); - BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode(this)); - DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved)); - append(new IfNode(currentGraph.unique(new IsNullNode(object)), successor, deopt, 1)); + BlockPlaceholderNode successor = currentGraph.add(BlockPlaceholderNode.create(this)); + DeoptimizeNode deopt = currentGraph.add(DeoptimizeNode.create(InvalidateRecompile, Unresolved)); + append(IfNode.create(currentGraph.unique(IsNullNode.create(object)), successor, deopt, 1)); lastInstr = successor; frameState.ipush(appendConstant(Constant.INT_0)); } @@ -354,7 +360,7 @@ @Override protected void handleUnresolvedNewInstance(JavaType type) { assert !graphBuilderConfig.eagerResolving(); - append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); + append(DeoptimizeNode.create(InvalidateRecompile, Unresolved)); } /** @@ -364,7 +370,7 @@ @Override protected void handleUnresolvedNewObjectArray(JavaType type, ValueNode length) { assert !graphBuilderConfig.eagerResolving(); - append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); + append(DeoptimizeNode.create(InvalidateRecompile, Unresolved)); } /** @@ -374,7 +380,7 @@ @Override protected void handleUnresolvedNewMultiArray(JavaType type, List dims) { assert !graphBuilderConfig.eagerResolving(); - append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); + append(DeoptimizeNode.create(InvalidateRecompile, Unresolved)); } /** @@ -385,7 +391,7 @@ @Override protected void handleUnresolvedLoadField(JavaField field, ValueNode receiver) { assert !graphBuilderConfig.eagerResolving(); - append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); + append(DeoptimizeNode.create(InvalidateRecompile, Unresolved)); } /** @@ -397,7 +403,7 @@ @Override protected void handleUnresolvedStoreField(JavaField field, ValueNode value, ValueNode receiver) { assert !graphBuilderConfig.eagerResolving(); - append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); + append(DeoptimizeNode.create(InvalidateRecompile, Unresolved)); } /** @@ -407,7 +413,7 @@ @Override protected void handleUnresolvedExceptionType(Representation representation, JavaType type) { assert !graphBuilderConfig.eagerResolving(); - append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); + append(DeoptimizeNode.create(InvalidateRecompile, Unresolved)); } /** @@ -416,7 +422,7 @@ */ protected void handleUnresolvedInvoke(JavaMethod javaMethod, InvokeKind invokeKind) { assert !graphBuilderConfig.eagerResolving(); - append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); + append(DeoptimizeNode.create(InvalidateRecompile, Unresolved)); } private DispatchBeginNode handleException(ValueNode exceptionObject, int bci) { @@ -438,12 +444,12 @@ DispatchBeginNode dispatchBegin; if (exceptionObject == null) { - dispatchBegin = currentGraph.add(new ExceptionObjectNode(metaAccess)); + dispatchBegin = currentGraph.add(ExceptionObjectNode.create(metaAccess)); dispatchState.apush(dispatchBegin); dispatchState.setRethrowException(true); dispatchBegin.setStateAfter(dispatchState.create(bci)); } else { - dispatchBegin = currentGraph.add(new DispatchBeginNode()); + dispatchBegin = currentGraph.add(DispatchBeginNode.create()); dispatchState.apush(exceptionObject); dispatchBegin.setStateAfter(dispatchState.create(bci)); dispatchState.setRethrowException(true); @@ -456,122 +462,122 @@ @Override protected ValueNode genLoadIndexed(ValueNode array, ValueNode index, Kind kind) { - return new LoadIndexedNode(array, index, kind); + return LoadIndexedNode.create(array, index, kind); } @Override protected ValueNode genStoreIndexed(ValueNode array, ValueNode index, Kind kind, ValueNode value) { - return new StoreIndexedNode(array, index, kind, value); + return StoreIndexedNode.create(array, index, kind, value); } @Override protected ValueNode genIntegerAdd(Kind kind, ValueNode x, ValueNode y) { - return new IntegerAddNode(x, y); + return IntegerAddNode.create(x, y); } @Override protected ValueNode genIntegerSub(Kind kind, ValueNode x, ValueNode y) { - return new IntegerSubNode(x, y); + return IntegerSubNode.create(x, y); } @Override protected ValueNode genIntegerMul(Kind kind, ValueNode x, ValueNode y) { - return new IntegerMulNode(x, y); + return IntegerMulNode.create(x, y); } @Override protected ValueNode genFloatAdd(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - return new FloatAddNode(x, y, isStrictFP); + return FloatAddNode.create(x, y, isStrictFP); } @Override protected ValueNode genFloatSub(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - return new FloatSubNode(x, y, isStrictFP); + return FloatSubNode.create(x, y, isStrictFP); } @Override protected ValueNode genFloatMul(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - return new FloatMulNode(x, y, isStrictFP); + return FloatMulNode.create(x, y, isStrictFP); } @Override protected ValueNode genFloatDiv(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - return new FloatDivNode(x, y, isStrictFP); + return FloatDivNode.create(x, y, isStrictFP); } @Override protected ValueNode genFloatRem(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - return new FloatRemNode(x, y, isStrictFP); + return FloatRemNode.create(x, y, isStrictFP); } @Override protected ValueNode genIntegerDiv(Kind kind, ValueNode x, ValueNode y) { - return new IntegerDivNode(x, y); + return IntegerDivNode.create(x, y); } @Override protected ValueNode genIntegerRem(Kind kind, ValueNode x, ValueNode y) { - return new IntegerRemNode(x, y); + return IntegerRemNode.create(x, y); } @Override protected ValueNode genNegateOp(ValueNode x) { - return (new NegateNode(x)); + return (NegateNode.create(x)); } @Override protected ValueNode genLeftShift(Kind kind, ValueNode x, ValueNode y) { - return new LeftShiftNode(x, y); + return LeftShiftNode.create(x, y); } @Override protected ValueNode genRightShift(Kind kind, ValueNode x, ValueNode y) { - return new RightShiftNode(x, y); + return RightShiftNode.create(x, y); } @Override protected ValueNode genUnsignedRightShift(Kind kind, ValueNode x, ValueNode y) { - return new UnsignedRightShiftNode(x, y); + return UnsignedRightShiftNode.create(x, y); } @Override protected ValueNode genAnd(Kind kind, ValueNode x, ValueNode y) { - return new AndNode(x, y); + return AndNode.create(x, y); } @Override protected ValueNode genOr(Kind kind, ValueNode x, ValueNode y) { - return new OrNode(x, y); + return OrNode.create(x, y); } @Override protected ValueNode genXor(Kind kind, ValueNode x, ValueNode y) { - return new XorNode(x, y); + return XorNode.create(x, y); } @Override protected ValueNode genNormalizeCompare(ValueNode x, ValueNode y, boolean isUnorderedLess) { - return new NormalizeCompareNode(x, y, isUnorderedLess); + return NormalizeCompareNode.create(x, y, isUnorderedLess); } @Override protected ValueNode genFloatConvert(FloatConvert op, ValueNode input) { - return new FloatConvertNode(op, input); + return FloatConvertNode.create(op, input); } @Override protected ValueNode genNarrow(ValueNode input, int bitCount) { - return new NarrowNode(input, bitCount); + return NarrowNode.create(input, bitCount); } @Override protected ValueNode genSignExtend(ValueNode input, int bitCount) { - return new SignExtendNode(input, bitCount); + return SignExtendNode.create(input, bitCount); } @Override protected ValueNode genZeroExtend(ValueNode input, int bitCount) { - return new ZeroExtendNode(input, bitCount); + return ZeroExtendNode.create(input, bitCount); } @Override @@ -582,17 +588,17 @@ @Override protected ValueNode genObjectEquals(ValueNode x, ValueNode y) { - return new ObjectEqualsNode(x, y); + return ObjectEqualsNode.create(x, y); } @Override protected ValueNode genIntegerEquals(ValueNode x, ValueNode y) { - return new IntegerEqualsNode(x, y); + return IntegerEqualsNode.create(x, y); } @Override protected ValueNode genIntegerLessThan(ValueNode x, ValueNode y) { - return new IntegerLessThanNode(x, y); + return IntegerLessThanNode.create(x, y); } @Override @@ -601,49 +607,49 @@ } protected ValueNode genIfNode(ValueNode condition, ValueNode falseSuccessor, ValueNode trueSuccessor, double d) { - return new IfNode((LogicNode) condition, (FixedNode) falseSuccessor, (FixedNode) trueSuccessor, d); + return IfNode.create((LogicNode) condition, (FixedNode) falseSuccessor, (FixedNode) trueSuccessor, d); } @Override protected void genThrow() { ValueNode exception = frameState.apop(); - append(new FixedGuardNode(currentGraph.unique(new IsNullNode(exception)), NullCheckException, InvalidateReprofile, true)); + append(FixedGuardNode.create(currentGraph.unique(IsNullNode.create(exception)), NullCheckException, InvalidateReprofile, true)); lastInstr.setNext(handleException(exception, bci())); } @Override protected ValueNode createCheckCast(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck, boolean forStoreCheck) { - return new CheckCastNode(type, object, profileForTypeCheck, forStoreCheck); + return CheckCastNode.create(type, object, profileForTypeCheck, forStoreCheck); } @Override protected ValueNode createInstanceOf(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck) { - return new InstanceOfNode(type, object, profileForTypeCheck); + return InstanceOfNode.create(type, object, profileForTypeCheck); } @Override protected ValueNode genConditional(ValueNode x) { - return new ConditionalNode((LogicNode) x); + return ConditionalNode.create((LogicNode) x); } @Override protected NewInstanceNode createNewInstance(ResolvedJavaType type, boolean fillContents) { - return new NewInstanceNode(type, fillContents); + return NewInstanceNode.create(type, fillContents); } @Override protected NewArrayNode createNewArray(ResolvedJavaType elementType, ValueNode length, boolean fillContents) { - return new NewArrayNode(elementType, length, fillContents); + return NewArrayNode.create(elementType, length, fillContents); } @Override protected NewMultiArrayNode createNewMultiArray(ResolvedJavaType type, List dimensions) { - return new NewMultiArrayNode(type, dimensions.toArray(new ValueNode[0])); + return NewMultiArrayNode.create(type, dimensions.toArray(new ValueNode[0])); } @Override protected ValueNode genLoadField(ValueNode receiver, ResolvedJavaField field) { - return new LoadFieldNode(receiver, field); + return LoadFieldNode.create(receiver, field); } @Override @@ -651,12 +657,12 @@ if (StampTool.isObjectNonNull(receiver.stamp())) { return; } - BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode(this)); - BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode(this)); - append(new IfNode(currentGraph.unique(new IsNullNode(receiver)), trueSucc, falseSucc, 0.01)); + BlockPlaceholderNode trueSucc = currentGraph.add(BlockPlaceholderNode.create(this)); + BlockPlaceholderNode falseSucc = currentGraph.add(BlockPlaceholderNode.create(this)); + append(IfNode.create(currentGraph.unique(IsNullNode.create(receiver)), trueSucc, falseSucc, 0.01)); lastInstr = falseSucc; - BytecodeExceptionNode exception = currentGraph.add(new BytecodeExceptionNode(metaAccess, NullPointerException.class)); + BytecodeExceptionNode exception = currentGraph.add(BytecodeExceptionNode.create(metaAccess, NullPointerException.class)); exception.setStateAfter(frameState.create(bci())); trueSucc.setNext(exception); exception.setNext(handleException(exception, bci())); @@ -664,12 +670,12 @@ @Override protected void emitBoundsCheck(ValueNode index, ValueNode length) { - BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode(this)); - BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode(this)); - append(new IfNode(currentGraph.unique(new IntegerBelowNode(index, length)), trueSucc, falseSucc, 0.99)); + BlockPlaceholderNode trueSucc = currentGraph.add(BlockPlaceholderNode.create(this)); + BlockPlaceholderNode falseSucc = currentGraph.add(BlockPlaceholderNode.create(this)); + append(IfNode.create(currentGraph.unique(IntegerBelowNode.create(index, length)), trueSucc, falseSucc, 0.99)); lastInstr = trueSucc; - BytecodeExceptionNode exception = currentGraph.add(new BytecodeExceptionNode(metaAccess, ArrayIndexOutOfBoundsException.class, index)); + BytecodeExceptionNode exception = currentGraph.add(BytecodeExceptionNode.create(metaAccess, ArrayIndexOutOfBoundsException.class, index)); exception.setStateAfter(frameState.create(bci())); falseSucc.setNext(exception); exception.setNext(handleException(exception, bci())); @@ -677,12 +683,12 @@ @Override protected ValueNode genArrayLength(ValueNode x) { - return new ArrayLengthNode(x); + return ArrayLengthNode.create(x); } @Override protected ValueNode genStoreField(ValueNode receiver, ResolvedJavaField field, ValueNode value) { - return new StoreFieldNode(receiver, field, value); + return StoreFieldNode.create(receiver, field, value); } /** @@ -783,7 +789,7 @@ private void appendInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args) { Kind resultType = targetMethod.getSignature().getReturnKind(); if (DeoptALot.getValue()) { - append(new DeoptimizeNode(DeoptimizationAction.None, RuntimeConstraint)); + append(DeoptimizeNode.create(DeoptimizationAction.None, RuntimeConstraint)); frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, currentGraph)); return; } @@ -796,7 +802,7 @@ emitExplicitExceptions(args[0], null); if (invokeKind != InvokeKind.Special && this.optimisticOpts.useTypeCheckHints()) { JavaTypeProfile profile = profilingInfo.getTypeProfile(bci()); - args[0] = TypeProfileProxyNode.create(args[0], profile); + args[0] = TypeProfileProxyNode.proxify(args[0], profile); } } MethodCallTargetNode callTarget = currentGraph.add(createMethodCallTarget(invokeKind, targetMethod, args, returnType)); @@ -818,18 +824,18 @@ } protected MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, JavaType returnType) { - return new MethodCallTargetNode(invokeKind, targetMethod, args, returnType); + return MethodCallTargetNode.create(invokeKind, targetMethod, args, returnType); } protected InvokeNode createInvoke(CallTargetNode callTarget, Kind resultType) { - InvokeNode invoke = append(new InvokeNode(callTarget, bci())); + InvokeNode invoke = append(InvokeNode.create(callTarget, bci())); frameState.pushReturn(resultType, invoke); return invoke; } protected InvokeWithExceptionNode createInvokeWithException(CallTargetNode callTarget, Kind resultType) { DispatchBeginNode exceptionEdge = handleException(null, bci()); - InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, bci())); + InvokeWithExceptionNode invoke = append(InvokeWithExceptionNode.create(callTarget, exceptionEdge, bci())); frameState.pushReturn(resultType, invoke); BciBlock nextBlock = currentBlock.getSuccessor(0); invoke.setStateAfter(frameState.create(nextBlock.startBci)); @@ -849,13 +855,13 @@ throw new BailoutException("unbalanced monitors"); } - append(new ReturnNode(x)); + append(ReturnNode.create(x)); } @Override protected MonitorEnterNode genMonitorEnter(ValueNode x) { - MonitorIdNode monitorId = currentGraph.add(new MonitorIdNode(frameState.lockDepth())); - MonitorEnterNode monitorEnter = append(new MonitorEnterNode(x, monitorId)); + MonitorIdNode monitorId = currentGraph.add(MonitorIdNode.create(frameState.lockDepth())); + MonitorEnterNode monitorEnter = append(MonitorEnterNode.create(x, monitorId)); frameState.pushLock(x, monitorId); return monitorEnter; } @@ -867,7 +873,7 @@ if (GraphUtil.originalValue(lockedObject) != GraphUtil.originalValue(x)) { throw new BailoutException("unbalanced monitors: mismatch at monitorexit, %s != %s", GraphUtil.originalValue(x), GraphUtil.originalValue(lockedObject)); } - MonitorExitNode monitorExit = append(new MonitorExitNode(x, monitorId, returnValue)); + MonitorExitNode monitorExit = append(MonitorExitNode.create(x, monitorId, returnValue)); return monitorExit; } @@ -892,7 +898,7 @@ ValueNode local = frameState.loadLocal(localIndex); JsrScope scope = currentBlock.jsrScope; int retAddress = scope.nextReturnAddress(); - append(new FixedGuardNode(currentGraph.unique(new IntegerEqualsNode(local, ConstantNode.forInt(retAddress, currentGraph))), JavaSubroutineMismatch, InvalidateReprofile)); + append(FixedGuardNode.create(currentGraph.unique(IntegerEqualsNode.create(local, ConstantNode.forInt(retAddress, currentGraph))), JavaSubroutineMismatch, InvalidateReprofile)); if (!successor.jsrScope.equals(scope.pop())) { throw new JsrNotSupportedBailout("unstructured control flow (ret leaves more than one scope)"); } @@ -902,7 +908,7 @@ @Override protected void genIntegerSwitch(ValueNode value, ArrayList actualSuccessors, int[] keys, double[] keyProbabilities, int[] keySuccessors) { double[] successorProbabilities = successorProbabilites(actualSuccessors.size(), keySuccessors, keyProbabilities); - IntegerSwitchNode switchNode = append(new IntegerSwitchNode(value, actualSuccessors.size(), keys, keyProbabilities, keySuccessors)); + IntegerSwitchNode switchNode = append(IntegerSwitchNode.create(value, actualSuccessors.size(), keys, keyProbabilities, keySuccessors)); for (int i = 0; i < actualSuccessors.size(); i++) { switchNode.setBlockSuccessor(i, createBlockTarget(successorProbabilities[i], actualSuccessors.get(i), frameState)); } @@ -997,7 +1003,7 @@ HIRFrameStateBuilder newState = state.copy(); for (BciBlock loop : exitLoops) { LoopBeginNode loopBegin = (LoopBeginNode) loop.firstInstruction; - LoopExitNode loopExit = currentGraph.add(new LoopExitNode(loopBegin)); + LoopExitNode loopExit = currentGraph.add(LoopExitNode.create(loopBegin)); if (lastLoopExit != null) { lastLoopExit.setNext(loopExit); } @@ -1020,7 +1026,7 @@ private FixedNode createTarget(double probability, BciBlock block, HIRFrameStateBuilder stateAfter) { assert probability >= 0 && probability <= 1.01 : probability; if (isNeverExecutedCode(probability)) { - return currentGraph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode)); + return currentGraph.add(DeoptimizeNode.create(InvalidateReprofile, UnreachedCode)); } else { assert block != null; return createTarget(block, stateAfter); @@ -1037,7 +1043,7 @@ * return a placeholder that later can be replaced with a MergeNode when we see * this block again. */ - block.firstInstruction = currentGraph.add(new BlockPlaceholderNode(this)); + block.firstInstruction = currentGraph.add(BlockPlaceholderNode.create(this)); Target target = checkLoopExit(block.firstInstruction, block, state); FixedNode result = target.fixed; block.entryState = target.state == state ? state.copy() : target.state; @@ -1059,7 +1065,7 @@ * the loop begin node created before. */ LoopBeginNode loopBegin = (LoopBeginNode) block.firstInstruction; - Target target = checkLoopExit(currentGraph.add(new LoopEndNode(loopBegin)), block, state); + Target target = checkLoopExit(currentGraph.add(LoopEndNode.create(loopBegin)), block, state); FixedNode result = target.fixed; ((HIRFrameStateBuilder) block.entryState).merge(loopBegin, target.state); @@ -1078,9 +1084,9 @@ BlockPlaceholderNode placeholder = (BlockPlaceholderNode) block.firstInstruction; // The EndNode for the already existing edge. - AbstractEndNode end = currentGraph.add(new EndNode()); + AbstractEndNode end = currentGraph.add(EndNode.create()); // The MergeNode that replaces the placeholder. - MergeNode mergeNode = currentGraph.add(new MergeNode()); + MergeNode mergeNode = currentGraph.add(MergeNode.create()); FixedNode next = placeholder.next(); placeholder.setNext(end); @@ -1093,7 +1099,7 @@ MergeNode mergeNode = (MergeNode) block.firstInstruction; // The EndNode for the newly merged edge. - AbstractEndNode newEnd = currentGraph.add(new EndNode()); + AbstractEndNode newEnd = currentGraph.add(EndNode.create()); Target target = checkLoopExit(newEnd, block, state); FixedNode result = target.fixed; ((HIRFrameStateBuilder) block.entryState).merge(mergeNode, target.state); @@ -1184,7 +1190,7 @@ assert frameState.stackSize() == 1 : frameState; ValueNode exception = frameState.apop(); synchronizedEpilogue(BytecodeFrame.AFTER_EXCEPTION_BCI, null); - append(new UnwindNode(exception)); + append(UnwindNode.create(exception)); } private void synchronizedEpilogue(int bci, ValueNode returnValue) { @@ -1217,9 +1223,9 @@ if (skippedType.isAssignableFrom(resolvedCatchType)) { BciBlock nextBlock = block.getSuccessorCount() == 1 ? unwindBlock() : block.getSuccessor(1); ValueNode exception = frameState.stackAt(0); - FixedNode trueSuccessor = currentGraph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode)); + FixedNode trueSuccessor = currentGraph.add(DeoptimizeNode.create(InvalidateReprofile, UnreachedCode)); FixedNode nextDispatch = createTarget(nextBlock, frameState); - append(new IfNode(currentGraph.unique(new InstanceOfNode((ResolvedJavaType) catchType, exception, null)), trueSuccessor, nextDispatch, 0)); + append(IfNode.create(currentGraph.unique(InstanceOfNode.create((ResolvedJavaType) catchType, exception, null)), trueSuccessor, nextDispatch, 0)); return; } } @@ -1228,7 +1234,7 @@ if (initialized) { BciBlock nextBlock = block.getSuccessorCount() == 1 ? unwindBlock() : block.getSuccessor(1); ValueNode exception = frameState.stackAt(0); - CheckCastNode checkCast = currentGraph.add(new CheckCastNode((ResolvedJavaType) catchType, exception, null, false)); + CheckCastNode checkCast = currentGraph.add(CheckCastNode.create((ResolvedJavaType) catchType, exception, null, false)); frameState.apop(); frameState.push(Kind.Object, checkCast); FixedNode catchSuccessor = createTarget(block.getSuccessor(0), frameState); @@ -1236,7 +1242,7 @@ frameState.push(Kind.Object, exception); FixedNode nextDispatch = createTarget(nextBlock, frameState); checkCast.setNext(catchSuccessor); - append(new IfNode(currentGraph.unique(new InstanceOfNode((ResolvedJavaType) catchType, exception, null)), checkCast, nextDispatch, 0.5)); + append(IfNode.create(currentGraph.unique(InstanceOfNode.create((ResolvedJavaType) catchType, exception, null)), checkCast, nextDispatch, 0.5)); } else { handleUnresolvedExceptionType(Representation.ObjectHub, catchType); } @@ -1258,8 +1264,8 @@ // Create the loop header block, which later will merge the backward branches of // the // loop. - AbstractEndNode preLoopEnd = currentGraph.add(new EndNode()); - LoopBeginNode loopBegin = currentGraph.add(new LoopBeginNode()); + AbstractEndNode preLoopEnd = currentGraph.add(EndNode.create()); + LoopBeginNode loopBegin = currentGraph.add(LoopBeginNode.create()); lastInstr.setNext(preLoopEnd); // Add the single non-loop predecessor of the loop header. loopBegin.addForwardEnd(preLoopEnd); @@ -1311,7 +1317,7 @@ if (block.jsrScope != JsrScope.EMPTY_SCOPE) { throw new BailoutException("OSR into a JSR scope is not supported"); } - EntryMarkerNode x = append(new EntryMarkerNode()); + EntryMarkerNode x = append(EntryMarkerNode.create()); frameState.insertProxies(x); x.setStateAfter(frameState.create(bci)); } @@ -1328,7 +1334,7 @@ frameState.clearNonLiveLocals(currentBlock, liveness, false); } if (lastInstr instanceof StateSplit) { - if (lastInstr.getClass() == BeginNode.class) { + if (lastInstr.getClass() == BeginNode.getGenClass()) { // BeginNodes do not need a frame state } else { StateSplit stateSplit = (StateSplit) lastInstr; @@ -1363,9 +1369,9 @@ private InfopointNode createInfoPointNode(InfopointReason reason) { if (graphBuilderConfig.insertFullDebugInfo()) { - return new FullInfopointNode(reason, frameState.create(bci())); + return FullInfopointNode.create(reason, frameState.create(bci())); } else { - return new SimpleInfopointNode(reason, new BytecodePosition(null, method, bci())); + return SimpleInfopointNode.create(reason, new BytecodePosition(null, method, bci())); } } @@ -1395,20 +1401,7 @@ return; } - double probability = profilingInfo.getBranchTakenProbability(bci()); - if (probability < 0) { - assert probability == -1 : "invalid probability"; - Debug.log("missing probability in %s at bci %d", method, bci()); - probability = 0.5; - } - - if (!optimisticOpts.removeNeverExecutedCode()) { - if (probability == 0) { - probability = 0.0000001; - } else if (probability == 1) { - probability = 0.999999; - } - } + double probability = branchProbability(); // the mirroring and negation operations get the condition into canonical form boolean mirror = cond.canonicalMirror(); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,13 +23,14 @@ package com.oracle.graal.java; import static com.oracle.graal.graph.iterators.NodePredicates.*; + import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; -import com.oracle.graal.graph.Node.Verbosity; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; @@ -55,7 +56,7 @@ int index = 0; if (!method.isStatic()) { // add the receiver - ParameterNode receiver = graph.unique(new ParameterNode(javaIndex, StampFactory.declaredNonNull(method.getDeclaringClass()))); + ParameterNode receiver = graph.unique(ParameterNode.create(javaIndex, StampFactory.declaredNonNull(method.getDeclaringClass()))); storeLocal(javaIndex, receiver); javaIndex = 1; index = 1; @@ -75,7 +76,7 @@ } else { stamp = StampFactory.forKind(kind); } - ParameterNode param = graph.unique(new ParameterNode(index, stamp)); + ParameterNode param = graph.unique(ParameterNode.create(index, stamp)); storeLocal(javaIndex, param); javaIndex += stackSlots(kind); index++; @@ -122,7 +123,7 @@ } public FrameState create(int bci) { - return graph.add(new FrameState(method, bci, locals, Arrays.asList(stack).subList(0, stackSize), lockedObjects, monitorIds, rethrowException, false)); + return graph.add(FrameState.create(method, bci, locals, Arrays.asList(stack).subList(0, stackSize), lockedObjects, monitorIds, rethrowException, false)); } @Override @@ -189,7 +190,7 @@ return null; } - ValuePhiNode phi = graph.addWithoutUnique(new ValuePhiNode(currentValue.stamp().unrestricted(), block)); + ValuePhiNode phi = graph.addWithoutUnique(ValuePhiNode.create(currentValue.stamp().unrestricted(), block)); for (int i = 0; i < block.phiPredecessorCount(); i++) { phi.addInput(currentValue); } @@ -287,7 +288,7 @@ } assert !block.isPhiAtMerge(value) : "phi function for this block already created"; - ValuePhiNode phi = graph.addWithoutUnique(new ValuePhiNode(value.stamp().unrestricted(), block)); + ValuePhiNode phi = graph.addWithoutUnique(ValuePhiNode.create(value.stamp().unrestricted(), block)); phi.addInput(value); return phi; } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -57,8 +57,8 @@ } @Override - protected StructuredGraph parse(Method m) { - StructuredGraph graph = super.parse(m); + protected StructuredGraph parseEager(Method m) { + StructuredGraph graph = super.parseEager(m); if (argsToBind != null) { Object receiver = isStatic(m.getModifiers()) ? null : this; Object[] args = argsWithReceiver(receiver, argsToBind); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Mon Aug 25 21:15:59 2014 -0700 @@ -926,16 +926,16 @@ break; case B2I: - masm.movsbl(asIntReg(dst), (AMD64Address) crb.asIntAddr(src)); + masm.movsbl(asIntReg(dst), (AMD64Address) crb.asByteAddr(src)); break; case S2I: - masm.movswl(asIntReg(dst), (AMD64Address) crb.asIntAddr(src)); + masm.movswl(asIntReg(dst), (AMD64Address) crb.asShortAddr(src)); break; case B2L: - masm.movsbq(asLongReg(dst), (AMD64Address) crb.asIntAddr(src)); + masm.movsbq(asLongReg(dst), (AMD64Address) crb.asByteAddr(src)); break; case S2L: - masm.movswq(asLongReg(dst), (AMD64Address) crb.asIntAddr(src)); + masm.movswq(asLongReg(dst), (AMD64Address) crb.asShortAddr(src)); break; case I2L: masm.movslq(asLongReg(dst), (AMD64Address) crb.asIntAddr(src)); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java --- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java Mon Aug 25 21:15:59 2014 -0700 @@ -167,7 +167,7 @@ public static class ShiftOp extends HSAILLIRInstruction { @Opcode private final HSAILArithmetic opcode; - @Def({REG, HINT}) protected Value result; + @Def({REG}) protected Value result; @Use({REG, CONST}) protected Value x; @Alive({REG, CONST}) protected Value y; diff -r ae0f235469db -r f8e60d11c0ec 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 25 21:15:59 2014 -0700 @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir.test; + +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.graal.lir.asm.*; + +/** + * This test verifies that {@link CompositeValue}s are immutable, i.e. that a write to a component + * of a {@link CompositeValue} results in a new {@link CompositeValue}. + */ +public class CompositeValueReplacementTest1 { + + private static class NestedCompositeValue extends CompositeValue { + + private static final long serialVersionUID = -8804214200173503527L; + @Component({REG, OperandFlag.ILLEGAL}) protected Value value; + + public NestedCompositeValue(Value value) { + super(LIRKind.Illegal); + this.value = value; + } + + } + + private static class DummyValue extends Value { + + private static final long serialVersionUID = -645435039553382737L; + private final int id; + private static int counter = 1; + + protected DummyValue() { + super(LIRKind.Illegal); + this.id = counter++; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + id; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + DummyValue other = (DummyValue) obj; + if (id != other.id) { + return false; + } + return true; + } + + @Override + public String toString() { + return "DummyValue [id=" + id + "]"; + } + + } + + private static class TestOp extends LIRInstruction { + + @Use({COMPOSITE}) protected NestedCompositeValue compValue; + + public TestOp(NestedCompositeValue compValue) { + this.compValue = compValue; + } + + @Override + public void emitCode(CompilationResultBuilder crb) { + fail("should not reach!"); + } + + } + + private static NestedCompositeValue createNestedCompValue(Value value, int nestingLevel) { + NestedCompositeValue compValue = new NestedCompositeValue(value); + for (int i = 0; i < nestingLevel; i++) { + compValue = new NestedCompositeValue(compValue); + } + return compValue; + } + + @Test + public void replaceCompValueTest0() { + DummyValue dummyValue1 = new DummyValue(); + DummyValue dummyValue2 = new DummyValue(); + DummyValue dummyValue3 = new DummyValue(); + NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 0); + LIRInstruction op1 = new TestOp(compValue1); + LIRInstruction op2 = new TestOp(compValue1); + + op1.forEachInput(new InstructionValueProcedure() { + @Override + public Value doValue(LIRInstruction instruction, Value value) { + assertEquals(dummyValue1, value); + return dummyValue2; + } + }); + + op2.forEachInput(new InstructionValueProcedure() { + @Override + public Value doValue(LIRInstruction instruction, Value value) { + assertEquals(dummyValue1, value); + return dummyValue3; + } + }); + + op1.visitEachInput(new InstructionValueConsumer() { + @Override + public void visitValue(LIRInstruction instruction, Value value) { + assertEquals(dummyValue2, value); + } + }); + + op2.visitEachInput(new InstructionValueConsumer() { + @Override + public void visitValue(LIRInstruction instruction, Value value) { + assertEquals(dummyValue3, value); + } + }); + } + + @Test + public void replaceCompValueTest1() { + DummyValue dummyValue1 = new DummyValue(); + DummyValue dummyValue2 = new DummyValue(); + DummyValue dummyValue3 = new DummyValue(); + NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 1); + LIRInstruction op1 = new TestOp(compValue1); + LIRInstruction op2 = new TestOp(compValue1); + + op1.forEachInput(new InstructionValueProcedure() { + @Override + public Value doValue(LIRInstruction instruction, Value value) { + assertEquals(dummyValue1, value); + return dummyValue2; + } + }); + + op2.forEachInput(new InstructionValueProcedure() { + @Override + public Value doValue(LIRInstruction instruction, Value value) { + assertEquals(dummyValue1, value); + return dummyValue3; + } + }); + + op1.visitEachInput(new InstructionValueConsumer() { + @Override + public void visitValue(LIRInstruction instruction, Value value) { + assertEquals(dummyValue2, value); + } + }); + + op2.visitEachInput(new InstructionValueConsumer() { + @Override + public void visitValue(LIRInstruction instruction, Value value) { + assertEquals(dummyValue3, value); + } + }); + } +} diff -r ae0f235469db -r f8e60d11c0ec 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 25 21:15:59 2014 -0700 @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir.test; + +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.graal.lir.asm.*; + +/** + * Same as {@link CompositeValueReplacementTest1} but with value arrays. + * + * @see CompositeValueReplacementTest1 + */ +public class CompositeValueReplacementTest2 { + + private static class NestedCompositeValue extends CompositeValue { + + private static final long serialVersionUID = -8804214200173503527L; + @Component({REG, OperandFlag.ILLEGAL}) protected Value[] values; + + public NestedCompositeValue(Value value) { + super(LIRKind.Illegal); + this.values = new Value[]{value}; + } + + } + + private static class DummyValue extends Value { + + private static final long serialVersionUID = -645435039553382737L; + private final int id; + private static int counter = 1; + + protected DummyValue() { + super(LIRKind.Illegal); + this.id = counter++; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + id; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + DummyValue other = (DummyValue) obj; + if (id != other.id) { + return false; + } + return true; + } + + @Override + public String toString() { + return "DummyValue [id=" + id + "]"; + } + + } + + private static class TestOp extends LIRInstruction { + + @Use({COMPOSITE}) protected NestedCompositeValue compValue; + + public TestOp(NestedCompositeValue compValue) { + this.compValue = compValue; + } + + @Override + public void emitCode(CompilationResultBuilder crb) { + fail("should not reach!"); + } + + } + + private static NestedCompositeValue createNestedCompValue(Value value, int nestingLevel) { + NestedCompositeValue compValue = new NestedCompositeValue(value); + for (int i = 0; i < nestingLevel; i++) { + compValue = new NestedCompositeValue(compValue); + } + return compValue; + } + + @Test + public void replaceCompValueTest0() { + DummyValue dummyValue1 = new DummyValue(); + DummyValue dummyValue2 = new DummyValue(); + DummyValue dummyValue3 = new DummyValue(); + NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 0); + LIRInstruction op1 = new TestOp(compValue1); + LIRInstruction op2 = new TestOp(compValue1); + + op1.forEachInput(new InstructionValueProcedure() { + @Override + public Value doValue(LIRInstruction instruction, Value value) { + assertEquals(dummyValue1, value); + return dummyValue2; + } + }); + + op2.forEachInput(new InstructionValueProcedure() { + @Override + public Value doValue(LIRInstruction instruction, Value value) { + assertEquals(dummyValue1, value); + return dummyValue3; + } + }); + + op1.visitEachInput(new InstructionValueConsumer() { + @Override + public void visitValue(LIRInstruction instruction, Value value) { + assertEquals(dummyValue2, value); + } + }); + + op2.visitEachInput(new InstructionValueConsumer() { + @Override + public void visitValue(LIRInstruction instruction, Value value) { + assertEquals(dummyValue3, value); + } + }); + } + + @Test + public void replaceCompValueTest1() { + DummyValue dummyValue1 = new DummyValue(); + DummyValue dummyValue2 = new DummyValue(); + DummyValue dummyValue3 = new DummyValue(); + NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 1); + LIRInstruction op1 = new TestOp(compValue1); + LIRInstruction op2 = new TestOp(compValue1); + + op1.forEachInput(new InstructionValueProcedure() { + @Override + public Value doValue(LIRInstruction instruction, Value value) { + assertEquals(dummyValue1, value); + return dummyValue2; + } + }); + + op2.forEachInput(new InstructionValueProcedure() { + @Override + public Value doValue(LIRInstruction instruction, Value value) { + assertEquals(dummyValue1, value); + return dummyValue3; + } + }); + + op1.visitEachInput(new InstructionValueConsumer() { + @Override + public void visitValue(LIRInstruction instruction, Value value) { + assertEquals(dummyValue2, value); + } + }); + + op2.visitEachInput(new InstructionValueConsumer() { + @Override + public void visitValue(LIRInstruction instruction, Value value) { + assertEquals(dummyValue3, value); + } + }); + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest3.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest3.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir.test; + +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.graal.lir.asm.*; + +/** + * Same as {@link CompositeValueReplacementTest1} but with for {@link ValuePosition}s. + * + * @see CompositeValueReplacementTest1 + */ +public class CompositeValueReplacementTest3 { + + private static class NestedCompositeValue extends CompositeValue { + + private static final long serialVersionUID = -8804214200173503527L; + @Component({REG, OperandFlag.ILLEGAL}) protected Value value; + + public NestedCompositeValue(Value value) { + super(LIRKind.Illegal); + this.value = value; + } + + } + + private static class DummyValue extends Value { + + private static final long serialVersionUID = -645435039553382737L; + private final int id; + private static int counter = 1; + + protected DummyValue() { + super(LIRKind.Illegal); + this.id = counter++; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + id; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + DummyValue other = (DummyValue) obj; + if (id != other.id) { + return false; + } + return true; + } + + @Override + public String toString() { + return "DummyValue [id=" + id + "]"; + } + + } + + private static class TestOp extends LIRInstruction { + + @Use({COMPOSITE}) protected NestedCompositeValue compValue; + + public TestOp(NestedCompositeValue compValue) { + this.compValue = compValue; + } + + @Override + public void emitCode(CompilationResultBuilder crb) { + fail("should not reach!"); + } + + } + + private static NestedCompositeValue createNestedCompValue(Value value, int nestingLevel) { + NestedCompositeValue compValue = new NestedCompositeValue(value); + for (int i = 0; i < nestingLevel; i++) { + compValue = new NestedCompositeValue(compValue); + } + return compValue; + } + + @Test + public void replaceCompValueTest0() { + DummyValue dummyValue1 = new DummyValue(); + DummyValue dummyValue2 = new DummyValue(); + DummyValue dummyValue3 = new DummyValue(); + NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 0); + LIRInstruction op1 = new TestOp(compValue1); + LIRInstruction op2 = new TestOp(compValue1); + + op1.forEachInput(new ValuePositionProcedure() { + + @Override + public void doValue(LIRInstruction instruction, ValuePosition position) { + Value value = position.get(instruction); + assertEquals(dummyValue1, value); + position.set(instruction, dummyValue2); + } + }); + + op2.forEachInput(new ValuePositionProcedure() { + @Override + public void doValue(LIRInstruction instruction, ValuePosition position) { + Value value = position.get(instruction); + assertEquals(dummyValue1, value); + position.set(instruction, dummyValue3); + } + }); + + op1.forEachInput(new ValuePositionProcedure() { + @Override + public void doValue(LIRInstruction instruction, ValuePosition position) { + Value value = position.get(instruction); + assertEquals(dummyValue2, value); + } + }); + + op2.forEachInput(new ValuePositionProcedure() { + @Override + public void doValue(LIRInstruction instruction, ValuePosition position) { + Value value = position.get(instruction); + assertEquals(dummyValue3, value); + } + }); + } + + @Test + public void replaceCompValueTest1() { + DummyValue dummyValue1 = new DummyValue(); + DummyValue dummyValue2 = new DummyValue(); + DummyValue dummyValue3 = new DummyValue(); + NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 1); + LIRInstruction op1 = new TestOp(compValue1); + LIRInstruction op2 = new TestOp(compValue1); + + op1.forEachInput(new ValuePositionProcedure() { + + @Override + public void doValue(LIRInstruction instruction, ValuePosition position) { + Value value = position.get(instruction); + assertEquals(dummyValue1, value); + position.set(instruction, dummyValue2); + } + }); + + op2.forEachInput(new ValuePositionProcedure() { + @Override + public void doValue(LIRInstruction instruction, ValuePosition position) { + Value value = position.get(instruction); + assertEquals(dummyValue1, value); + position.set(instruction, dummyValue3); + } + }); + + op1.forEachInput(new ValuePositionProcedure() { + @Override + public void doValue(LIRInstruction instruction, ValuePosition position) { + Value value = position.get(instruction); + assertEquals(dummyValue2, value); + } + }); + + op2.forEachInput(new ValuePositionProcedure() { + @Override + public void doValue(LIRInstruction instruction, ValuePosition position) { + Value value = position.get(instruction); + assertEquals(dummyValue3, value); + } + }); + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest4.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest4.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir.test; + +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.graal.lir.asm.*; + +/** + * Same as {@link CompositeValueReplacementTest2} but with value arrays {@link ValuePosition}s. + * + * @see CompositeValueReplacementTest2 + */ +public class CompositeValueReplacementTest4 { + + private static class NestedCompositeValue extends CompositeValue { + + private static final long serialVersionUID = -8804214200173503527L; + @Component({REG, OperandFlag.ILLEGAL}) protected Value[] values; + + public NestedCompositeValue(Value value) { + super(LIRKind.Illegal); + this.values = new Value[]{value}; + } + + } + + private static class DummyValue extends Value { + + private static final long serialVersionUID = -645435039553382737L; + private final int id; + private static int counter = 1; + + protected DummyValue() { + super(LIRKind.Illegal); + this.id = counter++; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + id; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + DummyValue other = (DummyValue) obj; + if (id != other.id) { + return false; + } + return true; + } + + @Override + public String toString() { + return "DummyValue [id=" + id + "]"; + } + + } + + private static class TestOp extends LIRInstruction { + + @Use({COMPOSITE}) protected NestedCompositeValue compValue; + + public TestOp(NestedCompositeValue compValue) { + this.compValue = compValue; + } + + @Override + public void emitCode(CompilationResultBuilder crb) { + fail("should not reach!"); + } + + } + + private static NestedCompositeValue createNestedCompValue(Value value, int nestingLevel) { + NestedCompositeValue compValue = new NestedCompositeValue(value); + for (int i = 0; i < nestingLevel; i++) { + compValue = new NestedCompositeValue(compValue); + } + return compValue; + } + + @Test + public void replaceCompValueTest0() { + DummyValue dummyValue1 = new DummyValue(); + DummyValue dummyValue2 = new DummyValue(); + DummyValue dummyValue3 = new DummyValue(); + NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 0); + LIRInstruction op1 = new TestOp(compValue1); + LIRInstruction op2 = new TestOp(compValue1); + + op1.forEachInput(new ValuePositionProcedure() { + + @Override + public void doValue(LIRInstruction instruction, ValuePosition position) { + Value value = position.get(instruction); + assertEquals(dummyValue1, value); + position.set(instruction, dummyValue2); + } + }); + + op2.forEachInput(new ValuePositionProcedure() { + @Override + public void doValue(LIRInstruction instruction, ValuePosition position) { + Value value = position.get(instruction); + assertEquals(dummyValue1, value); + position.set(instruction, dummyValue3); + } + }); + + op1.forEachInput(new ValuePositionProcedure() { + @Override + public void doValue(LIRInstruction instruction, ValuePosition position) { + Value value = position.get(instruction); + assertEquals(dummyValue2, value); + } + }); + + op2.forEachInput(new ValuePositionProcedure() { + @Override + public void doValue(LIRInstruction instruction, ValuePosition position) { + Value value = position.get(instruction); + assertEquals(dummyValue3, value); + } + }); + } + + @Test + public void replaceCompValueTest1() { + DummyValue dummyValue1 = new DummyValue(); + DummyValue dummyValue2 = new DummyValue(); + DummyValue dummyValue3 = new DummyValue(); + NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 1); + LIRInstruction op1 = new TestOp(compValue1); + LIRInstruction op2 = new TestOp(compValue1); + + op1.forEachInput(new ValuePositionProcedure() { + + @Override + public void doValue(LIRInstruction instruction, ValuePosition position) { + Value value = position.get(instruction); + assertEquals(dummyValue1, value); + position.set(instruction, dummyValue2); + } + }); + + op2.forEachInput(new ValuePositionProcedure() { + @Override + public void doValue(LIRInstruction instruction, ValuePosition position) { + Value value = position.get(instruction); + assertEquals(dummyValue1, value); + position.set(instruction, dummyValue3); + } + }); + + op1.forEachInput(new ValuePositionProcedure() { + @Override + public void doValue(LIRInstruction instruction, ValuePosition position) { + Value value = position.get(instruction); + assertEquals(dummyValue2, value); + } + }); + + op2.forEachInput(new ValuePositionProcedure() { + @Override + public void doValue(LIRInstruction instruction, ValuePosition position) { + Value value = position.get(instruction); + assertEquals(dummyValue3, value); + } + }); + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest1.java --- a/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest1.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest1.java Mon Aug 25 21:15:59 2014 -0700 @@ -32,7 +32,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.LIRInstruction.OperandFlag; -import com.oracle.graal.lir.LIRInstruction.ValuePositionProcedure; import com.oracle.graal.lir.asm.*; public class ValuePositionTest1 { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest2.java --- a/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest2.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest2.java Mon Aug 25 21:15:59 2014 -0700 @@ -32,7 +32,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.LIRInstruction.OperandFlag; -import com.oracle.graal.lir.LIRInstruction.ValuePositionProcedure; import com.oracle.graal.lir.asm.*; public class ValuePositionTest2 { diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,16 +25,15 @@ import java.lang.annotation.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; -import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure; import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; -import com.oracle.graal.lir.LIRInstruction.ValuePositionProcedure; /** * Base class to represent values that need to be stored in more than one register. */ -public abstract class CompositeValue extends Value { +public abstract class CompositeValue extends Value implements Cloneable { private static final long serialVersionUID = -169180052684126180L; @@ -55,11 +54,11 @@ valueClass = CompositeValueClass.get(getClass()); } - public final void forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueProcedure proc) { - valueClass.forEachComponent(inst, this, mode, proc); + final CompositeValue forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueProcedureBase proc) { + return valueClass.forEachComponent(inst, this, mode, proc); } - public final void forEachComponent(LIRInstruction inst, OperandMode mode, ValuePositionProcedure proc, ValuePosition outerPosition) { + final void forEachComponent(LIRInstruction inst, OperandMode mode, ValuePositionProcedure proc, ValuePosition outerPosition) { valueClass.forEachComponent(inst, this, mode, proc, outerPosition); } @@ -86,4 +85,19 @@ return valueClass; } + @Override + public final CompositeValue clone() { + CompositeValue compositeValue = null; + try { + compositeValue = (CompositeValue) super.clone(); + } catch (CloneNotSupportedException e) { + throw new GraalInternalError(e); + } + + // copy value arrays + getValueClass().copyValueArrays(compositeValue); + + return compositeValue; + } + } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java Mon Aug 25 21:15:59 2014 -0700 @@ -28,10 +28,8 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.lir.CompositeValue.Component; -import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure; import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; -import com.oracle.graal.lir.LIRInstruction.ValuePositionProcedure; /** * Lazily associated metadata for every {@link CompositeValue} type. The metadata includes: @@ -141,11 +139,11 @@ return str.toString(); } - public final void forEachComponent(LIRInstruction inst, CompositeValue obj, OperandMode mode, InstructionValueProcedure proc) { - forEach(inst, obj, directComponentCount, componentOffsets, mode, componentFlags, proc); + final CompositeValue forEachComponent(LIRInstruction inst, CompositeValue obj, OperandMode mode, InstructionValueProcedureBase proc) { + return forEachComponent(inst, obj, directComponentCount, componentOffsets, mode, componentFlags, proc); } - public final void forEachComponent(LIRInstruction inst, CompositeValue obj, OperandMode mode, ValuePositionProcedure proc, ValuePosition outerPosition) { + final void forEachComponent(LIRInstruction inst, CompositeValue obj, OperandMode mode, ValuePositionProcedure proc, ValuePosition outerPosition) { forEach(inst, obj, directComponentCount, componentOffsets, mode, componentFlags, proc, outerPosition); } @@ -165,11 +163,21 @@ return getValueForPosition(obj, componentOffsets, directComponentCount, pos); } - void setValue(CompositeValue obj, ValuePosition pos, Value value) { - setValueForPosition(obj, componentOffsets, directComponentCount, pos, value); + CompositeValue createUpdatedValue(CompositeValue compValue, ValuePosition pos, Value value) { + CompositeValue newCompValue = compValue.clone(); + setValueForPosition(newCompValue, componentOffsets, directComponentCount, pos, value); + return newCompValue; } EnumSet 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 ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InstructionStateProcedure.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InstructionStateProcedure.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir; + +public abstract class InstructionStateProcedure { + + protected abstract void doState(LIRInstruction instruction, LIRFrameState state); +} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InstructionValueConsumer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InstructionValueConsumer.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.lir.LIRInstruction.*; + +/** + * Non-modifying version of {@link InstructionValueProcedure}. + */ +public abstract class InstructionValueConsumer extends InstructionValueProcedureBase { + + /** + * Iterator method to be overwritten. This version of the iterator does not take additional + * parameters to keep the signature short. + * + * @param instruction The current instruction. + * @param value The value that is iterated. + */ + protected void visitValue(LIRInstruction instruction, Value value) { + throw GraalInternalError.shouldNotReachHere("One of the visitValue() methods must be overwritten"); + } + + /** + * Iterator method to be overwritten. This version of the iterator gets additional parameters + * about the processed value. + * + * @param instruction The current instruction. + * @param value The value that is iterated. + * @param mode The operand mode for the value. + * @param flags A set of flags for the value. + */ + protected void visitValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet flags) { + visitValue(instruction, value); + } + + @Override + public final Value processValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet flags) { + assert !(value instanceof CompositeValue) : String.format("Must not visit CompositeValues! Instruction: %s Value: %s", instruction, value); + visitValue(instruction, value, mode, flags); + return value; + } +} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InstructionValueProcedure.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InstructionValueProcedure.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.lir.LIRInstruction.*; + +/** + * Iterator for iterating over a list of values. Subclasses must overwrite one of the doValue + * methods. Clients should not use this class directly but call + * {@link InstructionValueProcedureBase#processValue} instead. + */ +public abstract class InstructionValueProcedure extends InstructionValueProcedureBase { + + /** + * Iterator method to be overwritten. This version of the iterator does not take additional + * parameters to keep the signature short. + * + * @param instruction The current instruction. + * @param value The value that is iterated. + * @return The new value to replace the value that was passed in. + */ + protected Value doValue(LIRInstruction instruction, Value value) { + throw GraalInternalError.shouldNotReachHere("One of the doValue() methods must be overwritten"); + } + + /** + * Iterator method to be overwritten. This version of the iterator gets additional parameters + * about the processed value. + * + * @param instruction The current instruction. + * @param value The value that is iterated. + * @param mode The operand mode for the value. + * @param flags A set of flags for the value. + * @return The new value to replace the value that was passed in. + */ + protected Value doValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet flags) { + return doValue(instruction, value); + } + + @Override + public final Value processValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet flags) { + assert !(value instanceof CompositeValue) : String.format("Must not visit CompositeValues! Instruction: %s Value: %s", instruction, value); + return doValue(instruction, value, mode, flags); + } +} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InstructionValueProcedureBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InstructionValueProcedureBase.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.LIRInstruction.*; + +/** + * Common base class for modifying and non-modifying {@link Value value} iterators. + * + * This type should not be sub-classed directly. Use {@link InstructionValueProcedureBase} or + * {@link InstructionValueConsumer} instead. + * + * @see InstructionValueProcedure + * @see InstructionValueConsumer + */ +public abstract class InstructionValueProcedureBase { + + /** + * Iterator method to be overwritten. This version of the iterator gets additional parameters + * about the processed value. + * + * @param instruction The current instruction. + * @param value The value that is iterated. + * @param mode The operand mode for the value. + * @param flags A set of flags for the value. + * @return The new value to replace the value that was passed in. + */ + abstract public Value processValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet flags); +} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,7 +26,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.cfg.*; -import com.oracle.graal.lir.LIRInstruction.StateProcedure; import com.oracle.graal.lir.StandardOp.BlockEndOp; /** diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java Mon Aug 25 21:15:59 2014 -0700 @@ -28,7 +28,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure; import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; @@ -63,7 +62,7 @@ * * @param proc The procedure called for variables. */ - public void forEachState(LIRInstruction inst, InstructionValueProcedure proc) { + public void forEachState(LIRInstruction inst, InstructionValueProcedureBase proc) { for (BytecodeFrame cur = topFrame; cur != null; cur = cur.caller()) { processValues(inst, cur.values, proc); } @@ -80,16 +79,16 @@ */ protected static final EnumSet STATE_FLAGS = EnumSet.of(OperandFlag.REG, OperandFlag.STACK); - protected void processValues(LIRInstruction inst, Value[] values, InstructionValueProcedure proc) { + protected void processValues(LIRInstruction inst, Value[] values, InstructionValueProcedureBase proc) { for (int i = 0; i < values.length; i++) { Value value = values[i]; values[i] = processValue(inst, proc, value); } } - protected Value processValue(LIRInstruction inst, InstructionValueProcedure proc, Value value) { + protected Value processValue(LIRInstruction inst, InstructionValueProcedureBase proc, Value value) { if (processed(value)) { - return proc.doValue(inst, value, OperandMode.ALIVE, STATE_FLAGS); + return proc.processValue(inst, value, OperandMode.ALIVE, STATE_FLAGS); } return value; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java Mon Aug 25 21:15:59 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.lir.asm.*; @@ -42,111 +41,6 @@ public static final Value[] NO_OPERANDS = {}; /** - * Iterator for iterating over a list of {@linkplain ValuePosition value positions}. - */ - public abstract static class ValuePositionProcedure { - - /** - * Iterator method to be overwritten. This version of the iterator does not take additional - * parameters to keep the signature short. - * - * @param instruction The current instruction. - * @param position The position of the value that is iterated. - */ - - public abstract void doValue(LIRInstruction instruction, ValuePosition position); - } - - /** - * Iterator for iterating over a list of values. Subclasses must overwrite one of the doValue - * methods. Clients of the class must only call the doValue method that takes additional - * parameters. - */ - public abstract static class InstructionValueProcedure { - - /** - * Iterator method to be overwritten. This version of the iterator does not take additional - * parameters to keep the signature short. - * - * @param instruction The current instruction. - * @param value The value that is iterated. - * @return The new value to replace the value that was passed in. - */ - protected Value doValue(LIRInstruction instruction, Value value) { - throw GraalInternalError.shouldNotReachHere("One of the doValue() methods must be overwritten"); - } - - /** - * Iterator method to be overwritten. This version of the iterator gets additional - * parameters about the processed value. - * - * @param instruction The current instruction. - * @param value The value that is iterated. - * @param mode The operand mode for the value. - * @param flags A set of flags for the value. - * @return The new value to replace the value that was passed in. - */ - public Value doValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet flags) { - return doValue(instruction, value); - } - } - - /** - * Similar to {@link InstructionValueProcedure} but without an {@link LIRInstruction} parameter. - */ - public abstract static class ValueProcedure extends InstructionValueProcedure { - - /** - * Iterator method to be overwritten. This version of the iterator does not take additional - * parameters to keep the signature short. - * - * @param value The value that is iterated. - * @return The new value to replace the value that was passed in. - */ - protected Value doValue(Value value) { - throw GraalInternalError.shouldNotReachHere("One of the doValue() methods must be overwritten"); - } - - /** - * Iterator method to be overwritten. This version of the iterator gets additional - * parameters about the processed value. - * - * @param value The value that is iterated. - * @param mode The operand mode for the value. - * @param flags A set of flags for the value. - * @return The new value to replace the value that was passed in. - */ - protected Value doValue(Value value, OperandMode mode, EnumSet flags) { - return doValue(value); - } - - @Override - protected final Value doValue(LIRInstruction instruction, Value value) { - throw GraalInternalError.shouldNotReachHere("This doValue() methods should never be called"); - } - - @Override - public final Value doValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet flags) { - return doValue(value, mode, flags); - } - } - - public abstract static class InstructionStateProcedure { - - protected abstract void doState(LIRInstruction instruction, LIRFrameState state); - } - - public abstract static class StateProcedure extends InstructionStateProcedure { - - protected abstract void doState(LIRFrameState state); - - @Override - protected final void doState(LIRInstruction instruction, LIRFrameState state) { - doState(state); - } - } - - /** * Constants denoting how a LIR instruction uses an operand. */ public enum OperandMode { @@ -323,6 +217,7 @@ return false; } + // ValuePositionProcedures public final void forEachInput(ValuePositionProcedure proc) { instructionClass.forEachUse(this, proc); } @@ -339,6 +234,7 @@ instructionClass.forEachDef(this, proc); } + // InstructionValueProcedures public final void forEachInput(InstructionValueProcedure proc) { instructionClass.forEachUse(this, proc); } @@ -355,6 +251,7 @@ instructionClass.forEachDef(this, proc); } + // States public final void forEachState(InstructionValueProcedure proc) { instructionClass.forEachState(this, proc); } @@ -363,6 +260,27 @@ instructionClass.forEachState(this, proc); } + // Consumers + public final void visitEachInput(InstructionValueConsumer proc) { + instructionClass.forEachUse(this, proc); + } + + public final void visitEachAlive(InstructionValueConsumer proc) { + instructionClass.forEachAlive(this, proc); + } + + public final void visitEachTemp(InstructionValueConsumer proc) { + instructionClass.forEachTemp(this, proc); + } + + public final void visitEachOutput(InstructionValueConsumer proc) { + instructionClass.forEachDef(this, proc); + } + + public final void visitEachState(InstructionValueConsumer proc) { + instructionClass.forEachState(this, proc); + } + /** * Iterates all register hints for the specified value, i.e., all preferred candidates for the * register to be assigned to the value. diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java Mon Aug 25 21:15:59 2014 -0700 @@ -28,15 +28,12 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.lir.LIRInstruction.InstructionStateProcedure; -import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure; import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; -import com.oracle.graal.lir.LIRInstruction.ValuePositionProcedure; public class LIRInstructionClass extends LIRIntrospection { - public static final LIRInstructionClass get(Class c) { + static final LIRInstructionClass get(Class c) { LIRInstructionClass clazz = (LIRInstructionClass) allClasses.get(c); if (clazz != null) { return clazz; @@ -74,12 +71,12 @@ private String opcodeConstant; private long opcodeOffset; - public LIRInstructionClass(Class clazz) { + private LIRInstructionClass(Class clazz) { this(clazz, new DefaultCalcOffset()); } @SuppressWarnings("unchecked") - public LIRInstructionClass(Class clazz, CalcOffset calcOffset) { + private LIRInstructionClass(Class clazz, CalcOffset calcOffset) { super(clazz); assert INSTRUCTION_CLASS.isAssignableFrom(clazz); @@ -309,7 +306,7 @@ } } - public final String getOpcode(LIRInstruction obj) { + final String getOpcode(LIRInstruction obj) { if (opcodeConstant != null) { return opcodeConstant; } @@ -317,11 +314,11 @@ return unsafe.getObject(obj, opcodeOffset).toString(); } - public final boolean hasOperands() { + final boolean hasOperands() { return useOffsets.length > 0 || aliveOffsets.length > 0 || tempOffsets.length > 0 || defOffsets.length > 0; } - public final boolean hasState(LIRInstruction obj) { + final boolean hasState(LIRInstruction obj) { for (int i = 0; i < stateOffsets.length; i++) { if (getState(obj, stateOffsets[i]) != null) { return true; @@ -330,39 +327,39 @@ return false; } - public final void forEachUse(LIRInstruction obj, ValuePositionProcedure proc) { + final void forEachUse(LIRInstruction obj, ValuePositionProcedure proc) { forEach(obj, obj, directUseCount, useOffsets, OperandMode.USE, useFlags, proc, ValuePosition.ROOT_VALUE_POSITION); } - public final void forEachAlive(LIRInstruction obj, ValuePositionProcedure proc) { + final void forEachAlive(LIRInstruction obj, ValuePositionProcedure proc) { forEach(obj, obj, directAliveCount, aliveOffsets, OperandMode.ALIVE, aliveFlags, proc, ValuePosition.ROOT_VALUE_POSITION); } - public final void forEachTemp(LIRInstruction obj, ValuePositionProcedure proc) { + final void forEachTemp(LIRInstruction obj, ValuePositionProcedure proc) { forEach(obj, obj, directTempCount, tempOffsets, OperandMode.TEMP, tempFlags, proc, ValuePosition.ROOT_VALUE_POSITION); } - public final void forEachDef(LIRInstruction obj, ValuePositionProcedure proc) { + final void forEachDef(LIRInstruction obj, ValuePositionProcedure proc) { forEach(obj, obj, directDefCount, defOffsets, OperandMode.DEF, defFlags, proc, ValuePosition.ROOT_VALUE_POSITION); } - public final void forEachUse(LIRInstruction obj, InstructionValueProcedure proc) { - forEach(obj, obj, directUseCount, useOffsets, OperandMode.USE, useFlags, proc); + final void forEachUse(LIRInstruction obj, InstructionValueProcedureBase proc) { + forEach(obj, directUseCount, useOffsets, OperandMode.USE, useFlags, proc); } - public final void forEachAlive(LIRInstruction obj, InstructionValueProcedure proc) { - forEach(obj, obj, directAliveCount, aliveOffsets, OperandMode.ALIVE, aliveFlags, proc); + final void forEachAlive(LIRInstruction obj, InstructionValueProcedureBase proc) { + forEach(obj, directAliveCount, aliveOffsets, OperandMode.ALIVE, aliveFlags, proc); } - public final void forEachTemp(LIRInstruction obj, InstructionValueProcedure proc) { - forEach(obj, obj, directTempCount, tempOffsets, OperandMode.TEMP, tempFlags, proc); + final void forEachTemp(LIRInstruction obj, InstructionValueProcedureBase proc) { + forEach(obj, directTempCount, tempOffsets, OperandMode.TEMP, tempFlags, proc); } - public final void forEachDef(LIRInstruction obj, InstructionValueProcedure proc) { - forEach(obj, obj, directDefCount, defOffsets, OperandMode.DEF, defFlags, proc); + final void forEachDef(LIRInstruction obj, InstructionValueProcedureBase proc) { + forEach(obj, directDefCount, defOffsets, OperandMode.DEF, defFlags, proc); } - public final void forEachState(LIRInstruction obj, InstructionValueProcedure proc) { + final void forEachState(LIRInstruction obj, InstructionValueProcedureBase proc) { for (int i = 0; i < stateOffsets.length; i++) { LIRFrameState state = getState(obj, stateOffsets[i]); if (state != null) { @@ -371,7 +368,7 @@ } } - public final void forEachState(LIRInstruction obj, InstructionStateProcedure proc) { + final void forEachState(LIRInstruction obj, InstructionStateProcedure proc) { for (int i = 0; i < stateOffsets.length; i++) { LIRFrameState state = getState(obj, stateOffsets[i]); if (state != null) { @@ -380,7 +377,7 @@ } } - public final Value forEachRegisterHint(LIRInstruction obj, OperandMode mode, InstructionValueProcedure proc) { + final Value forEachRegisterHint(LIRInstruction obj, OperandMode mode, InstructionValueProcedure proc) { int hintDirectCount = 0; long[] hintOffsets = null; if (mode == OperandMode.USE) { @@ -396,7 +393,7 @@ for (int i = 0; i < hintOffsets.length; i++) { if (i < hintDirectCount) { Value hintValue = getValue(obj, hintOffsets[i]); - Value result = proc.doValue(obj, hintValue, null, null); + Value result = proc.processValue(obj, hintValue, null, null); if (result != null) { return result; } @@ -404,7 +401,7 @@ Value[] hintValues = getValueArray(obj, hintOffsets[i]); for (int j = 0; j < hintValues.length; j++) { Value hintValue = hintValues[j]; - Value result = proc.doValue(obj, hintValue, null, null); + Value result = proc.processValue(obj, hintValue, null, null); if (result != null) { return result; } @@ -418,7 +415,7 @@ return (LIRFrameState) unsafe.getObject(obj, offset); } - public String toString(LIRInstruction obj) { + String toString(LIRInstruction obj) { StringBuilder result = new StringBuilder(); appendValues(result, obj, "", " = ", "(", ")", new String[]{""}, defOffsets); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java Mon Aug 25 21:15:59 2014 -0700 @@ -32,10 +32,8 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure; import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; -import com.oracle.graal.lir.LIRInstruction.ValuePositionProcedure; abstract class LIRIntrospection extends FieldIntrospection { @@ -120,31 +118,89 @@ } } - protected static void forEach(LIRInstruction inst, Object obj, int directCount, long[] offsets, OperandMode mode, EnumSet[] flags, InstructionValueProcedure proc) { + protected static void forEach(LIRInstruction inst, int directCount, long[] offsets, OperandMode mode, EnumSet[] flags, InstructionValueProcedureBase proc) { + for (int i = 0; i < offsets.length; i++) { + assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(flags[i]); + + if (i < directCount) { + Value value = getValue(inst, offsets[i]); + Value newValue; + if (value instanceof CompositeValue) { + CompositeValue composite = (CompositeValue) value; + newValue = composite.forEachComponent(inst, mode, proc); + } else { + newValue = proc.processValue(inst, value, mode, flags[i]); + } + if (!value.identityEquals(newValue)) { + setValue(inst, offsets[i], newValue); + } + } else { + Value[] values = getValueArray(inst, offsets[i]); + for (int j = 0; j < values.length; j++) { + Value value = values[j]; + Value newValue; + if (value instanceof CompositeValue) { + CompositeValue composite = (CompositeValue) value; + newValue = composite.forEachComponent(inst, mode, proc); + } else { + newValue = proc.processValue(inst, value, mode, flags[i]); + } + if (!value.identityEquals(newValue)) { + values[j] = newValue; + } + } + } + } + } + + protected static CompositeValue forEachComponent(LIRInstruction inst, CompositeValue obj, int directCount, long[] offsets, OperandMode mode, EnumSet[] flags, + InstructionValueProcedureBase proc) { + CompositeValue newCompValue = null; for (int i = 0; i < offsets.length; i++) { assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(flags[i]); if (i < directCount) { Value value = getValue(obj, offsets[i]); + Value newValue; if (value instanceof CompositeValue) { CompositeValue composite = (CompositeValue) value; - composite.forEachComponent(inst, mode, proc); + newValue = composite.forEachComponent(inst, mode, proc); } else { - setValue(obj, offsets[i], proc.doValue(inst, value, mode, flags[i])); + newValue = proc.processValue(inst, value, mode, flags[i]); + } + if (!value.identityEquals(newValue)) { + // lazy initialize + if (newCompValue == null) { + newCompValue = obj.clone(); + } + setValue(newCompValue, offsets[i], newValue); } } else { Value[] values = getValueArray(obj, offsets[i]); + Value[] newValues = null; for (int j = 0; j < values.length; j++) { Value value = values[j]; + Value newValue; if (value instanceof CompositeValue) { CompositeValue composite = (CompositeValue) value; - composite.forEachComponent(inst, mode, proc); + newValue = composite.forEachComponent(inst, mode, proc); } else { - values[j] = proc.doValue(inst, value, mode, flags[i]); + newValue = proc.processValue(inst, value, mode, flags[i]); + } + if (!value.identityEquals(newValue)) { + // lazy initialize + if (newValues == null) { + if (newCompValue == null) { + newCompValue = obj.clone(); + } + newValues = getValueArray(newCompValue, offsets[i]); + } + newValues[j] = newValue; } } } } + return newCompValue != null ? newCompValue : obj; } protected static void forEach(LIRInstruction inst, Object obj, int directCount, long[] offsets, OperandMode mode, EnumSet[] flags, ValuePositionProcedure proc, @@ -202,6 +258,10 @@ return (Value[]) unsafe.getObject(obj, offset); } + protected static void setValueArray(Object obj, long offset, Value[] valueArray) { + unsafe.putObject(obj, offset, valueArray); + } + protected void appendValues(StringBuilder result, Object obj, String start, String end, String startMultiple, String endMultiple, String[] prefix, long[]... moffsets) { int total = 0; for (long[] offsets : moffsets) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java Mon Aug 25 21:15:59 2014 -0700 @@ -32,10 +32,8 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; -import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure; import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; -import com.oracle.graal.lir.LIRInstruction.ValueProcedure; public final class LIRVerifier { @@ -63,21 +61,21 @@ return isRegister(value) && frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable(); } - private static InstructionValueProcedure allowedProc = new InstructionValueProcedure() { + private static InstructionValueConsumer allowedConsumer = new InstructionValueConsumer() { @Override - public Value doValue(LIRInstruction op, Value value, OperandMode mode, EnumSet flags) { - return allowed(op, value, mode, flags); + public void visitValue(LIRInstruction op, Value value, OperandMode mode, EnumSet flags) { + allowed(op, value, mode, flags); } }; public static boolean verify(final LIRInstruction op) { - op.forEachInput(allowedProc); - op.forEachAlive(allowedProc); - op.forEachState(allowedProc); - op.forEachTemp(allowedProc); - op.forEachOutput(allowedProc); + op.visitEachInput(allowedConsumer); + op.visitEachAlive(allowedConsumer); + op.visitEachState(allowedConsumer); + op.visitEachTemp(allowedConsumer); + op.visitEachOutput(allowedConsumer); op.verify(); return true; @@ -105,18 +103,18 @@ private BitSet curRegistersDefined; private void verify() { - ValueProcedure useProc = new ValueProcedure() { + ValueConsumer useConsumer = new ValueConsumer() { @Override - public Value doValue(Value value, OperandMode mode, EnumSet flags) { - return use(value, mode, flags); + public void visitValue(Value value, OperandMode mode, EnumSet flags) { + use(value, mode, flags); } }; - ValueProcedure defProc = new ValueProcedure() { + ValueConsumer defConsumer = new ValueConsumer() { @Override - public Value doValue(Value value, OperandMode mode, EnumSet flags) { - return def(value, mode, flags); + public void visitValue(Value value, OperandMode mode, EnumSet flags) { + def(value, mode, flags); } }; @@ -141,17 +139,17 @@ for (LIRInstruction op : lir.getLIRforBlock(block)) { curInstruction = op; - op.forEachInput(useProc); + op.visitEachInput(useConsumer); if (op.destroysCallerSavedRegisters()) { for (Register register : frameMap.registerConfig.getCallerSaveRegisters()) { curRegistersLive[register.number] = null; } } curRegistersDefined.clear(); - op.forEachAlive(useProc); - op.forEachState(useProc); - op.forEachTemp(defProc); - op.forEachOutput(defProc); + op.visitEachAlive(useConsumer); + op.visitEachState(useConsumer); + op.visitEachTemp(defConsumer); + op.visitEachOutput(defConsumer); curInstruction = null; } @@ -160,7 +158,7 @@ } } - private Value use(Value value, OperandMode mode, EnumSet flags) { + private void use(Value value, OperandMode mode, EnumSet flags) { allowed(curInstruction, value, mode, flags); if (isVariable(value)) { @@ -190,10 +188,9 @@ throw GraalInternalError.shouldNotReachHere(); } } - return value; } - private Value def(Value value, OperandMode mode, EnumSet flags) { + private void def(Value value, OperandMode mode, EnumSet flags) { allowed(curInstruction, value, mode, flags); if (isVariable(value)) { @@ -231,17 +228,16 @@ } } } - return value; } // @formatter:off - private static Value allowed(Object op, Value value, OperandMode mode, EnumSet flags) { + private static void allowed(Object op, Value value, OperandMode mode, EnumSet flags) { if ((isVariable(value) && flags.contains(OperandFlag.REG)) || (isRegister(value) && flags.contains(OperandFlag.REG)) || (isStackSlot(value) && flags.contains(OperandFlag.STACK)) || (isConstant(value) && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) || (isIllegal(value) && flags.contains(OperandFlag.ILLEGAL))) { - return value; + return; } throw new GraalInternalError("Invalid LIR%n Instruction: %s%n Mode: %s%n Flags: %s%n Unexpected value: %s %s", op, mode, flags, value.getClass().getSimpleName(), value); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java Mon Aug 25 21:15:59 2014 -0700 @@ -32,7 +32,6 @@ import com.oracle.graal.debug.*; import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; -import com.oracle.graal.lir.LIRInstruction.ValueProcedure; import com.oracle.graal.lir.StandardOp.MoveOp; /** @@ -363,16 +362,16 @@ /* * Value procedure for the instruction's output and temp values */ - class OutputValueProc extends ValueProcedure { + class OutputValueConsumer extends ValueConsumer { int opValueNum; - OutputValueProc(int opValueNum) { + OutputValueConsumer(int opValueNum) { this.opValueNum = opValueNum; } @Override - public Value doValue(Value operand, OperandMode mode, EnumSet flags) { + public void visitValue(Value operand, OperandMode mode, EnumSet flags) { int stateIdx = getStateIdx(operand); if (stateIdx >= 0) { /* @@ -381,19 +380,18 @@ state[stateIdx] = encodeValueNum(opValueNum++, !operand.getLIRKind().isValue()); Debug.log("set def %d for register %s(%d): %d", opValueNum, operand, stateIdx, state[stateIdx]); } - return operand; } } - OutputValueProc outputValueProc = new OutputValueProc(valueNum); + OutputValueConsumer outputValueConsumer = new OutputValueConsumer(valueNum); - op.forEachTemp(outputValueProc); + op.visitEachTemp(outputValueConsumer); /* * Semantically the output values are written _after_ the temp values */ - op.forEachOutput(outputValueProc); + op.visitEachOutput(outputValueConsumer); - valueNum = outputValueProc.opValueNum; + valueNum = outputValueConsumer.opValueNum; if (op.hasState()) { /* diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StateProcedure.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StateProcedure.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir; + +public abstract class StateProcedure extends InstructionStateProcedure { + + protected abstract void doState(LIRFrameState state); + + @Override + protected final void doState(LIRInstruction instruction, LIRFrameState state) { + doState(state); + } +} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValueConsumer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValueConsumer.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.lir.LIRInstruction.*; + +/** + * Non-modifying version of {@link ValueProcedure}. + */ +public abstract class ValueConsumer extends InstructionValueConsumer { + + /** + * Iterator method to be overwritten. This version of the iterator does not take additional + * parameters to keep the signature short. + * + * @param value The value that is iterated. + */ + protected void visitValue(Value value) { + throw GraalInternalError.shouldNotReachHere("One of the visitValue() methods must be overwritten"); + } + + /** + * Iterator method to be overwritten. This version of the iterator gets additional parameters + * about the processed value. + * + * @param value The value that is iterated. + * @param mode The operand mode for the value. + * @param flags A set of flags for the value. + */ + protected void visitValue(Value value, OperandMode mode, EnumSet flags) { + visitValue(value); + } + + @Override + protected final void visitValue(LIRInstruction instruction, Value value) { + throw GraalInternalError.shouldNotReachHere("This visitValue() method should never be called"); + } + + @Override + protected void visitValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet flags) { + visitValue(value, mode, flags); + } +} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValuePosition.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValuePosition.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValuePosition.java Mon Aug 25 21:15:59 2014 -0700 @@ -70,7 +70,8 @@ public void set(LIRInstruction inst, Value value) { if (isCompositePosition()) { CompositeValue compValue = (CompositeValue) outerPosition.get(inst); - compValue.getValueClass().setValue(compValue, this, value); + CompositeValue newCompValue = compValue.getValueClass().createUpdatedValue(compValue, this, value); + outerPosition.set(inst, newCompValue); } else { inst.getLIRInstructionClass().setValue(inst, this, value); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValuePositionProcedure.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValuePositionProcedure.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir; + +/** + * Iterator for iterating over a list of {@linkplain ValuePosition value positions}. + */ +public abstract class ValuePositionProcedure { + + /** + * Iterator method to be overwritten. This version of the iterator does not take additional + * parameters to keep the signature short. + * + * @param instruction The current instruction. + * @param position The position of the value that is iterated. + */ + + public abstract void doValue(LIRInstruction instruction, ValuePosition position); +} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValueProcedure.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValueProcedure.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.lir.LIRInstruction.*; + +/** + * Similar to {@link InstructionValueProcedure} but without an {@link LIRInstruction} parameter. + */ +public abstract class ValueProcedure extends InstructionValueProcedure { + + /** + * Iterator method to be overwritten. This version of the iterator does not take additional + * parameters to keep the signature short. + * + * @param value The value that is iterated. + * @return The new value to replace the value that was passed in. + */ + protected Value doValue(Value value) { + throw GraalInternalError.shouldNotReachHere("One of the doValue() methods must be overwritten"); + } + + /** + * Iterator method to be overwritten. This version of the iterator gets additional parameters + * about the processed value. + * + * @param value The value that is iterated. + * @param mode The operand mode for the value. + * @param flags A set of flags for the value. + * @return The new value to replace the value that was passed in. + */ + protected Value doValue(Value value, OperandMode mode, EnumSet flags) { + return doValue(value); + } + + @Override + protected final Value doValue(LIRInstruction instruction, Value value) { + throw GraalInternalError.shouldNotReachHere("This doValue() method should never be called"); + } + + @Override + public final Value doValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet flags) { + return doValue(value, mode, flags); + } +} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java Mon Aug 25 21:15:59 2014 -0700 @@ -86,7 +86,7 @@ return rawStride; } if (op instanceof IntegerSubNode) { - return graph().unique(new NegateNode(rawStride)); + return graph().unique(NegateNode.create(rawStride)); } throw GraalInternalError.shouldNotReachHere(); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java Mon Aug 25 21:15:59 2014 -0700 @@ -62,13 +62,13 @@ range = IntegerArithmeticNode.sub(graph, range, ConstantNode.forIntegerStamp(stamp, 1, graph)); } } - IntegerDivNode div = graph.add(new IntegerDivNode(range, iv.strideNode())); + IntegerDivNode div = graph.add(IntegerDivNode.create(range, iv.strideNode())); graph.addBeforeFixed(loop.entryPoint(), div); ConstantNode zero = ConstantNode.forIntegerStamp(stamp, 0, graph); if (assumePositive) { return div; } - return graph.unique(new ConditionalNode(graph.unique(new IntegerLessThanNode(zero, div)), div, zero)); + return graph.unique(ConditionalNode.create(graph.unique(IntegerLessThanNode.create(zero, div)), div, zero)); } public boolean isConstantMaxTripCount() { @@ -147,16 +147,16 @@ if (oneOff) { v1 = sub(graph, v1, one); } - cond = graph.unique(new IntegerLessThanNode(v1, end)); + cond = graph.unique(IntegerLessThanNode.create(v1, end)); } else { assert iv.direction() == Direction.Down; IntegerArithmeticNode v1 = add(graph, ConstantNode.forIntegerStamp(stamp, IntegerStamp.defaultMinValue(stamp.getBits()), graph), sub(graph, one, iv.strideNode())); if (oneOff) { v1 = add(graph, v1, one); } - cond = graph.unique(new IntegerLessThanNode(end, v1)); + cond = graph.unique(IntegerLessThanNode.create(end, v1)); } - overflowGuard = graph.unique(new GuardNode(cond, BeginNode.prevBegin(loop.entryPoint()), DeoptimizationReason.LoopLimitCheck, DeoptimizationAction.InvalidateRecompile, true, + overflowGuard = graph.unique(GuardNode.create(cond, BeginNode.prevBegin(loop.entryPoint()), DeoptimizationReason.LoopLimitCheck, DeoptimizationAction.InvalidateRecompile, true, Constant.NULL_OBJECT)); // TODO gd: use speculation loop.loopBegin().setOverflowGuard(overflowGuard); return overflowGuard; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java Mon Aug 25 21:15:59 2014 -0700 @@ -86,7 +86,7 @@ @Override public ValueNode strideNode() { if (value instanceof IntegerSubNode && base.valueNode() == value.getY()) { - return graph().unique(new NegateNode(base.strideNode())); + return graph().unique(NegateNode.create(base.strideNode())); } return base.strideNode(); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Mon Aug 25 21:15:59 2014 -0700 @@ -312,9 +312,9 @@ if (newEarlyExit == null) { continue; } - MergeNode merge = graph.add(new MergeNode()); - AbstractEndNode originalEnd = graph.add(new EndNode()); - AbstractEndNode newEnd = graph.add(new EndNode()); + MergeNode merge = graph.add(MergeNode.create()); + AbstractEndNode originalEnd = graph.add(EndNode.create()); + AbstractEndNode newEnd = graph.add(EndNode.create()); merge.addForwardEnd(originalEnd); merge.addForwardEnd(newEnd); loopEarlyExit.setNext(originalEnd); @@ -354,9 +354,9 @@ if (newVpn != null) { PhiNode phi; if (vpn instanceof ValueProxyNode) { - phi = graph.addWithoutUnique(new ValuePhiNode(vpn.stamp(), merge)); + phi = graph.addWithoutUnique(ValuePhiNode.create(vpn.stamp(), merge)); } else if (vpn instanceof GuardProxyNode) { - phi = graph.addWithoutUnique(new GuardPhiNode(merge)); + phi = graph.addWithoutUnique(GuardPhiNode.create(merge)); } else { throw GraalInternalError.shouldNotReachHere(); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java Mon Aug 25 21:15:59 2014 -0700 @@ -154,7 +154,7 @@ if (value != null) { return value; } - BeginNode newValue = graph.add(new BeginNode()); + BeginNode newValue = graph.add(BeginNode.create()); seenNode.put(original, newValue); return newValue; } @@ -163,7 +163,7 @@ if (value != null) { return value; } - BeginNode newValue = graph.add(new BeginNode()); + BeginNode newValue = graph.add(BeginNode.create()); seenNode.put(original, newValue); return newValue; } @@ -172,7 +172,7 @@ if (value != null) { return value; } - EndNode newValue = graph.add(new EndNode()); + EndNode newValue = graph.add(EndNode.create()); seenNode.put(original, newValue); return newValue; } @@ -189,11 +189,11 @@ private static PhiNode patchPhi(StructuredGraph graph, PhiNode phi, MergeNode merge) { PhiNode ret; if (phi instanceof ValuePhiNode) { - ret = new ValuePhiNode(phi.stamp(), merge); + ret = ValuePhiNode.create(phi.stamp(), merge); } else if (phi instanceof GuardPhiNode) { - ret = new GuardPhiNode(merge); + ret = GuardPhiNode.create(merge); } else if (phi instanceof MemoryPhiNode) { - ret = new MemoryPhiNode(merge, ((MemoryPhiNode) phi).getLocationIdentity()); + ret = MemoryPhiNode.create(merge, ((MemoryPhiNode) phi).getLocationIdentity()); } else { throw GraalInternalError.shouldNotReachHere(); } @@ -312,12 +312,12 @@ if (endsToMerge.size() == 1) { AbstractEndNode end = endsToMerge.get(0); assert end.usages().isEmpty(); - newExit = graph.add(new BeginNode()); + newExit = graph.add(BeginNode.create()); end.replaceAtPredecessor(newExit); end.safeDelete(); } else { assert endsToMerge.size() > 1; - MergeNode newExitMerge = graph.add(new MergeNode()); + MergeNode newExitMerge = graph.add(MergeNode.create()); newExit = newExitMerge; FrameState state = loopBegin.stateAfter(); FrameState duplicateState = null; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java Mon Aug 25 21:15:59 2014 -0700 @@ -79,7 +79,7 @@ public Node replacement(Node o) { if (o == entry) { if (endNode == null) { - endNode = graph.add(new EndNode()); + endNode = graph.add(EndNode.create()); } return endNode; } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Mon Aug 25 21:15:59 2014 -0700 @@ -30,7 +30,7 @@ import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.graph.*; import com.oracle.graal.graph.NodeClass.NodeClassIterator; -import com.oracle.graal.graph.NodeClass.Position; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.phases.common.*; @@ -167,7 +167,7 @@ invariantValue = switchNode.value(); controls = new ArrayList<>(); controls.add(switchNode); - } else if (switchNode.value() == invariantValue && firstSwitch.equalKeys(switchNode)) { + } else if (switchNode.value() == invariantValue && firstSwitch.structureEquals(switchNode)) { // Only collect switches which test the same values in the same order controls.add(switchNode); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodeinfo.processor/src/META-INF/services/javax.annotation.processing.Processor --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodeinfo.processor/src/META-INF/services/javax.annotation.processing.Processor Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,1 @@ +com.oracle.graal.nodeinfo.processor.GraphNodeProcessor diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/ElementException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/ElementException.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodeinfo.processor; + +import javax.lang.model.element.*; + +/** + * Denotes an error encountered while processing an element. + */ +@SuppressWarnings("serial") +public class ElementException extends RuntimeException { + public final Element element; + + public ElementException(Element element, String format, Object... args) { + super(String.format(format, args)); + this.element = element; + } +} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeGenerator.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,983 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodeinfo.processor; + +import static com.oracle.graal.nodeinfo.processor.GraphNodeGenerator.NodeRefsType.*; +import static com.oracle.truffle.dsl.processor.java.ElementUtils.*; +import static java.util.Arrays.*; +import static javax.lang.model.element.Modifier.*; + +import java.util.*; +import java.util.stream.*; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; +import javax.tools.Diagnostic.Kind; + +import com.oracle.graal.nodeinfo.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.java.model.*; + +/** + * Generates the source code for a Node class. + */ +public class GraphNodeGenerator { + + private final GraphNodeProcessor env; + private final Types types; + private final Elements elements; + + private final TypeElement Input; + private final TypeElement OptionalInput; + private final TypeElement Successor; + + final TypeElement Node; + private final TypeElement NodeList; + private final TypeElement NodeInputList; + private final TypeElement NodeSuccessorList; + private final TypeElement Position; + + private final List inputFields = new ArrayList<>(); + private final List inputListFields = new ArrayList<>(); + private final List successorFields = new ArrayList<>(); + private final List successorListFields = new ArrayList<>(); + private final List dataFields = new ArrayList<>(); + private final Set optionalInputs = new HashSet<>(); + private final Map inputTypes = new HashMap<>(); + + private CodeTypeElement genClass; + private String genClassName; + + public GraphNodeGenerator(GraphNodeProcessor processor) { + this.env = processor; + + this.types = processor.getProcessingEnv().getTypeUtils(); + this.elements = processor.getProcessingEnv().getElementUtils(); + + this.Input = getTypeElement("com.oracle.graal.graph.Node.Input"); + this.OptionalInput = getTypeElement("com.oracle.graal.graph.Node.OptionalInput"); + this.Successor = getTypeElement("com.oracle.graal.graph.Node.Successor"); + this.Node = getTypeElement("com.oracle.graal.graph.Node"); + this.NodeList = getTypeElement("com.oracle.graal.graph.NodeList"); + this.NodeInputList = getTypeElement("com.oracle.graal.graph.NodeInputList"); + this.NodeSuccessorList = getTypeElement("com.oracle.graal.graph.NodeSuccessorList"); + this.Position = getTypeElement("com.oracle.graal.graph.Position"); + } + + @SafeVarargs + private static Collection concat(List fields1, List fields2, List... tail) { + return new AbstractCollection() { + + @Override + public Iterator iterator() { + Stream joined = Stream.concat(fields1.stream(), fields2.stream()); + for (List t : tail) { + joined = Stream.concat(joined, t.stream()); + } + return joined.iterator(); + } + + @Override + public int size() { + return fields1.size() + fields2.size(); + } + }; + } + + /** + * Returns a type element given a canonical name. + * + * @throw {@link NoClassDefFoundError} if a type element does not exist for {@code name} + */ + public TypeElement getTypeElement(String name) { + TypeElement typeElement = elements.getTypeElement(name); + if (typeElement == null) { + throw new NoClassDefFoundError(name); + } + return typeElement; + } + + public TypeMirror getType(String name) { + return getTypeElement(name).asType(); + } + + public TypeMirror getType(Class primitiveClass) { + return ElementUtils.getType(getProcessingEnv(), primitiveClass); + } + + public ProcessingEnvironment getProcessingEnv() { + return env.getProcessingEnv(); + } + + private static String getGeneratedClassName(TypeElement node) { + + TypeElement typeElement = node; + + String genClassName = typeElement.getSimpleName().toString() + "Gen"; + Element enclosing = typeElement.getEnclosingElement(); + while (enclosing != null) { + if (enclosing.getKind() == ElementKind.CLASS || enclosing.getKind() == ElementKind.INTERFACE) { + if (enclosing.getModifiers().contains(Modifier.PRIVATE)) { + throw new ElementException(enclosing, "%s %s cannot be private", enclosing.getKind().name().toLowerCase(), enclosing); + } + genClassName = enclosing.getSimpleName() + "_" + genClassName; + } else { + assert enclosing.getKind() == ElementKind.PACKAGE; + } + enclosing = enclosing.getEnclosingElement(); + } + return genClassName; + } + + public boolean isAssignableWithErasure(Element from, Element to) { + TypeMirror fromType = types.erasure(from.asType()); + TypeMirror toType = types.erasure(to.asType()); + return types.isAssignable(fromType, toType); + } + + private void scanFields(TypeElement node) { + TypeElement currentClazz = node; + do { + for (VariableElement field : ElementFilter.fieldsIn(currentClazz.getEnclosedElements())) { + Set modifiers = field.getModifiers(); + if (modifiers.contains(STATIC) || modifiers.contains(TRANSIENT)) { + continue; + } + + List annotations = field.getAnnotationMirrors(); + + boolean isNonOptionalInput = findAnnotationMirror(annotations, Input) != null; + boolean isOptionalInput = findAnnotationMirror(annotations, OptionalInput) != null; + boolean isSuccessor = findAnnotationMirror(annotations, Successor) != null; + + if (isNonOptionalInput || isOptionalInput) { + if (findAnnotationMirror(annotations, Successor) != null) { + throw new ElementException(field, "Field cannot be both input and successor"); + } else if (isNonOptionalInput && isOptionalInput) { + throw new ElementException(field, "Inputs must be either optional or non-optional"); + } else if (isAssignableWithErasure(field, NodeInputList)) { + if (modifiers.contains(FINAL)) { + throw new ElementException(field, "Input list field must not be final"); + } + if (modifiers.contains(PUBLIC) || modifiers.contains(PRIVATE)) { + throw new ElementException(field, "Input list field must be protected or package-private"); + } + inputListFields.add(field); + } else { + if (!isAssignableWithErasure(field, Node) && field.getKind() == ElementKind.INTERFACE) { + throw new ElementException(field, "Input field type must be an interface or assignable to Node"); + } + if (modifiers.contains(FINAL)) { + throw new ElementException(field, "Input field must not be final"); + } + if (modifiers.contains(PUBLIC) || modifiers.contains(PRIVATE)) { + throw new ElementException(field, "Input field must be protected or package-private"); + } + inputFields.add(field); + } + if (isOptionalInput) { + inputTypes.put(field, getAnnotationValue(VariableElement.class, findAnnotationMirror(annotations, OptionalInput), "value")); + optionalInputs.add(field); + } else { + inputTypes.put(field, getAnnotationValue(VariableElement.class, findAnnotationMirror(annotations, Input), "value")); + } + } else if (isSuccessor) { + if (isAssignableWithErasure(field, NodeSuccessorList)) { + if (modifiers.contains(FINAL)) { + throw new ElementException(field, "Successor list field must not be final"); + } + if (modifiers.contains(PUBLIC)) { + throw new ElementException(field, "Successor list field must not be public"); + } + successorListFields.add(field); + } else { + if (!isAssignableWithErasure(field, Node)) { + throw new ElementException(field, "Successor field must be a Node type"); + } + if (modifiers.contains(FINAL)) { + throw new ElementException(field, "Successor field must not be final"); + } + if (modifiers.contains(PUBLIC) || modifiers.contains(PRIVATE)) { + throw new ElementException(field, "Successor field must be protected or package-private"); + } + successorFields.add(field); + } + + } else { + if (isAssignableWithErasure(field, Node) && !field.getSimpleName().contentEquals("Null")) { + throw new ElementException(field, "Node field must be annotated with @" + Input.getSimpleName() + ", @" + OptionalInput.getSimpleName() + " or @" + Successor.getSimpleName()); + } + if (isAssignableWithErasure(field, NodeInputList)) { + throw new ElementException(field, "NodeInputList field must be annotated with @" + Input.getSimpleName() + " or @" + OptionalInput.getSimpleName()); + } + if (isAssignableWithErasure(field, NodeSuccessorList)) { + throw new ElementException(field, "NodeSuccessorList field must be annotated with @" + Successor.getSimpleName()); + } + dataFields.add(field); + } + } + currentClazz = getSuperType(currentClazz); + } while (!isObject(getSuperType(currentClazz).asType())); + } + + /** + * Determines if two parameter lists contain the + * {@linkplain Types#isSameType(TypeMirror, TypeMirror) same} types. + */ + private boolean parametersMatch(List p1, List p2) { + if (p1.size() == p2.size()) { + for (int i = 0; i < p1.size(); i++) { + if (!types.isSameType(p1.get(i).asType(), p2.get(i).asType())) { + return false; + } + } + return true; + } + return false; + } + + /** + * Searches a type for a method based on a given name and parameter types. + */ + private ExecutableElement findMethod(TypeElement type, String name, List parameters) { + List methods = ElementFilter.methodsIn(type.getEnclosedElements()); + for (ExecutableElement method : methods) { + if (method.getSimpleName().toString().equals(name)) { + if (parametersMatch(method.getParameters(), parameters)) { + return method; + } + } + } + return null; + } + + enum NodeRefsType { + Inputs, + Successors; + } + + CodeCompilationUnit process(TypeElement node) { + try { + return process0(node); + } finally { + reset(); + } + } + + private CodeCompilationUnit process0(TypeElement node) { + + CodeCompilationUnit compilationUnit = new CodeCompilationUnit(); + + PackageElement packageElement = ElementUtils.findPackageElement(node); + + genClassName = getGeneratedClassName(node); + genClass = new CodeTypeElement(modifiers(FINAL), ElementKind.CLASS, packageElement, genClassName); + genClass.setSuperClass(node.asType()); + + for (ExecutableElement constructor : ElementFilter.constructorsIn(node.getEnclosedElements())) { + if (constructor.getModifiers().contains(PUBLIC)) { + throw new ElementException(constructor, "Node class constructor must not be public"); + } + + checkFactoryMethodExists(node, constructor); + + CodeExecutableElement subConstructor = createConstructor(genClass, constructor); + subConstructor.getModifiers().removeAll(Arrays.asList(PUBLIC, PRIVATE, PROTECTED)); + genClass.add(subConstructor); + } + + DeclaredType generatedNode = (DeclaredType) getType(GeneratedNode.class); + CodeAnnotationMirror generatedNodeMirror = new CodeAnnotationMirror(generatedNode); + generatedNodeMirror.setElementValue(generatedNodeMirror.findExecutableElement("value"), new CodeAnnotationValue(node.asType())); + genClass.getAnnotationMirrors().add(generatedNodeMirror); + + scanFields(node); + + boolean hasInputs = !inputFields.isEmpty() || !inputListFields.isEmpty(); + boolean hasSuccessors = !successorFields.isEmpty() || !successorListFields.isEmpty(); + + if (hasInputs || hasSuccessors) { + createGetNodeAtMethod(); + createGetInputTypeAtMethod(); + createGetNameOfMethod(); + createUpdateOrInitializeNodeAtMethod(false); + createUpdateOrInitializeNodeAtMethod(true); + createIsLeafNodeMethod(genClass); + + if (!inputListFields.isEmpty() || !successorListFields.isEmpty()) { + createGetNodeListAtMethod(); + createSetNodeListAtMethod(); + } + } + + if (hasInputs) { + createIsOptionalInputAtMethod(); + createGetFirstLevelPositionsMethod(Inputs, inputFields, inputListFields); + + createContainsMethod(Inputs, inputFields, inputListFields); + createIterableMethod(Inputs); + + CodeTypeElement inputsIteratorClass = createIteratorClass(Inputs, packageElement, inputFields, inputListFields); + createAllIteratorClass(Inputs, inputsIteratorClass.asType(), packageElement, inputFields, inputListFields); + createWithModCountIteratorClass(Inputs, inputsIteratorClass.asType(), packageElement); + createIterableClass(Inputs, packageElement); + } + + if (hasSuccessors) { + createGetFirstLevelPositionsMethod(Successors, successorFields, successorListFields); + + createContainsMethod(Successors, successorFields, successorListFields); + createIterableMethod(Successors); + + CodeTypeElement successorsIteratorClass = createIteratorClass(Successors, packageElement, successorFields, successorListFields); + createAllIteratorClass(Successors, successorsIteratorClass.asType(), packageElement, successorFields, successorListFields); + createWithModCountIteratorClass(Successors, successorsIteratorClass.asType(), packageElement); + createIterableClass(Successors, packageElement); + } + + compilationUnit.add(genClass); + return compilationUnit; + } + + /** + * Checks that a public static factory method named {@code "create"} exists in {@code node} + * whose signature matches that of a given constructor. + * + * @throws ElementException if the check fails + */ + private void checkFactoryMethodExists(TypeElement node, ExecutableElement constructor) { + ExecutableElement create = findMethod(node, "create", constructor.getParameters()); + if (create == null) { + Formatter f = new Formatter(); + f.format("public static %s create(", node.getSimpleName()); + String sep = ""; + Formatter callArgs = new Formatter(); + for (VariableElement v : constructor.getParameters()) { + f.format("%s%s %s", sep, ElementUtils.getSimpleName(v.asType()), v.getSimpleName()); + callArgs.format("%s%s", sep, v.getSimpleName()); + sep = ", "; + } + f.format(") { return new %s(%s); }", genClassName, callArgs); + throw new ElementException(constructor, "Missing Node class factory method '%s'", f); + } + if (!create.getModifiers().containsAll(asList(PUBLIC, STATIC))) { + throw new ElementException(constructor, "Node class factory method must be public and static"); + } + } + + private CodeExecutableElement createConstructor(TypeElement type, ExecutableElement element) { + CodeExecutableElement executable = CodeExecutableElement.clone(getProcessingEnv(), element); + + // to create a constructor we have to set the return type to null.(TODO needs fix) + executable.setReturnType(null); + // we have to set the name manually otherwise is inferred (TODO needs fix) + executable.setSimpleName(CodeNames.of(type.getSimpleName().toString())); + + CodeTreeBuilder b = executable.createBuilder(); + b.startStatement().startSuperCall(); + for (VariableElement v : element.getParameters()) { + b.string(v.getSimpleName().toString()); + } + b.end().end(); + + return executable; + } + + private void reset() { + inputFields.clear(); + inputListFields.clear(); + successorFields.clear(); + successorListFields.clear(); + dataFields.clear(); + optionalInputs.clear(); + inputTypes.clear(); + genClass = null; + genClassName = null; + } + + /** + * Checks that a generated method overrides exactly one method in a super type and that the + * super type is Node. + */ + private void checkOnlyInGenNode(CodeExecutableElement method) { + List overriddenMethods = getDeclaredMethodsInSuperTypes(method.getEnclosingClass(), method.getSimpleName().toString(), method.getParameterTypes()); + for (ExecutableElement overriddenMethod : overriddenMethods) { + if (!overriddenMethod.getEnclosingElement().equals(Node)) { + env.message(Kind.WARNING, overriddenMethod, "This method is overridden in a generated subclass will never be called"); + } + } + } + + private void createIsLeafNodeMethod(CodeTypeElement cls) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getType(boolean.class), "isLeafNode"); + method.createBuilder().startReturn().string("false").end(); + cls.add(method); + checkOnlyInGenNode(method); + } + + private ExecutableElement createIsOptionalInputAtMethod() { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getType(boolean.class), "isOptionalInputAt"); + method.addParameter(new CodeVariableElement(Position.asType(), "pos")); + CodeTreeBuilder b = method.createBuilder(); + b.startAssert().string("pos.isInput()").end(); + if (!optionalInputs.isEmpty()) { + b.startSwitch().string("pos.getIndex()").end().startBlock(); + int index = 0; + for (VariableElement f : concat(inputFields, inputListFields)) { + if (optionalInputs.contains(f)) { + b.startCase().string(String.valueOf(index)).end(); + } + index++; + } + b.startStatement().string("return true").end(); + b.end(); + } + b.startReturn().string("false").end(); + genClass.add(method); + checkOnlyInGenNode(method); + return method; + } + + private ExecutableElement createGetFirstLevelPositionsMethod(NodeRefsType nodeRefsType, List nodeFields, List nodeListFields) { + DeclaredType collectionOfPosition = types.getDeclaredType((TypeElement) types.asElement(getType(Collection.class)), Position.asType()); + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), collectionOfPosition, "getFirstLevel" + nodeRefsType); + CodeTreeBuilder b = method.createBuilder(); + b.startReturn().startNew(getTypeElement("com.oracle.graal.graph.FirstLevelPositionCollection").asType()); + b.string(String.valueOf(nodeFields.size())); + b.string(String.valueOf(nodeListFields.size())); + b.string(String.valueOf(nodeRefsType == NodeRefsType.Inputs)); + b.end().end(); + genClass.add(method); + checkOnlyInGenNode(method); + return method; + } + + private CodeTypeElement createIteratorClass(NodeRefsType nodeRefsType, PackageElement packageElement, List nodeFields, List nodeListFields) { + String name = nodeRefsType + "Iterator"; + CodeTypeElement cls = new CodeTypeElement(modifiers(PRIVATE), ElementKind.CLASS, packageElement, name); + cls.setSuperClass(getType("com.oracle.graal.graph.NodeRefIterator")); + + // Constructor + CodeExecutableElement ctor = new CodeExecutableElement(Collections.emptySet(), null, name); + ctor.addParameter(new CodeVariableElement(getType(boolean.class), "callForward")); + CodeTreeBuilder b = ctor.createBuilder(); + b.startStatement().startSuperCall(); + b.string(String.valueOf(nodeFields.size())); + b.string(String.valueOf(nodeListFields.size())); + b.string(String.valueOf(nodeRefsType == NodeRefsType.Inputs)); + b.end().end(); + b.startIf().string("callForward").end().startBlock(); + b.startStatement().string("forward()").end(); + b.end(); + cls.add(ctor); + + // Methods overriding those in NodeRefIterator + createGetFieldMethod(cls, nodeFields, Node.asType(), "getNode"); + createGetFieldMethod(cls, nodeListFields, types.getDeclaredType(NodeList, types.getWildcardType(Node.asType(), null)), "getNodeList"); + genClass.add(cls); + return cls; + } + + private void createGetFieldMethod(CodeTypeElement cls, List fields, TypeMirror returnType, String name) { + if (!fields.isEmpty()) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), returnType, name); + method.addParameter(new CodeVariableElement(getType(int.class), "at")); + CodeTreeBuilder b = method.createBuilder(); + createGetFieldCases(b, fields, returnType, null); + cls.add(method); + } + } + + private void createGetFieldCases(CodeTreeBuilder b, List fields, TypeMirror returnType, String returnExpressionSuffix) { + for (int i = 0; i < fields.size(); i++) { + VariableElement field = fields.get(i); + b.startIf().string("at == " + i).end().startBlock(); + b.startReturn(); + if (returnExpressionSuffix == null && !isAssignableWithErasure(field, types.asElement(returnType))) { + b.cast(((DeclaredType) returnType).asElement().getSimpleName().toString()); + } + b.string(genClassName + ".this." + field.getSimpleName()); + if (returnExpressionSuffix != null) { + b.string(returnExpressionSuffix); + } + b.end(); + b.end(); + } + b.startThrow().startNew(getType(NoSuchElementException.class)).end().end(); + } + + private void createSetNodeListAtCases(CodeTreeBuilder b, List fields, TypeMirror returnType, String returnExpressionSuffix) { + for (int i = 0; i < fields.size(); i++) { + VariableElement field = fields.get(i); + b.startIf().string("at == " + i).end().startBlock(); + if (returnExpressionSuffix == null && !isAssignableWithErasure(field, types.asElement(returnType))) { + b.cast(((DeclaredType) returnType).asElement().getSimpleName().toString()); + } + b.startStatement(); + b.string(genClassName + ".this." + field.getSimpleName(), " = "); + b.cast(field.asType(), CodeTreeBuilder.singleString("list")); + b.end(); + b.end(); + } + } + + private void createUpdateOrInitializeFieldCases(CodeTreeBuilder b, List fields, boolean isInitialization, boolean isList) { + boolean elseIf = false; + for (int i = 0; i < fields.size(); i++) { + VariableElement field = fields.get(i); + String fieldRef = genClassName + ".this." + field.getSimpleName(); + if (!isList) { + elseIf = b.startIf(elseIf); + b.string("at == " + i).end().startBlock(); + if (!isInitialization) { + b.startStatement().string("Node old = "); + if (!isAssignableWithErasure(field, Node)) { + b.cast(Node.asType(), CodeTreeBuilder.singleString(fieldRef)); + } else { + b.string(fieldRef); + } + b.end(); + } + b.startStatement().string(fieldRef, " = "); + if (!isAssignableWithErasure(Node, field)) { + b.cast(field.asType(), CodeTreeBuilder.singleString("newValue")); + } else { + b.string("newValue"); + } + b.end(); + if (!isInitialization) { + b.startIf().string("pos.isInput()").end().startBlock(); + b.startStatement().string("updateUsages(old, newValue)").end(); + b.end(); + b.startElseBlock(); + b.startStatement().string("updatePredecessor(old, newValue)").end(); + b.end(); + } + b.end(); + } else { + elseIf = b.startIf(elseIf); + b.string("at == " + i).end().startBlock(); + DeclaredType nodeListOfNode = types.getDeclaredType(NodeList, types.getWildcardType(Node.asType(), null)); + b.declaration(nodeListOfNode, "list", fieldRef); + if (!isInitialization) { + // if (pos.getSubIndex() < list.size()) { + b.startIf().string("pos.getSubIndex() < list.size()").end().startBlock(); + b.startStatement().string("list.set(pos.getSubIndex(), newValue)").end(); + b.end(); + b.startElseBlock(); + } + + b.startWhile().string("list.size() <= pos.getSubIndex()").end().startBlock(); + b.startStatement().string("list.add(null)").end(); + b.end(); + + if (isInitialization) { + b.startStatement().string("list.initialize(pos.getSubIndex(), newValue)").end(); + } else { + b.startStatement().string("list.add(newValue)").end(); + b.end(); + } + + b.end(); + } + } + b.startElseBlock(); + b.startThrow().startNew(getType(NoSuchElementException.class)).end().end(); + b.end(); + } + + private void createAllIteratorClass(NodeRefsType nodeRefsType, TypeMirror inputsIteratorType, PackageElement packageElement, List nodeFields, List nodeListFields) { + + String name = "All" + nodeRefsType + "Iterator"; + CodeTypeElement cls = new CodeTypeElement(modifiers(PRIVATE, FINAL), ElementKind.CLASS, packageElement, name); + cls.setSuperClass(inputsIteratorType); + + // Constructor + CodeExecutableElement ctor = new CodeExecutableElement(Collections.emptySet(), null, name); + CodeTreeBuilder b = ctor.createBuilder(); + b.startStatement().startSuperCall(); + b.string("true"); + b.end().end(); + cls.add(ctor); + + // forward() method + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), getType(void.class), "forward"); + b = method.createBuilder(); + int nodeFieldsSize = nodeFields.size(); + int nodeListFieldsSize = nodeListFields.size(); + String cond = "index < " + nodeFieldsSize; + b.startIf().string(cond).end().startBlock(); + b.startStatement().string("index++").end(); + b.startIf().string(cond).end().startBlock(); + b.startStatement().string("return").end(); + b.end(); + b.end(); + b.startElseBlock(); + b.startStatement().string("subIndex++").end(); + b.end(); + DeclaredType nodeListOfNode = types.getDeclaredType(NodeList, types.getWildcardType(Node.asType(), null)); + int count = nodeFieldsSize + nodeListFieldsSize; + b.startWhile().string("index < " + count).end().startBlock(); + b.declaration(nodeListOfNode, "list", "getNodeList(index - " + nodeFieldsSize + ")"); + b.startIf().string("subIndex < list.size()").end().startBlock(); + b.startStatement().string("return").end(); + b.end(); + b.startStatement().string("subIndex = 0").end(); + b.startStatement().string("index++").end(); + b.end(); + + cls.add(method); + + genClass.add(cls); + } + + private void createWithModCountIteratorClass(NodeRefsType nodeRefsType, TypeMirror superType, PackageElement packageElement) { + + String name = nodeRefsType + "WithModCountIterator"; + CodeTypeElement cls = new CodeTypeElement(modifiers(PRIVATE, FINAL), ElementKind.CLASS, packageElement, name); + cls.setSuperClass(superType); + + // modCount field + cls.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getType(int.class), "modCount")); + + // Constructor + CodeExecutableElement ctor = new CodeExecutableElement(Collections.emptySet(), null, name); + CodeTreeBuilder b = ctor.createBuilder(); + b.startStatement().startSuperCall(); + b.string("false"); + b.end().end(); + b.startAssert().staticReference(getType("com.oracle.graal.graph.Graph"), "MODIFICATION_COUNTS_ENABLED").end(); + b.startStatement().string("this.modCount = modCount()").end(); + b.startStatement().string("forward()").end(); + cls.add(ctor); + + // hasNext, next and nextPosition methods + overrideModWithCounterMethod(cls, "hasNext", getType(boolean.class)); + overrideModWithCounterMethod(cls, "next", Node.asType()); + overrideModWithCounterMethod(cls, "nextPosition", Position.asType()); + + genClass.add(cls); + } + + private static void overrideModWithCounterMethod(CodeTypeElement cls, String name, TypeMirror returnType) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, name); + CodeTreeBuilder b = method.createBuilder(); + b.startTryBlock(); + b.startStatement().string("return super." + name + "()").end(); + b.end().startFinallyBlock(); + b.startAssert().string("modCount == modCount() : \"must not be modified\"").end(); + b.end(); + cls.add(method); + } + + private void createIterableClass(NodeRefsType nodeRefsType, PackageElement packageElement) { + + String name = nodeRefsType + "Iterable"; + CodeTypeElement cls = new CodeTypeElement(modifiers(PRIVATE), ElementKind.CLASS, packageElement, name); + cls.getImplements().add(getType("com.oracle.graal.graph.NodeRefIterable")); + + // iterator() method + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType("com.oracle.graal.graph.NodeRefIterator"), "iterator"); + CodeTreeBuilder b = method.createBuilder(); + b.startIf().staticReference(getType("com.oracle.graal.graph.Graph"), "MODIFICATION_COUNTS_ENABLED").end().startBlock(); + b.startStatement().string("return new " + nodeRefsType + "WithModCountIterator()").end(); + b.end(); + b.startElseBlock(); + b.startStatement().string("return new " + nodeRefsType + "Iterator(true)").end(); + b.end(); + cls.add(method); + + // withNullIterator() method + method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType("com.oracle.graal.graph.NodeRefIterator"), "withNullIterator"); + b = method.createBuilder(); + b.startStatement().string("return new All" + nodeRefsType + "Iterator()").end(); + cls.add(method); + + // contains(Node) method + method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType(boolean.class), "contains"); + method.addParameter(new CodeVariableElement(Node.asType(), "n")); + b = method.createBuilder(); + b.startStatement().string("return " + nodeRefsType.name().toLowerCase() + "Contain(n)").end(); + cls.add(method); + genClass.add(cls); + } + + private void createContainsMethod(NodeRefsType nodeRefsType, List nodeFields, List nodeListFields) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, FINAL), getType(boolean.class), nodeRefsType.name().toLowerCase() + "Contain"); + method.addParameter(new CodeVariableElement(Node.asType(), "n")); + CodeTreeBuilder b = method.createBuilder(); + for (VariableElement f : nodeFields) { + b.startIf().string("n == " + f).end().startBlock(); + b.startStatement().string("return true").end(); + b.end(); + } + for (VariableElement f : nodeListFields) { + b.startIf().string(f + ".contains(n)").end().startBlock(); + b.startStatement().string("return true").end(); + b.end(); + } + b.startStatement().string("return false").end(); + genClass.add(method); + checkOnlyInGenNode(method); + } + + private static final String API_TAG = "V2"; + + private void createIterableMethod(NodeRefsType nodeRefsType) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType("com.oracle.graal.graph.NodeRefIterable"), (nodeRefsType == Inputs ? "inputs" : "successors") + + API_TAG); + CodeTreeBuilder b = method.createBuilder(); + b.startStatement().string("return new " + nodeRefsType + "Iterable()").end(); + genClass.add(method); + checkOnlyInGenNode(method); + } + + private void createGetNodeAtMethod() { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), Node.asType(), "getNodeAt"); + method.addParameter(new CodeVariableElement(Position.asType(), "pos")); + CodeTreeBuilder b = method.createBuilder(); + b.startIf().string("pos.isInput()").end().startBlock(); + createGetNodeAt(b, inputFields, inputListFields); + b.end(); + b.startElseBlock(); + createGetNodeAt(b, successorFields, successorListFields); + b.end(); + genClass.add(method); + checkOnlyInGenNode(method); + } + + private void createGetNodeListAtMethod() { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), types.getDeclaredType(NodeList, types.getWildcardType(Node.asType(), null)), "getNodeListAt"); + method.addParameter(new CodeVariableElement(Position.asType(), "pos")); + CodeTreeBuilder b = method.createBuilder(); + b.startIf().string("pos.isInput()").end().startBlock(); + createGetNodeListAt(b, inputFields, inputListFields); + b.end(); + b.startElseBlock(); + createGetNodeListAt(b, successorFields, successorListFields); + b.end(); + genClass.add(method); + checkOnlyInGenNode(method); + } + + private void createSetNodeListAtMethod() { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType(void.class), "SetNodeListAt"); + + DeclaredType suppress = (DeclaredType) getType(SuppressWarnings.class); + CodeAnnotationMirror suppressMirror = new CodeAnnotationMirror(suppress); + suppressMirror.setElementValue(suppressMirror.findExecutableElement("value"), new CodeAnnotationValue("unchecked")); + method.getAnnotationMirrors().add(suppressMirror); + + method.addParameter(new CodeVariableElement(Position.asType(), "pos")); + method.addParameter(new CodeVariableElement(types.getDeclaredType(NodeList, types.getWildcardType(Node.asType(), null)), "list")); + CodeTreeBuilder b = method.createBuilder(); + b.startIf().string("pos.isInput()").end().startBlock(); + createSetNodeListAt(b, inputFields, inputListFields); + b.end(); + b.startElseBlock(); + createSetNodeListAt(b, successorFields, successorListFields); + b.end(); + genClass.add(method); + checkOnlyInGenNode(method); + } + + private void createGetNameOfMethod() { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType(String.class), "getNameOf"); + method.addParameter(new CodeVariableElement(Position.asType(), "pos")); + CodeTreeBuilder b = method.createBuilder(); + + b.startIf().string("pos.isInput()").end().startBlock(); + createGetNameOf(b, inputFields, inputListFields); + b.end(); + b.startElseBlock(); + createGetNameOf(b, successorFields, successorListFields); + b.end(); + genClass.add(method); + checkOnlyInGenNode(method); + } + + private void createGetInputTypeAtMethod() { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType(InputType.class), "getInputTypeAt"); + method.addParameter(new CodeVariableElement(Position.asType(), "pos")); + CodeTreeBuilder b = method.createBuilder(); + b.startAssert().string("pos.isInput()").end(); + boolean hasNodes = !inputFields.isEmpty(); + boolean hasNodeLists = !inputListFields.isEmpty(); + if (hasNodeLists || hasNodes) { + int index = 0; + for (VariableElement f : concat(inputFields, inputListFields)) { + b.startIf().string("pos.getIndex() == " + index).end().startBlock(); + b.startStatement().string("return ").staticReference(getType(InputType.class), inputTypes.get(f).getSimpleName().toString()).end(); + b.end(); + index++; + } + } + b.startThrow().startNew(getType(NoSuchElementException.class)).end().end(); + genClass.add(method); + checkOnlyInGenNode(method); + } + + private boolean hidesField(String name) { + for (VariableElement field : concat(inputFields, inputListFields, successorFields, successorListFields, dataFields)) { + if (field.getSimpleName().contentEquals(name)) { + return true; + } + } + return false; + } + + private void createUpdateOrInitializeNodeAtMethod(boolean isInitialization) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType(void.class), (isInitialization ? "initialize" : "update") + "NodeAt"); + method.addParameter(new CodeVariableElement(Position.asType(), "pos")); + CodeVariableElement newValue = new CodeVariableElement(Node.asType(), "newValue"); + if (hidesField(newValue.getSimpleName().toString())) { + DeclaredType suppress = (DeclaredType) getType(SuppressWarnings.class); + CodeAnnotationMirror suppressMirror = new CodeAnnotationMirror(suppress); + suppressMirror.setElementValue(suppressMirror.findExecutableElement("value"), new CodeAnnotationValue("hiding")); + newValue.getAnnotationMirrors().add(suppressMirror); + } + method.addParameter(newValue); + CodeTreeBuilder b = method.createBuilder(); + b.startIf().string("pos.isInput()").end().startBlock(); + createUpdateOrInitializeNodeAt(b, inputFields, inputListFields, isInitialization); + b.end(); + b.startElseBlock(); + createUpdateOrInitializeNodeAt(b, successorFields, successorListFields, isInitialization); + b.end(); + genClass.add(method); + checkOnlyInGenNode(method); + } + + private void createGetNodeAt(CodeTreeBuilder b, List nodes, List nodeLists) { + boolean hasNodes = !nodes.isEmpty(); + boolean hasNodeLists = !nodeLists.isEmpty(); + if (!hasNodeLists && !hasNodes) { + b.startThrow().startNew(getType(NoSuchElementException.class)).end().end(); + } else { + if (hasNodes) { + if (!hasNodeLists) { + b.startAssert().string("pos.getSubIndex() == NOT_ITERABLE").end(); + } else { + b.startIf().string("pos.getSubIndex() == NOT_ITERABLE").end().startBlock(); + } + b.declaration("int", "at", "pos.getIndex()"); + createGetFieldCases(b, nodes, Node.asType(), null); + if (hasNodeLists) { + b.end(); + } + } + + if (hasNodeLists) { + if (!hasNodes) { + b.startAssert().string("pos.getSubIndex() != NOT_ITERABLE").end(); + } else { + b.startElseBlock(); + } + b.declaration("int", "at", "pos.getIndex() - " + nodes.size()); + createGetFieldCases(b, nodeLists, Node.asType(), ".get(pos.getSubIndex())"); + if (hasNodes) { + b.end(); + } + } + } + } + + private void createGetNodeListAt(CodeTreeBuilder b, List nodes, List nodeLists) { + boolean hasNodeLists = !nodeLists.isEmpty(); + if (!hasNodeLists) { + b.startThrow().startNew(getType(NoSuchElementException.class)).end().end(); + } else { + b.startAssert().string("pos.getSubIndex() == NODE_LIST").end(); + b.declaration("int", "at", "pos.getIndex() - " + nodes.size()); + createGetFieldCases(b, nodeLists, Node.asType(), ""); + } + } + + private void createSetNodeListAt(CodeTreeBuilder b, List nodes, List nodeLists) { + boolean hasNodeLists = !nodeLists.isEmpty(); + if (!hasNodeLists) { + b.startThrow().startNew(getType(NoSuchElementException.class)).end().end(); + } else { + b.startAssert().string("pos.getSubIndex() == NODE_LIST").end(); + b.declaration("int", "at", "pos.getIndex() - " + nodes.size()); + createSetNodeListAtCases(b, nodeLists, Node.asType(), ""); + } + } + + private void createGetNameOf(CodeTreeBuilder b, List nodes, List nodeLists) { + boolean hasNodes = !nodes.isEmpty(); + boolean hasNodeLists = !nodeLists.isEmpty(); + if (hasNodeLists || hasNodes) { + int index = 0; + for (VariableElement f : nodes) { + b.startIf().string("pos.getIndex() == " + index).end().startBlock(); + b.startStatement().string("return \"" + f.getSimpleName() + "\"").end(); + b.end(); + index++; + } + for (VariableElement f : nodeLists) { + b.startIf().string("pos.getIndex() == " + index).end().startBlock(); + b.startStatement().string("return \"" + f.getSimpleName() + "\"").end(); + b.end(); + index++; + } + } + b.startThrow().startNew(getType(NoSuchElementException.class)).end().end(); + } + + private void createUpdateOrInitializeNodeAt(CodeTreeBuilder b, List nodes, List nodeLists, boolean isInitialization) { + boolean hasNodes = !nodes.isEmpty(); + boolean hasNodeLists = !nodeLists.isEmpty(); + if (nodes.isEmpty() && nodeLists.isEmpty()) { + b.startThrow().startNew(getType(NoSuchElementException.class)).end().end(); + } else { + if (hasNodes) { + if (!hasNodeLists) { + b.startAssert().string("pos.getSubIndex() == NOT_ITERABLE").end(); + } else { + b.startIf().string("pos.getSubIndex() == NOT_ITERABLE").end().startBlock(); + } + b.declaration("int", "at", "pos.getIndex()"); + createUpdateOrInitializeFieldCases(b, nodes, isInitialization, false); + if (hasNodeLists) { + b.end(); + } + } + + if (hasNodeLists) { + if (!hasNodes) { + b.startAssert().string("pos.getSubIndex() != NOT_ITERABLE").end(); + } else { + b.startElseBlock(); + } + b.declaration("int", "at", "pos.getIndex() - " + nodes.size()); + createUpdateOrInitializeFieldCases(b, nodeLists, isInitialization, true); + if (hasNodes) { + b.end(); + } + } + } + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeProcessor.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodeinfo.processor; + +import java.io.*; +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; +import javax.tools.Diagnostic.Kind; + +import com.oracle.graal.nodeinfo.*; +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.java.model.*; +import com.oracle.truffle.dsl.processor.java.transform.*; + +@SupportedSourceVersion(SourceVersion.RELEASE_8) +@SupportedAnnotationTypes({"com.oracle.graal.nodeinfo.NodeInfo"}) +public class GraphNodeProcessor extends AbstractProcessor { + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + + void errorMessage(Element element, String format, Object... args) { + message(Kind.ERROR, element, format, args); + } + + void message(Kind kind, Element element, String format, Object... args) { + processingEnv.getMessager().printMessage(kind, String.format(format, args), element); + } + + /** + * Bugs in an annotation processor can cause silent failure so try to report any exception + * throws as errors. + */ + private void reportException(Element element, Throwable t) { + StringWriter buf = new StringWriter(); + t.printStackTrace(new PrintWriter(buf)); + buf.toString(); + errorMessage(element, "Exception thrown during processing: %s", buf.toString()); + } + + ProcessingEnvironment getProcessingEnv() { + return processingEnv; + } + + boolean isNodeType(Element element) { + if (element.getKind() != ElementKind.CLASS) { + return false; + } + TypeElement type = (TypeElement) element; + Types types = processingEnv.getTypeUtils(); + + while (type != null) { + if (type.toString().equals("com.oracle.graal.graph.Node")) { + return true; + } + type = (TypeElement) types.asElement(type.getSuperclass()); + } + return false; + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + if (roundEnv.processingOver()) { + return false; + } + + GraphNodeGenerator gen = new GraphNodeGenerator(this); + + for (Element element : roundEnv.getElementsAnnotatedWith(NodeInfo.class)) { + try { + if (!isNodeType(element)) { + errorMessage(element, "%s can only be applied to Node subclasses", NodeInfo.class.getSimpleName()); + continue; + } + + NodeInfo nodeInfo = element.getAnnotation(NodeInfo.class); + if (nodeInfo == null) { + errorMessage(element, "Cannot get %s annotation from annotated element", NodeInfo.class.getSimpleName()); + continue; + } + + TypeElement typeElement = (TypeElement) element; + + if (typeElement.getModifiers().contains(Modifier.FINAL)) { + errorMessage(element, "%s annotated class must not be final", NodeInfo.class.getSimpleName()); + continue; + } + + if (!typeElement.equals(gen.Node) && !typeElement.getModifiers().contains(Modifier.ABSTRACT)) { + CodeCompilationUnit unit = gen.process(typeElement); + unit.setGeneratorElement(typeElement); + + DeclaredType overrideType = (DeclaredType) ElementUtils.getType(processingEnv, Override.class); + DeclaredType unusedType = (DeclaredType) ElementUtils.getType(processingEnv, SuppressWarnings.class); + unit.accept(new GenerateOverrideVisitor(overrideType), null); + unit.accept(new FixWarningsVisitor(processingEnv, unusedType, overrideType), null); + unit.accept(new CodeWriter(processingEnv, typeElement), null); + } + } catch (ElementException ee) { + errorMessage(ee.element, ee.getMessage()); + } catch (Throwable t) { + if (!isBug367599(t)) { + reportException(element, t); + } else { + message(Kind.NOTE, element, t.toString()); + } + } + } + return false; + } + + /** + * Determines if a given exception is (most likely) caused by Bug 367599. + */ + public static boolean isBug367599(Throwable t) { + for (StackTraceElement ste : t.getStackTrace()) { + if (ste.toString().contains("org.eclipse.jdt.internal.apt.pluggable.core.filer.IdeFilerImpl.create")) { + // See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=367599 + return true; + } + } + if (t.getCause() != null) { + return isBug367599(t.getCause()); + } + return false; + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodeinfo/src/com/oracle/graal/nodeinfo/GeneratedNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodeinfo/src/com/oracle/graal/nodeinfo/GeneratedNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodeinfo; + +import java.lang.annotation.*; + +/** + * Denotes a Node subclass generated on the basis of a {@link NodeInfo} annotation on a Node type. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface GeneratedNode { + + /** + * The Node class from which the annotated type was generated. + */ + Class value(); +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodeinfo/src/com/oracle/graal/nodeinfo/InputType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodeinfo/src/com/oracle/graal/nodeinfo/InputType.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodeinfo; + +public enum InputType { + /** + * Inputs that consume an actual value generated by the referenced node. + */ + Value, + /** + * Inputs that consume the memory state of the referenced node. + */ + Memory, + /** + * Inputs that reference a condition. + */ + Condition, + /** + * Inputs that reference a frame state. + */ + State, + /** + * Inputs that reference a guard (guards, begin nodes). + */ + Guard, + /** + * Inputs that reference an anchor (begin nodes, value anchors). + */ + Anchor, + /** + * Inputs that represent an association between nodes, e.g., a phi and the merge or a loop begin + * and loop exits and ends. + */ + Association, + /** + * Inputs that connect tightly coupled nodes, e.g., an InvokeNode and its CallTargetNode. + */ + Extension, + /** + * Inputs of this type are temporarily exempt from type checking. This should only be used in + * exceptional cases and should never survive to later stages of compilation. + */ + Unchecked +} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodeinfo/src/com/oracle/graal/nodeinfo/NodeInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodeinfo/src/com/oracle/graal/nodeinfo/NodeInfo.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodeinfo; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface NodeInfo { + + String shortName() default ""; + + /** + * The template used to build the {@link Verbosity#Name} version. Variable part are specified + * using {i#inputName} or {p#propertyName}. + */ + String nameTemplate() default ""; + + InputType[] allowedUsageTypes() default {}; +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodeinfo/src/com/oracle/graal/nodeinfo/Verbosity.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodeinfo/src/com/oracle/graal/nodeinfo/Verbosity.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodeinfo; + +public enum Verbosity { + /** + * Only the id of the node. + */ + Id, + /** + * Only the name of the node, which may contain some more information for certain node types + * (constants, ...). + */ + Name, + /** + * {@link #Id} + {@link #Name}. + */ + Short, + /** + * Defaults to {@link #Short} and may be enhanced by subclasses. + */ + Long, + /** + * For use by a custom formatting facility in an IDE. + */ + Debugger, + /** + * All the other information plus all debug properties of the node. + */ + All +} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/LoopPhiCanonicalizerTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -56,7 +56,7 @@ @Test public void test() { - StructuredGraph graph = parse("loopSnippet"); + StructuredGraph graph = parseEager("loopSnippet"); NodePredicate loopPhis = node -> node instanceof PhiNode && ((PhiNode) node).merge() instanceof LoopBeginNode; PhaseContext context = new PhaseContext(getProviders(), null); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/NegateNodeCanonicalizationTest.java --- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/NegateNodeCanonicalizationTest.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/NegateNodeCanonicalizationTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -48,7 +48,7 @@ for (byte i : a) { ConstantNode node = ConstantNode.forByte(i, graph); Constant expected = Constant.forInt(-i); - assertEquals(expected, new NegateNode(node).evalConst(node.asConstant())); + assertEquals(expected, NegateNode.create(node).evalConst(node.asConstant())); } } @@ -58,7 +58,7 @@ for (char i : a) { ConstantNode node = ConstantNode.forChar(i, graph); Constant expected = Constant.forInt(-i); - assertEquals(expected, new NegateNode(node).evalConst(node.asConstant())); + assertEquals(expected, NegateNode.create(node).evalConst(node.asConstant())); } } @@ -68,7 +68,7 @@ for (short i : a) { ConstantNode node = ConstantNode.forShort(i, graph); Constant expected = Constant.forInt(-i); - assertEquals(expected, new NegateNode(node).evalConst(node.asConstant())); + assertEquals(expected, NegateNode.create(node).evalConst(node.asConstant())); } } @@ -78,7 +78,7 @@ for (int i : a) { ConstantNode node = ConstantNode.forInt(i, graph); Constant expected = Constant.forInt(-i); - assertEquals(expected, new NegateNode(node).evalConst(node.asConstant())); + assertEquals(expected, NegateNode.create(node).evalConst(node.asConstant())); } } @@ -88,7 +88,7 @@ for (long i : a) { ConstantNode node = ConstantNode.forLong(i, graph); Constant expected = Constant.forLong(-i); - assertEquals(expected, new NegateNode(node).evalConst(node.asConstant())); + assertEquals(expected, NegateNode.create(node).evalConst(node.asConstant())); } } @@ -98,7 +98,7 @@ for (float i : a) { ConstantNode node = ConstantNode.forFloat(i, graph); Constant expected = Constant.forFloat(-i); - assertEquals(expected, new NegateNode(node).evalConst(node.asConstant())); + assertEquals(expected, NegateNode.create(node).evalConst(node.asConstant())); } } @@ -108,7 +108,7 @@ for (double i : a) { ConstantNode node = ConstantNode.forDouble(i, graph); Constant expected = Constant.forDouble(-i); - assertEquals(expected, new NegateNode(node).evalConst(node.asConstant())); + assertEquals(expected, NegateNode.create(node).evalConst(node.asConstant())); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; /** * This node represents an unconditional explicit request for immediate deoptimization. @@ -32,9 +33,10 @@ * After this node, execution will continue using a fallback execution engine (such as an * interpreter) at the position described by the {@link #stateBefore() deoptimization state}. */ +@NodeInfo public abstract class AbstractDeoptimizeNode extends ControlSinkNode implements IterableNodeType, DeoptimizingNode.DeoptBefore { - @OptionalInput(InputType.State) private FrameState stateBefore; + @OptionalInput(InputType.State) FrameState stateBefore; public AbstractDeoptimizeNode() { super(StampFactory.forVoid()); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,8 +26,10 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public abstract class AbstractEndNode extends FixedNode implements IterableNodeType, LIRLowerable { protected AbstractEndNode() { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,14 +24,15 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.util.*; +@NodeInfo public abstract class AbstractFixedGuardNode extends DeoptimizingFixedWithNextNode implements Simplifiable, GuardingNode { - @Input(InputType.Condition) private LogicNode condition; + @Input(InputType.Condition) LogicNode condition; private final DeoptimizationReason reason; private final DeoptimizationAction action; private boolean negated; @@ -84,17 +85,17 @@ } public DeoptimizeNode lowerToIf() { - FixedNode next = next(); + FixedNode currentNext = next(); setNext(null); - DeoptimizeNode deopt = graph().add(new DeoptimizeNode(action, reason)); + DeoptimizeNode deopt = graph().add(DeoptimizeNode.create(action, reason)); deopt.setStateBefore(stateBefore()); IfNode ifNode; BeginNode noDeoptSuccessor; if (negated) { - ifNode = graph().add(new IfNode(condition, deopt, next, 0)); + ifNode = graph().add(IfNode.create(condition, deopt, currentNext, 0)); noDeoptSuccessor = ifNode.falseSuccessor(); } else { - ifNode = graph().add(new IfNode(condition, next, deopt, 1)); + ifNode = graph().add(IfNode.create(condition, currentNext, deopt, 1)); noDeoptSuccessor = ifNode.trueSuccessor(); } ((FixedWithNextNode) predecessor()).setNext(ifNode); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractLocalNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractLocalNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractLocalNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,8 +23,10 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; +@NodeInfo public abstract class AbstractLocalNode extends FloatingNode { private final int index; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMemoryCheckpoint.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMemoryCheckpoint.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMemoryCheckpoint.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,11 +23,13 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.extended.*; /** * Provides an implementation of {@link StateSplit}. */ +@NodeInfo public abstract class AbstractMemoryCheckpoint extends AbstractStateSplit implements MemoryCheckpoint { protected AbstractMemoryCheckpoint(Stamp stamp) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,14 +23,15 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; /** * Provides an implementation of {@link StateSplit}. */ +@NodeInfo public abstract class AbstractStateSplit extends FixedWithNextNode implements StateSplit { - @OptionalInput(InputType.State) private FrameState stateAfter; + @OptionalInput(InputType.State) protected FrameState stateAfter; public FrameState stateAfter() { return stateAfter; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -30,6 +30,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; @@ -37,11 +38,23 @@ @NodeInfo(allowedUsageTypes = {InputType.Guard, InputType.Anchor}) public class BeginNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, GuardingNode, AnchoringNode, IterableNodeType { - public BeginNode() { + public static BeginNode create() { + return USE_GENERATED_NODES ? new BeginNodeGen() : new BeginNode(); + } + + public static Class getGenClass() { + return USE_GENERATED_NODES ? BeginNodeGen.class : BeginNode.class; + } + + protected BeginNode() { super(StampFactory.forVoid()); } - public BeginNode(Stamp stamp) { + public static BeginNode create(Stamp stamp) { + return USE_GENERATED_NODES ? new BeginNodeGen(stamp) : new BeginNode(stamp); + } + + protected BeginNode(Stamp stamp) { super(stamp); } @@ -49,7 +62,7 @@ if (with instanceof BeginNode) { return (BeginNode) with; } - BeginNode begin = with.graph().add(new BeginNode()); + BeginNode begin = with.graph().add(BeginNode.create()); begin.setNext(with); return begin; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,7 +23,7 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; /** * Base class for {@link BeginNode}s that are associated with a frame state. @@ -32,9 +32,10 @@ * which is not possible until loop peeling works without requiring begin nodes to have frames * states. */ +@NodeInfo public abstract class BeginStateSplitNode extends BeginNode implements StateSplit { - @OptionalInput(InputType.State) private FrameState stateAfter; + @OptionalInput(InputType.State) protected FrameState stateAfter; public BeginStateSplitNode() { } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,12 +23,14 @@ package com.oracle.graal.nodes; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public abstract class BinaryOpLogicNode extends LogicNode implements LIRLowerable, Canonicalizable.Binary { - @Input private ValueNode x; - @Input private ValueNode y; + @Input protected ValueNode x; + @Input protected ValueNode y; public ValueNode getX() { return x; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,6 +24,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; /** @@ -33,22 +34,27 @@ * are set up as if the breakpoint instruction was a call to a compiled Java method. *

    * A breakpoint is usually place by defining a node intrinsic method as follows: - * + * *

      *     {@literal @}NodeIntrinsic(BreakpointNode.class)
      *     static void breakpoint(Object object, Word mark, Word value) {
      *          throw new GraalInternalError("");
      *     }
      * 
    - * + * * Note that the signature is arbitrary. It's sole purpose is to capture values you may want to * inspect in the native debugger when the breakpoint is hit. */ -public final class BreakpointNode extends FixedWithNextNode implements LIRLowerable { +@NodeInfo +public class BreakpointNode extends FixedWithNextNode implements LIRLowerable { + + @Input NodeInputList arguments; - @Input private final NodeInputList arguments; + public static BreakpointNode create(ValueNode[] arguments) { + return USE_GENERATED_NODES ? new BreakpointNodeGen(arguments) : new BreakpointNode(arguments); + } - public BreakpointNode(ValueNode... arguments) { + protected BreakpointNode(ValueNode... arguments) { super(StampFactory.forVoid()); this.arguments = new NodeInputList<>(this, arguments); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,6 +27,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(allowedUsageTypes = {InputType.Extension}) @@ -42,7 +43,7 @@ } } - @Input private final NodeInputList arguments; + @Input protected NodeInputList arguments; private ResolvedJavaMethod targetMethod; private InvokeKind invokeKind; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,20 +25,29 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(nameTemplate = "ConditionAnchor(!={p#negated})", allowedUsageTypes = {InputType.Guard}) -public final class ConditionAnchorNode extends FixedWithNextNode implements Canonicalizable.Unary, Lowerable, GuardingNode { +public class ConditionAnchorNode extends FixedWithNextNode implements Canonicalizable.Unary, Lowerable, GuardingNode { - @Input(InputType.Condition) private LogicNode condition; + @Input(InputType.Condition) LogicNode condition; private boolean negated; - public ConditionAnchorNode(LogicNode condition) { + public static ConditionAnchorNode create(LogicNode condition) { + return USE_GENERATED_NODES ? new ConditionAnchorNodeGen(condition) : new ConditionAnchorNode(condition); + } + + protected ConditionAnchorNode(LogicNode condition) { this(condition, false); } - public ConditionAnchorNode(LogicNode condition, boolean negated) { + public static ConditionAnchorNode create(LogicNode condition, boolean negated) { + return USE_GENERATED_NODES ? new ConditionAnchorNodeGen(condition, negated) : new ConditionAnchorNode(condition, negated); + } + + protected ConditionAnchorNode(LogicNode condition, boolean negated) { super(StampFactory.forVoid()); this.negated = negated; this.condition = condition; @@ -64,14 +73,14 @@ public Node canonical(CanonicalizerTool tool, Node forValue) { if (condition instanceof LogicNegationNode) { LogicNegationNode negation = (LogicNegationNode) condition; - return new ConditionAnchorNode(negation.getValue(), !negated); + return ConditionAnchorNode.create(negation.getValue(), !negated); } if (condition instanceof LogicConstantNode) { LogicConstantNode c = (LogicConstantNode) condition; if (c.getValue() != negated) { return null; } else { - return new ValueAnchorNode(null); + return ValueAnchorNode.create(null); } } return this; @@ -80,7 +89,7 @@ @Override public void lower(LoweringTool tool) { if (graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { - ValueAnchorNode newAnchor = graph().add(new ValueAnchorNode(null)); + ValueAnchorNode newAnchor = graph().add(ValueAnchorNode.create(null)); graph().replaceFixedWithFixed(this, newAnchor); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -30,6 +30,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -37,7 +38,7 @@ * The {@code ConstantNode} represents a {@link Constant constant}. */ @NodeInfo(shortName = "Const", nameTemplate = "Const({p#rawvalue})") -public final class ConstantNode extends FloatingNode implements LIRLowerable { +public class ConstantNode extends FloatingNode implements LIRLowerable { private static final DebugMetric ConstantNodes = Debug.metric("ConstantNodes"); @@ -45,7 +46,7 @@ private static ConstantNode createPrimitive(Constant value) { assert value.getKind() != Kind.Object; - return new ConstantNode(value, StampFactory.forConstant(value)); + return ConstantNode.create(value, StampFactory.forConstant(value)); } /** @@ -53,6 +54,10 @@ * * @param value the constant */ + public static ConstantNode create(Constant value, Stamp stamp) { + return USE_GENERATED_NODES ? new ConstantNodeGen(value, stamp) : new ConstantNode(value, stamp); + } + protected ConstantNode(Constant value, Stamp stamp) { super(stamp); assert stamp != null; @@ -108,7 +113,7 @@ return forInt(constant.asInt(), graph); } if (constant.getKind() == Kind.Object) { - return unique(graph, new ConstantNode(constant, StampFactory.forConstant(constant, metaAccess))); + return unique(graph, ConstantNode.create(constant, StampFactory.forConstant(constant, metaAccess))); } else { return unique(graph, createPrimitive(constant)); } @@ -119,18 +124,18 @@ return forInt(constant.asInt()); } if (constant.getKind() == Kind.Object) { - return new ConstantNode(constant, StampFactory.forConstant(constant, metaAccess)); + return ConstantNode.create(constant, StampFactory.forConstant(constant, metaAccess)); } else { return createPrimitive(constant); } } public static ConstantNode forConstant(Stamp stamp, Constant constant, MetaAccessProvider metaAccess, StructuredGraph graph) { - return graph.unique(new ConstantNode(constant, stamp.constant(constant, metaAccess))); + return graph.unique(ConstantNode.create(constant, stamp.constant(constant, metaAccess))); } public static ConstantNode forConstant(Stamp stamp, Constant constant, MetaAccessProvider metaAccess) { - return new ConstantNode(constant, stamp.constant(constant, metaAccess)); + return ConstantNode.create(constant, stamp.constant(constant, metaAccess)); } /** @@ -314,7 +319,7 @@ private static ConstantNode forIntegerBits(int bits, Constant constant, StructuredGraph graph) { long value = constant.asLong(); long bounds = SignExtendNode.signExtend(value, bits); - return unique(graph, new ConstantNode(constant, StampFactory.forInteger(bits, bounds, bounds))); + return unique(graph, ConstantNode.create(constant, StampFactory.forInteger(bits, bounds, bounds))); } /** @@ -328,7 +333,7 @@ private static ConstantNode forIntegerBits(int bits, Constant constant) { long value = constant.asLong(); long bounds = SignExtendNode.signExtend(value, bits); - return new ConstantNode(constant, StampFactory.forInteger(bits, bounds, bounds)); + return ConstantNode.create(constant, StampFactory.forInteger(bits, bounds, bounds)); } /** diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,7 +23,9 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; +@NodeInfo public abstract class ControlSinkNode extends FixedNode { public ControlSinkNode(Stamp stamp) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,11 +24,13 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; /** * The {@code ControlSplitNode} is a base class for all instructions that split the control flow * (ie. have more than one successor). */ +@NodeInfo public abstract class ControlSplitNode extends FixedNode implements IterableNodeType { public ControlSplitNode(Stamp stamp) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,7 +23,7 @@ package com.oracle.graal.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}") @@ -34,11 +34,19 @@ private final int debugId; private final Constant speculation; - public DeoptimizeNode(DeoptimizationAction action, DeoptimizationReason reason) { + public static DeoptimizeNode create(DeoptimizationAction action, DeoptimizationReason reason) { + return USE_GENERATED_NODES ? new DeoptimizeNodeGen(action, reason) : new DeoptimizeNode(action, reason); + } + + protected DeoptimizeNode(DeoptimizationAction action, DeoptimizationReason reason) { this(action, reason, 0, Constant.NULL_OBJECT, null); } - public DeoptimizeNode(DeoptimizationAction action, DeoptimizationReason reason, int debugId, Constant speculation, FrameState stateBefore) { + public static DeoptimizeNode create(DeoptimizationAction action, DeoptimizationReason reason, int debugId, Constant speculation, FrameState stateBefore) { + return USE_GENERATED_NODES ? new DeoptimizeNodeGen(action, reason, debugId, speculation, stateBefore) : new DeoptimizeNode(action, reason, debugId, speculation, stateBefore); + } + + protected DeoptimizeNode(DeoptimizationAction action, DeoptimizationReason reason, int debugId, Constant speculation, FrameState stateBefore) { super(stateBefore); assert action != null; assert reason != null; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,11 +23,12 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; +@NodeInfo public abstract class DeoptimizingFixedWithNextNode extends FixedWithNextNode implements DeoptimizingNode.DeoptBefore { - @OptionalInput(InputType.State) private FrameState stateBefore; + @OptionalInput(InputType.State) protected FrameState stateBefore; public DeoptimizingFixedWithNextNode(Stamp stamp) { super(stamp); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,10 +27,17 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; +@NodeInfo public class DirectCallTargetNode extends LoweredCallTargetNode { - public DirectCallTargetNode(List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType, InvokeKind invokeKind) { + public static DirectCallTargetNode create(List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType, InvokeKind invokeKind) { + return USE_GENERATED_NODES ? new DirectCallTargetNodeGen(arguments, returnStamp, signature, target, callType, invokeKind) : new DirectCallTargetNode(arguments, returnStamp, signature, target, + callType, invokeKind); + } + + protected DirectCallTargetNode(List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType, InvokeKind invokeKind) { super(arguments, returnStamp, signature, target, callType, invokeKind); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DispatchBeginNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DispatchBeginNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DispatchBeginNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,13 +23,23 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; /** * The entry node of an exception dispatcher block. */ +@NodeInfo public class DispatchBeginNode extends BeginStateSplitNode { - public DispatchBeginNode() { + public static DispatchBeginNode create() { + return USE_GENERATED_NODES ? new DispatchBeginNodeGen() : new DispatchBeginNode(); + } + + protected DispatchBeginNode() { + } + + public static DispatchBeginNode create(Stamp stamp) { + return USE_GENERATED_NODES ? new DispatchBeginNodeGen(stamp) : new DispatchBeginNode(stamp); } protected DispatchBeginNode(Stamp stamp) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,13 +25,19 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public class DynamicDeoptimizeNode extends AbstractDeoptimizeNode implements LIRLowerable, Canonicalizable { - @Input private ValueNode actionAndReason; - @Input private ValueNode speculation; + @Input ValueNode actionAndReason; + @Input ValueNode speculation; - public DynamicDeoptimizeNode(ValueNode actionAndReason, ValueNode speculation) { + public static DynamicDeoptimizeNode create(ValueNode actionAndReason, ValueNode speculation) { + return USE_GENERATED_NODES ? new DynamicDeoptimizeNodeGen(actionAndReason, speculation) : new DynamicDeoptimizeNode(actionAndReason, speculation); + } + + protected DynamicDeoptimizeNode(ValueNode actionAndReason, ValueNode speculation) { this.actionAndReason = actionAndReason; this.speculation = speculation; } @@ -63,8 +69,8 @@ if (actionAndReason.isConstant() && speculation.isConstant()) { Constant constant = actionAndReason.asConstant(); Constant speculationConstant = speculation.asConstant(); - DeoptimizeNode newDeopt = new DeoptimizeNode(tool.getMetaAccess().decodeDeoptAction(constant), tool.getMetaAccess().decodeDeoptReason(constant), tool.getMetaAccess().decodeDebugId( - constant), speculationConstant, stateBefore()); + DeoptimizeNode newDeopt = DeoptimizeNode.create(tool.getMetaAccess().decodeDeoptAction(constant), tool.getMetaAccess().decodeDeoptReason(constant), + tool.getMetaAccess().decodeDebugId(constant), speculationConstant, stateBefore()); return newDeopt; } return this; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,8 +22,18 @@ */ package com.oracle.graal.nodes; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; @NodeInfo(allowedUsageTypes = {InputType.Association}) -public final class EndNode extends AbstractEndNode { +public class EndNode extends AbstractEndNode { + public static EndNode create() { + return USE_GENERATED_NODES ? new EndNodeGen() : new EndNode(); + } + + public static Class getGenClass() { + return USE_GENERATED_NODES ? EndNodeGen.class : EndNode.class; + } + + EndNode() { + } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; /** @@ -34,6 +35,13 @@ @NodeInfo(allowedUsageTypes = {InputType.Association}) public class EntryMarkerNode extends BeginStateSplitNode implements IterableNodeType, Simplifiable, LIRLowerable { + public static EntryMarkerNode create() { + return USE_GENERATED_NODES ? new EntryMarkerNodeGen() : new EntryMarkerNode(); + } + + EntryMarkerNode() { + } + @Override public void simplify(SimplifierTool tool) { // this node should not be removed, this overrides BeginNode.simplify diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,17 +25,26 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}", allowedUsageTypes = {InputType.Guard}) -public final class FixedGuardNode extends AbstractFixedGuardNode implements Lowerable, IterableNodeType { +public class FixedGuardNode extends AbstractFixedGuardNode implements Lowerable, IterableNodeType { - public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action) { + public static FixedGuardNode create(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action) { + return USE_GENERATED_NODES ? new FixedGuardNodeGen(condition, deoptReason, action) : new FixedGuardNode(condition, deoptReason, action); + } + + protected FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action) { this(condition, deoptReason, action, false); } - public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) { + public static FixedGuardNode create(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) { + return USE_GENERATED_NODES ? new FixedGuardNodeGen(condition, deoptReason, action, negated) : new FixedGuardNode(condition, deoptReason, action, negated); + } + + protected FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) { super(condition, deoptReason, action, negated); } @@ -46,12 +55,12 @@ if (condition() instanceof LogicConstantNode) { LogicConstantNode c = (LogicConstantNode) condition(); if (c.getValue() == isNegated()) { - FixedNode next = this.next(); - if (next != null) { - tool.deleteBranch(next); + FixedNode currentNext = this.next(); + if (currentNext != null) { + tool.deleteBranch(currentNext); } - DeoptimizeNode deopt = graph().add(new DeoptimizeNode(getAction(), getReason())); + DeoptimizeNode deopt = graph().add(DeoptimizeNode.create(getAction(), getReason())); deopt.setStateBefore(stateBefore()); setNext(deopt); } @@ -65,7 +74,7 @@ if (graph().getGuardsStage() == StructuredGraph.GuardsStage.FLOATING_GUARDS) { ValueNode guard = tool.createGuard(this, condition(), getReason(), getAction(), isNegated()).asNode(); this.replaceAtUsages(guard); - ValueAnchorNode newAnchor = graph().add(new ValueAnchorNode(guard.asNode())); + ValueAnchorNode newAnchor = graph().add(ValueAnchorNode.create(guard.asNode())); graph().replaceFixedWithFixed(this, newAnchor); } else { lowerToIf().lower(tool); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,7 +23,9 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; +@NodeInfo public abstract class FixedNode extends ValueNode { public FixedNode(Stamp stamp) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,14 +23,16 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; /** * Base class of all nodes that are fixed within the control flow graph and have an immediate * successor. */ +@NodeInfo public abstract class FixedWithNextNode extends FixedNode { - @Successor private FixedNode next; + @Successor protected FixedNode next; public FixedNode next() { return next; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingAnchoredNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingAnchoredNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingAnchoredNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,13 +23,14 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; +@NodeInfo public abstract class FloatingAnchoredNode extends FloatingNode { - @Input(InputType.Anchor) private AnchoringNode anchor; + @Input(InputType.Anchor) AnchoringNode anchor; public FloatingAnchoredNode(Stamp stamp) { super(stamp); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,13 +23,14 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; +@NodeInfo public abstract class FloatingGuardedNode extends FloatingNode implements GuardedNode { - @OptionalInput(InputType.Guard) private GuardingNode guard; + @OptionalInput(InputType.Guard) protected GuardingNode guard; public FloatingGuardedNode(Stamp stamp) { super(stamp); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Mon Aug 25 21:15:59 2014 -0700 @@ -29,6 +29,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.virtual.*; @@ -39,7 +40,7 @@ * This can be used as debug or deoptimization information. */ @NodeInfo(nameTemplate = "FrameState@{p#method/s}:{p#bci}") -public final class FrameState extends VirtualState implements IterableNodeType { +public class FrameState extends VirtualState implements IterableNodeType { private static final DebugMetric METRIC_FRAMESTATE_COUNT = Debug.metric("FrameStateCount"); @@ -54,16 +55,16 @@ private boolean duringCall; - @OptionalInput(value = InputType.State) private FrameState outerFrameState; + @OptionalInput(value = InputType.State) FrameState outerFrameState; /** * Contains the locals, the expressions and the locked objects, in this order. */ - @OptionalInput private final NodeInputList values; + @OptionalInput NodeInputList values; - @OptionalInput(InputType.Association) private final NodeInputList monitorIds; + @OptionalInput(InputType.Association) NodeInputList monitorIds; - @Input(InputType.State) private final NodeInputList virtualObjectMappings; + @Input(InputType.State) NodeInputList virtualObjectMappings; /** * The bytecode index to which this frame state applies. @@ -86,7 +87,13 @@ * @param monitorIds one MonitorIdNode for each locked object * @param virtualObjectMappings a description of the current state for every virtual object */ - public FrameState(FrameState outerFrameState, ResolvedJavaMethod method, int bci, List values, int localsSize, int stackSize, boolean rethrowException, boolean duringCall, + public static FrameState create(FrameState outerFrameState, ResolvedJavaMethod method, int bci, List values, int localsSize, int stackSize, boolean rethrowException, + boolean duringCall, List monitorIds, List virtualObjectMappings) { + return USE_GENERATED_NODES ? new FrameStateGen(outerFrameState, method, bci, values, localsSize, stackSize, rethrowException, duringCall, monitorIds, virtualObjectMappings) : new FrameState( + outerFrameState, method, bci, values, localsSize, stackSize, rethrowException, duringCall, monitorIds, virtualObjectMappings); + } + + protected FrameState(FrameState outerFrameState, ResolvedJavaMethod method, int bci, List values, int localsSize, int stackSize, boolean rethrowException, boolean duringCall, List monitorIds, List virtualObjectMappings) { assert stackSize >= 0; this.outerFrameState = outerFrameState; @@ -109,13 +116,23 @@ * * @param bci marker bci, needs to be < 0 */ - public FrameState(int bci) { + public static FrameState create(int bci) { + return USE_GENERATED_NODES ? new FrameStateGen(bci) : new FrameState(bci); + } + + protected FrameState(int bci) { this(null, null, bci, Collections. emptyList(), 0, 0, false, false, Collections. emptyList(), Collections. emptyList()); assert bci == BytecodeFrame.BEFORE_BCI || bci == BytecodeFrame.AFTER_BCI || bci == BytecodeFrame.AFTER_EXCEPTION_BCI || bci == BytecodeFrame.UNKNOWN_BCI || bci == BytecodeFrame.INVALID_FRAMESTATE_BCI; } - public FrameState(ResolvedJavaMethod method, int bci, ValueNode[] locals, List stack, ValueNode[] locks, MonitorIdNode[] monitorIds, boolean rethrowException, boolean duringCall) { + public static FrameState create(ResolvedJavaMethod method, int bci, ValueNode[] locals, List stack, ValueNode[] locks, MonitorIdNode[] monitorIds, boolean rethrowException, + boolean duringCall) { + return USE_GENERATED_NODES ? new FrameStateGen(method, bci, locals, stack, locks, monitorIds, rethrowException, duringCall) : new FrameState(method, bci, locals, stack, locks, monitorIds, + rethrowException, duringCall); + } + + protected FrameState(ResolvedJavaMethod method, int bci, ValueNode[] locals, List stack, ValueNode[] locks, MonitorIdNode[] monitorIds, boolean rethrowException, boolean duringCall) { this(null, method, bci, createValues(locals, stack, locks), locals.length, stack.size(), rethrowException, duringCall, Arrays.asList(monitorIds), Collections. emptyList()); } @@ -192,7 +209,7 @@ * Gets a copy of this frame state. */ public FrameState duplicate(int newBci) { - return graph().add(new FrameState(outerFrameState(), method, newBci, values, localsSize, stackSize, rethrowException, duringCall, monitorIds, virtualObjectMappings)); + return graph().add(FrameState.create(outerFrameState(), method, newBci, values, localsSize, stackSize, rethrowException, duringCall, monitorIds, virtualObjectMappings)); } /** @@ -216,7 +233,7 @@ for (EscapeObjectState state : virtualObjectMappings) { newVirtualMappings.add(state.duplicateWithVirtualState()); } - return graph().add(new FrameState(newOuterFrameState, method, bci, values, localsSize, stackSize, rethrowException, duringCall, monitorIds, newVirtualMappings)); + return graph().add(FrameState.create(newOuterFrameState, method, bci, values, localsSize, stackSize, rethrowException, duringCall, monitorIds, newVirtualMappings)); } /** @@ -256,7 +273,7 @@ int newStackSize = copy.size() - localsSize; copy.addAll(values.subList(localsSize + stackSize, values.size())); - return graph().add(new FrameState(outerFrameState(), newMethod, newBci, copy, localsSize, newStackSize, newRethrowException, false, monitorIds, virtualObjectMappings)); + return graph().add(FrameState.create(outerFrameState(), newMethod, newBci, copy, localsSize, newStackSize, newRethrowException, false, monitorIds, virtualObjectMappings)); } /** diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FullInfopointNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FullInfopointNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FullInfopointNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,16 +23,21 @@ package com.oracle.graal.nodes; import com.oracle.graal.api.code.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; /** * Nodes of this type are inserted into the graph to denote points of interest to debugging. */ +@NodeInfo public class FullInfopointNode extends InfopointNode implements LIRLowerable, NodeWithState { - @Input(InputType.State) private FrameState state; + @Input(InputType.State) FrameState state; - public FullInfopointNode(InfopointReason reason, FrameState state) { + public static FullInfopointNode create(InfopointReason reason, FrameState state) { + return USE_GENERATED_NODES ? new FullInfopointNodeGen(reason, state) : new FullInfopointNode(reason, state); + } + + protected FullInfopointNode(InfopointReason reason, FrameState state) { super(reason); this.state = state; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.extended.*; /** @@ -43,13 +44,17 @@ @NodeInfo(nameTemplate = "Guard(!={p#negated}) {p#reason/s}", allowedUsageTypes = {InputType.Guard}) public class GuardNode extends FloatingAnchoredNode implements Canonicalizable, IterableNodeType, GuardingNode { - @Input(InputType.Condition) private LogicNode condition; + @Input(InputType.Condition) LogicNode condition; private final DeoptimizationReason reason; private Constant speculation; private DeoptimizationAction action; private boolean negated; - public GuardNode(LogicNode condition, AnchoringNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated, Constant speculation) { + public static GuardNode create(LogicNode condition, AnchoringNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated, Constant speculation) { + return USE_GENERATED_NODES ? new GuardNodeGen(condition, anchor, reason, action, negated, speculation) : new GuardNode(condition, anchor, reason, action, negated, speculation); + } + + protected GuardNode(LogicNode condition, AnchoringNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated, Constant speculation) { super(StampFactory.forVoid(), anchor); this.condition = condition; this.reason = reason; @@ -98,7 +103,7 @@ public Node canonical(CanonicalizerTool tool) { if (condition() instanceof LogicNegationNode) { LogicNegationNode negation = (LogicNegationNode) condition(); - return new GuardNode(negation.getValue(), getAnchor(), reason, action, !negated, speculation); + return GuardNode.create(negation.getValue(), getAnchor(), reason, action, !negated, speculation); } if (condition() instanceof LogicConstantNode) { LogicConstantNode c = (LogicConstantNode) condition(); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,6 +24,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.extended.*; /** @@ -32,14 +33,22 @@ @NodeInfo(nameTemplate = "GuardPhi({i#values})", allowedUsageTypes = {InputType.Guard}) public class GuardPhiNode extends PhiNode implements GuardingNode { - @OptionalInput(InputType.Guard) final NodeInputList values; + @OptionalInput(InputType.Guard) NodeInputList values; - public GuardPhiNode(MergeNode merge) { + public static GuardPhiNode create(MergeNode merge) { + return USE_GENERATED_NODES ? new GuardPhiNodeGen(merge) : new GuardPhiNode(merge); + } + + protected GuardPhiNode(MergeNode merge) { super(StampFactory.forVoid(), merge); this.values = new NodeInputList<>(this); } - public GuardPhiNode(MergeNode merge, ValueNode[] values) { + public static GuardPhiNode create(MergeNode merge, ValueNode[] values) { + return USE_GENERATED_NODES ? new GuardPhiNodeGen(merge, values) : new GuardPhiNode(merge, values); + } + + protected GuardPhiNode(MergeNode merge, ValueNode[] values) { super(StampFactory.forVoid(), merge); this.values = new NodeInputList<>(this, values); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,15 +24,20 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(allowedUsageTypes = {InputType.Guard}) public class GuardProxyNode extends ProxyNode implements GuardingNode, Proxy, LIRLowerable { - @Input(InputType.Guard) private GuardingNode value; + @Input(InputType.Guard) GuardingNode value; - public GuardProxyNode(GuardingNode value, BeginNode proxyPoint) { + public static GuardProxyNode create(GuardingNode value, BeginNode proxyPoint) { + return USE_GENERATED_NODES ? new GuardProxyNodeGen(value, proxyPoint) : new GuardProxyNode(value, proxyPoint); + } + + protected GuardProxyNode(GuardingNode value, BeginNode proxyPoint) { super(StampFactory.forVoid(), proxyPoint); this.value = value; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -35,18 +36,27 @@ * * A GuardedValueNode will only go away if its guard is null or {@link StructuredGraph#start()}. */ +@NodeInfo public class GuardedValueNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, IterableNodeType, Canonicalizable, ValueProxy { - @Input private ValueNode object; + @Input ValueNode object; private final Stamp piStamp; - public GuardedValueNode(ValueNode object, GuardingNode guard, Stamp stamp) { + public static GuardedValueNode create(ValueNode object, GuardingNode guard, Stamp stamp) { + return USE_GENERATED_NODES ? new GuardedValueNodeGen(object, guard, stamp) : new GuardedValueNode(object, guard, stamp); + } + + protected GuardedValueNode(ValueNode object, GuardingNode guard, Stamp stamp) { super(stamp, guard); this.object = object; this.piStamp = stamp; } - public GuardedValueNode(ValueNode object, GuardingNode guard) { + public static GuardedValueNode create(ValueNode object, GuardingNode guard) { + return USE_GENERATED_NODES ? new GuardedValueNodeGen(object, guard) : new GuardedValueNode(object, guard); + } + + protected GuardedValueNode(ValueNode object, GuardingNode guard) { this(object, guard, object.stamp()); } @@ -83,7 +93,7 @@ if (stamp().equals(object().stamp())) { return object(); } else { - return new PiNode(object(), stamp()); + return PiNode.create(object(), stamp()); } } return this; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -37,8 +38,8 @@ @NodeInfo(nameTemplate = "GuardingPi(!={p#negated}) {p#reason/s}") public class GuardingPiNode extends FixedWithNextNode implements Lowerable, Virtualizable, Canonicalizable, ValueProxy { - @Input private ValueNode object; - @Input(InputType.Condition) private LogicNode condition; + @Input ValueNode object; + @Input(InputType.Condition) LogicNode condition; private final DeoptimizationReason reason; private final DeoptimizationAction action; private final Stamp piStamp; @@ -67,8 +68,12 @@ /** * Constructor for {@link #guardingNonNull(Object)} node intrinsic. */ - private GuardingPiNode(ValueNode object) { - this(object, object.graph().unique(new IsNullNode(object)), true, DeoptimizationReason.NullCheckException, DeoptimizationAction.None, object.stamp().join(StampFactory.objectNonNull())); + public static GuardingPiNode create(ValueNode object) { + return USE_GENERATED_NODES ? new GuardingPiNodeGen(object) : new GuardingPiNode(object); + } + + GuardingPiNode(ValueNode object) { + this(object, object.graph().unique(IsNullNode.create(object)), true, DeoptimizationReason.NullCheckException, DeoptimizationAction.None, object.stamp().join(StampFactory.objectNonNull())); } /** @@ -79,7 +84,11 @@ * @param negateCondition the guard succeeds if {@code condition != negateCondition} * @param stamp the refined type of the object if the guard succeeds */ - public GuardingPiNode(ValueNode object, ValueNode condition, boolean negateCondition, DeoptimizationReason reason, DeoptimizationAction action, Stamp stamp) { + public static GuardingPiNode create(ValueNode object, ValueNode condition, boolean negateCondition, DeoptimizationReason reason, DeoptimizationAction action, Stamp stamp) { + return USE_GENERATED_NODES ? new GuardingPiNodeGen(object, condition, negateCondition, reason, action, stamp) : new GuardingPiNode(object, condition, negateCondition, reason, action, stamp); + } + + protected GuardingPiNode(ValueNode object, ValueNode condition, boolean negateCondition, DeoptimizationReason reason, DeoptimizationAction action, Stamp stamp) { super(stamp); assert stamp != null; this.piStamp = stamp; @@ -93,9 +102,9 @@ @Override public void lower(LoweringTool tool) { GuardingNode guard = tool.createGuard(next(), condition, reason, action, negated); - ValueAnchorNode anchor = graph().add(new ValueAnchorNode((ValueNode) guard)); + ValueAnchorNode anchor = graph().add(ValueAnchorNode.create((ValueNode) guard)); if (usages().isNotEmpty()) { - PiNode pi = graph().unique(new PiNode(object, stamp(), (ValueNode) guard)); + PiNode pi = graph().unique(PiNode.create(object, stamp(), (ValueNode) guard)); replaceAtUsages(pi); } graph().replaceFixedWithFixed(this, anchor); @@ -118,19 +127,19 @@ public Node canonical(CanonicalizerTool tool) { if (stamp() == StampFactory.illegal(object.getKind())) { // The guard always fails - return new DeoptimizeNode(action, reason); + return DeoptimizeNode.create(action, reason); } if (condition instanceof LogicConstantNode) { LogicConstantNode c = (LogicConstantNode) condition; if (c.getValue() == negated) { // The guard always fails - return new DeoptimizeNode(action, reason); + return DeoptimizeNode.create(action, reason); } else if (stamp().equals(object().stamp())) { // The guard always succeeds, and does not provide new type information return object; } else { // The guard always succeeds, and provides new type information - return new PiNode(object, stamp()); + return PiNode.create(object, stamp()); } } return this; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -34,6 +34,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; @@ -43,11 +44,12 @@ * The {@code IfNode} represents a branch that can go one of two directions depending on the outcome * of a comparison. */ -public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable { +@NodeInfo +public class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable { - @Successor private BeginNode trueSuccessor; - @Successor private BeginNode falseSuccessor; - @Input(InputType.Condition) private LogicNode condition; + @Successor BeginNode trueSuccessor; + @Successor BeginNode falseSuccessor; + @Input(InputType.Condition) LogicNode condition; private double trueSuccessorProbability; public LogicNode condition() { @@ -59,11 +61,19 @@ condition = x; } - public IfNode(LogicNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double trueSuccessorProbability) { + public static IfNode create(LogicNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double trueSuccessorProbability) { + return USE_GENERATED_NODES ? new IfNodeGen(condition, trueSuccessor, falseSuccessor, trueSuccessorProbability) : new IfNode(condition, trueSuccessor, falseSuccessor, trueSuccessorProbability); + } + + protected IfNode(LogicNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double trueSuccessorProbability) { this(condition, BeginNode.begin(trueSuccessor), BeginNode.begin(falseSuccessor), trueSuccessorProbability); } - public IfNode(LogicNode condition, BeginNode trueSuccessor, BeginNode falseSuccessor, double trueSuccessorProbability) { + public static IfNode create(LogicNode condition, BeginNode trueSuccessor, BeginNode falseSuccessor, double trueSuccessorProbability) { + return USE_GENERATED_NODES ? new IfNodeGen(condition, trueSuccessor, falseSuccessor, trueSuccessorProbability) : new IfNode(condition, trueSuccessor, falseSuccessor, trueSuccessorProbability); + } + + protected IfNode(LogicNode condition, BeginNode trueSuccessor, BeginNode falseSuccessor, double trueSuccessorProbability) { super(StampFactory.forVoid()); this.condition = condition; this.falseSuccessor = falseSuccessor; @@ -141,7 +151,7 @@ setTrueSuccessor(null); setFalseSuccessor(null); LogicNegationNode negation = (LogicNegationNode) condition(); - IfNode newIfNode = graph().add(new IfNode(negation.getValue(), falseSucc, trueSucc, 1 - trueSuccessorProbability)); + IfNode newIfNode = graph().add(IfNode.create(negation.getValue(), falseSucc, trueSucc, 1 - trueSuccessorProbability)); predecessor().replaceFirstSuccessor(this, newIfNode); GraphUtil.killWithUnusedFloatingInputs(this); return; @@ -210,7 +220,8 @@ do { BeginNode trueSucc = trueSuccessor(); BeginNode falseSucc = falseSuccessor(); - if (trueSucc.getClass() == BeginNode.class && falseSucc.getClass() == BeginNode.class && trueSucc.next() instanceof FixedWithNextNode && falseSucc.next() instanceof FixedWithNextNode) { + if (trueSucc.getClass() == BeginNode.getGenClass() && falseSucc.getClass() == BeginNode.getGenClass() && trueSucc.next() instanceof FixedWithNextNode && + falseSucc.next() instanceof FixedWithNextNode) { FixedWithNextNode trueNext = (FixedWithNextNode) trueSucc.next(); FixedWithNextNode falseNext = (FixedWithNextNode) falseSucc.next(); NodeClass nodeClass = trueNext.getNodeClass(); @@ -222,7 +233,7 @@ graph().addBeforeFixed(this, trueNext); for (Node usage : trueNext.usages().snapshot()) { if (usage.isAlive()) { - if (usage.getNodeClass().valueNumberable() && !usage.getNodeClass().isLeafNode()) { + if (usage.getNodeClass().valueNumberable() && !usage.isLeafNode()) { Node newNode = graph().findDuplicate(usage); if (newNode != null) { usage.replaceAtUsages(newNode); @@ -266,7 +277,7 @@ */ if (lessThan2.getX() == lessThan.getX() && lessThan2.getY().stamp() instanceof IntegerStamp && ((IntegerStamp) lessThan2.getY().stamp()).isPositive() && sameDestination(trueSuccessor(), ifNode2.falseSuccessor)) { - below = graph().unique(new IntegerBelowNode(lessThan2.getX(), lessThan2.getY())); + below = graph().unique(IntegerBelowNode.create(lessThan2.getX(), lessThan2.getY())); // swap direction BeginNode tmp = falseSucc; falseSucc = trueSucc; @@ -281,14 +292,14 @@ Constant positive = lessThan2.getX().asConstant(); if (positive != null && positive.asLong() > 0 && positive.asLong() < positive.getKind().getMaxValue()) { ConstantNode newLimit = ConstantNode.forIntegerKind(positive.getKind(), positive.asLong() + 1, graph()); - below = graph().unique(new IntegerBelowNode(lessThan.getX(), newLimit)); + below = graph().unique(IntegerBelowNode.create(lessThan.getX(), newLimit)); } } if (below != null) { ifNode2.setTrueSuccessor(null); ifNode2.setFalseSuccessor(null); - IfNode newIfNode = graph().add(new IfNode(below, falseSucc, trueSucc, 1 - trueSuccessorProbability)); + IfNode newIfNode = graph().add(IfNode.create(below, falseSucc, trueSucc, 1 - trueSuccessorProbability)); // Remove the < 0 test. tool.deleteBranch(trueSuccessor); graph().removeSplit(this, falseSuccessor); @@ -525,7 +536,7 @@ } } } - ReturnNode newReturn = graph().add(new ReturnNode(value)); + ReturnNode newReturn = graph().add(ReturnNode.create(value)); replaceAtPredecessor(newReturn); GraphUtil.killCFG(this); return true; @@ -547,7 +558,7 @@ return null; } if (trueValue.isConstant() && falseValue.isConstant()) { - return graph().unique(new ConditionalNode(condition(), trueValue, falseValue)); + return graph().unique(ConditionalNode.create(condition(), trueValue, falseValue)); } else { ConditionalNode conditional = null; ValueNode constant = null; @@ -577,7 +588,7 @@ if (otherValue.isConstant()) { double shortCutProbability = probability(trueSuccessor()); LogicNode newCondition = LogicNode.or(condition(), negateCondition, conditional.condition(), negateConditionalCondition, shortCutProbability); - return graph().unique(new ConditionalNode(newCondition, constant, otherValue)); + return graph().unique(ConditionalNode.create(newCondition, constant, otherValue)); } } return null; @@ -832,9 +843,9 @@ } else { // Need a new phi in case the frame state is used by more than the merge being // removed - MergeNode newMerge = graph().add(new MergeNode()); + MergeNode newMerge = graph().add(MergeNode.create()); PhiNode oldPhi = (PhiNode) oldMerge.usages().first(); - PhiNode newPhi = graph().addWithoutUnique(new ValuePhiNode(oldPhi.stamp(), newMerge)); + PhiNode newPhi = graph().addWithoutUnique(ValuePhiNode.create(oldPhi.stamp(), newMerge)); for (AbstractEndNode end : ends) { newPhi.addInput(phiValues.get(end)); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,12 +27,20 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; +@NodeInfo public class IndirectCallTargetNode extends LoweredCallTargetNode { - @Input private ValueNode computedAddress; + @Input protected ValueNode computedAddress; - public IndirectCallTargetNode(ValueNode computedAddress, List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType, + public static IndirectCallTargetNode create(ValueNode computedAddress, List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, + CallingConvention.Type callType, InvokeKind invokeKind) { + return USE_GENERATED_NODES ? new IndirectCallTargetNodeGen(computedAddress, arguments, returnStamp, signature, target, callType, invokeKind) : new IndirectCallTargetNode(computedAddress, + arguments, returnStamp, signature, target, callType, invokeKind); + } + + protected IndirectCallTargetNode(ValueNode computedAddress, List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType, InvokeKind invokeKind) { super(arguments, returnStamp, signature, target, callType, invokeKind); this.computedAddress = computedAddress; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,7 +24,9 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; +@NodeInfo public abstract class InfopointNode extends FixedWithNextNode { private final InfopointReason reason; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,7 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.CallTargetNode.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,6 +27,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; @@ -36,11 +37,11 @@ * The {@code InvokeNode} represents all kinds of method calls. */ @NodeInfo(nameTemplate = "Invoke#{p#targetMethod/s}", allowedUsageTypes = {InputType.Memory}) -public final class InvokeNode extends AbstractMemoryCheckpoint implements Invoke, LIRLowerable, MemoryCheckpoint.Single, IterableNodeType { +public class InvokeNode extends AbstractMemoryCheckpoint implements Invoke, LIRLowerable, MemoryCheckpoint.Single, IterableNodeType { - @Input(InputType.Extension) private CallTargetNode callTarget; - @OptionalInput(InputType.State) private FrameState stateDuring; - @OptionalInput(InputType.Guard) private GuardingNode guard; + @Input(InputType.Extension) CallTargetNode callTarget; + @OptionalInput(InputType.State) FrameState stateDuring; + @OptionalInput(InputType.Guard) GuardingNode guard; private final int bci; private boolean polymorphic; private boolean useForInlining; @@ -51,7 +52,11 @@ * @param callTarget the target method being called * @param bci the bytecode index of the original invoke (used for debug infos) */ - public InvokeNode(CallTargetNode callTarget, int bci) { + public static InvokeNode create(CallTargetNode callTarget, int bci) { + return USE_GENERATED_NODES ? new InvokeNodeGen(callTarget, bci) : new InvokeNode(callTarget, bci); + } + + protected InvokeNode(CallTargetNode callTarget, int bci) { this(callTarget, bci, callTarget.returnStamp()); } @@ -62,7 +67,11 @@ * @param bci the bytecode index of the original invoke (used for debug infos) * @param stamp the stamp to be used for this value */ - public InvokeNode(CallTargetNode callTarget, int bci, Stamp stamp) { + public static InvokeNode create(CallTargetNode callTarget, int bci, Stamp stamp) { + return USE_GENERATED_NODES ? new InvokeNodeGen(callTarget, bci, stamp) : new InvokeNode(callTarget, bci, stamp); + } + + protected InvokeNode(CallTargetNode callTarget, int bci, Stamp stamp) { super(stamp); this.callTarget = callTarget; this.bci = bci; @@ -150,10 +159,10 @@ public void intrinsify(Node node) { assert !(node instanceof ValueNode) || node.isAllowedUsageType(InputType.Value) == isAllowedUsageType(InputType.Value) : "replacing " + this + " with " + node; CallTargetNode call = callTarget; - FrameState stateAfter = stateAfter(); + FrameState currentStateAfter = stateAfter(); if (node instanceof StateSplit) { StateSplit stateSplit = (StateSplit) node; - stateSplit.setStateAfter(stateAfter); + stateSplit.setStateAfter(currentStateAfter); } if (node instanceof FixedWithNextNode) { graph().replaceFixedWithFixed(this, (FixedWithNextNode) node); @@ -166,8 +175,8 @@ graph().replaceFixed(this, node); } GraphUtil.killWithUnusedFloatingInputs(call); - if (stateAfter.usages().isEmpty()) { - GraphUtil.killWithUnusedFloatingInputs(stateAfter); + if (currentStateAfter.usages().isEmpty()) { + GraphUtil.killWithUnusedFloatingInputs(currentStateAfter); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; @@ -36,18 +37,22 @@ private static final double EXCEPTION_PROBA = 1e-5; - @Successor private BeginNode next; - @Successor private BeginNode exceptionEdge; - @Input(InputType.Extension) private CallTargetNode callTarget; - @OptionalInput(InputType.State) private FrameState stateDuring; - @OptionalInput(InputType.State) private FrameState stateAfter; - @OptionalInput(InputType.Guard) private GuardingNode guard; + @Successor BeginNode next; + @Successor BeginNode exceptionEdge; + @Input(InputType.Extension) CallTargetNode callTarget; + @OptionalInput(InputType.State) FrameState stateDuring; + @OptionalInput(InputType.State) FrameState stateAfter; + @OptionalInput(InputType.Guard) GuardingNode guard; private final int bci; private boolean polymorphic; private boolean useForInlining; private double exceptionProbability; - public InvokeWithExceptionNode(CallTargetNode callTarget, BeginNode exceptionEdge, int bci) { + public static InvokeWithExceptionNode create(CallTargetNode callTarget, BeginNode exceptionEdge, int bci) { + return USE_GENERATED_NODES ? new InvokeWithExceptionNodeGen(callTarget, exceptionEdge, bci) : new InvokeWithExceptionNode(callTarget, exceptionEdge, bci); + } + + protected InvokeWithExceptionNode(CallTargetNode callTarget, BeginNode exceptionEdge, int bci) { super(callTarget.returnStamp()); this.exceptionEdge = exceptionEdge; this.bci = bci; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,7 +23,7 @@ package com.oracle.graal.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.extended.*; @NodeInfo(allowedUsageTypes = {InputType.Memory}) @@ -31,7 +31,11 @@ private LocationIdentity locationIdentity; - public KillingBeginNode(LocationIdentity locationIdentity) { + public static KillingBeginNode create(LocationIdentity locationIdentity) { + return USE_GENERATED_NODES ? new KillingBeginNodeGen(locationIdentity) : new KillingBeginNode(locationIdentity); + } + + protected KillingBeginNode(LocationIdentity locationIdentity) { this.locationIdentity = locationIdentity; } @@ -39,7 +43,7 @@ if (with instanceof KillingBeginNode) { return (KillingBeginNode) with; } - KillingBeginNode begin = with.graph().add(new KillingBeginNode(locationIdentity)); + KillingBeginNode begin = with.graph().add(KillingBeginNode.create(locationIdentity)); begin.setNext(with); return begin; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicConstantNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicConstantNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicConstantNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; /** @@ -33,6 +34,10 @@ public final boolean value; + public static LogicConstantNode create(boolean value) { + return USE_GENERATED_NODES ? new LogicConstantNodeGen(value) : new LogicConstantNode(value); + } + protected LogicConstantNode(boolean value) { super(); this.value = value; @@ -46,7 +51,7 @@ * @return a node representing the boolean */ public static LogicConstantNode forBoolean(boolean v, Graph graph) { - return graph.unique(new LogicConstantNode(v)); + return graph.unique(LogicConstantNode.create(v)); } /** @@ -56,7 +61,7 @@ * @return a node representing the boolean */ public static LogicConstantNode forBoolean(boolean v) { - return new LogicConstantNode(v); + return LogicConstantNode.create(v); } /** diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNegationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNegationNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNegationNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,17 +22,22 @@ */ package com.oracle.graal.nodes; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; /** * Logic node that negates its argument. */ +@NodeInfo public class LogicNegationNode extends LogicNode implements Canonicalizable.Unary { - @Input(InputType.Condition) private LogicNode value; + @Input(InputType.Condition) LogicNode value; - public LogicNegationNode(LogicNode value) { + public static LogicNegationNode create(LogicNode value) { + return USE_GENERATED_NODES ? new LogicNegationNodeGen(value) : new LogicNegationNode(value); + } + + protected LogicNegationNode(LogicNode value) { this.value = value; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,10 +22,10 @@ */ package com.oracle.graal.nodes; -import static com.oracle.graal.graph.InputType.*; +import static com.oracle.graal.nodeinfo.InputType.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; @NodeInfo(allowedUsageTypes = {Condition}) @@ -41,8 +41,8 @@ public static LogicNode and(LogicNode a, boolean negateA, LogicNode b, boolean negateB, double shortCircuitProbability) { StructuredGraph graph = a.graph(); - ShortCircuitOrNode notAorNotB = graph.unique(new ShortCircuitOrNode(a, !negateA, b, !negateB, shortCircuitProbability)); - return graph.unique(new LogicNegationNode(notAorNotB)); + ShortCircuitOrNode notAorNotB = graph.unique(ShortCircuitOrNode.create(a, !negateA, b, !negateB, shortCircuitProbability)); + return graph.unique(LogicNegationNode.create(notAorNotB)); } public static LogicNode or(LogicNode a, LogicNode b, double shortCircuitProbability) { @@ -50,6 +50,6 @@ } public static LogicNode or(LogicNode a, boolean negateA, LogicNode b, boolean negateB, double shortCircuitProbability) { - return a.graph().unique(new ShortCircuitOrNode(a, negateA, b, negateB, shortCircuitProbability)); + return a.graph().unique(ShortCircuitOrNode.create(a, negateA, b, negateB, shortCircuitProbability)); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -29,19 +29,25 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; +@NodeInfo public class LoopBeginNode extends MergeNode implements IterableNodeType, LIRLowerable { private double loopFrequency; private int nextEndIndex; private int unswitches; - @OptionalInput(InputType.Guard) private GuardingNode overflowGuard; + @OptionalInput(InputType.Guard) GuardingNode overflowGuard; - public LoopBeginNode() { + public static LoopBeginNode create() { + return USE_GENERATED_NODES ? new LoopBeginNodeGen() : new LoopBeginNode(); + } + + protected LoopBeginNode() { loopFrequency = 1; } @@ -187,10 +193,10 @@ public void removeExits() { for (LoopExitNode loopexit : loopExits().snapshot()) { loopexit.removeProxies(); - FrameState stateAfter = loopexit.stateAfter(); - graph().replaceFixedWithFixed(loopexit, graph().add(new BeginNode())); - if (stateAfter != null && stateAfter.isAlive() && stateAfter.usages().isEmpty()) { - GraphUtil.killWithUnusedFloatingInputs(stateAfter); + FrameState loopStateAfter = loopexit.stateAfter(); + graph().replaceFixedWithFixed(loopexit, graph().add(BeginNode.create())); + if (loopStateAfter != null && loopStateAfter.isAlive() && loopStateAfter.usages().isEmpty()) { + GraphUtil.killWithUnusedFloatingInputs(loopStateAfter); } } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,15 +25,21 @@ import java.util.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; -public final class LoopEndNode extends AbstractEndNode { +@NodeInfo +public class LoopEndNode extends AbstractEndNode { - @Input(InputType.Association) private LoopBeginNode loopBegin; + @Input(InputType.Association) LoopBeginNode loopBegin; private boolean canSafepoint; private int endIndex; - public LoopEndNode(LoopBeginNode begin) { + public static LoopEndNode create(LoopBeginNode begin) { + return USE_GENERATED_NODES ? new LoopEndNodeGen(begin) : new LoopEndNode(begin); + } + + protected LoopEndNode(LoopBeginNode begin) { int idx = begin.nextEndIndex(); assert idx >= 0; this.endIndex = idx; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopExitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopExitNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopExitNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,13 +24,18 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; @NodeInfo(allowedUsageTypes = {InputType.Association}) public class LoopExitNode extends BeginStateSplitNode implements IterableNodeType { - @Input(InputType.Association) private LoopBeginNode loopBegin; + @Input(InputType.Association) LoopBeginNode loopBegin; - public LoopExitNode(LoopBeginNode loop) { + public static LoopExitNode create(LoopBeginNode loop) { + return USE_GENERATED_NODES ? new LoopExitNodeGen(loop) : new LoopExitNode(loop); + } + + protected LoopExitNode(LoopBeginNode loop) { assert loop != null; loopBegin = loop; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoweredCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoweredCallTargetNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoweredCallTargetNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,7 +27,9 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; +@NodeInfo public abstract class LoweredCallTargetNode extends CallTargetNode { private final Stamp returnStamp; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -29,6 +29,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -37,7 +38,7 @@ public class MemoryMapNode extends FloatingNode implements MemoryMap, LIRLowerable { private final List locationIdentities; - @Input(InputType.Memory) private final NodeInputList nodes; + @Input(InputType.Memory) NodeInputList nodes; private boolean checkOrder(Map mmap) { for (int i = 0; i < locationIdentities.size(); i++) { @@ -48,7 +49,11 @@ return true; } - public MemoryMapNode(Map mmap) { + public static MemoryMapNode create(Map mmap) { + return USE_GENERATED_NODES ? new MemoryMapNodeGen(mmap) : new MemoryMapNode(mmap); + } + + protected MemoryMapNode(Map mmap) { super(StampFactory.forVoid()); locationIdentities = new ArrayList<>(mmap.keySet()); nodes = new NodeInputList<>(this, mmap.values()); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.extended.*; /** @@ -33,16 +34,24 @@ @NodeInfo(nameTemplate = "MemoryPhi({i#values}) {p#locationIdentity/s}", allowedUsageTypes = {InputType.Memory}) public class MemoryPhiNode extends PhiNode implements MemoryNode { - @Input(InputType.Memory) final NodeInputList values; + @Input(InputType.Memory) NodeInputList values; private final LocationIdentity locationIdentity; - public MemoryPhiNode(MergeNode merge, LocationIdentity locationIdentity) { + public static MemoryPhiNode create(MergeNode merge, LocationIdentity locationIdentity) { + return USE_GENERATED_NODES ? new MemoryPhiNodeGen(merge, locationIdentity) : new MemoryPhiNode(merge, locationIdentity); + } + + protected MemoryPhiNode(MergeNode merge, LocationIdentity locationIdentity) { super(StampFactory.forVoid(), merge); this.locationIdentity = locationIdentity; this.values = new NodeInputList<>(this); } - public MemoryPhiNode(MergeNode merge, LocationIdentity locationIdentity, ValueNode[] values) { + public static MemoryPhiNode create(MergeNode merge, LocationIdentity locationIdentity, ValueNode[] values) { + return USE_GENERATED_NODES ? new MemoryPhiNodeGen(merge, locationIdentity, values) : new MemoryPhiNode(merge, locationIdentity, values); + } + + protected MemoryPhiNode(MergeNode merge, LocationIdentity locationIdentity, ValueNode[] values) { super(StampFactory.forVoid(), merge); this.locationIdentity = locationIdentity; this.values = new NodeInputList<>(this, values); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -30,6 +30,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; @@ -38,8 +39,18 @@ */ @NodeInfo(allowedUsageTypes = {InputType.Association}) public class MergeNode extends BeginStateSplitNode implements IterableNodeType, LIRLowerable { + public static MergeNode create() { + return USE_GENERATED_NODES ? new MergeNodeGen() : new MergeNode(); + } - @Input(InputType.Association) private final NodeInputList ends = new NodeInputList<>(this); + public static Class getGenClass() { + return USE_GENERATED_NODES ? MergeNodeGen.class : MergeNode.class; + } + + MergeNode() { + } + + @Input(InputType.Association) NodeInputList ends = new NodeInputList<>(this); @Override public void generate(NodeLIRBuilderTool gen) { @@ -138,9 +149,9 @@ */ @Override public void simplify(SimplifierTool tool) { - FixedNode next = next(); - if (next instanceof AbstractEndNode) { - AbstractEndNode origLoopEnd = (AbstractEndNode) next; + FixedNode currentNext = next(); + if (currentNext instanceof AbstractEndNode) { + AbstractEndNode origLoopEnd = (AbstractEndNode) currentNext; MergeNode merge = origLoopEnd.merge(); if (merge instanceof LoopBeginNode && !(origLoopEnd instanceof LoopEndNode)) { return; @@ -168,9 +179,9 @@ } AbstractEndNode newEnd; if (merge instanceof LoopBeginNode) { - newEnd = graph().add(new LoopEndNode((LoopBeginNode) merge)); + newEnd = graph().add(LoopEndNode.create((LoopBeginNode) merge)); } else { - newEnd = graph().add(new EndNode()); + newEnd = graph().add(EndNode.create()); merge.addForwardEnd(newEnd); } for (PhiNode phi : merge.phis()) { @@ -192,8 +203,8 @@ } } graph().reduceTrivialMerge(this); - } else if (next instanceof ReturnNode) { - ReturnNode returnNode = (ReturnNode) next; + } else if (currentNext instanceof ReturnNode) { + ReturnNode returnNode = (ReturnNode) currentNext; if (anchored().isNotEmpty() || returnNode.getMemoryMap() != null) { return; } @@ -209,7 +220,7 @@ ValuePhiNode returnValuePhi = returnNode.result() == null || !isPhiAtMerge(returnNode.result()) ? null : (ValuePhiNode) returnNode.result(); List endNodes = forwardEnds().snapshot(); for (AbstractEndNode end : endNodes) { - ReturnNode newReturn = graph().add(new ReturnNode(returnValuePhi == null ? returnNode.result() : returnValuePhi.valueAt(end))); + ReturnNode newReturn = graph().add(ReturnNode.create(returnValuePhi == null ? returnNode.result() : returnValuePhi.valueAt(end))); if (tool != null) { tool.addToWorkList(end.predecessor()); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,14 +24,19 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; /** * The {@code Parameter} instruction is a placeholder for an incoming argument to a function call. */ @NodeInfo(nameTemplate = "Param({p#index})") -public final class ParameterNode extends AbstractLocalNode implements IterableNodeType { +public class ParameterNode extends AbstractLocalNode implements IterableNodeType { - public ParameterNode(int index, Stamp stamp) { + public static ParameterNode create(int index, Stamp stamp) { + return USE_GENERATED_NODES ? new ParameterNodeGen(index, stamp) : new ParameterNode(index, stamp); + } + + protected ParameterNode(int index, Stamp stamp) { super(index, stamp); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,6 +27,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; /** @@ -35,9 +36,10 @@ * of the ends. For {@link LoopBeginNode}s, the first value corresponds to the loop's predecessor, * while the rest of the values correspond to the {@link LoopEndNode}s. */ +@NodeInfo public abstract class PhiNode extends FloatingNode implements Simplifiable { - @Input(InputType.Association) private MergeNode merge; + @Input(InputType.Association) MergeNode merge; protected PhiNode(Stamp stamp, MergeNode merge) { super(stamp); @@ -137,9 +139,20 @@ values().remove(index); } - public static final ValueNode MULTIPLE_VALUES = new ValueNode(null) { - // empty dummy class - }; + @NodeInfo + static class MultipleValuesNode extends ValueNode { + + public static MultipleValuesNode create() { + return USE_GENERATED_NODES ? new PhiNode_MultipleValuesNodeGen() : new MultipleValuesNode(); + } + + protected MultipleValuesNode() { + super(null); + } + + } + + public static final ValueNode MULTIPLE_VALUES = MultipleValuesNode.create(); /** * If all inputs are the same value, this value is returned, otherwise {@link #MULTIPLE_VALUES}. @@ -202,4 +215,4 @@ return merge() instanceof LoopBeginNode; } -} \ No newline at end of file +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; @@ -33,15 +34,20 @@ * that reads the array length, such as an {@link ArrayLengthNode}, can be canonicalized based on * this information. */ -public final class PiArrayNode extends PiNode implements ArrayLengthProvider { +@NodeInfo +public class PiArrayNode extends PiNode implements ArrayLengthProvider { - @Input private ValueNode length; + @Input ValueNode length; public ValueNode length() { return length; } - public PiArrayNode(ValueNode object, ValueNode length, Stamp stamp) { + public static PiArrayNode create(ValueNode object, ValueNode length, Stamp stamp) { + return USE_GENERATED_NODES ? new PiArrayNodeGen(object, length, stamp) : new PiArrayNode(object, length, stamp); + } + + protected PiArrayNode(ValueNode object, ValueNode length, Stamp stamp) { super(object, stamp); this.length = length; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -28,6 +28,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -40,28 +41,41 @@ * is as narrow or narrower than the PiNode's type. The PiNode, and therefore also the scheduling * restriction enforced by the anchor, will go away. */ +@NodeInfo public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, IterableNodeType, Canonicalizable, ValueProxy { - @Input private ValueNode object; + @Input ValueNode object; private final Stamp piStamp; public ValueNode object() { return object; } - public PiNode(ValueNode object, Stamp stamp) { + public static PiNode create(ValueNode object, Stamp stamp) { + return USE_GENERATED_NODES ? new PiNodeGen(object, stamp) : new PiNode(object, stamp); + } + + protected PiNode(ValueNode object, Stamp stamp) { super(stamp); this.piStamp = stamp; this.object = object; } - public PiNode(ValueNode object, Stamp stamp, ValueNode anchor) { + public static PiNode create(ValueNode object, Stamp stamp, ValueNode anchor) { + return USE_GENERATED_NODES ? new PiNodeGen(object, stamp, anchor) : new PiNode(object, stamp, anchor); + } + + protected PiNode(ValueNode object, Stamp stamp, ValueNode anchor) { super(stamp, (GuardingNode) anchor); this.object = object; this.piStamp = stamp; } - public PiNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) { + public static PiNode create(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) { + return USE_GENERATED_NODES ? new PiNodeGen(object, toType, exactType, nonNull) : new PiNode(object, toType, exactType, nonNull); + } + + protected PiNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) { this(object, StampFactory.object(toType, exactType, nonNull || StampTool.isObjectNonNull(object.stamp()))); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.ValueNumberable; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; @@ -32,9 +33,10 @@ * A proxy is inserted at loop exits for any value that is created inside the loop (i.e. was not * live on entry to the loop) and is (potentially) used after the loop. */ +@NodeInfo public abstract class ProxyNode extends FloatingNode implements IterableNodeType, ValueNumberable { - @Input(InputType.Association) private BeginNode proxyPoint; + @Input(InputType.Association) BeginNode proxyPoint; public ProxyNode(Stamp stamp, BeginNode proxyPoint) { super(stamp); @@ -57,10 +59,10 @@ } public static ValueProxyNode forValue(ValueNode value, BeginNode exit, StructuredGraph graph) { - return graph.unique(new ValueProxyNode(value, exit)); + return graph.unique(ValueProxyNode.create(value, exit)); } public static GuardProxyNode forGuard(GuardingNode value, BeginNode exit, StructuredGraph graph) { - return graph.unique(new GuardProxyNode(value, exit)); + return graph.unique(GuardProxyNode.create(value, exit)); } } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,12 +24,14 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; -public final class ReturnNode extends ControlSinkNode implements LIRLowerable, IterableNodeType { +@NodeInfo +public class ReturnNode extends ControlSinkNode implements LIRLowerable, IterableNodeType { - @OptionalInput private ValueNode result; - @OptionalInput(InputType.Extension) private MemoryMapNode memoryMap; + @OptionalInput ValueNode result; + @OptionalInput(InputType.Extension) MemoryMapNode memoryMap; public ValueNode result() { return result; @@ -41,22 +43,25 @@ * @param result the instruction producing the result for this return; {@code null} if this is a * void return */ - public ReturnNode(ValueNode result) { + public static ReturnNode create(ValueNode result) { + return USE_GENERATED_NODES ? new ReturnNodeGen(result) : new ReturnNode(result); + } + + protected ReturnNode(ValueNode result) { this(result, null); } - public ReturnNode(ValueNode result, MemoryMapNode memoryMap) { + public static ReturnNode create(ValueNode result, MemoryMapNode memoryMap) { + return USE_GENERATED_NODES ? new ReturnNodeGen(result, memoryMap) : new ReturnNode(result, memoryMap); + } + + protected ReturnNode(ValueNode result, MemoryMapNode memoryMap) { super(StampFactory.forVoid()); this.result = result; this.memoryMap = memoryMap; } @Override - public boolean verify() { - return super.verify(); - } - - @Override public void generate(NodeLIRBuilderTool gen) { if (this.result() == null) { gen.getLIRGeneratorTool().emitReturn(null); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,14 +23,20 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; /** * Marks a position in the graph where a safepoint should be emitted. */ +@NodeInfo public class SafepointNode extends DeoptimizingFixedWithNextNode implements LIRLowerable { - public SafepointNode() { + public static SafepointNode create() { + return USE_GENERATED_NODES ? new SafepointNodeGen() : new SafepointNode(); + } + + protected SafepointNode() { super(StampFactory.forVoid()); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,7 +23,9 @@ package com.oracle.graal.nodes; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; +@NodeInfo public abstract class ScheduledNode extends Node { @Override diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitOrNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitOrNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitOrNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,16 +24,22 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; +@NodeInfo public class ShortCircuitOrNode extends LogicNode implements IterableNodeType, Canonicalizable.Binary { - @Input(InputType.Condition) private LogicNode x; - @Input(InputType.Condition) private LogicNode y; + @Input(InputType.Condition) LogicNode x; + @Input(InputType.Condition) LogicNode y; private boolean xNegated; private boolean yNegated; private double shortCircuitProbability; - public ShortCircuitOrNode(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, double shortCircuitProbability) { + public static ShortCircuitOrNode create(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, double shortCircuitProbability) { + return USE_GENERATED_NODES ? new ShortCircuitOrNodeGen(x, xNegated, y, yNegated, shortCircuitProbability) : new ShortCircuitOrNode(x, xNegated, y, yNegated, shortCircuitProbability); + } + + protected ShortCircuitOrNode(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, double shortCircuitProbability) { this.x = x; this.xNegated = xNegated; this.y = y; @@ -81,7 +87,7 @@ } if (xCond != forX || yCond != forY) { - return new ShortCircuitOrNode(xCond, xNeg, yCond, yNeg, shortCircuitProbability); + return ShortCircuitOrNode.create(xCond, xNeg, yCond, yNeg, shortCircuitProbability); } else { return this; } @@ -103,7 +109,7 @@ if (isXNegated()) { if (isYNegated()) { // !a || !a = !a - return new LogicNegationNode(forX); + return LogicNegationNode.create(forX); } else { // !a || a = true return LogicConstantNode.tautology(); @@ -123,7 +129,7 @@ return LogicConstantNode.tautology(); } else { if (isYNegated()) { - return new LogicNegationNode(forY); + return LogicNegationNode.create(forY); } else { return forY; } @@ -134,7 +140,7 @@ return LogicConstantNode.tautology(); } else { if (isXNegated()) { - return new LogicNegationNode(forX); + return LogicNegationNode.create(forX); } else { return forX; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SimpleInfopointNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SimpleInfopointNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SimpleInfopointNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,12 +24,18 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public class SimpleInfopointNode extends InfopointNode implements LIRLowerable, IterableNodeType { private BytecodePosition position; - public SimpleInfopointNode(InfopointReason reason, BytecodePosition position) { + public static SimpleInfopointNode create(InfopointReason reason, BytecodePosition position) { + return USE_GENERATED_NODES ? new SimpleInfopointNodeGen(reason, position) : new SimpleInfopointNode(reason, position); + } + + protected SimpleInfopointNode(InfopointReason reason, BytecodePosition position) { super(reason); this.position = position; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,7 +23,7 @@ package com.oracle.graal.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.extended.*; /** @@ -31,6 +31,12 @@ */ @NodeInfo(allowedUsageTypes = {InputType.Memory}) public class StartNode extends BeginStateSplitNode implements MemoryCheckpoint.Single { + public static StartNode create() { + return USE_GENERATED_NODES ? new StartNodeGen() : new StartNode(); + } + + protected StartNode() { + } @Override public LocationIdentity getLocationIdentity() { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Mon Aug 25 21:15:59 2014 -0700 @@ -104,7 +104,7 @@ private StructuredGraph(String name, ResolvedJavaMethod method, long graphId, int entryBCI) { super(name); - this.setStart(add(new StartNode())); + this.setStart(add(StartNode.create())); this.method = method; this.graphId = graphId; this.entryBCI = entryBCI; @@ -374,7 +374,7 @@ if (begin.forwardEndCount() == 1) { // bypass merge and remove reduceTrivialMerge(begin); } else { // convert to merge - MergeNode merge = this.add(new MergeNode()); + MergeNode merge = this.add(MergeNode.create()); this.replaceFixedWithFixed(begin, merge); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -28,6 +28,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -35,13 +36,14 @@ /** * A node that attaches a type profile to a proxied input node. */ -public final class TypeProfileProxyNode extends UnaryNode implements IterableNodeType, ValueProxy { +@NodeInfo +public class TypeProfileProxyNode extends UnaryNode implements IterableNodeType, ValueProxy { private final JavaTypeProfile profile; private transient ResolvedJavaType lastCheckedType; private transient JavaTypeProfile lastCheckedProfile; - public static ValueNode create(ValueNode object, JavaTypeProfile profile) { + public static ValueNode proxify(ValueNode object, JavaTypeProfile profile) { if (StampTool.isExactType(object)) { return object; } @@ -53,10 +55,14 @@ // Only null profiling is not beneficial enough to keep the node around. return object; } - return object.graph().addWithoutUnique(new TypeProfileProxyNode(object, profile)); + return object.graph().addWithoutUnique(create(object, profile)); } - private TypeProfileProxyNode(ValueNode value, JavaTypeProfile profile) { + public static ValueNode create(ValueNode object, JavaTypeProfile profile) { + return USE_GENERATED_NODES ? new TypeProfileProxyNodeGen(object, profile) : new TypeProfileProxyNode(object, profile); + } + + TypeProfileProxyNode(ValueNode value, JavaTypeProfile profile) { super(value.stamp(), value); this.profile = profile; } @@ -91,7 +97,7 @@ } if (newProfile != this.profile) { Debug.log("Improved profile via other profile."); - return new TypeProfileProxyNode(forValue, newProfile); + return TypeProfileProxyNode.create(forValue, newProfile); } } else if (StampTool.typeOrNull(forValue) != null) { ResolvedJavaType type = StampTool.typeOrNull(forValue); @@ -113,7 +119,7 @@ // Only null profiling is not beneficial enough to keep the node around. return forValue; } - return new TypeProfileProxyNode(forValue, newProfile); + return TypeProfileProxyNode.create(forValue, newProfile); } } return this; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnaryOpLogicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnaryOpLogicNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnaryOpLogicNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,11 +23,13 @@ package com.oracle.graal.nodes; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public abstract class UnaryOpLogicNode extends LogicNode implements LIRLowerable, Canonicalizable.Unary { - @Input private ValueNode value; + @Input protected ValueNode value; public ValueNode getValue() { return value; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,20 +24,26 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; /** * Unwinds the current frame to an exception handler in the caller frame. */ -public final class UnwindNode extends ControlSinkNode implements Lowerable, LIRLowerable { +@NodeInfo +public class UnwindNode extends ControlSinkNode implements Lowerable, LIRLowerable { - @Input private ValueNode exception; + @Input ValueNode exception; public ValueNode exception() { return exception; } - public UnwindNode(ValueNode exception) { + public static UnwindNode create(ValueNode exception) { + return USE_GENERATED_NODES ? new UnwindNodeGen(exception) : new UnwindNode(exception); + } + + protected UnwindNode(ValueNode exception) { super(StampFactory.forVoid()); assert exception == null || exception.getKind() == Kind.Object; this.exception = exception; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,13 +24,14 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.nodeinfo.*; /** * This class represents a value within the graph, including local variables, phis, and all other * instructions. */ +@NodeInfo public abstract class ValueNode extends ScheduledNode implements StampProvider, KindProvider { /** diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,7 +26,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Node.Verbosity; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.extended.*; public class ValueNodeUtil { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,6 +24,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.type.*; /** @@ -32,7 +33,7 @@ @NodeInfo(nameTemplate = "ValuePhi({i#values})") public class ValuePhiNode extends PhiNode { - @Input final NodeInputList values; + @Input NodeInputList values; /** * Create a value phi with the specified stamp. @@ -40,7 +41,11 @@ * @param stamp the stamp of the value * @param merge the merge that the new phi belongs to */ - public ValuePhiNode(Stamp stamp, MergeNode merge) { + public static ValuePhiNode create(Stamp stamp, MergeNode merge) { + return USE_GENERATED_NODES ? new ValuePhiNodeGen(stamp, merge) : new ValuePhiNode(stamp, merge); + } + + protected ValuePhiNode(Stamp stamp, MergeNode merge) { super(stamp, merge); assert stamp != StampFactory.forVoid(); values = new NodeInputList<>(this); @@ -53,7 +58,11 @@ * @param merge the merge that the new phi belongs to * @param values the initial values of the phi */ - public ValuePhiNode(Stamp stamp, MergeNode merge, ValueNode[] values) { + public static ValuePhiNode create(Stamp stamp, MergeNode merge, ValueNode[] values) { + return USE_GENERATED_NODES ? new ValuePhiNodeGen(stamp, merge, values) : new ValuePhiNode(stamp, merge, values); + } + + protected ValuePhiNode(Stamp stamp, MergeNode merge, ValueNode[] values) { super(stamp, merge); assert stamp != StampFactory.forVoid(); this.values = new NodeInputList<>(this, values); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,13 +24,19 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public class ValueProxyNode extends ProxyNode implements Canonicalizable, Virtualizable, ValueAndStampProxy { - @Input private ValueNode value; + @Input ValueNode value; - public ValueProxyNode(ValueNode value, BeginNode proxyPoint) { + public static ValueProxyNode create(ValueNode value, BeginNode proxyPoint) { + return USE_GENERATED_NODES ? new ValueProxyNodeGen(value, proxyPoint) : new ValueProxyNode(value, proxyPoint); + } + + protected ValueProxyNode(ValueNode value, BeginNode proxyPoint) { super(value.stamp(), proxyPoint); this.value = value; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; /** * Base class for nodes that contain "virtual" state, like FrameState and VirtualObjectState. diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,18 +24,26 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "&") -public final class AndNode extends BitLogicNode implements NarrowableArithmeticNode { +public class AndNode extends BitLogicNode implements NarrowableArithmeticNode { + + public static AndNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new AndNodeGen(x, y) : new AndNode(x, y); + } - public AndNode(ValueNode x, ValueNode y) { + public static Class getGenClass() { + return USE_GENERATED_NODES ? AndNodeGen.class : AndNode.class; + } + + AndNode(ValueNode x, ValueNode y) { super(StampTool.and(x.stamp(), y.stamp()), x, y); assert x.stamp().isCompatible(y.stamp()); } @@ -57,7 +65,7 @@ return forX; } if (forX.isConstant() && !forY.isConstant()) { - return new AndNode(forY, forX); + return AndNode.create(forY, forX); } if (forX.isConstant()) { return ConstantNode.forPrimitive(stamp(), evalConst(forX.asConstant(), forY.asConstant())); @@ -73,7 +81,7 @@ if (forX instanceof SignExtendNode) { SignExtendNode ext = (SignExtendNode) forX; if (rawY == ((1L << ext.getInputBits()) - 1)) { - return new ZeroExtendNode(ext.getValue(), ext.getResultBits()); + return ZeroExtendNode.create(ext.getValue(), ext.getResultBits()); } } if (forX.stamp() instanceof IntegerStamp) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,15 +26,17 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; /** * The {@code BinaryNode} class is the base of arithmetic and logic operations with two inputs. */ +@NodeInfo public abstract class BinaryNode extends FloatingNode implements Canonicalizable.Binary { - @Input private ValueNode x; - @Input private ValueNode y; + @Input protected ValueNode x; + @Input protected ValueNode y; public ValueNode getX() { return x; @@ -90,7 +92,7 @@ if (stamp instanceof IntegerStamp) { return IntegerArithmeticNode.add(graph, x, y); } else if (stamp instanceof FloatStamp) { - return graph.unique(new FloatAddNode(x, y, false)); + return graph.unique(FloatAddNode.create(x, y, false)); } else { throw GraalInternalError.shouldNotReachHere(); } @@ -102,7 +104,7 @@ if (stamp instanceof IntegerStamp) { return IntegerArithmeticNode.sub(graph, x, y); } else if (stamp instanceof FloatStamp) { - return graph.unique(new FloatSubNode(x, y, false)); + return graph.unique(FloatSubNode.create(x, y, false)); } else { throw GraalInternalError.shouldNotReachHere(); } @@ -114,7 +116,7 @@ if (stamp instanceof IntegerStamp) { return IntegerArithmeticNode.mul(graph, x, y); } else if (stamp instanceof FloatStamp) { - return graph.unique(new FloatMulNode(x, y, false)); + return graph.unique(FloatMulNode.create(x, y, false)); } else { throw GraalInternalError.shouldNotReachHere(); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,12 +23,14 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; /** * The {@code LogicNode} class definition. */ +@NodeInfo public abstract class BitLogicNode extends BinaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode { /** @@ -43,26 +45,26 @@ } public static BitLogicNode and(StructuredGraph graph, ValueNode v1, ValueNode v2) { - return graph.unique(new AndNode(v1, v2)); + return graph.unique(AndNode.create(v1, v2)); } public static BitLogicNode and(ValueNode v1, ValueNode v2) { - return new AndNode(v1, v2); + return AndNode.create(v1, v2); } public static BitLogicNode or(StructuredGraph graph, ValueNode v1, ValueNode v2) { - return graph.unique(new OrNode(v1, v2)); + return graph.unique(OrNode.create(v1, v2)); } public static BitLogicNode or(ValueNode v1, ValueNode v2) { - return new OrNode(v1, v2); + return OrNode.create(v1, v2); } public static BitLogicNode xor(StructuredGraph graph, ValueNode v1, ValueNode v2) { - return graph.unique(new XorNode(v1, v2)); + return graph.unique(XorNode.create(v1, v2)); } public static BitLogicNode xor(ValueNode v1, ValueNode v2) { - return new XorNode(v1, v2); + return XorNode.create(v1, v2); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; /* TODO (thomaswue/gdub) For high-level optimization purpose the compare node should be a boolean *value* (it is currently only a helper node) @@ -34,6 +35,7 @@ * Compare should probably be made a value (so that it can be canonicalized for example) and in later stages some Compare usage should be transformed * into variants that do not materialize the value (CompareIf, CompareGuard...) */ +@NodeInfo public abstract class CompareNode extends BinaryOpLogicNode { /** @@ -76,7 +78,7 @@ return conditionalNode.condition(); } else { assert falseResult == true; - return new LogicNegationNode(conditionalNode.condition()); + return LogicNegationNode.create(conditionalNode.condition()); } } @@ -155,18 +157,18 @@ CompareNode comparison; if (condition == Condition.EQ) { if (x.getKind() == Kind.Object) { - comparison = new ObjectEqualsNode(x, y); + comparison = ObjectEqualsNode.create(x, y); } else { assert x.getKind().isNumericInteger(); - comparison = new IntegerEqualsNode(x, y); + comparison = IntegerEqualsNode.create(x, y); } } else if (condition == Condition.LT) { assert x.getKind().isNumericInteger(); - comparison = new IntegerLessThanNode(x, y); + comparison = IntegerLessThanNode.create(x, y); } else { assert condition == Condition.BT; assert x.getKind().isNumericInteger(); - comparison = new IntegerBelowNode(x, y); + comparison = IntegerBelowNode.create(x, y); } return comparison; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,8 +27,8 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; @@ -37,21 +37,30 @@ * The {@code ConditionalNode} class represents a comparison that yields one of two values. Note * that these nodes are not built directly from the bytecode but are introduced by canonicalization. */ -public final class ConditionalNode extends FloatingNode implements Canonicalizable, LIRLowerable { +@NodeInfo +public class ConditionalNode extends FloatingNode implements Canonicalizable, LIRLowerable { - @Input(InputType.Condition) private LogicNode condition; - @Input private ValueNode trueValue; - @Input private ValueNode falseValue; + @Input(InputType.Condition) LogicNode condition; + @Input ValueNode trueValue; + @Input ValueNode falseValue; public LogicNode condition() { return condition; } - public ConditionalNode(LogicNode condition) { + public static ConditionalNode create(LogicNode condition) { + return USE_GENERATED_NODES ? new ConditionalNodeGen(condition) : new ConditionalNode(condition); + } + + protected ConditionalNode(LogicNode condition) { this(condition, ConstantNode.forInt(1, condition.graph()), ConstantNode.forInt(0, condition.graph())); } - public ConditionalNode(LogicNode condition, ValueNode trueValue, ValueNode falseValue) { + public static ConditionalNode create(LogicNode condition, ValueNode trueValue, ValueNode falseValue) { + return USE_GENERATED_NODES ? new ConditionalNodeGen(condition, trueValue, falseValue) : new ConditionalNode(condition, trueValue, falseValue); + } + + protected ConditionalNode(LogicNode condition, ValueNode trueValue, ValueNode falseValue) { super(trueValue.stamp().meet(falseValue.stamp())); assert trueValue.stamp().isCompatible(falseValue.stamp()); this.condition = condition; @@ -76,7 +85,7 @@ public ValueNode canonical(CanonicalizerTool tool) { if (condition instanceof LogicNegationNode) { LogicNegationNode negated = (LogicNegationNode) condition; - return new ConditionalNode(negated.getValue(), falseValue(), trueValue()); + return ConditionalNode.create(negated.getValue(), falseValue(), trueValue()); } // this optimizes the case where a value that can only be 0 or 1 is materialized to 0 or 1 @@ -118,12 +127,20 @@ generator.emitConditional(this); } - private ConditionalNode(@InjectedNodeParameter StructuredGraph graph, Condition condition, ValueNode x, ValueNode y) { + public static ConditionalNode create(@InjectedNodeParameter StructuredGraph graph, Condition condition, ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new ConditionalNodeGen(graph, condition, x, y) : new ConditionalNode(graph, condition, x, y); + } + + ConditionalNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y) { this(createCompareNode(graph, condition, x, y)); } - private ConditionalNode(ValueNode type, ValueNode object) { - this(type.graph().unique(new InstanceOfDynamicNode(type, object))); + public static ConditionalNode create(ValueNode type, ValueNode object) { + return USE_GENERATED_NODES ? new ConditionalNodeGen(type, object) : new ConditionalNode(type, object); + } + + ConditionalNode(ValueNode type, ValueNode object) { + this(type.graph().unique(InstanceOfDynamicNode.create(type, object))); } @NodeIntrinsic diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,11 +26,13 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; /** * Represents a conversion between primitive types. */ +@NodeInfo public abstract class ConvertNode extends UnaryNode implements ArithmeticOperation { protected ConvertNode(Stamp stamp, ValueNode value) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,12 +24,14 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +@NodeInfo public abstract class FixedBinaryNode extends DeoptimizingFixedWithNextNode implements Canonicalizable.Binary { - @Input private ValueNode x; - @Input private ValueNode y; + @Input ValueNode x; + @Input ValueNode y; public FixedBinaryNode(Stamp stamp, ValueNode x, ValueNode y) { super(stamp); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,13 +26,22 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "+") -public final class FloatAddNode extends FloatArithmeticNode { +public class FloatAddNode extends FloatArithmeticNode { + + public static FloatAddNode create(ValueNode x, ValueNode y, boolean isStrictFP) { + return USE_GENERATED_NODES ? new FloatAddNodeGen(x, y, isStrictFP) : new FloatAddNode(x, y, isStrictFP); + } - public FloatAddNode(ValueNode x, ValueNode y, boolean isStrictFP) { + public static Class getGenClass() { + return USE_GENERATED_NODES ? FloatAddNodeGen.class : FloatAddNode.class; + } + + protected FloatAddNode(ValueNode x, ValueNode y, boolean isStrictFP) { super(x.stamp().unrestricted(), x, y, isStrictFP); } @@ -50,7 +59,7 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { if (forX.isConstant() && !forY.isConstant()) { - return new FloatAddNode(forY, forX, isStrictFP()); + return FloatAddNode.create(forY, forX, isStrictFP()); } if (forX.isConstant()) { return ConstantNode.forConstant(evalConst(forX.asConstant(), forY.asConstant()), null); @@ -58,6 +67,7 @@ // Constant 0.0 can't be eliminated since it can affect the sign of the result. // Constant -0.0 is an additive identity. if (forY.isConstant()) { + @SuppressWarnings("hiding") Constant y = forY.asConstant(); switch (y.getKind()) { case Float: @@ -76,6 +86,16 @@ throw GraalGraphInternalError.shouldNotReachHere(); } } + /* + * JVM spec, Chapter 6, dsub/fsub bytecode: For double subtraction, it is always the case + * that a-b produces the same result as a+(-b). + */ + if (forX instanceof NegateNode) { + return FloatSubNode.create(forY, ((NegateNode) forX).getValue(), isStrictFP()); + } + if (forY instanceof NegateNode) { + return FloatSubNode.create(forX, ((NegateNode) forY).getValue(), isStrictFP()); + } return this; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatArithmeticNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatArithmeticNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatArithmeticNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,9 +23,11 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public abstract class FloatArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable { private final boolean isStrictFP; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -28,6 +28,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -35,11 +36,16 @@ * A {@code FloatConvert} converts between integers and floating point numbers according to Java * semantics. */ +@NodeInfo public class FloatConvertNode extends ConvertNode implements Lowerable, ArithmeticLIRLowerable { private final FloatConvert op; - public FloatConvertNode(FloatConvert op, ValueNode input) { + public static FloatConvertNode create(FloatConvert op, ValueNode input) { + return USE_GENERATED_NODES ? new FloatConvertNodeGen(op, input) : new FloatConvertNode(op, input); + } + + protected FloatConvertNode(FloatConvert op, ValueNode input) { super(createStamp(op, input), input); this.op = op; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,13 +26,18 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "/") -public final class FloatDivNode extends FloatArithmeticNode { +public class FloatDivNode extends FloatArithmeticNode { - public FloatDivNode(ValueNode x, ValueNode y, boolean isStrictFP) { + public static FloatDivNode create(ValueNode x, ValueNode y, boolean isStrictFP) { + return USE_GENERATED_NODES ? new FloatDivNodeGen(x, y, isStrictFP) : new FloatDivNode(x, y, isStrictFP); + } + + protected FloatDivNode(ValueNode x, ValueNode y, boolean isStrictFP) { super(x.stamp().unrestricted(), x, y, isStrictFP); } @@ -53,6 +58,7 @@ return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant())); } if (forY.isConstant()) { + @SuppressWarnings("hiding") Constant y = forY.asConstant(); switch (y.getKind()) { case Float: diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,13 +25,13 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "==") -public final class FloatEqualsNode extends CompareNode { +public class FloatEqualsNode extends CompareNode { /** * Constructs a new floating point equality comparison node. @@ -39,7 +39,11 @@ * @param x the instruction producing the first input to the instruction * @param y the instruction that produces the second input to this instruction */ - public FloatEqualsNode(ValueNode x, ValueNode y) { + public static FloatEqualsNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new FloatEqualsNodeGen(x, y) : new FloatEqualsNode(x, y); + } + + protected FloatEqualsNode(ValueNode x, ValueNode y) { super(x, y); assert x.stamp() instanceof FloatStamp && y.stamp() instanceof FloatStamp : x.stamp() + " " + y.stamp(); assert x.stamp().isCompatible(y.stamp()); @@ -76,9 +80,9 @@ @Override protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) { if (newX.stamp() instanceof FloatStamp && newY.stamp() instanceof FloatStamp) { - return new FloatEqualsNode(newX, newY); + return FloatEqualsNode.create(newX, newY); } else if (newX.stamp() instanceof IntegerStamp && newY.stamp() instanceof IntegerStamp) { - return new IntegerEqualsNode(newX, newY); + return IntegerEqualsNode.create(newX, newY); } throw GraalInternalError.shouldNotReachHere(); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,13 +25,13 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "<") -public final class FloatLessThanNode extends CompareNode { +public class FloatLessThanNode extends CompareNode { private final boolean unorderedIsTrue; @@ -43,7 +43,11 @@ * @param unorderedIsTrue whether a comparison that is undecided (involving NaNs, etc.) leads to * a "true" result */ - public FloatLessThanNode(ValueNode x, ValueNode y, boolean unorderedIsTrue) { + public static FloatLessThanNode create(ValueNode x, ValueNode y, boolean unorderedIsTrue) { + return USE_GENERATED_NODES ? new FloatLessThanNodeGen(x, y, unorderedIsTrue) : new FloatLessThanNode(x, y, unorderedIsTrue); + } + + protected FloatLessThanNode(ValueNode x, ValueNode y, boolean unorderedIsTrue) { super(x, y); assert x.stamp() instanceof FloatStamp && y.stamp() instanceof FloatStamp; assert x.stamp().isCompatible(y.stamp()); @@ -75,9 +79,9 @@ @Override protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) { if (newX.stamp() instanceof FloatStamp && newY.stamp() instanceof FloatStamp) { - return new FloatLessThanNode(newX, newY, unorderedIsTrue); + return FloatLessThanNode.create(newX, newY, unorderedIsTrue); } else if (newX.stamp() instanceof IntegerStamp && newY.stamp() instanceof IntegerStamp) { - return new IntegerLessThanNode(newX, newY); + return IntegerLessThanNode.create(newX, newY); } throw GraalInternalError.shouldNotReachHere(); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,13 +26,22 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "*") -public final class FloatMulNode extends FloatArithmeticNode { +public class FloatMulNode extends FloatArithmeticNode { + + public static FloatMulNode create(ValueNode x, ValueNode y, boolean isStrictFP) { + return USE_GENERATED_NODES ? new FloatMulNodeGen(x, y, isStrictFP) : new FloatMulNode(x, y, isStrictFP); + } - public FloatMulNode(ValueNode x, ValueNode y, boolean isStrictFP) { + public static Class getGenClass() { + return USE_GENERATED_NODES ? FloatMulNodeGen.class : FloatMulNode.class; + } + + protected FloatMulNode(ValueNode x, ValueNode y, boolean isStrictFP) { super(x.stamp().unrestricted(), x, y, isStrictFP); } @@ -50,12 +59,13 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { if (forX.isConstant() && !forY.isConstant()) { - return new FloatMulNode(forY, forX, isStrictFP()); + return FloatMulNode.create(forY, forX, isStrictFP()); } if (forX.isConstant()) { return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant())); } if (forY.isConstant()) { + @SuppressWarnings("hiding") Constant y = forY.asConstant(); switch (y.getKind()) { case Float: diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,16 +23,20 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "%") public class FloatRemNode extends FloatArithmeticNode implements Lowerable { - public FloatRemNode(ValueNode x, ValueNode y, boolean isStrictFP) { + public static FloatRemNode create(ValueNode x, ValueNode y, boolean isStrictFP) { + return USE_GENERATED_NODES ? new FloatRemNodeGen(x, y, isStrictFP) : new FloatRemNode(x, y, isStrictFP); + } + + protected FloatRemNode(ValueNode x, ValueNode y, boolean isStrictFP) { super(x.stamp().unrestricted(), x, y, isStrictFP); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,14 +26,23 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "-") -public final class FloatSubNode extends FloatArithmeticNode { +public class FloatSubNode extends FloatArithmeticNode { + + public static FloatSubNode create(ValueNode x, ValueNode y, boolean isStrictFP) { + return USE_GENERATED_NODES ? new FloatSubNodeGen(x, y, isStrictFP) : new FloatSubNode(x, y, isStrictFP); + } - public FloatSubNode(ValueNode x, ValueNode y, boolean isStrictFP) { + public static Class getGenClass() { + return USE_GENERATED_NODES ? FloatSubNodeGen.class : FloatSubNode.class; + } + + protected FloatSubNode(ValueNode x, ValueNode y, boolean isStrictFP) { super(x.stamp().unrestricted(), x, y, isStrictFP); } @@ -56,9 +65,29 @@ if (forX.isConstant() && forY.isConstant()) { return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant())); } + // Constant -0.0 is an additive identity, so (-0.0) - x == (-0.0) + (-x) == -x. + if (forX.isConstant()) { + @SuppressWarnings("hiding") + Constant x = forX.asConstant(); + switch (x.getKind()) { + case Float: + if (Float.compare(x.asFloat(), -0.0f) == 0) { + return NegateNode.create(forY); + } + break; + case Double: + if (Double.compare(x.asDouble(), -0.0) == 0) { + return NegateNode.create(forY); + } + break; + default: + throw GraalGraphInternalError.shouldNotReachHere(); + } + } // Constant -0.0 can't be eliminated since it can affect the sign of the result. // Constant 0.0 is a subtractive identity. if (forY.isConstant()) { + @SuppressWarnings("hiding") Constant y = forY.asConstant(); switch (y.getKind()) { case Float: @@ -77,6 +106,13 @@ throw GraalGraphInternalError.shouldNotReachHere(); } } + /* + * JVM spec, Chapter 6, dsub/fsub bytecode: For double subtraction, it is always the case + * that a-b produces the same result as a+(-b). + */ + if (forY instanceof NegateNode) { + return FloatAddNode.create(forX, ((NegateNode) forY).getValue(), isStrictFP()); + } return this; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,8 +24,10 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +@NodeInfo public abstract class FloatingNode extends ValueNode implements Node.ValueNumberable { public FloatingNode(Stamp stamp) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,9 +24,9 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -34,7 +34,15 @@ @NodeInfo(shortName = "+") public class IntegerAddNode extends IntegerArithmeticNode implements NarrowableArithmeticNode { - public IntegerAddNode(ValueNode x, ValueNode y) { + public static IntegerAddNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new IntegerAddNodeGen(x, y) : new IntegerAddNode(x, y); + } + + public static Class getGenClass() { + return USE_GENERATED_NODES ? IntegerAddNodeGen.class : IntegerAddNode.class; + } + + protected IntegerAddNode(ValueNode x, ValueNode y) { super(StampTool.add(x.stamp(), y.stamp()), x, y); } @@ -52,7 +60,7 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { if (forX.isConstant() && !forY.isConstant()) { - return new IntegerAddNode(forY, forX); + return IntegerAddNode.create(forY, forX); } if (forX instanceof IntegerSubNode) { IntegerSubNode sub = (IntegerSubNode) forX; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,9 +23,11 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public abstract class IntegerArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable { public IntegerArithmeticNode(Stamp stamp, ValueNode x, ValueNode y) { @@ -34,26 +36,26 @@ } public static IntegerAddNode add(StructuredGraph graph, ValueNode v1, ValueNode v2) { - return graph.unique(new IntegerAddNode(v1, v2)); + return graph.unique(IntegerAddNode.create(v1, v2)); } public static IntegerAddNode add(ValueNode v1, ValueNode v2) { - return new IntegerAddNode(v1, v2); + return IntegerAddNode.create(v1, v2); } public static IntegerMulNode mul(StructuredGraph graph, ValueNode v1, ValueNode v2) { - return graph.unique(new IntegerMulNode(v1, v2)); + return graph.unique(IntegerMulNode.create(v1, v2)); } public static IntegerMulNode mul(ValueNode v1, ValueNode v2) { - return new IntegerMulNode(v1, v2); + return IntegerMulNode.create(v1, v2); } public static IntegerSubNode sub(StructuredGraph graph, ValueNode v1, ValueNode v2) { - return graph.unique(new IntegerSubNode(v1, v2)); + return graph.unique(IntegerSubNode.create(v1, v2)); } public static IntegerSubNode sub(ValueNode v1, ValueNode v2) { - return new IntegerSubNode(v1, v2); + return IntegerSubNode.create(v1, v2); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,13 +24,13 @@ import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "|<|") -public final class IntegerBelowNode extends CompareNode { +public class IntegerBelowNode extends CompareNode { /** * Constructs a new unsigned integer comparison node. @@ -38,7 +38,11 @@ * @param x the instruction producing the first input to the instruction * @param y the instruction that produces the second input to this instruction */ - public IntegerBelowNode(ValueNode x, ValueNode y) { + public static IntegerBelowNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new IntegerBelowNodeGen(x, y) : new IntegerBelowNode(x, y); + } + + protected IntegerBelowNode(ValueNode x, ValueNode y) { super(x, y); assert x.stamp() instanceof IntegerStamp; assert y.stamp() instanceof IntegerStamp; @@ -75,13 +79,13 @@ } if (forX.isConstant() && forX.asConstant().asLong() == 0) { // 0 |<| y is the same as 0 != y - return new LogicNegationNode(CompareNode.createCompareNode(Condition.EQ, forX, forY)); + return LogicNegationNode.create(CompareNode.createCompareNode(Condition.EQ, forX, forY)); } return this; } @Override protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) { - return new IntegerBelowNode(newX, newY); + return IntegerBelowNode.create(newX, newY); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,12 +23,14 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; /** * An {@code IntegerConvert} converts an integer to an integer of different width. */ +@NodeInfo public abstract class IntegerConvertNode extends ConvertNode implements ArithmeticLIRLowerable { private final int resultBits; @@ -58,7 +60,7 @@ } } - protected ValueNode canonicalConvert(ValueNode value) { + protected ValueNode canonicalConvert(@SuppressWarnings("hiding") ValueNode value) { if (value.stamp() instanceof IntegerStamp) { int inputBits = ((IntegerStamp) value.stamp()).getBits(); if (inputBits == resultBits) { @@ -95,13 +97,13 @@ if (toStamp.getBits() == fromStamp.getBits()) { result = input; } else if (toStamp.getBits() < fromStamp.getBits()) { - result = new NarrowNode(input, toStamp.getBits()); + result = NarrowNode.create(input, toStamp.getBits()); } else if (zeroExtend) { // toStamp.getBits() > fromStamp.getBits() - result = new ZeroExtendNode(input, toStamp.getBits()); + result = ZeroExtendNode.create(input, toStamp.getBits()); } else { // toStamp.getBits() > fromStamp.getBits() - result = new SignExtendNode(input, toStamp.getBits()); + result = SignExtendNode.create(input, toStamp.getBits()); } IntegerStamp resultStamp = (IntegerStamp) result.stamp(); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -33,7 +34,11 @@ @NodeInfo(shortName = "/") public class IntegerDivNode extends FixedBinaryNode implements Lowerable, LIRLowerable { - public IntegerDivNode(ValueNode x, ValueNode y) { + public static IntegerDivNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new IntegerDivNodeGen(x, y) : new IntegerDivNode(x, y); + } + + protected IntegerDivNode(ValueNode x, ValueNode y) { super(StampTool.div(x.stamp(), y.stamp()), x, y); } @@ -45,6 +50,7 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { if (forX.isConstant() && forY.isConstant()) { + @SuppressWarnings("hiding") long y = forY.asConstant().asLong(); if (y == 0) { return this; // this will trap, can not canonicalize @@ -56,7 +62,7 @@ return forX; } if (c == -1) { - return new NegateNode(forX); + return NegateNode.create(forX); } long abs = Math.abs(c); if (CodeUtil.isPowerOf2(abs) && forX.stamp() instanceof IntegerStamp) { @@ -66,13 +72,13 @@ // no rounding if dividend is positive or if its low bits are always 0 if (stampX.canBeNegative() || (stampX.upMask() & (abs - 1)) != 0) { int bits = PrimitiveStamp.getBits(stamp()); - RightShiftNode sign = new RightShiftNode(forX, ConstantNode.forInt(bits - 1)); - UnsignedRightShiftNode round = new UnsignedRightShiftNode(sign, ConstantNode.forInt(bits - log2)); + RightShiftNode sign = RightShiftNode.create(forX, ConstantNode.forInt(bits - 1)); + UnsignedRightShiftNode round = UnsignedRightShiftNode.create(sign, ConstantNode.forInt(bits - log2)); dividend = IntegerArithmeticNode.add(dividend, round); } - RightShiftNode shift = new RightShiftNode(dividend, ConstantNode.forInt(log2)); + RightShiftNode shift = RightShiftNode.create(dividend, ConstantNode.forInt(log2)); if (c < 0) { - return new NegateNode(shift); + return NegateNode.create(shift); } return shift; } @@ -85,7 +91,7 @@ IntegerRemNode integerRemNode = (IntegerRemNode) integerSubNode.getY(); if (integerSubNode.stamp().isCompatible(this.stamp()) && integerRemNode.stamp().isCompatible(this.stamp()) && integerSubNode.getX() == integerRemNode.getX() && forY == integerRemNode.getY()) { - return new IntegerDivNode(integerSubNode.getX(), forY); + return IntegerDivNode.create(integerSubNode.getX(), forY); } } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,13 +26,13 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "==") -public final class IntegerEqualsNode extends CompareNode { +public class IntegerEqualsNode extends CompareNode { /** * Constructs a new integer equality comparison node. @@ -40,7 +40,11 @@ * @param x the instruction producing the first input to the instruction * @param y the instruction that produces the second input to this instruction */ - public IntegerEqualsNode(ValueNode x, ValueNode y) { + public static IntegerEqualsNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new IntegerEqualsNodeGen(x, y) : new IntegerEqualsNode(x, y); + } + + protected IntegerEqualsNode(ValueNode x, ValueNode y) { super(x, y); assert !x.getKind().isNumericFloat() && x.getKind() != Kind.Object; assert !y.getKind().isNumericFloat() && y.getKind() != Kind.Object; @@ -63,9 +67,9 @@ ValueNode b = mirrored ? normalizeNode.getX() : normalizeNode.getY(); if (normalizeNode.getX().getKind() == Kind.Double || normalizeNode.getX().getKind() == Kind.Float) { - return new FloatEqualsNode(a, b); + return FloatEqualsNode.create(a, b); } else { - return new IntegerEqualsNode(a, b); + return IntegerEqualsNode.create(a, b); } } return this; @@ -74,9 +78,9 @@ @Override protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) { if (newX.stamp() instanceof FloatStamp && newY.stamp() instanceof FloatStamp) { - return new FloatEqualsNode(newX, newY); + return FloatEqualsNode.create(newX, newY); } else if (newX.stamp() instanceof IntegerStamp && newY.stamp() instanceof IntegerStamp) { - return new IntegerEqualsNode(newX, newY); + return IntegerEqualsNode.create(newX, newY); } throw GraalInternalError.shouldNotReachHere(); } @@ -96,7 +100,7 @@ if (constant.asLong() == 0) { if (nonConstant instanceof AndNode) { AndNode andNode = (AndNode) nonConstant; - return new IntegerTestNode(andNode.getX(), andNode.getY()); + return IntegerTestNode.create(andNode.getX(), andNode.getY()); } else if (nonConstant instanceof ShiftNode) { if (nonConstant instanceof LeftShiftNode) { LeftShiftNode shift = (LeftShiftNode) nonConstant; @@ -104,10 +108,10 @@ int mask = shift.getShiftAmountMask(); int amount = shift.getY().asConstant().asInt() & mask; if (shift.getX().getKind() == Kind.Int) { - return new IntegerTestNode(shift.getX(), ConstantNode.forInt(-1 >>> amount)); + return IntegerTestNode.create(shift.getX(), ConstantNode.forInt(-1 >>> amount)); } else { assert shift.getX().getKind() == Kind.Long; - return new IntegerTestNode(shift.getX(), ConstantNode.forLong(-1L >>> amount)); + return IntegerTestNode.create(shift.getX(), ConstantNode.forLong(-1L >>> amount)); } } } else if (nonConstant instanceof RightShiftNode) { @@ -116,10 +120,10 @@ int mask = shift.getShiftAmountMask(); int amount = shift.getY().asConstant().asInt() & mask; if (shift.getX().getKind() == Kind.Int) { - return new IntegerTestNode(shift.getX(), ConstantNode.forInt(-1 << amount)); + return IntegerTestNode.create(shift.getX(), ConstantNode.forInt(-1 << amount)); } else { assert shift.getX().getKind() == Kind.Long; - return new IntegerTestNode(shift.getX(), ConstantNode.forLong(-1L << amount)); + return IntegerTestNode.create(shift.getX(), ConstantNode.forLong(-1L << amount)); } } } else if (nonConstant instanceof UnsignedRightShiftNode) { @@ -128,10 +132,10 @@ int mask = shift.getShiftAmountMask(); int amount = shift.getY().asConstant().asInt() & mask; if (shift.getX().getKind() == Kind.Int) { - return new IntegerTestNode(shift.getX(), ConstantNode.forInt(-1 << amount)); + return IntegerTestNode.create(shift.getX(), ConstantNode.forInt(-1 << amount)); } else { assert shift.getX().getKind() == Kind.Long; - return new IntegerTestNode(shift.getX(), ConstantNode.forLong(-1L << amount)); + return IntegerTestNode.create(shift.getX(), ConstantNode.forLong(-1L << amount)); } } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,13 +26,13 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "<") -public final class IntegerLessThanNode extends CompareNode { +public class IntegerLessThanNode extends CompareNode { /** * Constructs a new integer comparison node. @@ -40,7 +40,11 @@ * @param x the instruction producing the first input to the instruction * @param y the instruction that produces the second input to this instruction */ - public IntegerLessThanNode(ValueNode x, ValueNode y) { + public static IntegerLessThanNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new IntegerLessThanNodeGen(x, y) : new IntegerLessThanNode(x, y); + } + + protected IntegerLessThanNode(ValueNode x, ValueNode y) { super(x, y); assert !x.getKind().isNumericFloat() && x.getKind() != Kind.Object; assert !y.getKind().isNumericFloat() && y.getKind() != Kind.Object; @@ -64,9 +68,9 @@ ValueNode b = mirrored ? normalizeNode.getX() : normalizeNode.getY(); if (normalizeNode.getX().getKind() == Kind.Double || normalizeNode.getX().getKind() == Kind.Float) { - return new FloatLessThanNode(a, b, mirrored ^ normalizeNode.isUnorderedLess); + return FloatLessThanNode.create(a, b, mirrored ^ normalizeNode.isUnorderedLess); } else { - return new IntegerLessThanNode(a, b); + return IntegerLessThanNode.create(a, b); } } return this; @@ -91,7 +95,7 @@ } if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) { if (IntegerStamp.sameSign((IntegerStamp) forX.stamp(), (IntegerStamp) forY.stamp())) { - return new IntegerBelowNode(forX, forY); + return IntegerBelowNode.create(forX, forY); } } return this; @@ -100,9 +104,9 @@ @Override protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) { if (newX.stamp() instanceof FloatStamp && newY.stamp() instanceof FloatStamp) { - return new FloatLessThanNode(newX, newY, true); + return FloatLessThanNode.create(newX, newY, true); } else if (newX.stamp() instanceof IntegerStamp && newY.stamp() instanceof IntegerStamp) { - return new IntegerLessThanNode(newX, newY); + return IntegerLessThanNode.create(newX, newY); } throw GraalInternalError.shouldNotReachHere(); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,16 +25,24 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "*") public class IntegerMulNode extends IntegerArithmeticNode implements NarrowableArithmeticNode { - public IntegerMulNode(ValueNode x, ValueNode y) { + public static IntegerMulNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new IntegerMulNodeGen(x, y) : new IntegerMulNode(x, y); + } + + public static Class getGenClass() { + return USE_GENERATED_NODES ? IntegerMulNodeGen.class : IntegerMulNode.class; + } + + protected IntegerMulNode(ValueNode x, ValueNode y) { super(x.stamp().unrestricted(), x, y); assert x.stamp().isCompatible(y.stamp()); } @@ -48,7 +56,7 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { if (forX.isConstant() && !forY.isConstant()) { - return new IntegerMulNode(forY, forX); + return IntegerMulNode.create(forY, forX); } if (forX.isConstant()) { return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant())); @@ -62,9 +70,9 @@ } long abs = Math.abs(c); if (abs > 0 && CodeUtil.isPowerOf2(abs)) { - LeftShiftNode shift = new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(abs))); + LeftShiftNode shift = LeftShiftNode.create(forX, ConstantNode.forInt(CodeUtil.log2(abs))); if (c < 0) { - return new NegateNode(shift); + return NegateNode.create(shift); } else { return shift; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,8 +24,8 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -33,7 +33,11 @@ @NodeInfo(shortName = "%") public class IntegerRemNode extends FixedBinaryNode implements Lowerable, LIRLowerable { - public IntegerRemNode(ValueNode x, ValueNode y) { + public static IntegerRemNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new IntegerRemNodeGen(x, y) : new IntegerRemNode(x, y); + } + + protected IntegerRemNode(ValueNode x, ValueNode y) { super(StampTool.rem(x.stamp(), y.stamp()), x, y); } @@ -45,6 +49,7 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { if (forX.isConstant() && forY.isConstant()) { + @SuppressWarnings("hiding") long y = forY.asConstant().asLong(); if (y == 0) { return this; // this will trap, can not canonicalize @@ -55,7 +60,7 @@ if (c == 1 || c == -1) { return ConstantNode.forIntegerStamp(stamp(), 0); } else if (c > 0 && CodeUtil.isPowerOf2(c) && forX.stamp() instanceof IntegerStamp && ((IntegerStamp) forX.stamp()).isPositive()) { - return new AndNode(forX, ConstantNode.forIntegerStamp(stamp(), c - 1)); + return AndNode.create(forX, ConstantNode.forIntegerStamp(stamp(), c - 1)); } } return this; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,9 +24,9 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -35,7 +35,15 @@ @NodeInfo(shortName = "-") public class IntegerSubNode extends IntegerArithmeticNode implements NarrowableArithmeticNode { - public IntegerSubNode(ValueNode x, ValueNode y) { + public static IntegerSubNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new IntegerSubNodeGen(x, y) : new IntegerSubNode(x, y); + } + + public static Class getGenClass() { + return USE_GENERATED_NODES ? IntegerSubNodeGen.class : IntegerSubNode.class; + } + + protected IntegerSubNode(ValueNode x, ValueNode y) { super(StampTool.sub(x.stamp(), y.stamp()), x, y); } @@ -50,6 +58,7 @@ return Constant.forPrimitiveInt(PrimitiveStamp.getBits(stamp()), inputs[0].asLong() - inputs[1].asLong()); } + @SuppressWarnings("hiding") @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { @@ -69,18 +78,18 @@ IntegerSubNode x = (IntegerSubNode) forX; if (x.getX() == forY) { // (a - b) - a - return new NegateNode(x.getY()); + return NegateNode.create(x.getY()); } } if (forY instanceof IntegerAddNode) { IntegerAddNode y = (IntegerAddNode) forY; if (y.getX() == forX) { // a - (a + b) - return new NegateNode(y.getY()); + return NegateNode.create(y.getY()); } if (y.getY() == forX) { // b - (a + b) - return new NegateNode(y.getX()); + return NegateNode.create(y.getX()); } } else if (forY instanceof IntegerSubNode) { IntegerSubNode y = (IntegerSubNode) forY; @@ -108,7 +117,7 @@ } else if (forX.isConstant()) { long c = forX.asConstant().asLong(); if (c == 0) { - return new NegateNode(forY); + return NegateNode.create(forY); } return BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,6 +24,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; /** @@ -31,6 +32,7 @@ * expression "(x & y) == 0", meaning that it will return true if (and only if) no bit is set in * both x and y. */ +@NodeInfo public class IntegerTestNode extends BinaryOpLogicNode { /** @@ -39,7 +41,11 @@ * @param x the instruction producing the first input to the instruction * @param y the instruction that produces the second input to this instruction */ - public IntegerTestNode(ValueNode x, ValueNode y) { + public static IntegerTestNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new IntegerTestNodeGen(x, y) : new IntegerTestNode(x, y); + } + + protected IntegerTestNode(ValueNode x, ValueNode y) { super(x, y); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -32,14 +33,19 @@ /** * An IsNullNode will be true if the supplied value is null, and false if it is non-null. */ -public final class IsNullNode extends UnaryOpLogicNode implements LIRLowerable, Virtualizable, PiPushable { +@NodeInfo +public class IsNullNode extends UnaryOpLogicNode implements LIRLowerable, Virtualizable, PiPushable { /** * Constructs a new IsNullNode instruction. * * @param object the instruction producing the object to check against null */ - public IsNullNode(ValueNode object) { + public static IsNullNode create(ValueNode object) { + return USE_GENERATED_NODES ? new IsNullNodeGen(object) : new IsNullNode(object); + } + + protected IsNullNode(ValueNode object) { super(object); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,17 +23,21 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "<<") -public final class LeftShiftNode extends ShiftNode { +public class LeftShiftNode extends ShiftNode { - public LeftShiftNode(ValueNode x, ValueNode y) { + public static LeftShiftNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new LeftShiftNodeGen(x, y) : new LeftShiftNode(x, y); + } + + protected LeftShiftNode(ValueNode x, ValueNode y) { super(x, y); } @@ -74,19 +78,19 @@ if (total != (total & mask)) { return ConstantNode.forIntegerKind(getKind(), 0); } - return new LeftShiftNode(other.getX(), ConstantNode.forInt(total)); + return LeftShiftNode.create(other.getX(), ConstantNode.forInt(total)); } else if ((other instanceof RightShiftNode || other instanceof UnsignedRightShiftNode) && otherAmount == amount) { if (getKind() == Kind.Long) { - return new AndNode(other.getX(), ConstantNode.forLong(-1L << amount)); + return AndNode.create(other.getX(), ConstantNode.forLong(-1L << amount)); } else { assert getKind() == Kind.Int; - return new AndNode(other.getX(), ConstantNode.forInt(-1 << amount)); + return AndNode.create(other.getX(), ConstantNode.forInt(-1 << amount)); } } } } if (originalAmout != amount) { - return new LeftShiftNode(forX, ConstantNode.forInt(amount)); + return LeftShiftNode.create(forX, ConstantNode.forInt(amount)); } } return this; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -33,9 +34,14 @@ /** * The {@code NarrowNode} converts an integer to a narrower integer. */ +@NodeInfo public class NarrowNode extends IntegerConvertNode { - public NarrowNode(ValueNode input, int resultBits) { + public static NarrowNode create(ValueNode input, int resultBits) { + return USE_GENERATED_NODES ? new NarrowNodeGen(input, resultBits) : new NarrowNode(input, resultBits); + } + + protected NarrowNode(ValueNode input, int resultBits) { super(StampTool.narrowingConversion(input.stamp(), resultBits), input, resultBits); } @@ -71,7 +77,7 @@ // zzzzzzzz yyyyxxxx -(narrow)-> yyyyxxxx -(narrow)-> xxxx // ==> zzzzzzzz yyyyxxxx -(narrow)-> xxxx NarrowNode other = (NarrowNode) forValue; - return new NarrowNode(other.getValue(), getResultBits()); + return NarrowNode.create(other.getValue(), getResultBits()); } else if (forValue instanceof IntegerConvertNode) { // SignExtendNode or ZeroExtendNode IntegerConvertNode other = (IntegerConvertNode) forValue; @@ -82,16 +88,16 @@ } else if (getResultBits() < other.getInputBits()) { // yyyyxxxx -(extend)-> zzzzzzzz yyyyxxxx -(narrow)-> xxxx // ==> yyyyxxxx -(narrow)-> xxxx - return new NarrowNode(other.getValue(), getResultBits()); + return NarrowNode.create(other.getValue(), getResultBits()); } else { if (other instanceof SignExtendNode) { // sxxx -(sign-extend)-> ssssssss sssssxxx -(narrow)-> sssssxxx // ==> sxxx -(sign-extend)-> sssssxxx - return new SignExtendNode(other.getValue(), getResultBits()); + return SignExtendNode.create(other.getValue(), getResultBits()); } else if (other instanceof ZeroExtendNode) { // xxxx -(zero-extend)-> 00000000 00000xxx -(narrow)-> 0000xxxx // ==> xxxx -(zero-extend)-> 0000xxxx - return new ZeroExtendNode(other.getValue(), getResultBits()); + return ZeroExtendNode.create(other.getValue(), getResultBits()); } } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -33,7 +34,8 @@ /** * The {@code NegateNode} node negates its operand. */ -public final class NegateNode extends UnaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode { +@NodeInfo +public class NegateNode extends UnaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode { @Override public boolean inferStamp() { @@ -45,7 +47,11 @@ * * @param value the instruction producing the value that is input to this instruction */ - public NegateNode(ValueNode value) { + public static NegateNode create(ValueNode value) { + return USE_GENERATED_NODES ? new NegateNodeGen(value) : new NegateNode(value); + } + + protected NegateNode(ValueNode value) { super(StampTool.negate(value.stamp()), value); } @@ -76,7 +82,7 @@ } if (forValue instanceof IntegerSubNode) { IntegerSubNode sub = (IntegerSubNode) forValue; - return new IntegerSubNode(sub.getY(), sub.getX()); + return IntegerSubNode.create(sub.getY(), sub.getX()); } return this; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -33,7 +34,8 @@ * of the inputs is NaN), the result is 1 if isUnorderedLess is false and -1 if isUnorderedLess is * true. */ -public final class NormalizeCompareNode extends BinaryNode implements Lowerable { +@NodeInfo +public class NormalizeCompareNode extends BinaryNode implements Lowerable { public final boolean isUnorderedLess; @@ -45,7 +47,11 @@ * @param isUnorderedLess true when an unordered floating point comparison is interpreted as * less, false when greater. */ - public NormalizeCompareNode(ValueNode x, ValueNode y, boolean isUnorderedLess) { + public static NormalizeCompareNode create(ValueNode x, ValueNode y, boolean isUnorderedLess) { + return USE_GENERATED_NODES ? new NormalizeCompareNodeGen(x, y, isUnorderedLess) : new NormalizeCompareNode(x, y, isUnorderedLess); + } + + protected NormalizeCompareNode(ValueNode x, ValueNode y, boolean isUnorderedLess) { super(StampFactory.forKind(Kind.Int), x, y); this.isUnorderedLess = isUnorderedLess; } @@ -61,15 +67,15 @@ LogicNode equalComp; LogicNode lessComp; if (getX().stamp() instanceof FloatStamp) { - equalComp = graph().unique(new FloatEqualsNode(getX(), getY())); - lessComp = graph().unique(new FloatLessThanNode(getX(), getY(), isUnorderedLess)); + equalComp = graph().unique(FloatEqualsNode.create(getX(), getY())); + lessComp = graph().unique(FloatLessThanNode.create(getX(), getY(), isUnorderedLess)); } else { - equalComp = graph().unique(new IntegerEqualsNode(getX(), getY())); - lessComp = graph().unique(new IntegerLessThanNode(getX(), getY())); + equalComp = graph().unique(IntegerEqualsNode.create(getX(), getY())); + lessComp = graph().unique(IntegerLessThanNode.create(getX(), getY())); } - ConditionalNode equalValue = graph().unique(new ConditionalNode(equalComp, ConstantNode.forInt(0, graph()), ConstantNode.forInt(1, graph()))); - ConditionalNode value = graph().unique(new ConditionalNode(lessComp, ConstantNode.forInt(-1, graph()), equalValue)); + ConditionalNode equalValue = graph().unique(ConditionalNode.create(equalComp, ConstantNode.forInt(0, graph()), ConstantNode.forInt(1, graph()))); + ConditionalNode value = graph().unique(ConditionalNode.create(lessComp, ConstantNode.forInt(-1, graph()), equalValue)); graph().replaceFloating(this, value); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -33,7 +34,8 @@ /** * Binary negation of long or integer values. */ -public final class NotNode extends UnaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode { +@NodeInfo +public class NotNode extends UnaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode { @Override public boolean inferStamp() { @@ -51,7 +53,11 @@ * * @param x the instruction producing the value that is input to this instruction */ - public NotNode(ValueNode x) { + public static NotNode create(ValueNode x) { + return USE_GENERATED_NODES ? new NotNodeGen(x) : new NotNode(x); + } + + protected NotNode(ValueNode x) { super(StampTool.not(x.stamp()), x); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,15 +24,15 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.calc.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "==") -public final class ObjectEqualsNode extends CompareNode implements Virtualizable { +public class ObjectEqualsNode extends CompareNode implements Virtualizable { /** * Constructs a new object equality comparison node. @@ -40,7 +40,11 @@ * @param x the instruction producing the first input to the instruction * @param y the instruction that produces the second input to this instruction */ - public ObjectEqualsNode(ValueNode x, ValueNode y) { + public static ObjectEqualsNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new ObjectEqualsNodeGen(x, y) : new ObjectEqualsNode(x, y); + } + + protected ObjectEqualsNode(ValueNode x, ValueNode y) { super(x, y); assert x.getKind() == Kind.Object; assert y.getKind() == Kind.Object; @@ -68,9 +72,9 @@ return LogicConstantNode.contradiction(); } if (StampTool.isObjectAlwaysNull(forX)) { - return new IsNullNode(forY); + return IsNullNode.create(forY); } else if (StampTool.isObjectAlwaysNull(forY)) { - return new IsNullNode(forX); + return IsNullNode.create(forX); } return this; } @@ -81,7 +85,7 @@ Constant otherUnboxed = tool.getConstantReflectionProvider().unboxPrimitive(other.asConstant()); if (otherUnboxed != null && otherUnboxed.getKind() == Kind.Boolean) { int expectedValue = otherUnboxed.asBoolean() ? 1 : 0; - IntegerEqualsNode equals = new IntegerEqualsNode(state.getEntry(0), ConstantNode.forInt(expectedValue, graph())); + IntegerEqualsNode equals = IntegerEqualsNode.create(state.getEntry(0), ConstantNode.forInt(expectedValue, graph())); tool.addNode(equals); tool.replaceWithValue(equals); } else { @@ -122,7 +126,7 @@ assert stateX.getVirtualObject().entryCount() == 1 && stateY.getVirtualObject().entryCount() == 1; assert stateX.getVirtualObject().type().equals(stateY.getVirtualObject().type()); assert stateX.getVirtualObject().entryKind(0).getStackKind() == Kind.Int || stateX.getVirtualObject().entryKind(0) == Kind.Long; - IntegerEqualsNode equals = new IntegerEqualsNode(stateX.getEntry(0), stateY.getEntry(0)); + IntegerEqualsNode equals = IntegerEqualsNode.create(stateX.getEntry(0), stateY.getEntry(0)); tool.addNode(equals); tool.replaceWithValue(equals); } else { @@ -134,6 +138,6 @@ @Override protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) { - return new ObjectEqualsNode(newX, newY); + return ObjectEqualsNode.create(newX, newY); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,18 +24,26 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "|") -public final class OrNode extends BitLogicNode { +public class OrNode extends BitLogicNode { + + public static OrNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new OrNodeGen(x, y) : new OrNode(x, y); + } - public OrNode(ValueNode x, ValueNode y) { + public static Class getGenClass() { + return USE_GENERATED_NODES ? OrNodeGen.class : OrNode.class; + } + + OrNode(ValueNode x, ValueNode y) { super(StampTool.or(x.stamp(), y.stamp()), x, y); assert x.stamp().isCompatible(y.stamp()); } @@ -57,7 +65,7 @@ return forX; } if (forX.isConstant() && !forY.isConstant()) { - return new OrNode(forY, forX); + return create(forY, forX); } if (forX.isConstant()) { return ConstantNode.forPrimitive(stamp(), evalConst(forX.asConstant(), forY.asConstant())); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,6 +27,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -35,13 +36,22 @@ * of a primitive value to some other incompatible stamp. The new stamp must have the same width as * the old stamp. */ +@NodeInfo public class ReinterpretNode extends UnaryNode implements ArithmeticLIRLowerable { - private ReinterpretNode(Kind to, ValueNode value) { + public static ReinterpretNode create(Kind to, ValueNode value) { + return USE_GENERATED_NODES ? new ReinterpretNodeGen(to, value) : new ReinterpretNode(to, value); + } + + ReinterpretNode(Kind to, ValueNode value) { this(StampFactory.forKind(to), value); } - public ReinterpretNode(Stamp to, ValueNode value) { + public static ReinterpretNode create(Stamp to, ValueNode value) { + return USE_GENERATED_NODES ? new ReinterpretNodeGen(to, value) : new ReinterpretNode(to, value); + } + + protected ReinterpretNode(Stamp to, ValueNode value) { super(to, value); assert to instanceof PrimitiveStamp; } @@ -89,7 +99,7 @@ } if (forValue instanceof ReinterpretNode) { ReinterpretNode reinterpret = (ReinterpretNode) forValue; - return new ReinterpretNode(stamp(), reinterpret.getValue()); + return ReinterpretNode.create(stamp(), reinterpret.getValue()); } return this; } @@ -101,7 +111,7 @@ } public static ValueNode reinterpret(Kind toKind, ValueNode value) { - return value.graph().unique(new ReinterpretNode(toKind, value)); + return value.graph().unique(ReinterpretNode.create(toKind, value)); } @NodeIntrinsic diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,17 +24,21 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = ">>") -public final class RightShiftNode extends ShiftNode { +public class RightShiftNode extends ShiftNode { - public RightShiftNode(ValueNode x, ValueNode y) { + public static RightShiftNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new RightShiftNodeGen(x, y) : new RightShiftNode(x, y); + } + + protected RightShiftNode(ValueNode x, ValueNode y) { super(x, y); } @@ -57,7 +61,7 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { if (forX.stamp() instanceof IntegerStamp && ((IntegerStamp) forX.stamp()).isPositive()) { - return new UnsignedRightShiftNode(forX, forY); + return UnsignedRightShiftNode.create(forX, forY); } if (forX.isConstant() && forY.isConstant()) { return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant())); @@ -91,14 +95,14 @@ * full shift for this kind */ assert total >= mask; - return new RightShiftNode(other.getX(), ConstantNode.forInt(mask)); + return RightShiftNode.create(other.getX(), ConstantNode.forInt(mask)); } - return new RightShiftNode(other.getX(), ConstantNode.forInt(total)); + return RightShiftNode.create(other.getX(), ConstantNode.forInt(total)); } } } if (originalAmout != amount) { - return new RightShiftNode(forX, ConstantNode.forInt(amount)); + return RightShiftNode.create(forX, ConstantNode.forInt(amount)); } } return this; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,12 +23,14 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; /** * The {@code ShiftOp} class represents shift operations. */ +@NodeInfo public abstract class ShiftNode extends BinaryNode implements ArithmeticLIRLowerable { /** diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -33,9 +34,14 @@ /** * The {@code SignExtendNode} converts an integer to a wider integer using sign extension. */ +@NodeInfo public class SignExtendNode extends IntegerConvertNode { - public SignExtendNode(ValueNode input, int resultBits) { + public static SignExtendNode create(ValueNode input, int resultBits) { + return USE_GENERATED_NODES ? new SignExtendNodeGen(input, resultBits) : new SignExtendNode(input, resultBits); + } + + protected SignExtendNode(ValueNode input, int resultBits) { super(StampTool.signExtend(input.stamp(), resultBits), input, resultBits); } @@ -77,13 +83,13 @@ // sxxx -(sign-extend)-> ssss sxxx -(sign-extend)-> ssssssss sssssxxx // ==> sxxx -(sign-extend)-> ssssssss sssssxxx SignExtendNode other = (SignExtendNode) forValue; - return new SignExtendNode(other.getValue(), getResultBits()); + return SignExtendNode.create(other.getValue(), getResultBits()); } else if (forValue instanceof ZeroExtendNode) { ZeroExtendNode other = (ZeroExtendNode) forValue; if (other.getResultBits() > other.getInputBits()) { // sxxx -(zero-extend)-> 0000 sxxx -(sign-extend)-> 00000000 0000sxxx // ==> sxxx -(zero-extend)-> 00000000 0000sxxx - return new ZeroExtendNode(other.getValue(), getResultBits()); + return ZeroExtendNode.create(other.getValue(), getResultBits()); } } @@ -92,7 +98,7 @@ if ((inputStamp.upMask() & (1L << (getInputBits() - 1))) == 0L) { // 0xxx -(sign-extend)-> 0000 0xxx // ==> 0xxx -(zero-extend)-> 0000 0xxx - return new ZeroExtendNode(forValue, getResultBits()); + return ZeroExtendNode.create(forValue, getResultBits()); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,15 +24,17 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; /** * The {@code UnaryNode} class is the base of arithmetic and bit logic operations with exactly one * input. */ +@NodeInfo public abstract class UnaryNode extends FloatingNode implements Canonicalizable.Unary { - @Input private ValueNode value; + @Input protected ValueNode value; public ValueNode getValue() { return value; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,15 +24,19 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "|/|") public class UnsignedDivNode extends FixedBinaryNode implements Lowerable, LIRLowerable { - public UnsignedDivNode(ValueNode x, ValueNode y) { + public static UnsignedDivNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new UnsignedDivNodeGen(x, y) : new UnsignedDivNode(x, y); + } + + protected UnsignedDivNode(ValueNode x, ValueNode y) { super(x.stamp().unrestricted(), x, y); } @@ -50,7 +54,7 @@ return forX; } if (CodeUtil.isPowerOf2(c)) { - return new UnsignedRightShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(c))); + return UnsignedRightShiftNode.create(forX, ConstantNode.forInt(CodeUtil.log2(c))); } } return this; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,15 +24,19 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "|%|") public class UnsignedRemNode extends FixedBinaryNode implements Lowerable, LIRLowerable { - public UnsignedRemNode(ValueNode x, ValueNode y) { + public static UnsignedRemNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new UnsignedRemNodeGen(x, y) : new UnsignedRemNode(x, y); + } + + protected UnsignedRemNode(ValueNode x, ValueNode y) { super(x.stamp().unrestricted(), x, y); } @@ -49,7 +53,7 @@ if (c == 1) { return ConstantNode.forIntegerStamp(stamp(), 0); } else if (CodeUtil.isPowerOf2(c)) { - return new AndNode(forX, ConstantNode.forIntegerStamp(stamp(), c - 1)); + return AndNode.create(forX, ConstantNode.forIntegerStamp(stamp(), c - 1)); } } return this; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,17 +23,21 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = ">>>") -public final class UnsignedRightShiftNode extends ShiftNode { +public class UnsignedRightShiftNode extends ShiftNode { - public UnsignedRightShiftNode(ValueNode x, ValueNode y) { + public static UnsignedRightShiftNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new UnsignedRightShiftNodeGen(x, y) : new UnsignedRightShiftNode(x, y); + } + + protected UnsignedRightShiftNode(ValueNode x, ValueNode y) { super(x, y); } @@ -74,19 +78,19 @@ if (total != (total & mask)) { return ConstantNode.forIntegerKind(getKind(), 0); } - return new UnsignedRightShiftNode(other.getX(), ConstantNode.forInt(total)); + return UnsignedRightShiftNode.create(other.getX(), ConstantNode.forInt(total)); } else if (other instanceof LeftShiftNode && otherAmount == amount) { if (getKind() == Kind.Long) { - return new AndNode(other.getX(), ConstantNode.forLong(-1L >>> amount)); + return AndNode.create(other.getX(), ConstantNode.forLong(-1L >>> amount)); } else { assert getKind() == Kind.Int; - return new AndNode(other.getX(), ConstantNode.forInt(-1 >>> amount)); + return AndNode.create(other.getX(), ConstantNode.forInt(-1 >>> amount)); } } } } if (originalAmout != amount) { - return new UnsignedRightShiftNode(forX, ConstantNode.forInt(amount)); + return UnsignedRightShiftNode.create(forX, ConstantNode.forInt(amount)); } } return this; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,18 +24,26 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "^") -public final class XorNode extends BitLogicNode { +public class XorNode extends BitLogicNode { + + public static XorNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new XorNodeGen(x, y) : new XorNode(x, y); + } - public XorNode(ValueNode x, ValueNode y) { + public static Class getGenClass() { + return USE_GENERATED_NODES ? XorNodeGen.class : XorNode.class; + } + + protected XorNode(ValueNode x, ValueNode y) { super(StampTool.xor(x.stamp(), y.stamp()), x, y); assert x.stamp().isCompatible(y.stamp()); } @@ -57,7 +65,7 @@ return ConstantNode.forIntegerStamp(stamp(), 0); } if (forX.isConstant() && !forY.isConstant()) { - return new XorNode(forY, forX); + return XorNode.create(forY, forX); } if (forX.isConstant()) { return ConstantNode.forPrimitive(stamp(), evalConst(forX.asConstant(), forY.asConstant())); @@ -67,7 +75,7 @@ if ((rawY & mask) == 0) { return forX; } else if ((rawY & mask) == mask) { - return new NotNode(forX); + return NotNode.create(forX); } return BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,6 +27,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -34,9 +35,14 @@ /** * The {@code ZeroExtendNode} converts an integer to a wider integer using zero extension. */ +@NodeInfo public class ZeroExtendNode extends IntegerConvertNode { - public ZeroExtendNode(ValueNode input, int resultBits) { + public static ZeroExtendNode create(ValueNode input, int resultBits) { + return USE_GENERATED_NODES ? new ZeroExtendNodeGen(input, resultBits) : new ZeroExtendNode(input, resultBits); + } + + protected ZeroExtendNode(ValueNode input, int resultBits) { super(StampTool.zeroExtend(input.stamp(), resultBits), input, resultBits); } @@ -87,7 +93,7 @@ // xxxx -(zero-extend)-> 0000 xxxx -(zero-extend)-> 00000000 0000xxxx // ==> xxxx -(zero-extend)-> 00000000 0000xxxx ZeroExtendNode other = (ZeroExtendNode) forValue; - return new ZeroExtendNode(other.getValue(), getResultBits()); + return ZeroExtendNode.create(other.getValue(), getResultBits()); } if (forValue instanceof NarrowNode) { NarrowNode narrow = (NarrowNode) forValue; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.debug; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -34,15 +35,20 @@ * A unique counter will be created for each unique name passed to the constructor. Depending on the * value of withContext, the name of the root method is added to the counter's name. */ +@NodeInfo public class DynamicCounterNode extends FixedWithNextNode implements Lowerable { - @Input private ValueNode increment; + @Input ValueNode increment; private final String name; private final String group; private final boolean withContext; - public DynamicCounterNode(String name, String group, ValueNode increment, boolean withContext) { + public static DynamicCounterNode create(String name, String group, ValueNode increment, boolean withContext) { + return USE_GENERATED_NODES ? new DynamicCounterNodeGen(name, group, increment, withContext) : new DynamicCounterNode(name, group, increment, withContext); + } + + DynamicCounterNode(String name, String group, ValueNode increment, boolean withContext) { super(StampFactory.forVoid()); this.name = name; this.group = group; @@ -73,7 +79,7 @@ public static void addCounterBefore(String group, String name, long increment, boolean withContext, FixedNode position) { StructuredGraph graph = position.graph(); - graph.addBeforeFixed(position, position.graph().add(new DynamicCounterNode(name, group, ConstantNode.forLong(increment, position.graph()), withContext))); + graph.addBeforeFixed(position, position.graph().add(DynamicCounterNode.create(name, group, ConstantNode.forLong(increment, position.graph()), withContext))); } @NodeIntrinsic diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/WeakCounterNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/WeakCounterNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/WeakCounterNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.debug; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -32,11 +33,16 @@ * only usage of the associated node. This way it only increments the counter if the node is * actually executed. */ +@NodeInfo public class WeakCounterNode extends DynamicCounterNode implements Simplifiable, Virtualizable { - @Input private ValueNode checkedValue; + @Input ValueNode checkedValue; - public WeakCounterNode(String group, String name, ValueNode increment, boolean addContext, ValueNode checkedValue) { + public static WeakCounterNode create(String group, String name, ValueNode increment, boolean addContext, ValueNode checkedValue) { + return USE_GENERATED_NODES ? new WeakCounterNodeGen(group, name, increment, addContext, checkedValue) : new WeakCounterNode(group, name, increment, addContext, checkedValue); + } + + WeakCounterNode(String group, String name, ValueNode increment, boolean addContext, ValueNode checkedValue) { super(group, name, increment, addContext); this.checkedValue = checkedValue; } @@ -59,7 +65,7 @@ public static void addCounterBefore(String group, String name, long increment, boolean addContext, ValueNode checkedValue, FixedNode position) { StructuredGraph graph = position.graph(); - WeakCounterNode counter = graph.add(new WeakCounterNode(name, group, ConstantNode.forLong(increment, graph), addContext, checkedValue)); + WeakCounterNode counter = graph.add(WeakCounterNode.create(name, group, ConstantNode.forLong(increment, graph), addContext, checkedValue)); graph.addBeforeFixed(position, counter); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,14 +25,15 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @NodeInfo(allowedUsageTypes = {InputType.Memory}) public abstract class AbstractWriteNode extends FixedAccessNode implements StateSplit, MemoryCheckpoint.Single, MemoryAccess, GuardingNode { - @Input private ValueNode value; - @OptionalInput(InputType.State) private FrameState stateAfter; - @OptionalInput(InputType.Memory) private Node lastLocationAccess; + @Input ValueNode value; + @OptionalInput(InputType.State) FrameState stateAfter; + @OptionalInput(InputType.Memory) Node lastLocationAccess; private final boolean initialization; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,6 +27,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -37,10 +38,10 @@ * [(base + x) + y] where base is a node and x and y are location nodes. */ @NodeInfo(nameTemplate = "AddLoc {p#locationIdentity/s}") -public final class AddLocationNode extends LocationNode implements Canonicalizable.Binary { +public class AddLocationNode extends LocationNode implements Canonicalizable.Binary { - @Input(InputType.Association) private ValueNode x; - @Input(InputType.Association) private ValueNode y; + @Input(InputType.Association) ValueNode x; + @Input(InputType.Association) ValueNode y; public LocationNode getX() { return (LocationNode) x; @@ -52,10 +53,14 @@ public static AddLocationNode create(LocationNode x, LocationNode y, Graph graph) { assert x.getValueKind().equals(y.getValueKind()) && x.getLocationIdentity() == y.getLocationIdentity(); - return graph.unique(new AddLocationNode(x, y)); + return graph.unique(AddLocationNode.create(x, y)); } - private AddLocationNode(ValueNode x, ValueNode y) { + public static AddLocationNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new AddLocationNodeGen(x, y) : new AddLocationNode(x, y); + } + + AddLocationNode(ValueNode x, ValueNode y) { super(StampFactory.forVoid()); this.x = x; this.y = y; @@ -101,7 +106,7 @@ AddLocationNode otherAdd = (AddLocationNode) other; LocationNode newInner = otherAdd.canonical(constant, otherAdd.getX()); if (newInner != otherAdd) { - return new AddLocationNode(newInner, otherAdd.getY()); + return AddLocationNode.create(newInner, otherAdd.getY()); } } return this; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,11 +23,13 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; /** * Base class for nodes that modify a range of an array. */ +@NodeInfo public abstract class ArrayRangeWriteNode extends AbstractMemoryCheckpoint { protected ArrayRangeWriteNode(Stamp stamp) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,6 +27,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; @@ -38,11 +39,16 @@ * This node represents the boxing of a primitive value. This corresponds to a call to the valueOf * methods in Integer, Long, etc. */ +@NodeInfo public class BoxNode extends UnaryNode implements VirtualizableAllocation, Lowerable { private final Kind boxingKind; - public BoxNode(ValueNode value, ResolvedJavaType resultType, Kind boxingKind) { + public static BoxNode create(ValueNode value, ResolvedJavaType resultType, Kind boxingKind) { + return USE_GENERATED_NODES ? new BoxNodeGen(value, resultType, boxingKind) : new BoxNode(value, resultType, boxingKind); + } + + BoxNode(ValueNode value, ResolvedJavaType resultType, Kind boxingKind) { super(StampFactory.exactNonNull(resultType), value); this.boxingKind = boxingKind; } @@ -70,7 +76,7 @@ ValueNode v = tool.getReplacedValue(getValue()); ResolvedJavaType type = StampTool.typeOrNull(stamp()); - VirtualBoxingNode newVirtual = new VirtualBoxingNode(type, boxingKind); + VirtualBoxingNode newVirtual = VirtualBoxingNode.create(type, boxingKind); assert newVirtual.getFields().length == 1; tool.createVirtualObject(newVirtual, new ValueNode[]{v}, Collections. emptyList()); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -34,6 +35,7 @@ * the if node's taken probability. Then the branch probability node will be removed. This node is * intended primarily for snippets, so that they can define their fast and slow paths. */ +@NodeInfo public class BranchProbabilityNode extends FloatingNode implements Simplifiable, Lowerable { public static final double LIKELY_PROBABILITY = 0.6; @@ -48,10 +50,14 @@ public static final double VERY_FAST_PATH_PROBABILITY = 0.999; public static final double VERY_SLOW_PATH_PROBABILITY = 1 - VERY_FAST_PATH_PROBABILITY; - @Input private ValueNode probability; - @Input private ValueNode condition; + @Input ValueNode probability; + @Input ValueNode condition; - public BranchProbabilityNode(ValueNode probability, ValueNode condition) { + public static BranchProbabilityNode create(ValueNode probability, ValueNode condition) { + return USE_GENERATED_NODES ? new BranchProbabilityNodeGen(probability, condition) : new BranchProbabilityNode(probability, condition); + } + + BranchProbabilityNode(ValueNode probability, ValueNode condition) { super(condition.stamp()); this.probability = probability; this.condition = condition; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BytecodeExceptionNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BytecodeExceptionNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BytecodeExceptionNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -32,12 +33,17 @@ * A node that represents an exception thrown implicitly by a Java bytecode. It can be lowered to * either a {@linkplain ForeignCallDescriptor foreign} call or a pre-allocated exception object. */ +@NodeInfo public class BytecodeExceptionNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single { private final Class exceptionClass; - @Input private final NodeInputList arguments; + @Input NodeInputList arguments; - public BytecodeExceptionNode(MetaAccessProvider metaAccess, Class exceptionClass, ValueNode... arguments) { + public static BytecodeExceptionNode create(MetaAccessProvider metaAccess, Class exceptionClass, ValueNode... arguments) { + return USE_GENERATED_NODES ? new BytecodeExceptionNodeGen(metaAccess, exceptionClass, arguments) : new BytecodeExceptionNode(metaAccess, exceptionClass, arguments); + } + + BytecodeExceptionNode(MetaAccessProvider metaAccess, Class exceptionClass, ValueNode... arguments) { super(StampFactory.exactNonNull(metaAccess.lookupJavaType(exceptionClass))); this.exceptionClass = exceptionClass; this.arguments = new NodeInputList<>(this, arguments); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,15 +24,16 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public class ComputeAddressNode extends FloatingNode implements LIRLowerable { - @Input private ValueNode object; - @Input(InputType.Association) private ValueNode location; + @Input ValueNode object; + @Input(InputType.Association) ValueNode location; public ValueNode getObject() { return object; @@ -42,7 +43,11 @@ return (LocationNode) location; } - public ComputeAddressNode(ValueNode object, ValueNode location, Stamp stamp) { + public static ComputeAddressNode create(ValueNode object, ValueNode location, Stamp stamp) { + return USE_GENERATED_NODES ? new ComputeAddressNodeGen(object, location, stamp) : new ComputeAddressNode(object, location, stamp); + } + + ComputeAddressNode(ValueNode object, ValueNode location, Stamp stamp) { super(stamp); this.object = object; this.location = location; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; /** @@ -33,21 +34,21 @@ * where base is a node and disp is a constant. */ @NodeInfo(nameTemplate = "Loc {p#locationIdentity/s}") -public final class ConstantLocationNode extends LocationNode { +public class ConstantLocationNode extends LocationNode { private final Kind valueKind; private final LocationIdentity locationIdentity; private final long displacement; public static ConstantLocationNode create(LocationIdentity identity, Kind kind, long displacement, Graph graph) { - return graph.unique(new ConstantLocationNode(identity, kind, displacement)); + return graph.unique(ConstantLocationNode.create(identity, kind, displacement)); } public static ConstantLocationNode create(LocationIdentity identity, Kind kind, long displacement) { - return new ConstantLocationNode(identity, kind, displacement); + return USE_GENERATED_NODES ? new ConstantLocationNodeGen(identity, kind, displacement) : new ConstantLocationNode(identity, kind, displacement); } - private ConstantLocationNode(LocationIdentity identity, Kind kind, long displacement) { + ConstantLocationNode(LocationIdentity identity, Kind kind, long displacement) { super(StampFactory.forVoid()); assert kind != Kind.Illegal && kind != Kind.Void; this.valueKind = kind; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedAccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedAccessNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedAccessNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,18 +23,19 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; /** * Accesses a value at an memory address specified by an {@linkplain #object object} and a * {@linkplain #accessLocation() location}. The access does not include a null check on the object. */ +@NodeInfo public abstract class FixedAccessNode extends DeoptimizingFixedWithNextNode implements Access { - @OptionalInput(InputType.Guard) private GuardingNode guard; - @Input private ValueNode object; - @Input(InputType.Association) private ValueNode location; + @OptionalInput(InputType.Guard) protected GuardingNode guard; + @Input protected ValueNode object; + @Input(InputType.Association) protected ValueNode location; private boolean nullCheck; private BarrierType barrierType; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,18 +23,24 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -public final class FixedValueAnchorNode extends FixedWithNextNode implements LIRLowerable, ValueProxy { +@NodeInfo +public class FixedValueAnchorNode extends FixedWithNextNode implements LIRLowerable, ValueProxy { - @Input private ValueNode object; + @Input ValueNode object; public ValueNode object() { return object; } - public FixedValueAnchorNode(ValueNode object) { + public static FixedValueAnchorNode create(ValueNode object) { + return USE_GENERATED_NODES ? new FixedValueAnchorNodeGen(object) : new FixedValueAnchorNode(object); + } + + FixedValueAnchorNode(ValueNode object) { super(StampFactory.forNodeIntrinsic()); this.object = object; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,11 +24,13 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; /** * An {@link FixedAccessNode} that can be converted to a {@link FloatingAccessNode}. */ +@NodeInfo public abstract class FloatableAccessNode extends FixedAccessNode { public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,13 +24,14 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +@NodeInfo public abstract class FloatingAccessNode extends FloatingGuardedNode implements Access, MemoryAccess { - @Input private ValueNode object; - @Input(InputType.Association) private LocationNode location; + @Input ValueNode object; + @Input(InputType.Association) LocationNode location; private BarrierType barrierType; public ValueNode object() { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -33,19 +34,33 @@ * A floating read of a value from memory specified in terms of an object base and an object * relative location. This node does not null check the object. */ -public final class FloatingReadNode extends FloatingAccessNode implements IterableNodeType, LIRLowerable, Canonicalizable { +@NodeInfo +public class FloatingReadNode extends FloatingAccessNode implements IterableNodeType, LIRLowerable, Canonicalizable { + + @OptionalInput(InputType.Memory) MemoryNode lastLocationAccess; - @OptionalInput(InputType.Memory) private MemoryNode lastLocationAccess; + public static FloatingReadNode create(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp) { + return USE_GENERATED_NODES ? new FloatingReadNodeGen(object, location, lastLocationAccess, stamp) : new FloatingReadNode(object, location, lastLocationAccess, stamp); + } - public FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp) { + FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp) { this(object, location, lastLocationAccess, stamp, null, BarrierType.NONE); } - public FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard) { + public static FloatingReadNode create(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard) { + return USE_GENERATED_NODES ? new FloatingReadNodeGen(object, location, lastLocationAccess, stamp, guard) : new FloatingReadNode(object, location, lastLocationAccess, stamp, guard); + } + + FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard) { this(object, location, lastLocationAccess, stamp, guard, BarrierType.NONE); } - public FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard, BarrierType barrierType) { + public static FloatingReadNode create(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard, BarrierType barrierType) { + return USE_GENERATED_NODES ? new FloatingReadNodeGen(object, location, lastLocationAccess, stamp, guard, barrierType) : new FloatingReadNode(object, location, lastLocationAccess, stamp, + guard, barrierType); + } + + FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard, BarrierType barrierType) { super(object, location, stamp, guard, barrierType); this.lastLocationAccess = lastLocationAccess; } @@ -69,14 +84,14 @@ @Override public Node canonical(CanonicalizerTool tool) { if (object() instanceof PiNode && ((PiNode) object()).getGuard() == getGuard()) { - return new FloatingReadNode(((PiNode) object()).getOriginalNode(), location(), getLastLocationAccess(), stamp(), getGuard(), getBarrierType()); + return FloatingReadNode.create(((PiNode) object()).getOriginalNode(), location(), getLastLocationAccess(), stamp(), getGuard(), getBarrierType()); } return ReadNode.canonicalizeRead(this, location(), object(), tool); } @Override public FixedAccessNode asFixedNode() { - return graph().add(new ReadNode(object(), accessLocation(), stamp(), getGuard(), getBarrierType())); + return graph().add(ReadNode.create(object(), accessLocation(), stamp(), getGuard(), getBarrierType())); } @Override diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -28,6 +28,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -37,31 +38,47 @@ @NodeInfo(nameTemplate = "ForeignCall#{p#descriptor/s}", allowedUsageTypes = {InputType.Memory}) public class ForeignCallNode extends AbstractMemoryCheckpoint implements LIRLowerable, DeoptimizingNode.DeoptDuring, MemoryCheckpoint.Multi { - @Input private final NodeInputList arguments; - @OptionalInput(InputType.State) private FrameState stateDuring; + @Input protected NodeInputList arguments; + @OptionalInput(InputType.State) protected FrameState stateDuring; private final ForeignCallsProvider foreignCalls; private final ForeignCallDescriptor descriptor; - public ForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) { + public static ForeignCallNode create(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) { + return USE_GENERATED_NODES ? new ForeignCallNodeGen(foreignCalls, descriptor, arguments) : new ForeignCallNode(foreignCalls, descriptor, arguments); + } + + ForeignCallNode(ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) { super(StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType()))); this.arguments = new NodeInputList<>(this, arguments); this.descriptor = descriptor; this.foreignCalls = foreignCalls; } - public ForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, List arguments) { + public static ForeignCallNode create(ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, List arguments) { + return USE_GENERATED_NODES ? new ForeignCallNodeGen(foreignCalls, descriptor, arguments) : new ForeignCallNode(foreignCalls, descriptor, arguments); + } + + ForeignCallNode(ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, List arguments) { this(foreignCalls, descriptor, StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType())), arguments); } - public ForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp, List arguments) { + public static ForeignCallNode create(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp, List arguments) { + return USE_GENERATED_NODES ? new ForeignCallNodeGen(foreignCalls, descriptor, stamp, arguments) : new ForeignCallNode(foreignCalls, descriptor, stamp, arguments); + } + + ForeignCallNode(ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp, List arguments) { super(stamp); this.arguments = new NodeInputList<>(this, arguments); this.descriptor = descriptor; this.foreignCalls = foreignCalls; } - protected ForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp) { + public static ForeignCallNode create(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp) { + return USE_GENERATED_NODES ? new ForeignCallNodeGen(foreignCalls, descriptor, stamp) : new ForeignCallNode(foreignCalls, descriptor, stamp); + } + + protected ForeignCallNode(ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp) { super(stamp); this.arguments = new NodeInputList<>(this); this.descriptor = descriptor; @@ -112,12 +129,13 @@ } @Override - public void computeStateDuring(FrameState stateAfter) { + public void computeStateDuring(FrameState currentStateAfter) { FrameState newStateDuring; - if ((stateAfter.stackSize() > 0 && stateAfter.stackAt(stateAfter.stackSize() - 1) == this) || (stateAfter.stackSize() > 1 && stateAfter.stackAt(stateAfter.stackSize() - 2) == this)) { - newStateDuring = stateAfter.duplicateModified(stateAfter.bci, stateAfter.rethrowException(), this.getKind()); + if ((currentStateAfter.stackSize() > 0 && currentStateAfter.stackAt(currentStateAfter.stackSize() - 1) == this) || + (currentStateAfter.stackSize() > 1 && currentStateAfter.stackAt(currentStateAfter.stackSize() - 2) == this)) { + newStateDuring = currentStateAfter.duplicateModified(currentStateAfter.bci, currentStateAfter.rethrowException(), this.getKind()); } else { - newStateDuring = stateAfter; + newStateDuring = currentStateAfter; } setStateDuring(newStateDuring); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -28,6 +28,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -38,12 +39,12 @@ * constants. */ @NodeInfo(nameTemplate = "IdxLoc {p#locationIdentity/s}") -public final class IndexedLocationNode extends LocationNode implements Canonicalizable { +public class IndexedLocationNode extends LocationNode implements Canonicalizable { private final Kind valueKind; private final LocationIdentity locationIdentity; private final long displacement; - @Input private ValueNode index; + @Input ValueNode index; private final int indexScaling; /** @@ -65,14 +66,14 @@ } public static IndexedLocationNode create(LocationIdentity identity, Kind kind, long displacement, ValueNode index, Graph graph, int indexScaling) { - return graph.unique(new IndexedLocationNode(identity, kind, displacement, index, indexScaling)); + return graph.unique(IndexedLocationNode.create(identity, kind, displacement, index, indexScaling)); } public static IndexedLocationNode create(LocationIdentity identity, Kind kind, long displacement, ValueNode index, int indexScaling) { - return new IndexedLocationNode(identity, kind, displacement, index, indexScaling); + return USE_GENERATED_NODES ? new IndexedLocationNodeGen(identity, kind, displacement, index, indexScaling) : new IndexedLocationNode(identity, kind, displacement, index, indexScaling); } - public IndexedLocationNode(LocationIdentity identity, Kind kind, long displacement, ValueNode index, int indexScaling) { + IndexedLocationNode(LocationIdentity identity, Kind kind, long displacement, ValueNode index, int indexScaling) { super(StampFactory.forVoid()); assert index != null; assert indexScaling != 0; diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,6 +27,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; @@ -35,7 +36,8 @@ * The {@code IntegerSwitchNode} represents a switch on integer keys, with a sorted array of key * values. The actual implementation of the switch will be decided by the backend. */ -public final class IntegerSwitchNode extends SwitchNode implements LIRLowerable, Simplifiable { +@NodeInfo +public class IntegerSwitchNode extends SwitchNode implements LIRLowerable, Simplifiable { private final int[] keys; @@ -49,7 +51,12 @@ * @param keyProbabilities the probabilities of the keys * @param keySuccessors the successor index for each key */ - public IntegerSwitchNode(ValueNode value, BeginNode[] successors, int[] keys, double[] keyProbabilities, int[] keySuccessors) { + public static IntegerSwitchNode create(ValueNode value, BeginNode[] successors, int[] keys, double[] keyProbabilities, int[] keySuccessors) { + return USE_GENERATED_NODES ? new IntegerSwitchNodeGen(value, successors, keys, keyProbabilities, keySuccessors) : new IntegerSwitchNode(value, successors, keys, keyProbabilities, + keySuccessors); + } + + IntegerSwitchNode(ValueNode value, BeginNode[] successors, int[] keys, double[] keyProbabilities, int[] keySuccessors) { super(value, successors, keySuccessors, keyProbabilities); assert keySuccessors.length == keys.length + 1; assert keySuccessors.length == keyProbabilities.length; @@ -75,7 +82,12 @@ * @param keyProbabilities the probabilities of the keys * @param keySuccessors the successor index for each key */ - public IntegerSwitchNode(ValueNode value, int successorCount, int[] keys, double[] keyProbabilities, int[] keySuccessors) { + public static IntegerSwitchNode create(ValueNode value, int successorCount, int[] keys, double[] keyProbabilities, int[] keySuccessors) { + return USE_GENERATED_NODES ? new IntegerSwitchNodeGen(value, successorCount, keys, keyProbabilities, keySuccessors) : new IntegerSwitchNode(value, successorCount, keys, keyProbabilities, + keySuccessors); + } + + IntegerSwitchNode(ValueNode value, int successorCount, int[] keys, double[] keyProbabilities, int[] keySuccessors) { this(value, new BeginNode[successorCount], keys, keyProbabilities, keySuccessors); } @@ -189,7 +201,7 @@ } BeginNode[] successorsArray = newSuccessors.toArray(new BeginNode[newSuccessors.size()]); - IntegerSwitchNode newSwitch = graph().add(new IntegerSwitchNode(value(), successorsArray, newKeys, newKeyProbabilities, newKeySuccessors)); + IntegerSwitchNode newSwitch = graph().add(IntegerSwitchNode.create(value(), successorsArray, newKeys, newKeyProbabilities, newKeySuccessors)); ((FixedWithNextNode) predecessor()).setNext(newSwitch); GraphUtil.killWithUnusedFloatingInputs(this); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -30,11 +31,16 @@ * Read a raw memory location according to Java field or array read semantics. It will perform read * barriers, implicit conversions and optionally oop uncompression. */ -public final class JavaReadNode extends FixedAccessNode implements Lowerable, GuardingNode { +@NodeInfo +public class JavaReadNode extends FixedAccessNode implements Lowerable, GuardingNode { private final boolean compressible; - public JavaReadNode(ValueNode object, LocationNode location, BarrierType barrierType, boolean compressible) { + public static JavaReadNode create(ValueNode object, LocationNode location, BarrierType barrierType, boolean compressible) { + return USE_GENERATED_NODES ? new JavaReadNodeGen(object, location, barrierType, compressible) : new JavaReadNode(object, location, barrierType, compressible); + } + + JavaReadNode(ValueNode object, LocationNode location, BarrierType barrierType, boolean compressible) { super(object, location, StampFactory.forKind(location.getValueKind()), barrierType); this.compressible = compressible; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaWriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaWriteNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaWriteNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,6 +22,7 @@ */ package com.oracle.graal.nodes.extended; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -29,11 +30,17 @@ * Write a raw memory location according to Java field or array write semantics. It will perform * write barriers, implicit conversions and optionally oop compression. */ -public final class JavaWriteNode extends AbstractWriteNode implements Lowerable, StateSplit, MemoryAccess, MemoryCheckpoint.Single { +@NodeInfo +public class JavaWriteNode extends AbstractWriteNode implements Lowerable, StateSplit, MemoryAccess, MemoryCheckpoint.Single { private final boolean compressible; - public JavaWriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible, boolean initialization) { + public static JavaWriteNode create(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible, boolean initialization) { + return USE_GENERATED_NODES ? new JavaWriteNodeGen(object, value, location, barrierType, compressible, initialization) : new JavaWriteNode(object, value, location, barrierType, compressible, + initialization); + } + + JavaWriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible, boolean initialization) { super(object, value, location, barrierType, initialization); this.compressible = compressible; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.api.meta.ResolvedJavaType.Representation; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -33,20 +34,29 @@ * Loads an object's {@linkplain Representation#ObjectHub hub}. The object is not null-checked by * this operation. */ -public final class LoadHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, Virtualizable { +@NodeInfo +public class LoadHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, Virtualizable { - @Input private ValueNode value; + @Input ValueNode value; public ValueNode getValue() { return value; } - public LoadHubNode(ValueNode value, Kind kind) { + public static LoadHubNode create(ValueNode value, Kind kind) { + return USE_GENERATED_NODES ? new LoadHubNodeGen(value, kind) : new LoadHubNode(value, kind); + } + + LoadHubNode(ValueNode value, Kind kind) { super(getKind(kind), null); this.value = value; } - public LoadHubNode(ValueNode value, Kind kind, ValueNode guard) { + public static LoadHubNode create(ValueNode value, Kind kind, ValueNode guard) { + return USE_GENERATED_NODES ? new LoadHubNodeGen(value, kind, guard) : new LoadHubNode(value, kind, guard); + } + + LoadHubNode(ValueNode value, Kind kind, ValueNode guard) { super(getKind(kind), (GuardingNode) guard); assert value != guard; this.value = value; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -33,9 +34,10 @@ /** * Loads a method from the virtual method table of a given hub. */ -public final class LoadMethodNode extends FixedWithNextNode implements Lowerable, Canonicalizable { +@NodeInfo +public class LoadMethodNode extends FixedWithNextNode implements Lowerable, Canonicalizable { - @Input private ValueNode hub; + @Input ValueNode hub; private final ResolvedJavaMethod method; private final ResolvedJavaType receiverType; @@ -43,7 +45,11 @@ return hub; } - public LoadMethodNode(ResolvedJavaMethod method, ResolvedJavaType receiverType, ValueNode hub, Kind kind) { + public static LoadMethodNode create(ResolvedJavaMethod method, ResolvedJavaType receiverType, ValueNode hub, Kind kind) { + return USE_GENERATED_NODES ? new LoadMethodNodeGen(method, receiverType, hub, kind) : new LoadMethodNode(method, receiverType, hub, kind); + } + + LoadMethodNode(ResolvedJavaMethod method, ResolvedJavaType receiverType, ValueNode hub, Kind kind) { super(kind == Kind.Object ? StampFactory.objectNonNull() : StampFactory.forKind(kind)); this.receiverType = receiverType; this.hub = hub; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,9 +24,9 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.ValueNumberable; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -32,7 +32,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -47,7 +47,11 @@ /** * @param barriers a mask of the barrier constants defined in {@link MemoryBarriers} */ - public MembarNode(int barriers) { + public static MembarNode create(int barriers) { + return USE_GENERATED_NODES ? new MembarNodeGen(barriers) : new MembarNode(barriers); + } + + MembarNode(int barriers) { super(StampFactory.forVoid()); this.barriers = barriers; } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryAccess.java Mon Aug 25 21:15:59 2014 -0700 @@ -32,7 +32,14 @@ LocationIdentity getLocationIdentity(); - MemoryNode getLastLocationAccess(); + default MemoryNode getLastLocationAccess() { + return null; + } - void setLastLocationAccess(MemoryNode lla); + /** + * @param lla the {@link MemoryNode} that represents the last kill of the location + */ + default void setLastLocationAccess(MemoryNode lla) { + // empty + } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,16 +23,20 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(allowedUsageTypes = {InputType.Guard}) public class NullCheckNode extends DeoptimizingFixedWithNextNode implements LIRLowerable, GuardingNode { - @Input private ValueNode object; + @Input ValueNode object; - public NullCheckNode(ValueNode object) { + public static NullCheckNode create(ValueNode object) { + return USE_GENERATED_NODES ? new NullCheckNodeGen(object) : new NullCheckNode(object); + } + + NullCheckNode(ValueNode object) { super(StampFactory.forVoid()); this.object = object; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRLocalNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRLocalNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRLocalNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,12 +24,17 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @NodeInfo(nameTemplate = "OSRLocal({p#index})") public class OSRLocalNode extends AbstractLocalNode implements IterableNodeType { - public OSRLocalNode(int index, Stamp stamp) { + public static OSRLocalNode create(int index, Stamp stamp) { + return USE_GENERATED_NODES ? new OSRLocalNodeGen(index, stamp) : new OSRLocalNode(index, stamp); + } + + OSRLocalNode(int index, Stamp stamp) { super(index, stamp); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRStartNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRStartNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRStartNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,10 +23,18 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public class OSRStartNode extends StartNode implements Lowerable { + public static OSRStartNode create() { + return USE_GENERATED_NODES ? new OSRStartNodeGen() : new OSRStartNode(); + } + + OSRStartNode() { + } @Override public void lower(LoweringTool tool) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -34,21 +35,39 @@ /** * Reads an {@linkplain FixedAccessNode accessed} value. */ -public final class ReadNode extends FloatableAccessNode implements LIRLowerable, Canonicalizable, PiPushable, Virtualizable, GuardingNode { +@NodeInfo +public class ReadNode extends FloatableAccessNode implements LIRLowerable, Canonicalizable, PiPushable, Virtualizable, GuardingNode { - public ReadNode(ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType) { + public static ReadNode create(ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType) { + return USE_GENERATED_NODES ? new ReadNodeGen(object, location, stamp, barrierType) : new ReadNode(object, location, stamp, barrierType); + } + + ReadNode(ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType) { super(object, location, stamp, null, barrierType); } - public ReadNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType) { + public static ReadNode create(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType) { + return USE_GENERATED_NODES ? new ReadNodeGen(object, location, stamp, guard, barrierType) : new ReadNode(object, location, stamp, guard, barrierType); + } + + ReadNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType) { super(object, location, stamp, guard, barrierType); } - public ReadNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck, FrameState stateBefore) { + public static ReadNode create(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck, FrameState stateBefore) { + return USE_GENERATED_NODES ? new ReadNodeGen(object, location, stamp, guard, barrierType, nullCheck, stateBefore) : new ReadNode(object, location, stamp, guard, barrierType, nullCheck, + stateBefore); + } + + ReadNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck, FrameState stateBefore) { super(object, location, stamp, guard, barrierType, nullCheck, stateBefore); } - private ReadNode(ValueNode object, ValueNode location, ValueNode guard, BarrierType barrierType) { + public static ReadNode create(ValueNode object, ValueNode location, ValueNode guard, BarrierType barrierType) { + return USE_GENERATED_NODES ? new ReadNodeGen(object, location, guard, barrierType) : new ReadNode(object, location, guard, barrierType); + } + + ReadNode(ValueNode object, ValueNode location, ValueNode guard, BarrierType barrierType) { /* * Used by node intrinsics. Really, you can trust me on that! Since the initial value for * location is a parameter, i.e., a ParameterNode, the constructor cannot use the declared @@ -67,17 +86,16 @@ @Override public Node canonical(CanonicalizerTool tool) { if (usages().isEmpty()) { - GuardingNode guard = getGuard(); - if (guard != null && !(guard instanceof FixedNode)) { + if (getGuard() != null && !(getGuard() instanceof FixedNode)) { // The guard is necessary even if the read goes away. - return new ValueAnchorNode((ValueNode) guard); + return ValueAnchorNode.create((ValueNode) getGuard()); } else { // Read without usages or guard can be safely removed. return null; } } if (object() instanceof PiNode && ((PiNode) object()).getGuard() == getGuard()) { - return new ReadNode(((PiNode) object()).getOriginalNode(), location(), stamp(), getGuard(), getBarrierType(), getNullCheck(), stateBefore()); + return ReadNode.create(((PiNode) object()).getOriginalNode(), location(), stamp(), getGuard(), getBarrierType(), getNullCheck(), stateBefore()); } if (!getNullCheck()) { return canonicalizeRead(this, location(), object(), tool); @@ -90,7 +108,7 @@ @Override public FloatingAccessNode asFloatingNode(MemoryNode lastLocationAccess) { - return graph().unique(new FloatingReadNode(object(), location(), lastLocationAccess, stamp(), getGuard(), getBarrierType())); + return graph().unique(FloatingReadNode.create(object(), location(), lastLocationAccess, stamp(), getGuard(), getBarrierType())); } @Override diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,13 +23,15 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -public final class StoreHubNode extends FixedWithNextNode implements Lowerable { +@NodeInfo +public class StoreHubNode extends FixedWithNextNode implements Lowerable { - @Input private ValueNode value; - @Input private ValueNode object; + @Input ValueNode value; + @Input ValueNode object; public ValueNode getValue() { return value; @@ -39,7 +41,11 @@ return object; } - private StoreHubNode(ValueNode object, ValueNode value) { + public static StoreHubNode create(ValueNode object, ValueNode value) { + return USE_GENERATED_NODES ? new StoreHubNodeGen(object, value) : new StoreHubNode(object, value); + } + + StoreHubNode(ValueNode object, ValueNode value) { super(StampFactory.forVoid()); this.value = value; this.object = object; diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,19 +22,23 @@ */ package com.oracle.graal.nodes.extended; +import java.util.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; /** * The {@code SwitchNode} class is the base of both lookup and table switches. */ +@NodeInfo public abstract class SwitchNode extends ControlSplitNode { - @Successor private final NodeSuccessorList successors; - @Input private ValueNode value; + @Successor protected NodeSuccessorList successors; + @Input protected ValueNode value; // do not change the contents of these arrays: private final double[] keyProbabilities; @@ -103,6 +107,10 @@ */ public abstract Constant keyAt(int i); + public boolean structureEquals(SwitchNode switchNode) { + return Arrays.equals(keySuccessors, switchNode.keySuccessors) && equalKeys(switchNode); + } + /** * Returns true if the switch has the same keys in the same order as this switch. */ diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,15 +25,21 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public class UnboxNode extends UnaryNode implements Virtualizable, Lowerable { private final Kind boxingKind; - public UnboxNode(ValueNode value, Kind boxingKind) { + public static UnboxNode create(ValueNode value, Kind boxingKind) { + return USE_GENERATED_NODES ? new UnboxNodeGen(value, boxingKind) : new UnboxNode(value, boxingKind); + } + + UnboxNode(ValueNode value, Kind boxingKind) { super(StampFactory.forKind(boxingKind.getStackKind()), value); this.boxingKind = boxingKind; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,13 +26,15 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; +@NodeInfo public abstract class UnsafeAccessNode extends FixedWithNextNode implements Canonicalizable { - @Input private ValueNode object; - @Input private ValueNode offset; + @Input ValueNode object; + @Input ValueNode offset; private final Kind accessKind; private final LocationIdentity locationIdentity; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -36,21 +37,34 @@ * information, i.e., an unsafe cast is removed if the input object has a more precise or equal type * than the type this nodes casts to. */ +@NodeInfo public class UnsafeCastNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, GuardingNode, IterableNodeType, Canonicalizable, ValueProxy { - @Input private ValueNode object; + @Input ValueNode object; - public UnsafeCastNode(ValueNode object, Stamp stamp) { + public static UnsafeCastNode create(ValueNode object, Stamp stamp) { + return USE_GENERATED_NODES ? new UnsafeCastNodeGen(object, stamp) : new UnsafeCastNode(object, stamp); + } + + UnsafeCastNode(ValueNode object, Stamp stamp) { super(stamp); this.object = object; } - public UnsafeCastNode(ValueNode object, Stamp stamp, ValueNode anchor) { + public static UnsafeCastNode create(ValueNode object, Stamp stamp, ValueNode anchor) { + return USE_GENERATED_NODES ? new UnsafeCastNodeGen(object, stamp, anchor) : new UnsafeCastNode(object, stamp, anchor); + } + + UnsafeCastNode(ValueNode object, Stamp stamp, ValueNode anchor) { super(stamp, (GuardingNode) anchor); this.object = object; } - public UnsafeCastNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) { + public static UnsafeCastNode create(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) { + return USE_GENERATED_NODES ? new UnsafeCastNodeGen(object, toType, exactType, nonNull) : new UnsafeCastNode(object, toType, exactType, nonNull); + } + + UnsafeCastNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) { this(object, toType.getKind() == Kind.Object ? StampFactory.object(toType, exactType, nonNull || StampTool.isObjectNonNull(object.stamp())) : StampFactory.forKind(toType.getKind())); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,7 +26,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; @@ -35,14 +35,23 @@ * Load of a value from a location specified as an offset relative to an object. No null check is * performed before the load. */ +@NodeInfo public class UnsafeLoadNode extends UnsafeAccessNode implements Lowerable, Virtualizable { - @OptionalInput(InputType.Condition) private LogicNode guardingCondition; + @OptionalInput(InputType.Condition) LogicNode guardingCondition; - public UnsafeLoadNode(ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity) { + public static UnsafeLoadNode create(ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity) { + return USE_GENERATED_NODES ? new UnsafeLoadNodeGen(object, offset, accessKind, locationIdentity) : new UnsafeLoadNode(object, offset, accessKind, locationIdentity); + } + + UnsafeLoadNode(ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity) { this(object, offset, accessKind, locationIdentity, null); } - public UnsafeLoadNode(ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity, LogicNode condition) { + public static UnsafeLoadNode create(ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity, LogicNode condition) { + return USE_GENERATED_NODES ? new UnsafeLoadNodeGen(object, offset, accessKind, locationIdentity, condition) : new UnsafeLoadNode(object, offset, accessKind, locationIdentity, condition); + } + + UnsafeLoadNode(ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity, LogicNode condition) { super(StampFactory.forKind(accessKind.getStackKind()), object, offset, accessKind, locationIdentity); this.guardingCondition = condition; } @@ -62,8 +71,8 @@ if (state != null && state.getState() == EscapeState.Virtual) { ValueNode offsetValue = tool.getReplacedValue(offset()); if (offsetValue.isConstant()) { - long offset = offsetValue.asConstant().asLong(); - int entryIndex = state.getVirtualObject().entryIndexForOffset(offset); + long off = offsetValue.asConstant().asLong(); + int entryIndex = state.getVirtualObject().entryIndexForOffset(off); if (entryIndex != -1) { ValueNode entry = state.getEntry(entryIndex); if (entry.getKind() == getKind() || state.getVirtualObject().entryKind(entryIndex) == accessKind()) { @@ -76,12 +85,12 @@ @Override protected ValueNode cloneAsFieldAccess(ResolvedJavaField field) { - return new LoadFieldNode(object(), field); + return LoadFieldNode.create(object(), field); } @Override protected ValueNode cloneAsArrayAccess(ValueNode location, LocationIdentity identity) { - return new UnsafeLoadNode(object(), location, accessKind(), identity); + return UnsafeLoadNode.create(object(), location, accessKind(), identity, guardingCondition); } @SuppressWarnings({"unchecked", "unused"}) diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,7 +26,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; @@ -35,16 +35,26 @@ * Store of a value at a location specified as an offset relative to an object. No null check is * performed before the store. */ +@NodeInfo public class UnsafeStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, MemoryCheckpoint.Single { - @Input private ValueNode value; - @OptionalInput(InputType.State) private FrameState stateAfter; + @Input ValueNode value; + @OptionalInput(InputType.State) FrameState stateAfter; - public UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, LocationIdentity locationIdentity) { + public static UnsafeStoreNode create(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, LocationIdentity locationIdentity) { + return USE_GENERATED_NODES ? new UnsafeStoreNodeGen(object, offset, value, accessKind, locationIdentity) : new UnsafeStoreNode(object, offset, value, accessKind, locationIdentity); + } + + UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, LocationIdentity locationIdentity) { this(object, offset, value, accessKind, locationIdentity, null); } - public UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, LocationIdentity locationIdentity, FrameState stateAfter) { + public static UnsafeStoreNode create(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, LocationIdentity locationIdentity, FrameState stateAfter) { + return USE_GENERATED_NODES ? new UnsafeStoreNodeGen(object, offset, value, accessKind, locationIdentity, stateAfter) : new UnsafeStoreNode(object, offset, value, accessKind, locationIdentity, + stateAfter); + } + + UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, LocationIdentity locationIdentity, FrameState stateAfter) { super(StampFactory.forVoid(), object, offset, accessKind, locationIdentity); this.value = value; this.stateAfter = stateAfter; @@ -80,8 +90,8 @@ if (state != null && state.getState() == EscapeState.Virtual) { ValueNode indexValue = tool.getReplacedValue(offset()); if (indexValue.isConstant()) { - long offset = indexValue.asConstant().asLong(); - int entryIndex = state.getVirtualObject().entryIndexForOffset(offset); + long off = indexValue.asConstant().asLong(); + int entryIndex = state.getVirtualObject().entryIndexForOffset(off); if (entryIndex != -1) { Kind entryKind = state.getVirtualObject().entryKind(entryIndex); ValueNode entry = state.getEntry(entryIndex); @@ -90,7 +100,7 @@ tool.delete(); } else { if ((accessKind() == Kind.Long || accessKind() == Kind.Double) && entryKind == Kind.Int) { - int nextIndex = state.getVirtualObject().entryIndexForOffset(offset + 4); + int nextIndex = state.getVirtualObject().entryIndexForOffset(off + 4); if (nextIndex != -1) { Kind nextKind = state.getVirtualObject().entryKind(nextIndex); if (nextKind == Kind.Int) { @@ -108,12 +118,12 @@ @Override protected ValueNode cloneAsFieldAccess(ResolvedJavaField field) { - return new StoreFieldNode(object(), field, value(), stateAfter()); + return StoreFieldNode.create(object(), field, value(), stateAfter()); } @Override protected ValueNode cloneAsArrayAccess(ValueNode location, LocationIdentity identity) { - return new UnsafeStoreNode(object(), location, value, accessKind(), identity); + return UnsafeStoreNode.create(object(), location, value, accessKind(), identity, stateAfter()); } public FrameState getState() { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,8 +23,8 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -34,11 +34,15 @@ * The ValueAnchor instruction keeps non-CFG (floating) nodes above a certain point in the graph. */ @NodeInfo(allowedUsageTypes = {InputType.Anchor, InputType.Guard}) -public final class ValueAnchorNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, Virtualizable, AnchoringNode, GuardingNode { +public class ValueAnchorNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, Virtualizable, AnchoringNode, GuardingNode { + + @OptionalInput(InputType.Guard) ValueNode anchored; - @OptionalInput(InputType.Guard) private ValueNode anchored; + public static ValueAnchorNode create(ValueNode value) { + return USE_GENERATED_NODES ? new ValueAnchorNodeGen(value) : new ValueAnchorNode(value); + } - public ValueAnchorNode(ValueNode value) { + ValueAnchorNode(ValueNode value) { super(StampFactory.forVoid()); this.anchored = value; } @@ -66,13 +70,13 @@ } } if (usages().isEmpty() && next() instanceof FixedAccessNode) { - FixedAccessNode next = (FixedAccessNode) next(); - if (next.getGuard() == anchored) { + FixedAccessNode currentNext = (FixedAccessNode) next(); + if (currentNext.getGuard() == anchored) { GraphUtil.removeFixedWithUnusedInputs(this); return; - } else if (next.getGuard() == null && anchored instanceof GuardNode && ((GuardNode) anchored).condition() instanceof IsNullNode) { + } else if (currentNext.getGuard() == null && anchored instanceof GuardNode && ((GuardNode) anchored).condition() instanceof IsNullNode) { // coalesce null check guards into subsequent read/write - next.setGuard((GuardingNode) anchored); + currentNext.setGuard((GuardingNode) anchored); tool.addToWorkList(next()); return; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.LocationNode.Location; import com.oracle.graal.nodes.spi.*; @@ -32,17 +33,30 @@ /** * Writes a given {@linkplain #value() value} a {@linkplain FixedAccessNode memory location}. */ -public final class WriteNode extends AbstractWriteNode implements LIRLowerable, Simplifiable, Virtualizable { +@NodeInfo +public class WriteNode extends AbstractWriteNode implements LIRLowerable, Simplifiable, Virtualizable { - public WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType) { + public static WriteNode create(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType) { + return USE_GENERATED_NODES ? new WriteNodeGen(object, value, location, barrierType) : new WriteNode(object, value, location, barrierType); + } + + WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType) { super(object, value, location, barrierType); } - public WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean initialization) { + public static WriteNode create(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean initialization) { + return USE_GENERATED_NODES ? new WriteNodeGen(object, value, location, barrierType, initialization) : new WriteNode(object, value, location, barrierType, initialization); + } + + WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean initialization) { super(object, value, location, barrierType, initialization); } - public WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, GuardingNode guard, boolean initialization) { + public static WriteNode create(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, GuardingNode guard, boolean initialization) { + return USE_GENERATED_NODES ? new WriteNodeGen(object, value, location, barrierType, guard, initialization) : new WriteNode(object, value, location, barrierType, guard, initialization); + } + + WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, GuardingNode guard, boolean initialization) { super(object, value, location, barrierType, guard, initialization); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,15 +24,17 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; /** * The {@code AbstractNewArrayNode} is used for all 1-dimensional array allocations. */ +@NodeInfo public class AbstractNewArrayNode extends AbstractNewObjectNode implements ArrayLengthProvider { - @Input private ValueNode length; + @Input ValueNode length; @Override public ValueNode length() { @@ -41,11 +43,15 @@ /** * Constructs a new AbstractNewArrayNode. - * + * * @param stamp the stamp of the newly created array * @param length the node that produces the length for this allocation. * @param fillContents determines whether the array elements should be initialized to zero/null. */ + public static AbstractNewArrayNode create(Stamp stamp, ValueNode length, boolean fillContents) { + return USE_GENERATED_NODES ? new AbstractNewArrayNodeGen(stamp, length, fillContents) : new AbstractNewArrayNode(stamp, length, fillContents); + } + protected AbstractNewArrayNode(Stamp stamp, ValueNode length, boolean fillContents) { super(stamp, fillContents); this.length = length; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,6 +27,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -34,6 +35,7 @@ /** * The {@code AbstractNewObjectNode} is the base class for the new instance and new array nodes. */ +@NodeInfo public class AbstractNewObjectNode extends DeoptimizingFixedWithNextNode implements Simplifiable, Lowerable { private final boolean fillContents; @@ -44,6 +46,10 @@ * @param stamp the stamp of the newly created object * @param fillContents determines if the object's contents should be initialized to zero/null. */ + public static AbstractNewObjectNode create(Stamp stamp, boolean fillContents) { + return USE_GENERATED_NODES ? new AbstractNewObjectNodeGen(stamp, fillContents) : new AbstractNewObjectNode(stamp, fillContents); + } + protected AbstractNewObjectNode(Stamp stamp, boolean fillContents) { super(stamp); this.fillContents = fillContents; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessArrayNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessArrayNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,14 +23,16 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; /** * This the base class of all array operations. */ +@NodeInfo public abstract class AccessArrayNode extends FixedWithNextNode { - @Input private ValueNode array; + @Input protected ValueNode array; public ValueNode array() { return array; @@ -38,7 +40,7 @@ /** * Creates a new AccessArrayNode. - * + * * @param array the instruction that produces the array object value */ public AccessArrayNode(Stamp stamp, ValueNode array) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,15 +24,17 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; /** * The base class of all instructions that access fields. */ +@NodeInfo public abstract class AccessFieldNode extends FixedWithNextNode implements Lowerable { - @OptionalInput private ValueNode object; + @OptionalInput ValueNode object; protected final ResolvedJavaField field; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -31,9 +32,10 @@ * The {@code AccessIndexedNode} class is the base class of instructions that read or write elements * of an array. */ +@NodeInfo public abstract class AccessIndexedNode extends AccessArrayNode implements Lowerable { - @Input private ValueNode index; + @Input protected ValueNode index; private final Kind elementKind; public ValueNode index() { @@ -42,7 +44,7 @@ /** * Create an new AccessIndexedNode. - * + * * @param stamp the result kind of the access * @param array the instruction producing the array * @param index the instruction producing the index @@ -56,7 +58,7 @@ /** * Gets the element type of the array. - * + * * @return the element type */ public Kind elementKind() { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,7 +24,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -37,9 +37,9 @@ @NodeInfo(allowedUsageTypes = {InputType.Memory}) public abstract class AccessMonitorNode extends AbstractMemoryCheckpoint implements MemoryCheckpoint, DeoptimizingNode.DeoptBefore, DeoptimizingNode.DeoptAfter { - @OptionalInput(InputType.State) private FrameState stateBefore; - @Input private ValueNode object; - @Input(InputType.Association) private MonitorIdNode monitorId; + @OptionalInput(InputType.State) FrameState stateBefore; + @Input ValueNode object; + @Input(InputType.Association) MonitorIdNode monitorId; @Override public boolean canDeoptimize() { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; @@ -32,9 +33,10 @@ /** * The {@code ArrayLength} instruction gets the length of an array. */ -public final class ArrayLengthNode extends FixedWithNextNode implements Canonicalizable.Unary, Lowerable, Virtualizable { +@NodeInfo +public class ArrayLengthNode extends FixedWithNextNode implements Canonicalizable.Unary, Lowerable, Virtualizable { - @Input private ValueNode array; + @Input ValueNode array; public ValueNode array() { return array; @@ -44,7 +46,11 @@ return array; } - public ArrayLengthNode(ValueNode array) { + public static ArrayLengthNode create(ValueNode array) { + return USE_GENERATED_NODES ? new ArrayLengthNodeGen(array) : new ArrayLengthNode(array); + } + + ArrayLengthNode(ValueNode array) { super(StampFactory.positiveInt()); this.array = array; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,29 +23,32 @@ package com.oracle.graal.nodes.java; import static com.oracle.graal.compiler.common.UnsafeAccess.*; +import sun.misc.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import sun.misc.*; - /** * Represents an atomic read-and-add operation like {@link Unsafe#getAndAddInt(Object, long, int)}. */ @NodeInfo(allowedUsageTypes = {InputType.Memory}) public class AtomicReadAndAddNode extends AbstractMemoryCheckpoint implements LIRLowerable, MemoryCheckpoint.Single { - @Input private ValueNode object; - @Input private ValueNode offset; - @Input private ValueNode delta; + @Input ValueNode object; + @Input ValueNode offset; + @Input ValueNode delta; private final LocationIdentity locationIdentity; - public AtomicReadAndAddNode(ValueNode object, ValueNode offset, ValueNode delta, LocationIdentity locationIdentity) { + public static AtomicReadAndAddNode create(ValueNode object, ValueNode offset, ValueNode delta, LocationIdentity locationIdentity) { + return USE_GENERATED_NODES ? new AtomicReadAndAddNodeGen(object, offset, delta, locationIdentity) : new AtomicReadAndAddNode(object, offset, delta, locationIdentity); + } + + AtomicReadAndAddNode(ValueNode object, ValueNode offset, ValueNode delta, LocationIdentity locationIdentity) { super(StampFactory.forKind(delta.getKind())); this.object = object; this.offset = offset; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndWriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndWriteNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndWriteNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,29 +23,35 @@ package com.oracle.graal.nodes.java; import static com.oracle.graal.compiler.common.UnsafeAccess.*; +import sun.misc.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import sun.misc.*; - /** * Represents an atomic read-and-write operation like {@link Unsafe#getAndSetInt(Object, long, int)} * . */ +@NodeInfo public class AtomicReadAndWriteNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single { - @Input private ValueNode object; - @Input private ValueNode offset; - @Input private ValueNode newValue; + @Input ValueNode object; + @Input ValueNode offset; + @Input ValueNode newValue; private final Kind valueKind; private final LocationIdentity locationIdentity; - public AtomicReadAndWriteNode(ValueNode object, ValueNode offset, ValueNode newValue, Kind valueKind, LocationIdentity locationIdentity) { + public static AtomicReadAndWriteNode create(ValueNode object, ValueNode offset, ValueNode newValue, Kind valueKind, LocationIdentity locationIdentity) { + return USE_GENERATED_NODES ? new AtomicReadAndWriteNodeGen(object, offset, newValue, valueKind, locationIdentity) : new AtomicReadAndWriteNode(object, offset, newValue, valueKind, + locationIdentity); + } + + AtomicReadAndWriteNode(ValueNode object, ValueNode offset, ValueNode newValue, Kind valueKind, LocationIdentity locationIdentity) { super(StampFactory.forKind(newValue.getKind())); this.object = object; this.offset = offset; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -32,10 +33,11 @@ * Implements a type check where the type being checked is loaded at runtime. This is used, for * instance, to implement an object array store check. */ -public final class CheckCastDynamicNode extends FixedWithNextNode implements Canonicalizable.Binary, Lowerable { +@NodeInfo +public class CheckCastDynamicNode extends FixedWithNextNode implements Canonicalizable.Binary, Lowerable { - @Input private ValueNode object; - @Input private ValueNode hub; + @Input ValueNode object; + @Input ValueNode hub; /** * Determines the exception thrown by this node if the check fails: {@link ClassCastException} @@ -47,7 +49,11 @@ * @param hub the type being cast to * @param object the object being cast */ - public CheckCastDynamicNode(ValueNode hub, ValueNode object, boolean forStoreCheck) { + public static CheckCastDynamicNode create(ValueNode hub, ValueNode object, boolean forStoreCheck) { + return USE_GENERATED_NODES ? new CheckCastDynamicNodeGen(hub, object, forStoreCheck) : new CheckCastDynamicNode(hub, object, forStoreCheck); + } + + CheckCastDynamicNode(ValueNode hub, ValueNode object, boolean forStoreCheck) { super(object.stamp()); this.hub = hub; this.object = object; @@ -95,7 +101,7 @@ if (forHub.isConstant()) { ResolvedJavaType t = tool.getConstantReflection().asJavaType(forHub.asConstant()); if (t != null) { - return new CheckCastNode(t, forObject, null, forStoreCheck); + return CheckCastNode.create(t, forObject, null, forStoreCheck); } } return this; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -31,6 +31,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -39,9 +40,10 @@ /** * Implements a type check against a compile-time known type. */ +@NodeInfo public class CheckCastNode extends FixedWithNextNode implements Canonicalizable, Simplifiable, Lowerable, Virtualizable, ValueProxy { - @Input private ValueNode object; + @Input ValueNode object; private final ResolvedJavaType type; private final JavaTypeProfile profile; @@ -57,7 +59,11 @@ * @param type the type being cast to * @param object the instruction producing the object */ - public CheckCastNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile, boolean forStoreCheck) { + public static CheckCastNode create(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile, boolean forStoreCheck) { + return USE_GENERATED_NODES ? new CheckCastNodeGen(type, object, profile, forStoreCheck) : new CheckCastNode(type, object, profile, forStoreCheck); + } + + CheckCastNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile, boolean forStoreCheck) { super(StampFactory.declared(type)); assert type != null; this.type = type; @@ -109,12 +115,12 @@ condition = LogicConstantNode.contradiction(graph()); stamp = StampFactory.declared(type); } else if (StampTool.isObjectNonNull(object)) { - condition = graph().addWithoutUnique(new InstanceOfNode(type, object, profile)); + condition = graph().addWithoutUnique(InstanceOfNode.create(type, object, profile)); } else { if (profile != null && profile.getNullSeen() == TriState.FALSE) { - FixedGuardNode nullCheck = graph().add(new FixedGuardNode(graph().unique(new IsNullNode(object)), UnreachedCode, InvalidateReprofile, true)); - PiNode nullGuarded = graph().unique(new PiNode(object, object().stamp().join(StampFactory.objectNonNull()), nullCheck)); - InstanceOfNode typeTest = graph().addWithoutUnique(new InstanceOfNode(type, nullGuarded, profile)); + FixedGuardNode nullCheck = graph().add(FixedGuardNode.create(graph().unique(IsNullNode.create(object)), UnreachedCode, InvalidateReprofile, true)); + PiNode nullGuarded = graph().unique(PiNode.create(object, object().stamp().join(StampFactory.objectNonNull()), nullCheck)); + InstanceOfNode typeTest = graph().addWithoutUnique(InstanceOfNode.create(type, nullGuarded, profile)); graph().addBeforeFixed(this, nullCheck); condition = typeTest; /* @@ -128,11 +134,11 @@ } else { // TODO (ds) replace with probability of null-seen when available double shortCircuitProbability = NOT_FREQUENT_PROBABILITY; - InstanceOfNode typeTest = graph().addWithoutUnique(new InstanceOfNode(type, object, profile)); - condition = LogicNode.or(graph().unique(new IsNullNode(object)), typeTest, shortCircuitProbability); + InstanceOfNode typeTest = graph().addWithoutUnique(InstanceOfNode.create(type, object, profile)); + condition = LogicNode.or(graph().unique(IsNullNode.create(object)), typeTest, shortCircuitProbability); } } - GuardingPiNode checkedObject = graph().add(new GuardingPiNode(theValue, condition, false, forStoreCheck ? ArrayStoreException : ClassCastException, InvalidateReprofile, stamp)); + GuardingPiNode checkedObject = graph().add(GuardingPiNode.create(theValue, condition, false, forStoreCheck ? ArrayStoreException : ClassCastException, InvalidateReprofile, stamp)); graph().replaceFixedWithFixed(this, checkedObject); checkedObject.lower(tool); } @@ -164,7 +170,7 @@ if (exactType != null && !exactType.equals(type)) { // Propagate more precise type information to usages of the checkcast. tool.assumptions().recordConcreteSubtype(type, exactType); - return new CheckCastNode(exactType, object, profile, forStoreCheck); + return CheckCastNode.create(exactType, object, profile, forStoreCheck); } } @@ -179,7 +185,7 @@ CheckCastNode ccn = (CheckCastNode) predecessor(); if (ccn != null && ccn.type != null && ccn == object && ccn.forStoreCheck == forStoreCheck && ccn.type.isAssignableFrom(type)) { StructuredGraph graph = ccn.graph(); - CheckCastNode newccn = graph.add(new CheckCastNode(type, ccn.object, ccn.profile, ccn.forStoreCheck)); + CheckCastNode newccn = graph.add(CheckCastNode.create(type, ccn.object, ccn.profile, ccn.forStoreCheck)); graph.replaceFixedWithFixed(ccn, newccn); replaceAtUsages(newccn); graph.removeFixed(this); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,7 +26,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -38,15 +38,20 @@ @NodeInfo(allowedUsageTypes = {InputType.Memory}) public class CompareAndSwapNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single { - @Input private ValueNode object; - @Input private ValueNode offset; - @Input private ValueNode expected; - @Input private ValueNode newValue; + @Input ValueNode object; + @Input ValueNode offset; + @Input ValueNode expected; + @Input ValueNode newValue; private final Kind valueKind; private final LocationIdentity locationIdentity; - public CompareAndSwapNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, Kind valueKind, LocationIdentity locationIdentity) { + public static CompareAndSwapNode create(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, Kind valueKind, LocationIdentity locationIdentity) { + return USE_GENERATED_NODES ? new CompareAndSwapNodeGen(object, offset, expected, newValue, valueKind, locationIdentity) : new CompareAndSwapNode(object, offset, expected, newValue, valueKind, + locationIdentity); + } + + CompareAndSwapNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, Kind valueKind, LocationIdentity locationIdentity) { super(StampFactory.forKind(Kind.Boolean.getStackKind())); assert expected.stamp().isCompatible(newValue.stamp()); this.object = object; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -30,21 +30,31 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; /** * The {@code DynamicNewArrayNode} is used for allocation of arrays when the type is not a * compile-time constant. */ +@NodeInfo public class DynamicNewArrayNode extends AbstractNewArrayNode { - @Input private ValueNode elementType; + @Input ValueNode elementType; - public DynamicNewArrayNode(ValueNode elementType, ValueNode length) { + public static DynamicNewArrayNode create(ValueNode elementType, ValueNode length) { + return USE_GENERATED_NODES ? new DynamicNewArrayNodeGen(elementType, length) : new DynamicNewArrayNode(elementType, length); + } + + DynamicNewArrayNode(ValueNode elementType, ValueNode length) { this(elementType, length, true); } - public DynamicNewArrayNode(ValueNode elementType, ValueNode length, boolean fillContents) { + public static DynamicNewArrayNode create(ValueNode elementType, ValueNode length, boolean fillContents) { + return USE_GENERATED_NODES ? new DynamicNewArrayNodeGen(elementType, length, fillContents) : new DynamicNewArrayNode(elementType, length, fillContents); + } + + DynamicNewArrayNode(ValueNode elementType, ValueNode length, boolean fillContents) { super(StampFactory.objectNonNull(), length, fillContents); this.elementType = elementType; } @@ -58,8 +68,8 @@ if (isAlive() && elementType.isConstant()) { ResolvedJavaType javaType = tool.getConstantReflection().asJavaType(elementType.asConstant()); if (javaType != null && !javaType.equals(tool.getMetaAccess().lookupJavaType(void.class))) { - ValueNode length = length(); - NewArrayNode newArray = graph().add(new NewArrayNode(javaType, length.isAlive() ? length : graph().addOrUniqueWithInputs(length), fillContents())); + ValueNode len = length(); + NewArrayNode newArray = graph().add(NewArrayNode.create(javaType, len.isAlive() ? len : graph().addOrUniqueWithInputs(len), fillContents())); List snapshot = inputs().snapshot(); graph().replaceFixedWithFixed(this, newArray); for (Node input : snapshot) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,13 +26,19 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +@NodeInfo public class DynamicNewInstanceNode extends AbstractNewObjectNode implements Canonicalizable { - @Input private ValueNode clazz; + @Input ValueNode clazz; - public DynamicNewInstanceNode(ValueNode clazz, boolean fillContents) { + public static DynamicNewInstanceNode create(ValueNode clazz, boolean fillContents) { + return USE_GENERATED_NODES ? new DynamicNewInstanceNodeGen(clazz, fillContents) : new DynamicNewInstanceNode(clazz, fillContents); + } + + DynamicNewInstanceNode(ValueNode clazz, boolean fillContents) { super(StampFactory.objectNonNull(), fillContents); this.clazz = clazz; } @@ -42,7 +48,7 @@ if (clazz.isConstant()) { ResolvedJavaType type = tool.getConstantReflection().asJavaType(clazz.asConstant()); if (type != null && type.isInitialized() && !type.isArray() && !type.isInterface() && !type.isPrimitive()) { - return new NewInstanceNode(type, fillContents()); + return NewInstanceNode.create(type, fillContents()); } } return this; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,7 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -36,7 +36,11 @@ @NodeInfo(allowedUsageTypes = {InputType.Memory}) public class ExceptionObjectNode extends DispatchBeginNode implements Lowerable, MemoryCheckpoint.Single { - public ExceptionObjectNode(MetaAccessProvider metaAccess) { + public static ExceptionObjectNode create(MetaAccessProvider metaAccess) { + return USE_GENERATED_NODES ? new ExceptionObjectNodeGen(metaAccess) : new ExceptionObjectNode(metaAccess); + } + + ExceptionObjectNode(MetaAccessProvider metaAccess) { super(StampFactory.declaredNonNull(metaAccess.lookupJavaType(Throwable.class))); } @@ -53,8 +57,8 @@ * deopts can float in between the begin node and the load exception node. */ LocationIdentity locationsKilledByInvoke = ((InvokeWithExceptionNode) predecessor()).getLocationIdentity(); - BeginNode entry = graph().add(new KillingBeginNode(locationsKilledByInvoke)); - LoadExceptionObjectNode loadException = graph().add(new LoadExceptionObjectNode(stamp())); + BeginNode entry = graph().add(KillingBeginNode.create(locationsKilledByInvoke)); + LoadExceptionObjectNode loadException = graph().add(LoadExceptionObjectNode.create(stamp())); loadException.setStateAfter(stateAfter()); replaceAtUsages(InputType.Value, loadException); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -33,16 +34,21 @@ * known at compile time. This is used, for instance, to intrinsify {@link Class#isInstance(Object)} * . */ -public final class InstanceOfDynamicNode extends LogicNode implements Canonicalizable.Binary, Lowerable { +@NodeInfo +public class InstanceOfDynamicNode extends LogicNode implements Canonicalizable.Binary, Lowerable { - @Input private ValueNode object; - @Input private ValueNode mirror; + @Input ValueNode object; + @Input ValueNode mirror; /** * @param mirror the {@link Class} value representing the target target type of the test * @param object the object being tested */ - public InstanceOfDynamicNode(ValueNode mirror, ValueNode object) { + public static InstanceOfDynamicNode create(ValueNode mirror, ValueNode object) { + return USE_GENERATED_NODES ? new InstanceOfDynamicNodeGen(mirror, object) : new InstanceOfDynamicNode(mirror, object); + } + + InstanceOfDynamicNode(ValueNode mirror, ValueNode object) { this.mirror = mirror; this.object = object; assert mirror.getKind() == Kind.Object : mirror.getKind(); @@ -62,7 +68,7 @@ if (t.isPrimitive()) { return LogicConstantNode.contradiction(); } else { - return new InstanceOfNode(t, forObject, null); + return InstanceOfNode.create(t, forObject, null); } } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -32,6 +33,7 @@ /** * The {@code InstanceOfNode} represents an instanceof test. */ +@NodeInfo public class InstanceOfNode extends UnaryOpLogicNode implements Lowerable, Virtualizable { private final ResolvedJavaType type; @@ -43,7 +45,11 @@ * @param type the target type of the instanceof check * @param object the object being tested by the instanceof */ - public InstanceOfNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile) { + public static InstanceOfNode create(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile) { + return USE_GENERATED_NODES ? new InstanceOfNodeGen(type, object, profile) : new InstanceOfNode(type, object, profile); + } + + InstanceOfNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile) { super(object); this.type = type; this.profile = profile; @@ -112,7 +118,7 @@ if (!nonNull) { // the instanceof matches if the object is non-null, so return true // depending on the null-ness. - return new LogicNegationNode(new IsNullNode(forValue)); + return LogicNegationNode.create(IsNullNode.create(forValue)); } } return null; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,12 +23,18 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public class LoadExceptionObjectNode extends AbstractStateSplit implements Lowerable { - public LoadExceptionObjectNode(Stamp stamp) { + public static LoadExceptionObjectNode create(Stamp stamp) { + return USE_GENERATED_NODES ? new LoadExceptionObjectNodeGen(stamp) : new LoadExceptionObjectNode(stamp); + } + + LoadExceptionObjectNode(Stamp stamp) { super(stamp); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,8 +26,8 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -37,7 +37,7 @@ * The {@code LoadFieldNode} represents a read of a static or instance field. */ @NodeInfo(nameTemplate = "LoadField#{p#field/s}") -public final class LoadFieldNode extends AccessFieldNode implements Canonicalizable.Unary, VirtualizableRoot { +public class LoadFieldNode extends AccessFieldNode implements Canonicalizable.Unary, VirtualizableRoot { /** * Creates a new LoadFieldNode instance. @@ -45,7 +45,11 @@ * @param object the receiver object * @param field the compiler interface field */ - public LoadFieldNode(ValueNode object, ResolvedJavaField field) { + public static LoadFieldNode create(ValueNode object, ResolvedJavaField field) { + return USE_GENERATED_NODES ? new LoadFieldNodeGen(object, field) : new LoadFieldNode(object, field); + } + + protected LoadFieldNode(ValueNode object, ResolvedJavaField field) { super(createStamp(field), object, field); } @@ -78,7 +82,7 @@ } } if (!isStatic() && forObject.isNullConstant()) { - return new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.NullCheckException); + return DeoptimizeNode.create(DeoptimizationAction.None, DeoptimizationReason.NullCheckException); } return this; } @@ -114,7 +118,7 @@ for (int i = 0; i < phi.valueCount(); i++) { constantNodes[i] = ConstantNode.forConstant(constants[i], metaAccess); } - return new ValuePhiNode(stamp(), phi.merge(), constantNodes); + return ValuePhiNode.create(stamp(), phi.merge(), constantNodes); } return null; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -31,7 +32,8 @@ /** * The {@code LoadIndexedNode} represents a read from an element of an array. */ -public final class LoadIndexedNode extends AccessIndexedNode implements Virtualizable { +@NodeInfo +public class LoadIndexedNode extends AccessIndexedNode implements Virtualizable { /** * Creates a new LoadIndexedNode. @@ -40,7 +42,11 @@ * @param index the instruction producing the index * @param elementKind the element type */ - public LoadIndexedNode(ValueNode array, ValueNode index, Kind elementKind) { + public static LoadIndexedNode create(ValueNode array, ValueNode index, Kind elementKind) { + return USE_GENERATED_NODES ? new LoadIndexedNodeGen(array, index, elementKind) : new LoadIndexedNode(array, index, elementKind); + } + + LoadIndexedNode(ValueNode array, ValueNode index, Kind elementKind) { super(createStamp(array, elementKind), array, index, elementKind); } @@ -63,9 +69,9 @@ State arrayState = tool.getObjectState(array()); if (arrayState != null && arrayState.getState() == EscapeState.Virtual) { ValueNode indexValue = tool.getReplacedValue(index()); - int index = indexValue.isConstant() ? indexValue.asConstant().asInt() : -1; - if (index >= 0 && index < arrayState.getVirtualObject().entryCount()) { - tool.replaceWith(arrayState.getEntry(index)); + int idx = indexValue.isConstant() ? indexValue.asConstant().asInt() : -1; + if (idx >= 0 && idx < arrayState.getVirtualObject().entryCount()) { + tool.replaceWith(arrayState.getEntry(idx)); } } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredAtomicReadAndWriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredAtomicReadAndWriteNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredAtomicReadAndWriteNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,14 +22,14 @@ */ package com.oracle.graal.nodes.java; +import sun.misc.*; + import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import sun.misc.*; - /** * Represents the lowered version of an atomic read-and-write operation like * {@link Unsafe#getAndSetInt(Object, long, int)} . @@ -37,10 +37,14 @@ @NodeInfo(allowedUsageTypes = {InputType.Memory}) public class LoweredAtomicReadAndWriteNode extends FixedAccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single { - @Input private ValueNode newValue; - @OptionalInput(InputType.State) private FrameState stateAfter; + @Input ValueNode newValue; + @OptionalInput(InputType.State) FrameState stateAfter; - public LoweredAtomicReadAndWriteNode(ValueNode object, LocationNode location, ValueNode newValue, BarrierType barrierType) { + public static LoweredAtomicReadAndWriteNode create(ValueNode object, LocationNode location, ValueNode newValue, BarrierType barrierType) { + return USE_GENERATED_NODES ? new LoweredAtomicReadAndWriteNodeGen(object, location, newValue, barrierType) : new LoweredAtomicReadAndWriteNode(object, location, newValue, barrierType); + } + + LoweredAtomicReadAndWriteNode(ValueNode object, LocationNode location, ValueNode newValue, BarrierType barrierType) { super(object, location, newValue.stamp().unrestricted(), barrierType); this.newValue = newValue; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,7 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -35,9 +35,9 @@ @NodeInfo(allowedUsageTypes = {InputType.Value, InputType.Memory}) public class LoweredCompareAndSwapNode extends FixedAccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single { - @Input private ValueNode expectedValue; - @Input private ValueNode newValue; - @OptionalInput(InputType.State) private FrameState stateAfter; + @Input ValueNode expectedValue; + @Input ValueNode newValue; + @OptionalInput(InputType.State) FrameState stateAfter; public FrameState stateAfter() { return stateAfter; @@ -61,7 +61,12 @@ return newValue; } - public LoweredCompareAndSwapNode(ValueNode object, LocationNode location, ValueNode expectedValue, ValueNode newValue, BarrierType barrierType) { + public static LoweredCompareAndSwapNode create(ValueNode object, LocationNode location, ValueNode expectedValue, ValueNode newValue, BarrierType barrierType) { + return USE_GENERATED_NODES ? new LoweredCompareAndSwapNodeGen(object, location, expectedValue, newValue, barrierType) : new LoweredCompareAndSwapNode(object, location, expectedValue, + newValue, barrierType); + } + + LoweredCompareAndSwapNode(ValueNode object, LocationNode location, ValueNode expectedValue, ValueNode newValue, BarrierType barrierType) { super(object, location, StampFactory.forKind(Kind.Boolean.getStackKind()), barrierType); assert expectedValue.getKind() == newValue.getKind(); this.expectedValue = expectedValue; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,16 +26,22 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; +@NodeInfo public class MethodCallTargetNode extends CallTargetNode implements IterableNodeType, Canonicalizable { private final JavaType returnType; /** * @param arguments */ - public MethodCallTargetNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType) { + public static MethodCallTargetNode create(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType) { + return USE_GENERATED_NODES ? new MethodCallTargetNodeGen(invokeKind, targetMethod, arguments, returnType) : new MethodCallTargetNode(invokeKind, targetMethod, arguments, returnType); + } + + MethodCallTargetNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType) { super(arguments, targetMethod, invokeKind); this.returnType = returnType; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -31,14 +32,19 @@ /** * The {@code MonitorEnterNode} represents the acquisition of a monitor. */ -public final class MonitorEnterNode extends AccessMonitorNode implements Virtualizable, Lowerable, IterableNodeType, MonitorEnter, MemoryCheckpoint.Single { +@NodeInfo +public class MonitorEnterNode extends AccessMonitorNode implements Virtualizable, Lowerable, IterableNodeType, MonitorEnter, MemoryCheckpoint.Single { /** * Creates a new MonitorEnterNode. - * + * * @param object the instruction producing the object */ - public MonitorEnterNode(ValueNode object, MonitorIdNode monitorId) { + public static MonitorEnterNode create(ValueNode object, MonitorIdNode monitorId) { + return USE_GENERATED_NODES ? new MonitorEnterNodeGen(object, monitorId) : new MonitorEnterNode(object, monitorId); + } + + MonitorEnterNode(ValueNode object, MonitorIdNode monitorId) { super(object, monitorId); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -35,14 +36,19 @@ * a synchronized method, then the return value of the method will be referenced, so that it will be * materialized before releasing the monitor. */ -public final class MonitorExitNode extends AccessMonitorNode implements Virtualizable, Simplifiable, Lowerable, IterableNodeType, MonitorExit, MemoryCheckpoint.Single { +@NodeInfo +public class MonitorExitNode extends AccessMonitorNode implements Virtualizable, Simplifiable, Lowerable, IterableNodeType, MonitorExit, MemoryCheckpoint.Single { - @OptionalInput private ValueNode escapedReturnValue; + @OptionalInput ValueNode escapedReturnValue; /** * Creates a new MonitorExitNode. */ - public MonitorExitNode(ValueNode object, MonitorIdNode monitorId, ValueNode escapedReturnValue) { + public static MonitorExitNode create(ValueNode object, MonitorIdNode monitorId, ValueNode escapedReturnValue) { + return USE_GENERATED_NODES ? new MonitorExitNodeGen(object, monitorId, escapedReturnValue) : new MonitorExitNode(object, monitorId, escapedReturnValue); + } + + MonitorExitNode(ValueNode object, MonitorIdNode monitorId, ValueNode escapedReturnValue) { super(object, monitorId); this.escapedReturnValue = escapedReturnValue; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,6 +24,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -37,7 +38,11 @@ private int lockDepth; - public MonitorIdNode(int lockDepth) { + public static MonitorIdNode create(int lockDepth) { + return USE_GENERATED_NODES ? new MonitorIdNodeGen(lockDepth) : new MonitorIdNode(lockDepth); + } + + MonitorIdNode(int lockDepth) { super(StampFactory.forVoid()); this.lockDepth = lockDepth; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -35,6 +36,7 @@ * The {@code NewArrayNode} is used for all array allocations where the element type is know at * compile time. */ +@NodeInfo public class NewArrayNode extends AbstractNewArrayNode implements VirtualizableAllocation { /** @@ -45,7 +47,11 @@ * @param length the node that produces the length for this allocation. * @param fillContents determines whether the array elements should be initialized to zero/null. */ - public NewArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents) { + public static NewArrayNode create(ResolvedJavaType elementType, ValueNode length, boolean fillContents) { + return USE_GENERATED_NODES ? new NewArrayNodeGen(elementType, length, fillContents) : new NewArrayNode(elementType, length, fillContents); + } + + NewArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents) { super(StampFactory.exactNonNull(elementType.getArrayClass()), length, fillContents); } @@ -75,7 +81,7 @@ for (int i = 0; i < constantLength; i++) { state[i] = defaultForKind; } - VirtualObjectNode virtualObject = new VirtualArrayNode(elementType(), constantLength); + VirtualObjectNode virtualObject = VirtualArrayNode.create(elementType(), constantLength); tool.createVirtualObject(virtualObject, state, Collections. emptyList()); tool.replaceWithVirtual(virtualObject); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,7 +27,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.virtual.*; @@ -47,7 +47,11 @@ * @param fillContents determines whether the new object's fields should be initialized to * zero/null. */ - public NewInstanceNode(ResolvedJavaType type, boolean fillContents) { + public static NewInstanceNode create(ResolvedJavaType type, boolean fillContents) { + return USE_GENERATED_NODES ? new NewInstanceNodeGen(type, fillContents) : new NewInstanceNode(type, fillContents); + } + + NewInstanceNode(ResolvedJavaType type, boolean fillContents) { super(StampFactory.exactNonNull(type), fillContents); assert !type.isArray() && !type.isInterface() && !type.isPrimitive(); this.instanceClass = type; @@ -69,7 +73,7 @@ * they're excluded from escape analysis. */ if (!tool.getMetaAccessProvider().lookupJavaType(Reference.class).isAssignableFrom(instanceClass)) { - VirtualInstanceNode virtualObject = new VirtualInstanceNode(instanceClass(), true); + VirtualInstanceNode virtualObject = VirtualInstanceNode.create(instanceClass(), true); ResolvedJavaField[] fields = virtualObject.getFields(); ValueNode[] state = new ValueNode[fields.length]; for (int i = 0; i < state.length; i++) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,15 +25,17 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; /** * The {@code NewMultiArrayNode} represents an allocation of a multi-dimensional object array. */ +@NodeInfo public class NewMultiArrayNode extends DeoptimizingFixedWithNextNode implements Lowerable, ArrayLengthProvider { - @Input private final NodeInputList dimensions; + @Input NodeInputList dimensions; private final ResolvedJavaType type; public ValueNode dimension(int index) { @@ -54,7 +56,11 @@ * @param type the element type of the array * @param dimensions the node which produce the dimensions for this array */ - public NewMultiArrayNode(ResolvedJavaType type, ValueNode[] dimensions) { + public static NewMultiArrayNode create(ResolvedJavaType type, ValueNode[] dimensions) { + return USE_GENERATED_NODES ? new NewMultiArrayNodeGen(type, dimensions) : new NewMultiArrayNode(type, dimensions); + } + + NewMultiArrayNode(ResolvedJavaType type, ValueNode[] dimensions) { super(StampFactory.exactNonNull(type)); this.type = type; this.dimensions = new NodeInputList<>(this, dimensions); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,8 +26,8 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -35,12 +35,17 @@ * This node is used to perform the finalizer registration at the end of the java.lang.Object * constructor. */ -public final class RegisterFinalizerNode extends AbstractStateSplit implements Canonicalizable.Unary, LIRLowerable, Virtualizable, DeoptimizingNode.DeoptAfter { +@NodeInfo +public class RegisterFinalizerNode extends AbstractStateSplit implements Canonicalizable.Unary, LIRLowerable, Virtualizable, DeoptimizingNode.DeoptAfter { + + @OptionalInput(InputType.State) FrameState deoptState; + @Input ValueNode value; - @OptionalInput(InputType.State) private FrameState deoptState; - @Input private ValueNode value; + public static RegisterFinalizerNode create(ValueNode value) { + return USE_GENERATED_NODES ? new RegisterFinalizerNodeGen(value) : new RegisterFinalizerNode(value); + } - public RegisterFinalizerNode(ValueNode value) { + RegisterFinalizerNode(ValueNode value) { super(StampFactory.forVoid()); this.value = value; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,24 +25,32 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; /** * A SelfReplacingMethodCallTargetNode replaces itself in the graph when being lowered with a * {@link MethodCallTargetNode} that calls the stored replacement target method. - * + * * This node is used for method handle call nodes which have a constant call target but are not * inlined. */ +@NodeInfo public class SelfReplacingMethodCallTargetNode extends MethodCallTargetNode implements Lowerable { // Replacement method data private final ResolvedJavaMethod replacementTargetMethod; private final JavaType replacementReturnType; - @Input private final NodeInputList replacementArguments; + @Input NodeInputList replacementArguments; - public SelfReplacingMethodCallTargetNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType, ResolvedJavaMethod replacementTargetMethod, + public static SelfReplacingMethodCallTargetNode create(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType, + ResolvedJavaMethod replacementTargetMethod, ValueNode[] replacementArguments, JavaType replacementReturnType) { + return USE_GENERATED_NODES ? new SelfReplacingMethodCallTargetNodeGen(invokeKind, targetMethod, arguments, returnType, replacementTargetMethod, replacementArguments, replacementReturnType) + : new SelfReplacingMethodCallTargetNode(invokeKind, targetMethod, arguments, returnType, replacementTargetMethod, replacementArguments, replacementReturnType); + } + + SelfReplacingMethodCallTargetNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType, ResolvedJavaMethod replacementTargetMethod, ValueNode[] replacementArguments, JavaType replacementReturnType) { super(invokeKind, targetMethod, arguments, returnType); this.replacementTargetMethod = replacementTargetMethod; @@ -66,7 +74,7 @@ public void lower(LoweringTool tool) { InvokeKind invokeKind = replacementTargetMethod.isStatic() ? InvokeKind.Static : InvokeKind.Special; MethodCallTargetNode replacement = graph().add( - new MethodCallTargetNode(invokeKind, replacementTargetMethod, replacementArguments.toArray(new ValueNode[replacementArguments.size()]), replacementReturnType)); + MethodCallTargetNode.create(invokeKind, replacementTargetMethod, replacementArguments.toArray(new ValueNode[replacementArguments.size()]), replacementReturnType)); // Replace myself... this.replaceAndDelete(replacement); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,7 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.virtual.*; @@ -33,10 +33,10 @@ * The {@code StoreFieldNode} represents a write to a static or instance field. */ @NodeInfo(nameTemplate = "StoreField#{p#field/s}") -public final class StoreFieldNode extends AccessFieldNode implements StateSplit, VirtualizableRoot { +public class StoreFieldNode extends AccessFieldNode implements StateSplit, VirtualizableRoot { - @Input private ValueNode value; - @OptionalInput(InputType.State) private FrameState stateAfter; + @Input ValueNode value; + @OptionalInput(InputType.State) FrameState stateAfter; public FrameState stateAfter() { return stateAfter; @@ -63,12 +63,20 @@ * @param field the compiler interface field * @param value the node representing the value to store to the field */ - public StoreFieldNode(ValueNode object, ResolvedJavaField field, ValueNode value) { + public static StoreFieldNode create(ValueNode object, ResolvedJavaField field, ValueNode value) { + return USE_GENERATED_NODES ? new StoreFieldNodeGen(object, field, value) : new StoreFieldNode(object, field, value); + } + + StoreFieldNode(ValueNode object, ResolvedJavaField field, ValueNode value) { super(StampFactory.forVoid(), object, field); this.value = value; } - public StoreFieldNode(ValueNode object, ResolvedJavaField field, ValueNode value, FrameState stateAfter) { + public static StoreFieldNode create(ValueNode object, ResolvedJavaField field, ValueNode value, FrameState stateAfter) { + return USE_GENERATED_NODES ? new StoreFieldNodeGen(object, field, value, stateAfter) : new StoreFieldNode(object, field, value, stateAfter); + } + + StoreFieldNode(ValueNode object, ResolvedJavaField field, ValueNode value, FrameState stateAfter) { super(StampFactory.forVoid(), object, field); this.value = value; this.stateAfter = stateAfter; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,7 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -32,10 +32,11 @@ /** * The {@code StoreIndexedNode} represents a write to an array element. */ -public final class StoreIndexedNode extends AccessIndexedNode implements StateSplit, Lowerable, Virtualizable { +@NodeInfo +public class StoreIndexedNode extends AccessIndexedNode implements StateSplit, Lowerable, Virtualizable { - @Input private ValueNode value; - @OptionalInput(InputType.State) private FrameState stateAfter; + @Input ValueNode value; + @OptionalInput(InputType.State) FrameState stateAfter; public FrameState stateAfter() { return stateAfter; @@ -63,7 +64,11 @@ * @param elementKind the element type * @param value the value to store into the array */ - public StoreIndexedNode(ValueNode array, ValueNode index, Kind elementKind, ValueNode value) { + public static StoreIndexedNode create(ValueNode array, ValueNode index, Kind elementKind, ValueNode value) { + return USE_GENERATED_NODES ? new StoreIndexedNodeGen(array, index, elementKind, value) : new StoreIndexedNode(array, index, elementKind, value); + } + + StoreIndexedNode(ValueNode array, ValueNode index, Kind elementKind, ValueNode value) { super(StampFactory.forVoid(), array, index, elementKind); this.value = value; } @@ -73,12 +78,12 @@ State arrayState = tool.getObjectState(array()); if (arrayState != null && arrayState.getState() == EscapeState.Virtual) { ValueNode indexValue = tool.getReplacedValue(index()); - int index = indexValue.isConstant() ? indexValue.asConstant().asInt() : -1; - if (index >= 0 && index < arrayState.getVirtualObject().entryCount()) { + int idx = indexValue.isConstant() ? indexValue.asConstant().asInt() : -1; + if (idx >= 0 && idx < arrayState.getVirtualObject().entryCount()) { ResolvedJavaType componentType = arrayState.getVirtualObject().type().getComponentType(); if (componentType.isPrimitive() || StampTool.isObjectAlwaysNull(value) || componentType.getSuperclass() == null || (StampTool.typeOrNull(value) != null && componentType.isAssignableFrom(StampTool.typeOrNull(value)))) { - tool.setVirtualEntry(arrayState, index, value(), false); + tool.setVirtualEntry(arrayState, idx, value(), false); tool.delete(); } } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -28,6 +28,7 @@ import com.oracle.graal.api.meta.ResolvedJavaType.Representation; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -37,7 +38,8 @@ * The {@code TypeSwitchNode} performs a lookup based on the type of the input value. The type * comparison is an exact type comparison, not an instanceof. */ -public final class TypeSwitchNode extends SwitchNode implements LIRLowerable, Simplifiable { +@NodeInfo +public class TypeSwitchNode extends SwitchNode implements LIRLowerable, Simplifiable { private final ResolvedJavaType[] keys; @@ -51,7 +53,11 @@ * @param keyProbabilities the probabilities of the keys * @param keySuccessors the successor index for each key */ - public TypeSwitchNode(ValueNode value, BeginNode[] successors, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) { + public static TypeSwitchNode create(ValueNode value, BeginNode[] successors, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) { + return USE_GENERATED_NODES ? new TypeSwitchNodeGen(value, successors, keys, keyProbabilities, keySuccessors) : new TypeSwitchNode(value, successors, keys, keyProbabilities, keySuccessors); + } + + TypeSwitchNode(ValueNode value, BeginNode[] successors, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) { super(value, successors, keySuccessors, keyProbabilities); assert successors.length <= keys.length + 1; assert keySuccessors.length == keyProbabilities.length; @@ -199,7 +205,7 @@ } BeginNode[] successorsArray = newSuccessors.toArray(new BeginNode[newSuccessors.size()]); - TypeSwitchNode newSwitch = graph().add(new TypeSwitchNode(value(), successorsArray, newKeys, newKeyProbabilities, newKeySuccessors)); + TypeSwitchNode newSwitch = graph().add(TypeSwitchNode.create(value(), successorsArray, newKeys, newKeyProbabilities, newKeySuccessors)); ((FixedWithNextNode) predecessor()).setNext(newSwitch); GraphUtil.killWithUnusedFloatingInputs(this); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,7 +23,7 @@ package com.oracle.graal.nodes.virtual; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -32,12 +32,17 @@ * Selects one object from a {@link CommitAllocationNode}. The object is identified by its * {@link VirtualObjectNode}. */ +@NodeInfo public class AllocatedObjectNode extends FloatingNode implements Virtualizable, ArrayLengthProvider { - @Input private VirtualObjectNode virtualObject; - @Input(InputType.Extension) private CommitAllocationNode commit; + @Input VirtualObjectNode virtualObject; + @Input(InputType.Extension) CommitAllocationNode commit; - public AllocatedObjectNode(VirtualObjectNode virtualObject) { + public static AllocatedObjectNode create(VirtualObjectNode virtualObject) { + return USE_GENERATED_NODES ? new AllocatedObjectNodeGen(virtualObject) : new AllocatedObjectNode(virtualObject); + } + + AllocatedObjectNode(VirtualObjectNode virtualObject) { super(StampFactory.exactNonNull(virtualObject.type())); this.virtualObject = virtualObject; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,19 +27,24 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(nameTemplate = "Alloc {i#virtualObjects}", allowedUsageTypes = {InputType.Extension}) -public final class CommitAllocationNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Simplifiable { +public class CommitAllocationNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Simplifiable { - @Input private final NodeInputList virtualObjects = new NodeInputList<>(this); - @Input private final NodeInputList values = new NodeInputList<>(this); - @Input(InputType.Association) private final NodeInputList locks = new NodeInputList<>(this); + @Input NodeInputList virtualObjects = new NodeInputList<>(this); + @Input NodeInputList values = new NodeInputList<>(this); + @Input(InputType.Association) NodeInputList locks = new NodeInputList<>(this); private ArrayList lockIndexes = new ArrayList<>(Arrays.asList(0)); - public CommitAllocationNode() { + public static CommitAllocationNode create() { + return USE_GENERATED_NODES ? new CommitAllocationNodeGen() : new CommitAllocationNode(); + } + + CommitAllocationNode() { super(StampFactory.forVoid()); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EscapeObjectState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EscapeObjectState.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EscapeObjectState.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,11 +23,13 @@ package com.oracle.graal.nodes.virtual; import com.oracle.graal.graph.Node.ValueNumberable; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +@NodeInfo public abstract class EscapeObjectState extends VirtualState implements ValueNumberable { - @Input private VirtualObjectNode object; + @Input protected VirtualObjectNode object; public VirtualObjectNode object() { return object; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,7 +25,7 @@ import sun.misc.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -35,7 +35,11 @@ private final ResolvedJavaType componentType; private final int length; - public VirtualArrayNode(ResolvedJavaType componentType, int length) { + public static VirtualArrayNode create(ResolvedJavaType componentType, int length) { + return USE_GENERATED_NODES ? new VirtualArrayNodeGen(componentType, length) : new VirtualArrayNode(componentType, length); + } + + VirtualArrayNode(ResolvedJavaType componentType, int length) { super(componentType.getArrayClass(), true); this.componentType = componentType; this.length = length; @@ -137,12 +141,12 @@ @Override public VirtualArrayNode duplicate() { - return new VirtualArrayNode(componentType, length); + return VirtualArrayNode.create(componentType, length); } @Override public ValueNode getMaterializedRepresentation(FixedNode fixed, ValueNode[] entries, LockState locks) { - return new AllocatedObjectNode(this); + return AllocatedObjectNode.create(this); } public ValueNode length() { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualBoxingNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualBoxingNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualBoxingNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,27 +23,33 @@ package com.oracle.graal.nodes.virtual; import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; +@NodeInfo public class VirtualBoxingNode extends VirtualInstanceNode { private final Kind boxingKind; - public VirtualBoxingNode(ResolvedJavaType type, Kind boxingKind) { + public static VirtualBoxingNode create(ResolvedJavaType type, Kind boxingKind) { + return USE_GENERATED_NODES ? new VirtualBoxingNodeGen(type, boxingKind) : new VirtualBoxingNode(type, boxingKind); + } + + VirtualBoxingNode(ResolvedJavaType type, Kind boxingKind) { super(type, false); this.boxingKind = boxingKind; } @Override public VirtualBoxingNode duplicate() { - return new VirtualBoxingNode(type(), boxingKind); + return VirtualBoxingNode.create(type(), boxingKind); } @Override public ValueNode getMaterializedRepresentation(FixedNode fixed, ValueNode[] entries, LockState locks) { assert entries.length == 1; assert locks == null; - return new BoxNode(entries[0], type(), boxingKind); + return BoxNode.create(entries[0], type(), boxingKind); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,7 +23,7 @@ package com.oracle.graal.nodes.virtual; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @NodeInfo(nameTemplate = "VirtualInstance {p#type/s}") @@ -32,11 +32,19 @@ private final ResolvedJavaType type; private final ResolvedJavaField[] fields; - public VirtualInstanceNode(ResolvedJavaType type, boolean hasIdentity) { + public static VirtualInstanceNode create(ResolvedJavaType type, boolean hasIdentity) { + return USE_GENERATED_NODES ? new VirtualInstanceNodeGen(type, hasIdentity) : new VirtualInstanceNode(type, hasIdentity); + } + + VirtualInstanceNode(ResolvedJavaType type, boolean hasIdentity) { this(type, type.getInstanceFields(true), hasIdentity); } - public VirtualInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields, boolean hasIdentity) { + public static VirtualInstanceNode create(ResolvedJavaType type, ResolvedJavaField[] fields, boolean hasIdentity) { + return USE_GENERATED_NODES ? new VirtualInstanceNodeGen(type, fields, hasIdentity) : new VirtualInstanceNode(type, fields, hasIdentity); + } + + protected VirtualInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields, boolean hasIdentity) { super(type, hasIdentity); this.type = type; this.fields = fields; @@ -97,11 +105,11 @@ @Override public VirtualInstanceNode duplicate() { - return new VirtualInstanceNode(type, fields, super.hasIdentity()); + return VirtualInstanceNode.create(type, fields, super.hasIdentity()); } @Override public ValueNode getMaterializedRepresentation(FixedNode fixed, ValueNode[] entries, LockState locks) { - return new AllocatedObjectNode(this); + return AllocatedObjectNode.create(this); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,9 +25,11 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public abstract class VirtualObjectNode extends ValueNode implements LIRLowerable, IterableNodeType { private boolean hasIdentity; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.options/src/com/oracle/graal/options/DerivedOptionValue.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/DerivedOptionValue.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.options; + +import java.util.function.*; + +import com.oracle.graal.options.OptionValue.OverrideScope; + +/** + * A cached value that needs to be recomputed when an option changes. + */ +public class DerivedOptionValue { + + private final T initialValue; + private final Supplier supplier; + + public DerivedOptionValue(Supplier supplier) { + this.supplier = supplier; + assert OptionValue.overrideScopes.get() == null : "derived option value should be initialized outside any override scope"; + this.initialValue = createValue(); + } + + public T getValue() { + OverrideScope overrideScope = OptionValue.overrideScopes.get(); + if (overrideScope != null) { + return overrideScope.getDerived(this); + } else { + return initialValue; + } + } + + T createValue() { + return supplier.get(); + } +} diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java Mon Aug 25 21:15:59 2014 -0700 @@ -39,7 +39,7 @@ * retrieved as follows: * *
    - * 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 ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java
    --- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java	Mon Aug 25 14:42:42 2014 -0700
    +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java	Mon Aug 25 21:15:59 2014 -0700
    @@ -128,7 +128,7 @@
             return new MultipleOverridesScope(current, map);
         }
     
    -    private static final ThreadLocal overrideScopes = new ThreadLocal<>();
    +    static final ThreadLocal overrideScopes = new ThreadLocal<>();
     
         /**
          * The raw option value.
    @@ -252,6 +252,22 @@
          * {@link OptionValue#override(OptionValue, Object)} or {@link OptionValue#override(Map)}.
          */
         public abstract static class OverrideScope implements AutoCloseable {
    +
    +        private Map, Object> derivedCache = null;
    +
    +        public  T getDerived(DerivedOptionValue key) {
    +            if (derivedCache == null) {
    +                derivedCache = new HashMap<>();
    +            }
    +            @SuppressWarnings("unchecked")
    +            T ret = (T) derivedCache.get(key);
    +            if (ret == null) {
    +                ret = key.createValue();
    +                derivedCache.put(key, ret);
    +            }
    +            return ret;
    +        }
    +
             abstract void addToInherited(Map, Object> inherited);
     
             abstract  T getOverride(OptionValue option);
    diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java
    --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Mon Aug 25 14:42:42 2014 -0700
    +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Mon Aug 25 21:15:59 2014 -0700
    @@ -29,6 +29,7 @@
     import com.oracle.graal.graph.*;
     import com.oracle.graal.graph.Graph.*;
     import com.oracle.graal.graph.spi.*;
    +import com.oracle.graal.nodeinfo.*;
     import com.oracle.graal.nodes.*;
     import com.oracle.graal.nodes.calc.*;
     import com.oracle.graal.nodes.util.*;
    @@ -212,7 +213,7 @@
             }
     
             public static boolean tryGlobalValueNumbering(Node node, NodeClass nodeClass) {
    -            if (nodeClass.valueNumberable() && !nodeClass.isLeafNode()) {
    +            if (nodeClass.valueNumberable() && !node.isLeafNode()) {
                     Node newNode = node.graph().findDuplicate(node);
                     if (newNode != null) {
                         assert !(node instanceof FixedNode || newNode instanceof FixedNode);
    diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java
    --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Mon Aug 25 14:42:42 2014 -0700
    +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Mon Aug 25 21:15:59 2014 -0700
    @@ -716,9 +716,9 @@
                         PiNode piNode;
                         if (isNull) {
                             ConstantNode nullObject = ConstantNode.defaultForKind(Kind.Object, graph);
    -                        piNode = graph.unique(new PiNode(nullObject, StampFactory.forConstant(nullObject.getValue(), metaAccess), replacementAnchor.asNode()));
    +                        piNode = graph.unique(PiNode.create(nullObject, StampFactory.forConstant(nullObject.getValue(), metaAccess), replacementAnchor.asNode()));
                         } else {
    -                        piNode = graph.unique(new PiNode(object, StampFactory.declared(type, nonNull), replacementAnchor.asNode()));
    +                        piNode = graph.unique(PiNode.create(object, StampFactory.declared(type, nonNull), replacementAnchor.asNode()));
                         }
                         checkCast.replaceAtUsages(piNode);
                         graph.removeFixed(checkCast);
    @@ -770,7 +770,7 @@
     
                     if (replacement != null) {
                         if (replacementAnchor != null && !(replacementAnchor instanceof BeginNode)) {
    -                        ValueAnchorNode anchor = graph.add(new ValueAnchorNode(replacementAnchor));
    +                        ValueAnchorNode anchor = graph.add(ValueAnchorNode.create(replacementAnchor));
                             graph.addBeforeFixed(ifNode, anchor);
                         }
                         for (Node n : survivingSuccessor.usages().snapshot()) {
    diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java
    --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Mon Aug 25 14:42:42 2014 -0700
    +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Mon Aug 25 21:15:59 2014 -0700
    @@ -122,7 +122,7 @@
                 IfNode ifNode = (IfNode) deoptBegin.predecessor();
                 BeginNode otherBegin = ifNode.trueSuccessor();
                 LogicNode conditionNode = ifNode.condition();
    -            FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deoptReason, deoptAction, deoptBegin == ifNode.trueSuccessor()));
    +            FixedGuardNode guard = graph.add(FixedGuardNode.create(conditionNode, deoptReason, deoptAction, deoptBegin == ifNode.trueSuccessor()));
                 FixedWithNextNode pred = (FixedWithNextNode) ifNode.predecessor();
                 BeginNode survivingSuccessor;
                 if (deoptBegin == ifNode.trueSuccessor()) {
    @@ -160,7 +160,7 @@
             FixedNode next = deoptPred.next();
     
             if (!(next instanceof DeoptimizeNode)) {
    -            DeoptimizeNode newDeoptNode = graph.add(new DeoptimizeNode(deoptAction, deoptReason));
    +            DeoptimizeNode newDeoptNode = graph.add(DeoptimizeNode.create(deoptAction, deoptReason));
                 deoptPred.setNext(newDeoptNode);
                 assert deoptPred == newDeoptNode.predecessor();
                 GraphUtil.killCFG(next);
    diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java
    --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Mon Aug 25 14:42:42 2014 -0700
    +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Mon Aug 25 21:15:59 2014 -0700
    @@ -55,10 +55,10 @@
                         }
                         MergeNode merge;
                         if (target instanceof AbstractDeoptimizeNode) {
    -                        merge = graph.add(new MergeNode());
    -                        EndNode firstEnd = graph.add(new EndNode());
    -                        reasonActionPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(Kind.Int), merge));
    -                        speculationPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(Kind.Object), merge));
    +                        merge = graph.add(MergeNode.create());
    +                        EndNode firstEnd = graph.add(EndNode.create());
    +                        reasonActionPhi = graph.addWithoutUnique(ValuePhiNode.create(StampFactory.forKind(Kind.Int), merge));
    +                        speculationPhi = graph.addWithoutUnique(ValuePhiNode.create(StampFactory.forKind(Kind.Object), merge));
                             merge.addForwardEnd(firstEnd);
                             reasonActionPhi.addInput(((AbstractDeoptimizeNode) target).getActionAndReason(context.getMetaAccess()));
                             speculationPhi.addInput(((AbstractDeoptimizeNode) target).getSpeculation(context.getMetaAccess()));
    @@ -66,14 +66,14 @@
     
                             exitLoops((AbstractDeoptimizeNode) target, firstEnd, cfg);
     
    -                        merge.setNext(graph.add(new DynamicDeoptimizeNode(reasonActionPhi, speculationPhi)));
    +                        merge.setNext(graph.add(DynamicDeoptimizeNode.create(reasonActionPhi, speculationPhi)));
                             obsoletes = new LinkedList<>();
                             obsoletes.add((AbstractDeoptimizeNode) target);
                             target = merge;
                         } else {
                             merge = (MergeNode) target;
                         }
    -                    EndNode newEnd = graph.add(new EndNode());
    +                    EndNode newEnd = graph.add(EndNode.create());
                         merge.addForwardEnd(newEnd);
                         reasonActionPhi.addInput(deopt.getActionAndReason(context.getMetaAccess()));
                         speculationPhi.addInput(deopt.getSpeculation(context.getMetaAccess()));
    @@ -95,7 +95,7 @@
             Block block = cfg.blockFor(deopt);
             Loop loop = block.getLoop();
             while (loop != null) {
    -            end.graph().addBeforeFixed(end, end.graph().add(new LoopExitNode((LoopBeginNode) loop.getHeader().getBeginNode())));
    +            end.graph().addBeforeFixed(end, end.graph().add(LoopExitNode.create((LoopBeginNode) loop.getHeader().getBeginNode())));
                 loop = loop.getParent();
             }
         }
    diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java
    --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java	Mon Aug 25 14:42:42 2014 -0700
    +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java	Mon Aug 25 21:15:59 2014 -0700
    @@ -72,16 +72,16 @@
             }
             ifNode.clearSuccessors();
             Graph graph = ifNode.graph();
    -        MergeNode trueTargetMerge = graph.add(new MergeNode());
    +        MergeNode trueTargetMerge = graph.add(MergeNode.create());
             trueTargetMerge.setNext(trueTarget);
    -        EndNode firstTrueEnd = graph.add(new EndNode());
    -        EndNode secondTrueEnd = graph.add(new EndNode());
    +        EndNode firstTrueEnd = graph.add(EndNode.create());
    +        EndNode secondTrueEnd = graph.add(EndNode.create());
             trueTargetMerge.addForwardEnd(firstTrueEnd);
             trueTargetMerge.addForwardEnd(secondTrueEnd);
             BeginNode firstTrueTarget = BeginNode.begin(firstTrueEnd);
             BeginNode secondTrueTarget = BeginNode.begin(secondTrueEnd);
    -        BeginNode secondIf = BeginNode.begin(graph.add(new IfNode(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfProbability)));
    -        IfNode firstIf = graph.add(new IfNode(x, xNegated ? secondIf : firstTrueTarget, xNegated ? firstTrueTarget : secondIf, firstIfProbability));
    +        BeginNode secondIf = BeginNode.begin(graph.add(IfNode.create(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfProbability)));
    +        IfNode firstIf = graph.add(IfNode.create(x, xNegated ? secondIf : firstTrueTarget, xNegated ? firstTrueTarget : secondIf, firstIfProbability));
             ifNode.replaceAtPredecessor(firstIf);
             ifNode.safeDelete();
         }
    @@ -90,8 +90,8 @@
             ValueNode trueTarget = conditional.trueValue();
             ValueNode falseTarget = conditional.falseValue();
             Graph graph = conditional.graph();
    -        ConditionalNode secondConditional = graph.unique(new ConditionalNode(y, yNegated ? falseTarget : trueTarget, yNegated ? trueTarget : falseTarget));
    -        ConditionalNode firstConditional = graph.unique(new ConditionalNode(x, xNegated ? secondConditional : trueTarget, xNegated ? trueTarget : secondConditional));
    +        ConditionalNode secondConditional = graph.unique(ConditionalNode.create(y, yNegated ? falseTarget : trueTarget, yNegated ? trueTarget : falseTarget));
    +        ConditionalNode firstConditional = graph.unique(ConditionalNode.create(x, xNegated ? secondConditional : trueTarget, xNegated ? trueTarget : secondConditional));
             conditional.replaceAndDelete(firstConditional);
         }
     }
    diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java
    --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Mon Aug 25 14:42:42 2014 -0700
    +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Mon Aug 25 21:15:59 2014 -0700
    @@ -186,7 +186,7 @@
                         } else {
                             MemoryPhiNode phi = null;
                             if (existingPhis == null || (phi = existingPhis.remove(key)) == null) {
    -                            phi = merge.graph().addWithoutUnique(new MemoryPhiNode(merge, key));
    +                            phi = merge.graph().addWithoutUnique(MemoryPhiNode.create(merge, key));
                             }
                             for (int j = 0; j < mergedStatesCount; j++) {
                                 phi.addInput(ValueNodeUtil.asNode(merged));
    @@ -291,7 +291,7 @@
                 assert MemoryCheckpoint.TypeAssertion.correctType(node) : node;
     
                 if (createMemoryMapNodes && node instanceof ReturnNode) {
    -                ((ReturnNode) node).setMemoryMap(node.graph().unique(new MemoryMapNode(state.lastMemorySnapshot)));
    +                ((ReturnNode) node).setMemoryMap(node.graph().unique(MemoryMapNode.create(state.lastMemorySnapshot)));
                 }
                 return state;
             }
    @@ -331,7 +331,7 @@
                     ValueAnchorNode anchor = null;
                     GuardingNode guard = accessNode.getGuard();
                     if (guard != null) {
    -                    anchor = graph.add(new ValueAnchorNode(guard.asNode()));
    +                    anchor = graph.add(ValueAnchorNode.create(guard.asNode()));
                         graph.addAfterFixed(accessNode, anchor);
                     }
                     graph.replaceFixedWithFloating(accessNode, floatingNode);
    @@ -385,7 +385,7 @@
     
                 for (LocationIdentity location : modifiedLocations) {
                     if (!updateExistingPhis || !phis.containsKey(location)) {
    -                    MemoryPhiNode phi = loop.graph().addWithoutUnique(new MemoryPhiNode(loop, location));
    +                    MemoryPhiNode phi = loop.graph().addWithoutUnique(MemoryPhiNode.create(loop, location));
                         phi.addInput(ValueNodeUtil.asNode(initialState.getLastLocationAccess(location)));
                         phis.put(location, phi);
                     }
    diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java
    --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Mon Aug 25 14:42:42 2014 -0700
    +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Mon Aug 25 21:15:59 2014 -0700
    @@ -162,9 +162,9 @@
     
             private void lowerToIf(GuardNode guard) {
                 StructuredGraph graph = guard.graph();
    -            BeginNode fastPath = graph.add(new BeginNode());
    +            BeginNode fastPath = graph.add(BeginNode.create());
                 @SuppressWarnings("deprecation")
    -            DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.action(), guard.reason(), useGuardIdAsDebugId ? guard.getId() : 0, guard.getSpeculation(), null));
    +            DeoptimizeNode deopt = graph.add(DeoptimizeNode.create(guard.action(), guard.reason(), useGuardIdAsDebugId ? guard.getId() : 0, guard.getSpeculation(), null));
                 BeginNode deoptBranch = BeginNode.begin(deopt);
                 BeginNode trueSuccessor;
                 BeginNode falseSuccessor;
    @@ -176,7 +176,7 @@
                     trueSuccessor = fastPath;
                     falseSuccessor = deoptBranch;
                 }
    -            IfNode ifNode = graph.add(new IfNode(guard.condition(), trueSuccessor, falseSuccessor, trueSuccessor == fastPath ? 1 : 0));
    +            IfNode ifNode = graph.add(IfNode.create(guard.condition(), trueSuccessor, falseSuccessor, trueSuccessor == fastPath ? 1 : 0));
                 guard.replaceAndDelete(fastPath);
                 insert(ifNode, fastPath);
             }
    @@ -185,7 +185,7 @@
                 Loop loop = block.getLoop();
                 StructuredGraph graph = deopt.graph();
                 while (loop != null) {
    -                LoopExitNode exit = graph.add(new LoopExitNode((LoopBeginNode) loop.getHeader().getBeginNode()));
    +                LoopExitNode exit = graph.add(LoopExitNode.create((LoopBeginNode) loop.getHeader().getBeginNode()));
                     graph.addBeforeFixed(deopt, exit);
                     loop = loop.getParent();
                 }
    diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java
    --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java	Mon Aug 25 14:42:42 2014 -0700
    +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java	Mon Aug 25 21:15:59 2014 -0700
    @@ -37,7 +37,7 @@
             if (GenLoopSafepoints.getValue()) {
                 for (LoopEndNode loopEndNode : graph.getNodes(LoopEndNode.class)) {
                     if (loopEndNode.canSafepoint()) {
    -                    SafepointNode safepointNode = graph.add(new SafepointNode());
    +                    SafepointNode safepointNode = graph.add(SafepointNode.create());
                         graph.addBeforeFixed(loopEndNode, safepointNode);
                     }
                 }
    diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java
    --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Mon Aug 25 14:42:42 2014 -0700
    +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Mon Aug 25 21:15:59 2014 -0700
    @@ -32,6 +32,7 @@
     import com.oracle.graal.graph.Graph.Mark;
     import com.oracle.graal.graph.*;
     import com.oracle.graal.graph.iterators.*;
    +import com.oracle.graal.nodeinfo.*;
     import com.oracle.graal.nodes.*;
     import com.oracle.graal.nodes.calc.*;
     import com.oracle.graal.nodes.cfg.*;
    @@ -46,6 +47,34 @@
      */
     public class LoweringPhase extends BasePhase {
     
    +    @NodeInfo
    +    static class DummyGuardHandle extends ValueNode implements GuardedNode {
    +        @Input(InputType.Guard) GuardingNode guard;
    +
    +        public static DummyGuardHandle create(GuardingNode guard) {
    +            return USE_GENERATED_NODES ? new LoweringPhase_DummyGuardHandleGen(guard) : new DummyGuardHandle(guard);
    +        }
    +
    +        protected DummyGuardHandle(GuardingNode guard) {
    +            super(StampFactory.forVoid());
    +            this.guard = guard;
    +        }
    +
    +        public GuardingNode getGuard() {
    +            return guard;
    +        }
    +
    +        public void setGuard(GuardingNode guard) {
    +            updateUsagesInterface(this.guard, guard);
    +            this.guard = guard;
    +        }
    +
    +        @Override
    +        public ValueNode asNode() {
    +            return this;
    +        }
    +    }
    +
         final class LoweringToolImpl implements LoweringTool {
     
             private final PhaseContext context;
    @@ -102,30 +131,6 @@
                 return context.getAssumptions();
             }
     
    -        private class DummyGuardHandle extends ValueNode implements GuardedNode {
    -            @Input(InputType.Guard) private GuardingNode guard;
    -
    -            public DummyGuardHandle(GuardingNode guard) {
    -                super(StampFactory.forVoid());
    -                this.guard = guard;
    -            }
    -
    -            public GuardingNode getGuard() {
    -                return guard;
    -            }
    -
    -            public void setGuard(GuardingNode guard) {
    -                updateUsagesInterface(this.guard, guard);
    -                this.guard = guard;
    -            }
    -
    -            @Override
    -            public ValueNode asNode() {
    -                return this;
    -            }
    -
    -        }
    -
             @Override
             public GuardingNode createGuard(FixedNode before, LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
                 if (OptEliminateGuards.getValue()) {
    @@ -137,13 +142,13 @@
                 }
                 StructuredGraph graph = before.graph();
                 if (condition.graph().getGuardsStage().ordinal() >= StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal()) {
    -                FixedGuardNode fixedGuard = graph.add(new FixedGuardNode(condition, deoptReason, action, negated));
    +                FixedGuardNode fixedGuard = graph.add(FixedGuardNode.create(condition, deoptReason, action, negated));
                     graph.addBeforeFixed(before, fixedGuard);
    -                DummyGuardHandle handle = graph.add(new DummyGuardHandle(fixedGuard));
    +                DummyGuardHandle handle = graph.add(DummyGuardHandle.create(fixedGuard));
                     fixedGuard.lower(this);
                     return handle.getGuard();
                 } else {
    -                GuardNode newGuard = graph.unique(new GuardNode(condition, guardAnchor, deoptReason, action, negated, Constant.NULL_OBJECT));
    +                GuardNode newGuard = graph.unique(GuardNode.create(condition, guardAnchor, deoptReason, action, negated, Constant.NULL_OBJECT));
                     if (OptEliminateGuards.getValue()) {
                         activeGuards.markAndGrow(newGuard);
                     }
    @@ -336,7 +341,7 @@
                             // FixedWithNextNode is followed by some kind of BeginNode.
                             // For example the when a FixedGuard followed by a loop exit is lowered to a
                             // control-split + deopt.
    -                        BeginNode begin = node.graph().add(new BeginNode());
    +                        BeginNode begin = node.graph().add(BeginNode.create());
                             nextLastFixed.replaceFirstSuccessor(nextNode, begin);
                             begin.setNext(nextNode);
                             nextLastFixed = begin;
    diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java
    --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java	Mon Aug 25 14:42:42 2014 -0700
    +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java	Mon Aug 25 21:15:59 2014 -0700
    @@ -110,7 +110,7 @@
     
                 if (otherGuards.size() == successorCount - 1) {
                     BeginNode anchor = computeOptimalAnchor(cfg.get(), BeginNode.prevBegin(controlSplit));
    -                GuardNode newGuard = controlSplit.graph().unique(new GuardNode(guard.condition(), anchor, guard.reason(), guard.action(), guard.negated(), guard.getSpeculation()));
    +                GuardNode newGuard = controlSplit.graph().unique(GuardNode.create(guard.condition(), anchor, guard.reason(), guard.action(), guard.negated(), guard.getSpeculation()));
                     for (GuardNode otherGuard : otherGuards) {
                         otherGuard.replaceAndDelete(newGuard);
                     }
    diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java
    --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Mon Aug 25 14:42:42 2014 -0700
    +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Mon Aug 25 21:15:59 2014 -0700
    @@ -34,7 +34,7 @@
     import com.oracle.graal.graph.Graph.Mark;
     import com.oracle.graal.graph.*;
     import com.oracle.graal.graph.NodeClass.NodeClassIterator;
    -import com.oracle.graal.graph.NodeClass.Position;
    +import com.oracle.graal.nodeinfo.*;
     import com.oracle.graal.nodes.*;
     import com.oracle.graal.nodes.VirtualState.NodeClosure;
     import com.oracle.graal.nodes.extended.*;
    @@ -61,8 +61,13 @@
     
         private final CanonicalizerPhase canonicalizer;
     
    -    private static final class DummyAnchorNode extends FixedWithNextNode implements GuardingNode {
    -        public DummyAnchorNode() {
    +    @NodeInfo
    +    static class DummyAnchorNode extends FixedWithNextNode implements GuardingNode {
    +        public static DummyAnchorNode create() {
    +            return USE_GENERATED_NODES ? new TailDuplicationPhase_DummyAnchorNodeGen() : new DummyAnchorNode();
    +        }
    +
    +        protected DummyAnchorNode() {
                 super(StampFactory.forVoid());
             }
         }
    @@ -337,7 +342,7 @@
              * @return The new {@link ValueAnchorNode} that was created.
              */
             private DummyAnchorNode addValueAnchor() {
    -            DummyAnchorNode anchor = graph.add(new DummyAnchorNode());
    +            DummyAnchorNode anchor = graph.add(DummyAnchorNode.create());
                 graph.addAfterFixed(merge, anchor);
                 merge.replaceAtUsages(InputType.Guard, anchor);
                 merge.replaceAtUsages(InputType.Anchor, anchor);
    @@ -447,8 +452,8 @@
              * @return The newly created end node.
              */
             private AbstractEndNode createNewMerge(FixedNode successor, FrameState stateAfterMerge) {
    -            MergeNode newBottomMerge = graph.add(new MergeNode());
    -            AbstractEndNode newBottomEnd = graph.add(new EndNode());
    +            MergeNode newBottomMerge = graph.add(MergeNode.create());
    +            AbstractEndNode newBottomEnd = graph.add(EndNode.create());
                 newBottomMerge.addForwardEnd(newBottomEnd);
                 newBottomMerge.setStateAfter(stateAfterMerge);
                 ((FixedWithNextNode) successor.predecessor()).setNext(newBottomEnd);
    @@ -522,7 +527,7 @@
                                         ValueNode node = (ValueNode) duplicated;
                                         PhiNode newPhi = bottomPhis.get(node);
                                         if (newPhi == null) {
    -                                        newPhi = graph.addWithoutUnique(new ValuePhiNode(node.stamp().unrestricted(), newBottomMerge));
    +                                        newPhi = graph.addWithoutUnique(ValuePhiNode.create(node.stamp().unrestricted(), newBottomMerge));
                                             bottomPhis.put(node, newPhi);
                                             newPhi.addInput(node);
                                         }
    diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java
    --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Mon Aug 25 14:42:42 2014 -0700
    +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Mon Aug 25 21:15:59 2014 -0700
    @@ -27,6 +27,7 @@
     import com.oracle.graal.api.meta.*;
     import com.oracle.graal.debug.*;
     import com.oracle.graal.graph.*;
    +import com.oracle.graal.nodeinfo.*;
     import com.oracle.graal.nodes.*;
     import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
     import com.oracle.graal.nodes.calc.*;
    @@ -161,7 +162,7 @@
             IsNullNode isNullNode = (IsNullNode) condition;
             BeginNode nonTrappingContinuation = ifNode.falseSuccessor();
             BeginNode trappingContinuation = ifNode.trueSuccessor();
    -        NullCheckNode trappingNullCheck = deopt.graph().add(new NullCheckNode(isNullNode.getValue()));
    +        NullCheckNode trappingNullCheck = deopt.graph().add(NullCheckNode.create(isNullNode.getValue()));
             trappingNullCheck.setStateBefore(deopt.stateBefore());
             deopt.graph().replaceSplit(ifNode, trappingNullCheck, nonTrappingContinuation);
     
    diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/BaseReduction.java
    --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/BaseReduction.java	Mon Aug 25 14:42:42 2014 -0700
    +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/BaseReduction.java	Mon Aug 25 21:15:59 2014 -0700
    @@ -97,7 +97,7 @@
                 metricUnconditionalDeoptInserted.increment();
                 StructuredGraph graph = fixed.graph();
                 // have to insert a FixedNode other than a ControlSinkNode
    -            FixedGuardNode buckStopsHere = graph.add(new FixedGuardNode(falseConstant, deoptReason, DeoptimizationAction.None));
    +            FixedGuardNode buckStopsHere = graph.add(FixedGuardNode.create(falseConstant, deoptReason, DeoptimizationAction.None));
                 if (goesBeforeFixed) {
                     fixed.replaceAtPredecessor(buckStopsHere);
                 } else {
    diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CheckCastReduction.java
    --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CheckCastReduction.java	Mon Aug 25 14:42:42 2014 -0700
    +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CheckCastReduction.java	Mon Aug 25 21:15:59 2014 -0700
    @@ -231,7 +231,7 @@
                  * (1 of 3) definitely-non-null
                  */
                 // addWithoutUnique for the same reason as in CheckCastNode.lower()
    -            condition = graph.addWithoutUnique(new InstanceOfNode(toType, subject, profile));
    +            condition = graph.addWithoutUnique(InstanceOfNode.create(toType, subject, profile));
                 reasoner.added.add(condition);
                 resultStamp = FlowUtil.asNonNullStamp(resultStamp);
                 // TODO fix in CheckCastNode.lower()
    @@ -240,15 +240,15 @@
                     /*
                      * (2 of 3) null-not-seen-in-profiling
                      */
    -                IsNullNode isNN = graph.unique(new IsNullNode(subject));
    +                IsNullNode isNN = graph.unique(IsNullNode.create(subject));
                     reasoner.added.add(isNN);
    -                FixedGuardNode nullCheck = graph.add(new FixedGuardNode(isNN, UnreachedCode, InvalidateReprofile, true));
    +                FixedGuardNode nullCheck = graph.add(FixedGuardNode.create(isNN, UnreachedCode, InvalidateReprofile, true));
                     graph.addBeforeFixed(checkCast, nullCheck);
                     // not calling wrapInPiNode() because we don't want to rememberSubstitution()
    -                PiNode nonNullGuarded = graph.unique(new PiNode(subject, FlowUtil.asNonNullStamp(subjectStamp), nullCheck));
    +                PiNode nonNullGuarded = graph.unique(PiNode.create(subject, FlowUtil.asNonNullStamp(subjectStamp), nullCheck));
                     reasoner.added.add(nonNullGuarded);
                     // addWithoutUnique for the same reason as in CheckCastNode.lower()
    -                condition = graph.addWithoutUnique(new InstanceOfNode(toType, nonNullGuarded, profile));
    +                condition = graph.addWithoutUnique(InstanceOfNode.create(toType, nonNullGuarded, profile));
                     reasoner.added.add(condition);
                     resultStamp = FlowUtil.asNonNullStamp(resultStamp);
                 } else {
    @@ -256,9 +256,9 @@
                      * (3 of 3) runtime-null-check-needed
                      */
                     // addWithoutUnique for the same reason as in CheckCastNode.lower()
    -                InstanceOfNode typeTest = graph.addWithoutUnique(new InstanceOfNode(toType, subject, profile));
    +                InstanceOfNode typeTest = graph.addWithoutUnique(InstanceOfNode.create(toType, subject, profile));
                     reasoner.added.add(typeTest);
    -                LogicNode nullTest = graph.unique(new IsNullNode(subject));
    +                LogicNode nullTest = graph.unique(IsNullNode.create(subject));
                     reasoner.added.add(nullTest);
                     // TODO (ds) replace with probability of null-seen when available
                     final double shortCircuitProbability = NOT_FREQUENT_PROBABILITY;
    @@ -271,7 +271,7 @@
              * Add a cast-guard (checking only what needs to be checked) and a PiNode (to be used in
              * place of the CheckCastNode).
              */
    -        FixedGuardNode castGuard = graph.add(new FixedGuardNode(condition, checkCast.isForStoreCheck() ? ArrayStoreException : ClassCastException, InvalidateReprofile));
    +        FixedGuardNode castGuard = graph.add(FixedGuardNode.create(condition, checkCast.isForStoreCheck() ? ArrayStoreException : ClassCastException, InvalidateReprofile));
             graph.addBeforeFixed(checkCast, castGuard);
     
             assert FlowUtil.isLegalObjectStamp(resultStamp);
    @@ -280,7 +280,7 @@
     
             if (!FlowUtil.lacksUsages(checkCast)) {
                 // not calling wrapInPiNode() because we don't want to rememberSubstitution()
    -            PiNode checkedObject = graph.unique(new PiNode(subject, resultStamp, castGuard));
    +            PiNode checkedObject = graph.unique(PiNode.create(subject, resultStamp, castGuard));
                 reasoner.added.add(checkedObject);
                 assert !precisionLoss(originalCheckCastObject, checkedObject);
                 assert !precisionLoss(subject, checkedObject);
    diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java
    --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java	Mon Aug 25 14:42:42 2014 -0700
    +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java	Mon Aug 25 21:15:59 2014 -0700
    @@ -46,8 +46,8 @@
      * Such evaluator comes handy when visiting a {@link com.oracle.graal.nodes.FixedNode} N, just
      * before updating the state for N. At the pre-state, an {@link EquationalReasoner} can be used to
      * reduce N's inputs (actually only those inputs of Value and Condition
    - * {@link com.oracle.graal.graph.InputType InputType}). For an explanation of where it's warranted
    - * to replace "old input" with "reduced input", see the inline comments in method
    + * {@link com.oracle.graal.nodeinfo.InputType InputType}). For an explanation of where it's
    + * warranted to replace "old input" with "reduced input", see the inline comments in method
      * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node n) deverbosify(Node n)}
      * 

    * @@ -664,7 +664,7 @@ try (Debug.Scope s = Debug.scope("Downcast", payload)) { assert payload != anchor : payload.graph().toString(); metricDowncasting.increment(); - PiNode result = graph.unique(new PiNode(payload, newStamp, anchor.asNode())); + PiNode result = graph.unique(PiNode.create(payload, newStamp, anchor.asNode())); // we've possibly got a new node in the graph --- bookkeeping is in order. added.add(result); if (remember) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java Mon Aug 25 21:15:59 2014 -0700 @@ -499,9 +499,9 @@ * state-tracking. TODO the assumption here is that the code emitted for the resulting * FixedGuardNode is as efficient as for NullCheckNode. */ - IsNullNode isNN = graph.unique(new IsNullNode(object)); + IsNullNode isNN = graph.unique(IsNullNode.create(object)); reasoner.added.add(isNN); - FixedGuardNode nullCheck = graph.add(new FixedGuardNode(isNN, UnreachedCode, InvalidateReprofile, true)); + FixedGuardNode nullCheck = graph.add(FixedGuardNode.create(isNN, UnreachedCode, InvalidateReprofile, true)); graph.replaceFixedWithFixed(ncn, nullCheck); state.trackNN(object, nullCheck); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,18 +22,13 @@ */ package com.oracle.graal.phases.common.cfs; -import com.oracle.graal.api.meta.ResolvedJavaType; -import com.oracle.graal.graph.InputType; -import com.oracle.graal.graph.Node; -import com.oracle.graal.graph.NodeClass; +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.compiler.common.type.ObjectStamp; -import com.oracle.graal.compiler.common.type.Stamp; -import com.oracle.graal.compiler.common.type.StampFactory; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; public class FlowUtil { @@ -236,7 +231,7 @@ ArrayList result = null; NodeClass.NodeClassIterator iter = n.inputs().iterator(); while (iter.hasNext()) { - NodeClass.Position pos = iter.nextPosition(); + Position pos = iter.nextPosition(); InputType inputType = pos.getInputType(n); boolean isReducibleInput = (inputType == InputType.Value || inputType == InputType.Condition); if (isReducibleInput) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/GuardingPiReduction.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/GuardingPiReduction.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/GuardingPiReduction.java Mon Aug 25 21:15:59 2014 -0700 @@ -141,7 +141,7 @@ * FixedGuardNode allows tracking the condition via a GuardingNode, thus potentially * triggering simplifications down the road. */ - FixedGuardNode fixedGuard = graph.add(new FixedGuardNode(envelope.condition(), envelope.getReason(), envelope.getAction(), envelope.isNegated())); + FixedGuardNode fixedGuard = graph.add(FixedGuardNode.create(envelope.condition(), envelope.getReason(), envelope.getAction(), envelope.isNegated())); graph.addBeforeFixed(envelope, fixedGuard); /* @@ -152,7 +152,7 @@ if (!FlowUtil.lacksUsages(envelope)) { // not calling wrapInPiNode() because we don't want to rememberSubstitution() - PiNode replacement = graph.unique(new PiNode(envelope.object(), envelope.stamp(), fixedGuard)); + PiNode replacement = graph.unique(PiNode.create(envelope.object(), envelope.stamp(), fixedGuard)); reasoner.added.add(replacement); // before removing the GuardingPiNode replace its usages envelope.replaceAtUsages(replacement); @@ -182,8 +182,8 @@ * Provided a condition as above can be reduced to a constant (and an anchor obtained in the * process), this method replaces all usages of the * {@link com.oracle.graal.nodes.GuardingPiNode} (necessarily of - * {@link com.oracle.graal.graph.InputType#Value}) with a {@link com.oracle.graal.nodes.PiNode} - * that wraps the payload and the anchor in question. + * {@link com.oracle.graal.nodeinfo.InputType#Value}) with a + * {@link com.oracle.graal.nodes.PiNode} that wraps the payload and the anchor in question. *

    * *

    @@ -281,7 +281,7 @@ * TODO The GuardingPiNode has an outgoing stamp whose narrowing goes beyond what * the condition checks. That's suspicious. */ - PiNode replacement = graph.unique(new PiNode(payload, envelope.stamp())); + PiNode replacement = graph.unique(PiNode.create(payload, envelope.stamp())); reasoner.added.add(replacement); removeGuardingPiNode(envelope, replacement); return true; @@ -295,7 +295,7 @@ Witness w = state.typeInfo(payload); GuardingNode nonNullAnchor = (w != null && w.isNonNull()) ? w.guard() : null; if (nonNullAnchor != null) { - PiNode replacement = graph.unique(new PiNode(payload, envelope.stamp(), nonNullAnchor.asNode())); + PiNode replacement = graph.unique(PiNode.create(payload, envelope.stamp(), nonNullAnchor.asNode())); reasoner.added.add(replacement); removeGuardingPiNode(envelope, replacement); return true; diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,6 +27,7 @@ import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.compiler.common.type.StampFactory.*; +import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.code.*; @@ -37,7 +38,7 @@ import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Graph.DuplicationReplacement; -import com.oracle.graal.graph.Node.Verbosity; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.calc.*; @@ -175,7 +176,7 @@ public static void replaceInvokeCallTarget(Invoke invoke, StructuredGraph graph, InvokeKind invokeKind, ResolvedJavaMethod targetMethod) { MethodCallTargetNode oldCallTarget = (MethodCallTargetNode) invoke.callTarget(); - MethodCallTargetNode newCallTarget = graph.add(new MethodCallTargetNode(invokeKind, targetMethod, oldCallTarget.arguments().toArray(new ValueNode[0]), oldCallTarget.returnType())); + MethodCallTargetNode newCallTarget = graph.add(MethodCallTargetNode.create(invokeKind, targetMethod, oldCallTarget.arguments().toArray(new ValueNode[0]), oldCallTarget.returnType())); invoke.asNode().replaceFirstInput(oldCallTarget, newCallTarget); } @@ -185,7 +186,7 @@ private static GuardedValueNode createAnchoredReceiver(StructuredGraph graph, GuardingNode anchor, ValueNode receiver, Stamp stamp) { // to avoid that floating reads on receiver fields float above the type check - return graph.unique(new GuardedValueNode(receiver, anchor, stamp)); + return graph.unique(GuardedValueNode.create(receiver, anchor, stamp)); } /** @@ -301,7 +302,7 @@ // get rid of memory kill BeginNode begin = invokeWithException.next(); if (begin instanceof KillingBeginNode) { - BeginNode newBegin = new BeginNode(); + BeginNode newBegin = BeginNode.create(); graph.addAfterFixed(begin, graph.add(newBegin)); begin.replaceAtUsages(newBegin); graph.removeFixed(begin); @@ -309,7 +310,7 @@ } else { if (unwindNode != null) { UnwindNode unwindDuplicate = (UnwindNode) duplicates.get(unwindNode); - DeoptimizeNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler)); + DeoptimizeNode deoptimizeNode = graph.add(DeoptimizeNode.create(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler)); unwindDuplicate.replaceAndDelete(deoptimizeNode); } } @@ -340,7 +341,7 @@ for (ReturnNode returnNode : returnNodes) { returnDuplicates.add((ReturnNode) duplicates.get(returnNode)); } - MergeNode merge = graph.add(new MergeNode()); + MergeNode merge = graph.add(MergeNode.create()); merge.setStateAfter(stateAfter); ValueNode returnValue = mergeReturns(merge, returnDuplicates, canonicalizedNodes); invokeNode.replaceAtUsages(returnValue); @@ -385,7 +386,7 @@ * return value (top of stack) */ FrameState stateAfterReturn = stateAtReturn; - if (invokeReturnKind != Kind.Void && (alwaysDuplicateStateAfter || frameState.stackSize() > 0 && stateAfterReturn.stackAt(0) != frameState.stackAt(0))) { + if (invokeReturnKind != Kind.Void && (alwaysDuplicateStateAfter || (frameState.stackSize() > 0 && stateAfterReturn.stackAt(0) != frameState.stackAt(0)))) { stateAfterReturn = stateAtReturn.duplicateModified(invokeReturnKind, frameState.stackAt(0)); } frameState.replaceAndDelete(stateAfterReturn); @@ -442,12 +443,12 @@ MergeNode merge = (MergeNode) fixedStateSplit; while (merge.isAlive()) { AbstractEndNode end = merge.forwardEnds().first(); - DeoptimizeNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler)); + DeoptimizeNode deoptimizeNode = graph.add(DeoptimizeNode.create(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler)); end.replaceAtPredecessor(deoptimizeNode); GraphUtil.killCFG(end); } } else { - FixedNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler)); + FixedNode deoptimizeNode = graph.add(DeoptimizeNode.create(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler)); if (fixedStateSplit instanceof BeginNode) { deoptimizeNode = BeginNode.begin(deoptimizeNode); } @@ -464,12 +465,12 @@ for (ReturnNode returnNode : returnNodes) { // create and wire up a new EndNode - EndNode endNode = merge.graph().add(new EndNode()); + EndNode endNode = merge.graph().add(EndNode.create()); merge.addForwardEnd(endNode); if (returnNode.result() != null) { if (returnValuePhi == null) { - returnValuePhi = merge.graph().addWithoutUnique(new ValuePhiNode(returnNode.result().stamp().unrestricted(), merge)); + returnValuePhi = merge.graph().addWithoutUnique(ValuePhiNode.create(returnNode.result().stamp().unrestricted(), merge)); if (canonicalizedNodes != null) { canonicalizedNodes.add(returnValuePhi); } @@ -501,9 +502,9 @@ StructuredGraph graph = callTarget.graph(); ValueNode firstParam = callTarget.arguments().get(0); if (firstParam.getKind() == Kind.Object && !StampTool.isObjectNonNull(firstParam)) { - IsNullNode condition = graph.unique(new IsNullNode(firstParam)); + IsNullNode condition = graph.unique(IsNullNode.create(firstParam)); Stamp stamp = firstParam.stamp().join(objectNonNull()); - GuardingPiNode nonNullReceiver = graph.add(new GuardingPiNode(firstParam, condition, true, NullCheckException, InvalidateReprofile, stamp)); + GuardingPiNode nonNullReceiver = graph.add(GuardingPiNode.create(firstParam, condition, true, NullCheckException, InvalidateReprofile, stamp)); graph.addBeforeFixed(invoke.asNode(), nonNullReceiver); callTarget.replaceFirstInput(firstParam, nonNullReceiver); return nonNullReceiver; @@ -546,7 +547,8 @@ private static FixedWithNextNode createMacroNodeInstance(Class macroNodeClass, Invoke invoke) throws GraalInternalError { try { - return macroNodeClass.getConstructor(Invoke.class).newInstance(invoke); + Method factory = macroNodeClass.getDeclaredMethod("create", Invoke.class); + return (FixedWithNextNode) factory.invoke(null, invoke); } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) { throw new GraalGraphInternalError(e).addContext(invoke.asNode()).addContext("macroSubstitution", macroNodeClass); } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Mon Aug 25 21:15:59 2014 -0700 @@ -172,12 +172,12 @@ ValueNode originalReceiver = ((MethodCallTargetNode) invoke.callTarget()).receiver(); // setup merge and phi nodes for results and exceptions - MergeNode returnMerge = graph.add(new MergeNode()); + MergeNode returnMerge = graph.add(MergeNode.create()); returnMerge.setStateAfter(invoke.stateAfter()); PhiNode returnValuePhi = null; if (invoke.asNode().getKind() != Kind.Void) { - returnValuePhi = graph.addWithoutUnique(new ValuePhiNode(invoke.asNode().stamp().unrestricted(), returnMerge)); + returnValuePhi = graph.addWithoutUnique(ValuePhiNode.create(invoke.asNode().stamp().unrestricted(), returnMerge)); } MergeNode exceptionMerge = null; @@ -186,11 +186,11 @@ InvokeWithExceptionNode invokeWithException = (InvokeWithExceptionNode) invoke; ExceptionObjectNode exceptionEdge = (ExceptionObjectNode) invokeWithException.exceptionEdge(); - exceptionMerge = graph.add(new MergeNode()); + exceptionMerge = graph.add(MergeNode.create()); FixedNode exceptionSux = exceptionEdge.next(); graph.addBeforeFixed(exceptionSux, exceptionMerge); - exceptionObjectPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(Kind.Object), exceptionMerge)); + exceptionObjectPhi = graph.addWithoutUnique(ValuePhiNode.create(StampFactory.forKind(Kind.Object), exceptionMerge)); exceptionMerge.setStateAfter(exceptionEdge.stateAfter().duplicateModified(invoke.stateAfter().bci, true, Kind.Object, exceptionObjectPhi)); } @@ -205,7 +205,7 @@ if (shouldFallbackToInvoke()) { unknownTypeSux = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, false); } else { - unknownTypeSux = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated)); + unknownTypeSux = graph.add(DeoptimizeNode.create(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated)); } successors[successors.length - 1] = BeginNode.begin(unknownTypeSux); @@ -329,7 +329,7 @@ private Collection inlineSingleMethod(StructuredGraph graph, MetaAccessProvider metaAccess, Assumptions assumptions) { assert concretes.size() == 1 && inlineableElements.length == 1 && ptypes.size() > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0; - BeginNode calleeEntryNode = graph.add(new BeginNode()); + BeginNode calleeEntryNode = graph.add(BeginNode.create()); BeginNode unknownTypeSux = createUnknownTypeSuccessor(graph); BeginNode[] successors = new BeginNode[]{calleeEntryNode, unknownTypeSux}; @@ -344,7 +344,7 @@ assert ptypes.size() >= 1; ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke); Kind hubKind = ((MethodCallTargetNode) invoke.callTarget()).targetMethod().getDeclaringClass().getEncoding(ResolvedJavaType.Representation.ObjectHub).getKind(); - LoadHubNode hub = graph.unique(new LoadHubNode(nonNullReceiver, hubKind)); + LoadHubNode hub = graph.unique(LoadHubNode.create(nonNullReceiver, hubKind)); if (!invokeIsOnlySuccessor && chooseMethodDispatch()) { assert successors.length == concretes.size() + 1; @@ -375,9 +375,9 @@ ResolvedJavaType receiverType = invoke.getReceiverType(); FixedNode lastSucc = successors[concretes.size()]; for (int i = concretes.size() - 1; i >= 0; --i) { - LoadMethodNode method = graph.add(new LoadMethodNode(concretes.get(i), receiverType, hub, constantMethods[i].getKind())); + LoadMethodNode method = graph.add(LoadMethodNode.create(concretes.get(i), receiverType, hub, constantMethods[i].getKind())); CompareNode methodCheck = CompareNode.createCompareNode(graph, Condition.EQ, method, constantMethods[i]); - IfNode ifNode = graph.add(new IfNode(methodCheck, successors[i], lastSucc, probability[i])); + IfNode ifNode = graph.add(IfNode.create(methodCheck, successors[i], lastSucc, probability[i])); method.setNext(ifNode); lastSucc = method; } @@ -408,7 +408,7 @@ keyProbabilities[i] /= totalProbability; } - TypeSwitchNode typeSwitch = graph.add(new TypeSwitchNode(hub, successors, keys, keyProbabilities, keySuccessors)); + TypeSwitchNode typeSwitch = graph.add(TypeSwitchNode.create(hub, successors, keys, keyProbabilities, keySuccessors)); FixedWithNextNode pred = (FixedWithNextNode) invoke.asNode().predecessor(); pred.setNext(typeSwitch); return false; @@ -462,10 +462,10 @@ private static BeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, MergeNode returnMerge, PhiNode returnValuePhi, MergeNode exceptionMerge, PhiNode exceptionObjectPhi, boolean useForInlining) { Invoke duplicatedInvoke = duplicateInvokeForInlining(graph, invoke, exceptionMerge, exceptionObjectPhi, useForInlining); - BeginNode calleeEntryNode = graph.add(new BeginNode()); + BeginNode calleeEntryNode = graph.add(BeginNode.create()); calleeEntryNode.setNext(duplicatedInvoke.asNode()); - AbstractEndNode endNode = graph.add(new EndNode()); + AbstractEndNode endNode = graph.add(EndNode.create()); duplicatedInvoke.setNext(endNode); returnMerge.addForwardEnd(endNode); @@ -500,7 +500,7 @@ // set new state (pop old exception object, push new one) newExceptionEdge.setStateAfter(stateAfterException.duplicateModified(stateAfterException.bci, stateAfterException.rethrowException(), Kind.Object, newExceptionEdge)); - AbstractEndNode endNode = graph.add(new EndNode()); + AbstractEndNode endNode = graph.add(EndNode.create()); newExceptionEdge.setNext(endNode); exceptionMerge.addForwardEnd(endNode); exceptionObjectPhi.addInput(newExceptionEdge); @@ -538,7 +538,7 @@ } private void devirtualizeWithTypeSwitch(StructuredGraph graph, InvokeKind kind, ResolvedJavaMethod target, MetaAccessProvider metaAccess) { - BeginNode invocationEntry = graph.add(new BeginNode()); + BeginNode invocationEntry = graph.add(BeginNode.create()); BeginNode unknownTypeSux = createUnknownTypeSuccessor(graph); BeginNode[] successors = new BeginNode[]{invocationEntry, unknownTypeSux}; createDispatchOnTypeBeforeInvoke(graph, successors, true, metaAccess); @@ -551,7 +551,7 @@ } private static BeginNode createUnknownTypeSuccessor(StructuredGraph graph) { - return BeginNode.begin(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated))); + return BeginNode.begin(graph.add(DeoptimizeNode.create(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated))); } @Override diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java Mon Aug 25 21:15:59 2014 -0700 @@ -104,10 +104,10 @@ private void createGuard(StructuredGraph graph, MetaAccessProvider metaAccess) { ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke); ConstantNode typeHub = ConstantNode.forConstant(type.getEncoding(ResolvedJavaType.Representation.ObjectHub), metaAccess, graph); - LoadHubNode receiverHub = graph.unique(new LoadHubNode(nonNullReceiver, typeHub.getKind())); + LoadHubNode receiverHub = graph.unique(LoadHubNode.create(nonNullReceiver, typeHub.getKind())); CompareNode typeCheck = CompareNode.createCompareNode(graph, Condition.EQ, receiverHub, typeHub); - FixedGuardNode guard = graph.add(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile)); + FixedGuardNode guard = graph.add(FixedGuardNode.create(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile)); assert invoke.predecessor() != null; ValueNode anchoredReceiver = InliningUtil.createAnchoredReceiver(graph, guard, type, nonNullReceiver, true); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/ComputeInliningRelevance.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/ComputeInliningRelevance.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/ComputeInliningRelevance.java Mon Aug 25 21:15:59 2014 -0700 @@ -116,7 +116,7 @@ parent = loops.get(null); break; } else { - assert current.getClass() == MergeNode.class : current; + assert current.getClass() == MergeNode.getGenClass() : current; // follow any path upwards - it doesn't matter which one current = ((MergeNode) current).forwardEndAt(0); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Mon Aug 25 21:15:59 2014 -0700 @@ -33,7 +33,7 @@ import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Node.Verbosity; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java Mon Aug 25 21:15:59 2014 -0700 @@ -83,26 +83,19 @@ } } - if (CompilerConfiguration.getValue().equals("")) { - if (nonBasicCount == 1) { - /* - * There is exactly one non-basic configuration. We use this one as default. - */ - defaultConfiguration = nonBasic; - } else { - /* - * There is either no extended configuration available, or more than one. In that - * case, default to "basic". - */ - defaultConfiguration = basic; - if (defaultConfiguration == null) { - throw new GraalInternalError("unable to find basic compiler configuration"); - } - } + if (nonBasicCount == 1) { + /* + * There is exactly one non-basic configuration. We use this one as default. + */ + defaultConfiguration = nonBasic; } else { - defaultConfiguration = configurations.get(CompilerConfiguration.getValue()); + /* + * There is either no extended configuration available, or more than one. In that case, + * default to "basic". + */ + defaultConfiguration = basic; if (defaultConfiguration == null) { - throw new GraalInternalError("unknown compiler configuration: " + CompilerConfiguration.getValue()); + throw new GraalInternalError("unable to find basic compiler configuration"); } } } @@ -120,7 +113,12 @@ } public static Suites createDefaultSuites() { - return new Suites(defaultConfiguration); + String selected = CompilerConfiguration.getValue(); + if (selected.equals("")) { + return new Suites(defaultConfiguration); + } else { + return createSuites(selected); + } } public static Suites createSuites(String name) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyNoNodeClassLiteralIdentityTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyNoNodeClassLiteralIdentityTests.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.phases.verify; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.tiers.*; + +/** + * Since only {@linkplain GeneratedNode generated} {@link Node} types can be instantiated (which is + * checked by an assertion in {@link Node#Node()}), any identity test of a node's + * {@linkplain Object#getClass() class} against a class literal of a non-generated node types will + * always return false. Instead, a static {@code getGenClass()} helper method should be used for + * such identity tests. For example, instead of: + * + *

    + *     if (operation.getClass() == IntegerAddNode.class) { ... }
    + * 
    + * + * this should be used: + * + *
    + *     if (operation.getClass() == IntegerAddNode.getGenClass()) { ... }
    + * 
    + * + * This phase verifies there are no identity tests against class literals for non-generated Node + * types. + */ +public class VerifyNoNodeClassLiteralIdentityTests extends VerifyPhase { + + @Override + protected boolean verify(StructuredGraph graph, PhaseContext context) { + Map errors = new HashMap<>(); + + for (ConstantNode c : ConstantNode.getConstantNodes(graph)) { + ResolvedJavaType nodeClassType = context.getMetaAccess().lookupJavaType(Node.class); + ResolvedJavaType nodeType = context.getConstantReflection().asJavaType(c.asConstant()); + if (nodeType != null && nodeClassType.isAssignableFrom(nodeType)) { + NodeIterable usages = c.usages(); + for (Node n : usages) { + if (!(n instanceof ObjectEqualsNode)) { + continue; + } + String loc = GraphUtil.approxSourceLocation(n); + if (loc == null) { + loc = graph.method().asStackTraceElement(0).toString() + " " + n; + } + errors.put(nodeType.toJavaName(false), loc); + } + } + } + if (errors.isEmpty()) { + return true; + } + Formatter f = new Formatter(); + boolean first = true; + for (Map.Entry e : errors.entrySet()) { + if (!first) { + f.format("%n"); + } else { + first = false; + } + f.format("Found illegal use of Node class literal %s near:%n %s", e.getKey(), e.getValue()); + } + throw new VerificationError(f.toString()); + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Mon Aug 25 21:15:59 2014 -0700 @@ -34,7 +34,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.NodeClass.Position; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.phases.graph.*; @@ -299,14 +298,14 @@ Collection directInputPositions = nodeClass.getFirstLevelInputPositions(); writeShort((char) directInputPositions.size()); for (Position pos : directInputPositions) { - writeByte(pos.getSubIndex() == NodeClass.NOT_ITERABLE ? 0 : 1); + writeByte(pos.getSubIndex() == Node.NOT_ITERABLE ? 0 : 1); writePoolObject(nodeClass.getName(pos)); writePoolObject(nodeClass.getInputType(pos)); } Collection directSuccessorPositions = nodeClass.getFirstLevelSuccessorPositions(); writeShort((char) directSuccessorPositions.size()); for (Position pos : directSuccessorPositions) { - writeByte(pos.getSubIndex() == NodeClass.NOT_ITERABLE ? 0 : 1); + writeByte(pos.getSubIndex() == Node.NOT_ITERABLE ? 0 : 1); writePoolObject(nodeClass.getName(pos)); } } else if (object instanceof ResolvedJavaMethod) { @@ -440,7 +439,7 @@ private void writeEdges(Node node, Collection positions) throws IOException { NodeClass nodeClass = node.getNodeClass(); for (Position pos : positions) { - if (pos.getSubIndex() == NodeClass.NOT_ITERABLE) { + if (pos.getSubIndex() == Node.NOT_ITERABLE) { Node edge = nodeClass.get(node, pos); writeNodeRef(edge); } else { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Mon Aug 25 21:15:59 2014 -0700 @@ -34,12 +34,11 @@ import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Node.Verbosity; import com.oracle.graal.graph.NodeClass.NodeClassIterator; -import com.oracle.graal.graph.NodeClass.Position; import com.oracle.graal.java.*; import com.oracle.graal.java.BciBlockMapping.BciBlock; import com.oracle.graal.lir.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.cfg.*; @@ -459,7 +458,7 @@ out.printf("nr %4d ", inst.id()).print(COLUMN_END); final StringBuilder stateString = new StringBuilder(); - inst.forEachState(new LIRInstruction.StateProcedure() { + inst.forEachState(new StateProcedure() { @Override protected void doState(LIRFrameState state) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java Mon Aug 25 21:15:59 2014 -0700 @@ -30,10 +30,9 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Node.Verbosity; import com.oracle.graal.graph.NodeClass.NodeClassIterator; -import com.oracle.graal.graph.NodeClass.Position; import com.oracle.graal.java.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.phases.schedule.*; @@ -175,9 +174,9 @@ printProperty(bit, "true"); } } - if (node.getClass() == BeginNode.class) { + if (node.getClass() == BeginNode.getGenClass()) { printProperty("shortName", "B"); - } else if (node.getClass() == AbstractEndNode.class) { + } else if (node.getClass() == EndNode.getGenClass()) { printProperty("shortName", "E"); } if (node.predecessor() != null) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Mon Aug 25 21:15:59 2014 -0700 @@ -182,7 +182,7 @@ Arguments args = new Arguments(key, graph.getGuardsStage(), tool.getLoweringStage()); args.add("input", convert.getValue()); - args.add("result", graph.unique(new AMD64FloatConvertNode(convert.stamp(), convert.getOp(), convert.getValue()))); + args.add("result", graph.unique(AMD64FloatConvertNode.create(convert.stamp(), convert.getOp(), convert.getValue()))); SnippetTemplate template = template(args); Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.getOp(), graph, convert, template, args); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -28,6 +28,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -37,11 +38,16 @@ * of the {@link FloatConvertNode} which, on AMD64 needs a {@link AMD64FloatConvertNode} plus some * fixup code that handles the corner cases that differ between AMD64 and Java. */ +@NodeInfo public class AMD64FloatConvertNode extends UnaryNode implements ArithmeticLIRLowerable { private final FloatConvert op; - public AMD64FloatConvertNode(Stamp stamp, FloatConvert op, ValueNode value) { + public static AMD64FloatConvertNode create(Stamp stamp, FloatConvert op, ValueNode value) { + return USE_GENERATED_NODES ? new AMD64FloatConvertNodeGen(stamp, op, value) : new AMD64FloatConvertNode(stamp, op, value); + } + + protected AMD64FloatConvertNode(Stamp stamp, FloatConvert op, ValueNode value) { super(stamp, value); this.op = op; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java --- a/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -30,6 +30,7 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.hsail.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -37,12 +38,13 @@ /** * This node implements HSAIL intrinsics for specific {@link Math} routines. */ +@NodeInfo public class HSAILMathIntrinsicsNode extends FloatingNode implements Canonicalizable, ArithmeticLIRLowerable { /** * The parameter passed to the math operation that this node represents. */ - @Input private ValueNode param; + @Input ValueNode param; /** * The math operation that this Node represents. @@ -73,7 +75,11 @@ * @param x the argument to the math operation * @param op the math operation */ - public HSAILMathIntrinsicsNode(ValueNode x, HSAILArithmetic op) { + public static HSAILMathIntrinsicsNode create(ValueNode x, HSAILArithmetic op) { + return USE_GENERATED_NODES ? new HSAILMathIntrinsicsNodeGen(x, op) : new HSAILMathIntrinsicsNode(x, op); + } + + protected HSAILMathIntrinsicsNode(ValueNode x, HSAILArithmetic op) { super(StampFactory.forKind(x.getKind())); this.param = x; this.operation = op; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/JStrictMath.java --- a/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/JStrictMath.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/JStrictMath.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,13 +23,12 @@ package com.oracle.graal.replacements.hsail; -import java.util.Random; +import java.util.*; + +import sun.misc.*; import com.oracle.graal.api.replacements.*; -import sun.misc.FpUtils; -import sun.misc.DoubleConsts; - /** * This class contains methods for performing basic numeric operations such as the elementary * exponential, logarithm, square root, and trigonometric functions. It is a Java port of the native diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -72,7 +72,7 @@ } // Force compilation - InstalledCode code = getCode(getMetaAccess().lookupJavaMethod(testMethod), parse(testMethod)); + InstalledCode code = getCode(getMetaAccess().lookupJavaMethod(testMethod), parseEager(testMethod)); assert optional || code != null; for (int i = 0; i < args1.length; i++) { @@ -374,7 +374,7 @@ @Test public void testCanonicalLength() { - StructuredGraph graph = parse("testCanonicalLengthSnippet"); + StructuredGraph graph = parseEager("testCanonicalLengthSnippet"); Assumptions assumptions = new Assumptions(false); HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); @@ -391,7 +391,7 @@ @Test public void testCanonicalEqual() { - StructuredGraph graph = parse("testCanonicalEqualSnippet"); + StructuredGraph graph = parseEager("testCanonicalEqualSnippet"); Assumptions assumptions = new Assumptions(false); HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); @@ -406,7 +406,7 @@ @Test public void testVirtualEqual() { - StructuredGraph graph = parse("testVirtualEqualSnippet"); + StructuredGraph graph = parseEager("testVirtualEqualSnippet"); Assumptions assumptions = new Assumptions(false); HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); @@ -425,7 +425,7 @@ @Test public void testVirtualNotEqual() { - StructuredGraph graph = parse("testVirtualNotEqualSnippet"); + StructuredGraph graph = parseEager("testVirtualNotEqualSnippet"); Assumptions assumptions = new Assumptions(false); HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -247,7 +247,7 @@ * @return the returned value or null if {@code expectedClass} is not found in the graph. */ private ValueNode parseAndInline(String name, Class expectedClass) { - StructuredGraph graph = parse(name); + StructuredGraph graph = parseEager(name); HighTierContext context = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); canonicalizer.apply(graph, context); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -37,7 +37,7 @@ protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) { CheckCastNode ccn = graph.getNodes().filter(CheckCastNode.class).first(); if (ccn != null) { - CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.type(), ccn.object(), profile, false)); + CheckCastNode ccnNew = graph.add(CheckCastNode.create(ccn.type(), ccn.object(), profile, false)); graph.replaceFixedWithFixed(ccn, ccnNew); } } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -41,8 +41,8 @@ } @Override - protected StructuredGraph parse(Method m) { - StructuredGraph graph = super.parse(m); + protected StructuredGraph parseEager(Method m) { + StructuredGraph graph = super.parseEager(m); int handlers = graph.getNodes().filter(ExceptionObjectNode.class).count(); Assert.assertEquals(1, handlers); return graph; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -50,7 +50,7 @@ protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) { InstanceOfNode ion = graph.getNodes().filter(InstanceOfNode.class).first(); if (ion != null) { - InstanceOfNode ionNew = graph.unique(new InstanceOfNode(ion.type(), ion.getValue(), profile)); + InstanceOfNode ionNew = graph.unique(InstanceOfNode.create(ion.type(), ion.getValue(), profile)); graph.replaceFloating(ion, ionNew); } } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -44,7 +44,7 @@ protected StructuredGraph test(final String snippet) { try (Scope s = Debug.scope("MethodSubstitutionTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) { - StructuredGraph graph = parse(snippet); + StructuredGraph graph = parseEager(snippet); Assumptions assumptions = new Assumptions(true); HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); Debug.dump(graph, "Graph"); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewMultiArrayTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewMultiArrayTest.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewMultiArrayTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -63,7 +63,7 @@ dimensionNodes[i] = ConstantNode.forInt(dimensions[i], graph); } - NewMultiArrayNode repl = graph.add(new NewMultiArrayNode(arrayType, dimensionNodes)); + NewMultiArrayNode repl = graph.add(NewMultiArrayNode.create(arrayType, dimensionNodes)); graph.replaceFixedWithFixed(node, repl); forceCompile = true; } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -53,7 +53,7 @@ private static final ThreadLocal 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 ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -59,7 +59,7 @@ private static final ThreadLocal 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 ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -94,7 +94,7 @@ } // Force compilation - InstalledCode code = getCode(getMetaAccess().lookupJavaMethod(testMethod), parse(testMethod)); + InstalledCode code = getCode(getMetaAccess().lookupJavaMethod(testMethod), parseEager(testMethod)); assert optional || code != null; for (Object l : args) { // Verify that the original method and the substitution produce the same value diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StringSubstitutionsTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -66,7 +66,7 @@ } // Force compilation - InstalledCode code = getCode(getMetaAccess().lookupJavaMethod(testMethod), parse(testMethod)); + InstalledCode code = getCode(getMetaAccess().lookupJavaMethod(testMethod), parseEager(testMethod)); assert optional || code != null; for (int i = 0; i < args1.length; i++) { diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/UnsafeSubstitutionsTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -62,7 +62,7 @@ Method testMethod = getMethod(testMethodName); // Force compilation - InstalledCode code = getCode(getMetaAccess().lookupJavaMethod(testMethod), parse(testMethod)); + InstalledCode code = getCode(getMetaAccess().lookupJavaMethod(testMethod), parseEager(testMethod)); assert code != null; // Verify that the original method and the substitution produce the same value diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -49,7 +49,7 @@ private static final ThreadLocal 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 ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/AbstractVerifier.java --- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/AbstractVerifier.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/AbstractVerifier.java Mon Aug 25 21:15:59 2014 -0700 @@ -44,7 +44,7 @@ @SuppressWarnings("unchecked") protected static T resolveAnnotationValue(Class expectedType, AnnotationValue value) { if (value == null) { - throw new NullPointerException("Value must not be null."); + return null; } Object unboxedValue = value.getValue(); if (unboxedValue != null) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java --- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java Mon Aug 25 21:15:59 2014 -0700 @@ -94,7 +94,7 @@ env.getMessager().printMessage(Kind.ERROR, String.format("Cannot make @NodeIntrinsic for abstract node class %s.", nodeClass.getSimpleName()), element, annotation); } else { TypeMirror[] constructorSignature = constructorSignature(intrinsicMethod); - findConstructor(nodeClass, constructorSignature, intrinsicMethod, annotation); + findFactory(nodeClass, constructorSignature, intrinsicMethod, annotation); } } else { env.getMessager().printMessage(Kind.ERROR, String.format("The class %s is not a Node subclass.", nodeClass.getSimpleName()), element, annotation); @@ -122,37 +122,40 @@ return parameters; } - private void findConstructor(TypeElement nodeClass, TypeMirror[] signature, ExecutableElement intrinsicMethod, AnnotationMirror intrinsicAnnotation) { - List constructors = ElementFilter.constructorsIn(nodeClass.getEnclosedElements()); + private void findFactory(TypeElement nodeClass, TypeMirror[] signature, ExecutableElement intrinsicMethod, AnnotationMirror intrinsicAnnotation) { + List methods = ElementFilter.methodsIn(nodeClass.getEnclosedElements()); List failureReasons = new ArrayList<>(); - nextConstructor: for (ExecutableElement constructor : constructors) { + nextMethod: for (ExecutableElement method : methods) { + if (!method.getSimpleName().contentEquals("create") || !method.getModifiers().contains(Modifier.STATIC)) { + continue; + } int sIdx = 0; - int cIdx = 0; - while (cIdx < constructor.getParameters().size()) { - VariableElement parameter = constructor.getParameters().get(cIdx++); + int mIdx = 0; + while (mIdx < method.getParameters().size()) { + VariableElement parameter = method.getParameters().get(mIdx++); if (parameter.getAnnotation(InjectedNodeParameter.class) != null) { // skip injected parameters continue; } TypeMirror paramType = parameter.asType(); - if (cIdx == constructor.getParameters().size() && paramType.getKind() == TypeKind.ARRAY) { - // last argument of constructor is varargs, match remaining intrinsic arguments + if (mIdx == method.getParameters().size() && paramType.getKind() == TypeKind.ARRAY) { + // last argument of method is varargs, match remaining intrinsic arguments TypeMirror varargsType = ((ArrayType) paramType).getComponentType(); while (sIdx < signature.length) { if (!isTypeCompatible(varargsType, signature[sIdx++])) { - failureReasons.add(String.format("Constructor %s failed because the types of argument %d are incompatible: %s != %s", constructor, sIdx, varargsType, signature[sIdx - 1])); - continue nextConstructor; + failureReasons.add(String.format("Factory method %s failed because the types of argument %d are incompatible: %s != %s", method, sIdx, varargsType, signature[sIdx - 1])); + continue nextMethod; } } } else if (sIdx >= signature.length) { // too many arguments in intrinsic method - failureReasons.add(String.format("Too many arguments for %s", constructor)); - continue nextConstructor; + failureReasons.add(String.format("Too many arguments for %s", method)); + continue nextMethod; } else if (!isTypeCompatible(paramType, signature[sIdx++])) { - failureReasons.add(String.format("Constructor %s failed because the types of argument %d are incompatible: %s != %s", constructor, sIdx, paramType, signature[sIdx - 1])); - continue nextConstructor; + failureReasons.add(String.format("Factory method %s failed because the types of argument %d are incompatible: %s != %s", method, sIdx, paramType, signature[sIdx - 1])); + continue nextMethod; } } @@ -162,12 +165,12 @@ } // too many arguments in constructor - failureReasons.add(String.format("Not enough arguments for %s", constructor)); + failureReasons.add(String.format("Not enough arguments for %s", method)); } // not found if (failureReasons.isEmpty()) { - env.getMessager().printMessage(Kind.ERROR, "Could not find matching constructor for node intrinsic.", intrinsicMethod, intrinsicAnnotation); + env.getMessager().printMessage(Kind.ERROR, "Could not find matching factory method for node intrinsic.", intrinsicMethod, intrinsicAnnotation); } else { for (String reason : failureReasons) { env.getMessager().printMessage(Kind.ERROR, reason, intrinsicMethod, intrinsicAnnotation); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java Mon Aug 25 21:15:59 2014 -0700 @@ -228,7 +228,7 @@ assert bci == AFTER_BCI || bci == AFTER_EXCEPTION_BCI || bci == INVALID_FRAMESTATE_BCI; FrameState currentStateAfter = node.stateAfter(); if (currentStateAfter != null || !replaceOnly) { - node.setStateAfter(graph.add(new FrameState(bci))); + node.setStateAfter(graph.add(FrameState.create(bci))); if (currentStateAfter != null && currentStateAfter.usages().isEmpty()) { GraphUtil.killWithUnusedFloatingInputs(currentStateAfter); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java Mon Aug 25 21:15:59 2014 -0700 @@ -113,7 +113,7 @@ ConstantLocationNode location = createFieldLocation(graph, field, false); assert location != null : "Field that is loaded must not be eliminated"; - ReadNode memoryRead = graph.add(new ReadNode(object, location, loadStamp, fieldLoadBarrierType(field))); + ReadNode memoryRead = graph.add(ReadNode.create(object, location, loadStamp, fieldLoadBarrierType(field))); ValueNode readValue = implicitLoadConvert(graph, field.getKind(), memoryRead); loadField.replaceAtUsages(readValue); graph.replaceFixed(loadField, memoryRead); @@ -121,9 +121,9 @@ memoryRead.setGuard(createNullCheck(object, memoryRead, tool)); if (loadField.isVolatile()) { - MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ)); + MembarNode preMembar = graph.add(MembarNode.create(JMM_PRE_VOLATILE_READ)); graph.addBeforeFixed(memoryRead, preMembar); - MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_READ)); + MembarNode postMembar = graph.add(MembarNode.create(JMM_POST_VOLATILE_READ)); graph.addAfterFixed(memoryRead, postMembar); } } @@ -141,15 +141,15 @@ graph.removeFixed(storeField); return; } - WriteNode memoryWrite = graph.add(new WriteNode(object, value, location, fieldStoreBarrierType(storeField.field()))); + WriteNode memoryWrite = graph.add(WriteNode.create(object, value, location, fieldStoreBarrierType(storeField.field()))); memoryWrite.setStateAfter(storeField.stateAfter()); graph.replaceFixedWithFixed(storeField, memoryWrite); memoryWrite.setGuard(createNullCheck(object, memoryWrite, tool)); if (storeField.isVolatile()) { - MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE)); + MembarNode preMembar = graph.add(MembarNode.create(JMM_PRE_VOLATILE_WRITE)); graph.addBeforeFixed(memoryWrite, preMembar); - MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_WRITE)); + MembarNode postMembar = graph.add(MembarNode.create(JMM_POST_VOLATILE_WRITE)); graph.addAfterFixed(memoryWrite, postMembar); } } @@ -160,7 +160,7 @@ LocationNode location = createArrayLocation(graph, elementKind, loadIndexed.index(), false); Stamp loadStamp = loadStamp(loadIndexed.stamp(), elementKind); - ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), location, loadStamp, BarrierType.NONE)); + ReadNode memoryRead = graph.add(ReadNode.create(loadIndexed.array(), location, loadStamp, BarrierType.NONE)); ValueNode readValue = implicitLoadConvert(graph, elementKind, memoryRead); memoryRead.setGuard(createBoundsCheck(loadIndexed, tool)); @@ -184,20 +184,20 @@ if (arrayType != null && StampTool.isExactType(array)) { ResolvedJavaType elementType = arrayType.getComponentType(); if (!elementType.isJavaLangObject()) { - checkCastNode = graph.add(new CheckCastNode(elementType, value, null, true)); + checkCastNode = graph.add(CheckCastNode.create(elementType, value, null, true)); graph.addBeforeFixed(storeIndexed, checkCastNode); value = checkCastNode; } } else { ValueNode arrayClass = createReadHub(graph, array, boundsCheck); ValueNode componentHub = createReadArrayComponentHub(graph, arrayClass, storeIndexed); - checkCastNode = graph.add(new CheckCastDynamicNode(componentHub, value, true)); + checkCastNode = graph.add(CheckCastDynamicNode.create(componentHub, value, true)); graph.addBeforeFixed(storeIndexed, checkCastNode); value = checkCastNode; } } - WriteNode memoryWrite = graph.add(new WriteNode(array, implicitStoreConvert(graph, elementKind, value), location, arrayStoreBarrierType(storeIndexed.elementKind()))); + WriteNode memoryWrite = graph.add(WriteNode.create(array, implicitStoreConvert(graph, elementKind, value), location, arrayStoreBarrierType(storeIndexed.elementKind()))); memoryWrite.setGuard(boundsCheck); memoryWrite.setStateAfter(storeIndexed.stateAfter()); graph.replaceFixedWithFixed(storeIndexed, memoryWrite); @@ -213,7 +213,7 @@ ValueNode array = arrayLengthNode.array(); ConstantLocationNode location = ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, arrayLengthOffset(), graph); - ReadNode arrayLengthRead = graph.add(new ReadNode(array, location, StampFactory.positiveInt(), BarrierType.NONE)); + ReadNode arrayLengthRead = graph.add(ReadNode.create(array, location, StampFactory.positiveInt(), BarrierType.NONE)); arrayLengthRead.setGuard(createNullCheck(array, arrayLengthNode, tool)); graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead); } @@ -235,7 +235,7 @@ ValueNode expectedValue = implicitStoreConvert(graph, valueKind, cas.expected()); ValueNode newValue = implicitStoreConvert(graph, valueKind, cas.newValue()); - LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(cas.object(), location, expectedValue, newValue, compareAndSwapBarrierType(cas))); + LoweredCompareAndSwapNode atomicNode = graph.add(LoweredCompareAndSwapNode.create(cas.object(), location, expectedValue, newValue, compareAndSwapBarrierType(cas))); atomicNode.setStateAfter(cas.stateAfter()); graph.replaceFixedWithFixed(cas, atomicNode); } @@ -247,7 +247,7 @@ ValueNode newValue = implicitStoreConvert(graph, valueKind, n.newValue()); - LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(n.object(), location, newValue, atomicReadAndWriteBarrierType(n))); + LoweredAtomicReadAndWriteNode memoryRead = graph.add(LoweredAtomicReadAndWriteNode.create(n.object(), location, newValue, atomicReadAndWriteBarrierType(n))); memoryRead.setStateAfter(n.stateAfter()); ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead); @@ -258,7 +258,7 @@ protected void lowerUnsafeLoadNode(UnsafeLoadNode load, @SuppressWarnings("unused") LoweringTool tool) { StructuredGraph graph = load.graph(); if (load.getGuardingCondition() != null) { - ConditionAnchorNode valueAnchorNode = graph.add(new ConditionAnchorNode(load.getGuardingCondition())); + ConditionAnchorNode valueAnchorNode = graph.add(ConditionAnchorNode.create(load.getGuardingCondition())); ReadNode memoryRead = createUnsafeRead(graph, load, valueAnchorNode); graph.replaceFixedWithFixed(load, valueAnchorNode); graph.addAfterFixed(valueAnchorNode, memoryRead); @@ -275,9 +275,17 @@ protected ReadNode createUnsafeRead(StructuredGraph graph, UnsafeLoadNode load, GuardingNode guard) { boolean compressible = load.accessKind() == Kind.Object; Kind readKind = load.accessKind(); - LocationNode location = createLocation(load); + ValueNode[] base = null; + ValueNode object = load.object(); + if (object.isConstant() && object.asConstant().isDefaultForKind()) { + base = new ValueNode[1]; + } + LocationNode location = createLocation(load, base); + if (base != null && base[0] != null) { + object = base[0]; + } Stamp loadStamp = loadStamp(load.stamp(), readKind, compressible); - ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, loadStamp, guard, BarrierType.NONE)); + ReadNode memoryRead = graph.add(ReadNode.create(object, location, loadStamp, guard, BarrierType.NONE)); ValueNode readValue = implicitLoadConvert(graph, readKind, memoryRead, compressible); load.replaceAtUsages(readValue); return memoryRead; @@ -285,12 +293,19 @@ protected void lowerUnsafeStoreNode(UnsafeStoreNode store) { StructuredGraph graph = store.graph(); - LocationNode location = createLocation(store); ValueNode object = store.object(); + ValueNode[] base = null; + if (object.isConstant() && object.asConstant().isDefaultForKind()) { + base = new ValueNode[1]; + } + LocationNode location = createLocation(store, base); + if (base != null && base[0] != null) { + object = base[0]; + } boolean compressible = store.value().getKind() == Kind.Object; Kind valueKind = store.accessKind(); ValueNode value = implicitStoreConvert(graph, valueKind, store.value(), compressible); - WriteNode write = graph.add(new WriteNode(object, value, location, unsafeStoreBarrierType(store))); + WriteNode write = graph.add(WriteNode.create(object, value, location, unsafeStoreBarrierType(store))); write.setStateAfter(store.stateAfter()); graph.replaceFixedWithFixed(store, write); } @@ -300,7 +315,7 @@ Kind valueKind = read.location().getValueKind(); Stamp loadStamp = loadStamp(read.stamp(), valueKind, read.isCompressible()); - ReadNode memoryRead = graph.add(new ReadNode(read.object(), read.location(), loadStamp, read.getBarrierType())); + ReadNode memoryRead = graph.add(ReadNode.create(read.object(), read.location(), loadStamp, read.getBarrierType())); ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead, read.isCompressible()); memoryRead.setGuard(read.getGuard()); read.replaceAtUsages(readValue); @@ -312,7 +327,7 @@ Kind valueKind = write.location().getValueKind(); ValueNode value = implicitStoreConvert(graph, valueKind, write.value(), write.isCompressible()); - WriteNode memoryWrite = graph.add(new WriteNode(write.object(), value, write.location(), write.getBarrierType(), write.isInitialization())); + WriteNode memoryWrite = graph.add(WriteNode.create(write.object(), value, write.location(), write.getBarrierType(), write.isInitialization())); memoryWrite.setStateAfter(write.stateAfter()); graph.replaceFixedWithFixed(write, memoryWrite); memoryWrite.setGuard(write.getGuard()); @@ -331,9 +346,9 @@ int entryCount = virtual.entryCount(); AbstractNewObjectNode newObject; if (virtual instanceof VirtualInstanceNode) { - newObject = graph.add(new NewInstanceNode(virtual.type(), true)); + newObject = graph.add(NewInstanceNode.create(virtual.type(), true)); } else { - newObject = graph.add(new NewArrayNode(((VirtualArrayNode) virtual).componentType(), ConstantNode.forInt(entryCount, graph), true)); + newObject = graph.add(NewArrayNode.create(((VirtualArrayNode) virtual).componentType(), ConstantNode.forInt(entryCount, graph), true)); } recursiveLowerings.add(newObject); graph.addBeforeFixed(commit, newObject); @@ -368,7 +383,7 @@ barrierType = arrayInitializationBarrier(entryKind); } if (location != null) { - WriteNode write = new WriteNode(newObject, implicitStoreConvert(graph, entryKind, value), location, barrierType); + WriteNode write = WriteNode.create(newObject, implicitStoreConvert(graph, entryKind, value), location, barrierType); graph.addAfterFixed(newObject, graph.add(write)); } } @@ -400,7 +415,7 @@ barrierType = BarrierType.PRECISE; } if (location != null) { - WriteNode write = new WriteNode(newObject, implicitStoreConvert(graph, Kind.Object, allocValue), location, barrierType); + WriteNode write = WriteNode.create(newObject, implicitStoreConvert(graph, Kind.Object, allocValue), location, barrierType); graph.addBeforeFixed(commit, graph.add(write)); } } @@ -421,13 +436,13 @@ public static void finishAllocatedObjects(LoweringTool tool, CommitAllocationNode commit, ValueNode[] allocations) { StructuredGraph graph = commit.graph(); for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { - FixedValueAnchorNode anchor = graph.add(new FixedValueAnchorNode(allocations[objIndex])); + FixedValueAnchorNode anchor = graph.add(FixedValueAnchorNode.create(allocations[objIndex])); allocations[objIndex] = anchor; graph.addBeforeFixed(commit, anchor); } for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { for (MonitorIdNode monitorId : commit.getLocks(objIndex)) { - MonitorEnterNode enter = graph.add(new MonitorEnterNode(allocations[objIndex], monitorId)); + MonitorEnterNode enter = graph.add(MonitorEnterNode.create(allocations[objIndex], monitorId)); graph.addBeforeFixed(commit, enter); enter.lower(tool); } @@ -528,10 +543,10 @@ switch (kind) { case Byte: case Short: - return graph.unique(new SignExtendNode(value, 32)); + return graph.unique(SignExtendNode.create(value, 32)); case Boolean: case Char: - return graph.unique(new ZeroExtendNode(value, 32)); + return graph.unique(ZeroExtendNode.create(value, 32)); } return value; } @@ -544,10 +559,10 @@ switch (kind) { case Boolean: case Byte: - return graph.unique(new NarrowNode(value, 8)); + return graph.unique(NarrowNode.create(value, 8)); case Char: case Short: - return graph.unique(new NarrowNode(value, 16)); + return graph.unique(NarrowNode.create(value, 16)); } return value; } @@ -566,11 +581,26 @@ } } - protected LocationNode createLocation(UnsafeAccessNode access) { - return createLocation(access.offset(), access.getLocationIdentity(), access.accessKind()); + protected LocationNode createLocation(UnsafeAccessNode access, ValueNode[] base) { + return createLocation(access.offset(), access.getLocationIdentity(), access.accessKind(), base); } protected LocationNode createLocation(ValueNode offsetNode, LocationIdentity locationIdentity, Kind accessKind) { + return createLocation(offsetNode, locationIdentity, accessKind, null); + } + + /** + * Try to unpack the operations in offsetNode into a LocationNode, taking advantage of + * addressing modes if possible. + * + * @param offsetNode the computed offset into the base of the memory operation + * @param locationIdentity + * @param accessKind + * @param base if non-null try to find a value that can be used as the base of the memory + * operation and return it as base[0] + * @return the newly created LocationNode + */ + protected LocationNode createLocation(ValueNode offsetNode, LocationIdentity locationIdentity, Kind accessKind, ValueNode[] base) { ValueNode offset = offsetNode; if (offset.isConstant()) { long offsetValue = offset.asConstant().asLong(); @@ -594,7 +624,27 @@ offset = integerAddNode.getX(); } } - + if (base != null && signExtend == false && offset instanceof IntegerAddNode) { + /* + * Try to decompose the operation into base plus offset so the base can go into a new + * node. Prefer the unshifted side of an add as the base. + */ + IntegerAddNode integerAddNode = (IntegerAddNode) offset; + if (integerAddNode.getY() instanceof LeftShiftNode) { + base[0] = integerAddNode.getX(); + offset = integerAddNode.getY(); + } else { + base[0] = integerAddNode.getY(); + offset = integerAddNode.getX(); + } + if (offset instanceof IntegerAddNode) { + integerAddNode = (IntegerAddNode) offset; + if (integerAddNode.getY() instanceof ConstantNode) { + displacement = integerAddNode.getY().asConstant().asLong(); + offset = integerAddNode.getX(); + } + } + } if (offset instanceof LeftShiftNode) { LeftShiftNode leftShiftNode = (LeftShiftNode) offset; if (leftShiftNode.getY() instanceof ConstantNode) { @@ -613,7 +663,7 @@ } if (signExtend) { // If we were using sign extended values before restore the sign extension. - offset = offset.graph().addOrUnique(new SignExtendNode(offset, 64)); + offset = offset.graph().addOrUnique(SignExtendNode.create(offset, 64)); } return IndexedLocationNode.create(locationIdentity, accessKind, displacement, offset, offset.graph(), indexScaling); } @@ -629,7 +679,7 @@ ValueNode arrayLength = readArrayLength(array, tool.getConstantReflection()); if (arrayLength == null) { Stamp stamp = StampFactory.positiveInt(); - ReadNode readArrayLength = graph.add(new ReadNode(array, ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, arrayLengthOffset(), graph), stamp, BarrierType.NONE)); + ReadNode readArrayLength = graph.add(ReadNode.create(array, ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, arrayLengthOffset(), graph), stamp, BarrierType.NONE)); graph.addBeforeFixed(n, readArrayLength); readArrayLength.setGuard(createNullCheck(array, readArrayLength, tool)); arrayLength = readArrayLength; @@ -646,14 +696,14 @@ } } - return tool.createGuard(n, graph.unique(new IntegerBelowNode(n.index(), arrayLength)), BoundsCheckException, InvalidateReprofile); + return tool.createGuard(n, graph.unique(IntegerBelowNode.create(n.index(), arrayLength)), BoundsCheckException, InvalidateReprofile); } protected GuardingNode createNullCheck(ValueNode object, FixedNode before, LoweringTool tool) { if (StampTool.isObjectNonNull(object)) { return null; } - return tool.createGuard(before, before.graph().unique(new IsNullNode(object)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true); + return tool.createGuard(before, before.graph().unique(IsNullNode.create(object)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true); } @Override diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Mon Aug 25 21:15:59 2014 -0700 @@ -131,7 +131,7 @@ JavaType returnType = signature.getReturnType(null); assert checkArgs(method, args); MethodCallTargetNode callTarget = graph.add(createMethodCallTarget(invokeKind, method, args, returnType, bci)); - InvokeNode invoke = append(new InvokeNode(callTarget, bci)); + InvokeNode invoke = append(InvokeNode.create(callTarget, bci)); if (frameStateBuilder != null) { if (invoke.getKind() != Kind.Void) { @@ -146,7 +146,7 @@ } protected MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, JavaType returnType, @SuppressWarnings("unused") int bci) { - return new MethodCallTargetNode(invokeKind, targetMethod, args, returnType); + return MethodCallTargetNode.create(invokeKind, targetMethod, args, returnType); } /** @@ -246,9 +246,9 @@ * @param trueProbability The estimated probability the the condition is true */ public void startIf(LogicNode condition, double trueProbability) { - BeginNode thenSuccessor = graph.add(new BeginNode()); - BeginNode elseSuccessor = graph.add(new BeginNode()); - append(new IfNode(condition, thenSuccessor, elseSuccessor, trueProbability)); + BeginNode thenSuccessor = graph.add(BeginNode.create()); + BeginNode elseSuccessor = graph.add(BeginNode.create()); + append(IfNode.create(condition, thenSuccessor, elseSuccessor, trueProbability)); lastFixedNode = null; IfStructure s = new IfStructure(); @@ -298,12 +298,12 @@ if (thenPart != null && elsePart != null) { /* Both parts are alive, we need a real merge. */ - EndNode thenEnd = graph.add(new EndNode()); + EndNode thenEnd = graph.add(EndNode.create()); graph.addAfterFixed(thenPart, thenEnd); - EndNode elseEnd = graph.add(new EndNode()); + EndNode elseEnd = graph.add(EndNode.create()); graph.addAfterFixed(elsePart, elseEnd); - MergeNode merge = graph.add(new MergeNode()); + MergeNode merge = graph.add(MergeNode.create()); merge.addForwardEnd(thenEnd); merge.addForwardEnd(elseEnd); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Mon Aug 25 21:15:59 2014 -0700 @@ -160,7 +160,7 @@ // Can simply use the phi result if the same materialized values are expected. return result; } else { - return graph.unique(new ConditionalNode(asCondition(trueValue), t, f)); + return graph.unique(ConditionalNode.create(asCondition(trueValue), t, f)); } } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Mon Aug 25 21:15:59 2014 -0700 @@ -85,15 +85,15 @@ ResolvedJavaType[] parameterTypes = resolveJavaTypes(target.toParameterTypes(), declaringClass); - // Prepare the arguments for the reflective constructor call on the node class. - Constant[] nodeConstructorArguments = prepareArguments(methodCallTargetNode, parameterTypes, target, false); - if (nodeConstructorArguments == null) { + // Prepare the arguments for the reflective factory method call on the node class. + Constant[] nodeFactoryArguments = prepareArguments(methodCallTargetNode, parameterTypes, target, false); + if (nodeFactoryArguments == null) { return false; } // Create the new node instance. ResolvedJavaType c = getNodeClass(target, intrinsic); - Node newInstance = createNodeInstance(graph, c, parameterTypes, methodCallTargetNode.invoke().asNode().stamp(), intrinsic.setStampFromReturnType(), nodeConstructorArguments); + Node newInstance = createNodeInstance(graph, c, parameterTypes, methodCallTargetNode.invoke().asNode().stamp(), intrinsic.setStampFromReturnType(), nodeFactoryArguments); // Replace the invoke with the new node. newInstance = graph.addOrUnique(newInstance); @@ -150,7 +150,7 @@ /** * Converts the arguments of an invoke node to object values suitable for use as the arguments - * to a reflective invocation of a Java constructor or method. + * to a reflective invocation of a Java method. * * @param folding specifies if the invocation is for handling a {@link Fold} annotation * @return the arguments for the reflective invocation or null if an argument of {@code invoke} @@ -209,35 +209,38 @@ } private Node createNodeInstance(StructuredGraph graph, ResolvedJavaType nodeClass, ResolvedJavaType[] parameterTypes, Stamp invokeStamp, boolean setStampFromReturnType, - Constant[] nodeConstructorArguments) { - ResolvedJavaMethod constructor = null; + Constant[] nodeFactoryArguments) { + ResolvedJavaMethod factory = null; Constant[] arguments = null; - for (ResolvedJavaMethod c : nodeClass.getDeclaredConstructors()) { - Constant[] match = match(graph, c, parameterTypes, nodeConstructorArguments); + for (ResolvedJavaMethod m : nodeClass.getDeclaredMethods()) { + if (m.getName().equals("create") && !m.isSynthetic()) { + Constant[] match = match(graph, m, parameterTypes, nodeFactoryArguments); - if (match != null) { - if (constructor == null) { - constructor = c; - arguments = match; - } else { - throw new GraalInternalError("Found multiple constructors in %s compatible with signature %s: %s, %s", nodeClass.toJavaName(), sigString(parameterTypes), constructor, c); + if (match != null) { + if (factory == null) { + factory = m; + arguments = match; + } else { + throw new GraalInternalError("Found multiple factory methods in %s compatible with signature %s: %s, %s", nodeClass.toJavaName(), sigString(parameterTypes), + factory.format("%n(%p)%r"), m.format("%n(%p)%r")); + } } } } - if (constructor == null) { - throw new GraalInternalError("Could not find constructor in %s compatible with signature %s", nodeClass.toJavaName(), sigString(parameterTypes)); + if (factory == null) { + throw new GraalInternalError("Could not find factory method in %s compatible with signature %s", nodeClass.toJavaName(), sigString(parameterTypes)); } try { - ValueNode intrinsicNode = (ValueNode) snippetReflection.asObject(constructor.newInstance(arguments)); + ValueNode intrinsicNode = (ValueNode) snippetReflection.asObject(factory.invoke(null, arguments)); if (setStampFromReturnType) { intrinsicNode.setStamp(invokeStamp); } return intrinsicNode; } catch (Exception e) { - throw new RuntimeException(constructor + Arrays.toString(nodeConstructorArguments), e); + throw new RuntimeException(factory + Arrays.toString(nodeFactoryArguments), e); } } @@ -261,14 +264,14 @@ return false; } - private Constant[] match(StructuredGraph graph, ResolvedJavaMethod c, ResolvedJavaType[] parameterTypes, Constant[] nodeConstructorArguments) { + private Constant[] match(StructuredGraph graph, ResolvedJavaMethod m, ResolvedJavaType[] parameterTypes, Constant[] nodeFactoryArguments) { Constant[] arguments = null; Constant[] injected = null; - ResolvedJavaType[] signature = resolveJavaTypes(c.getSignature().toParameterTypes(null), c.getDeclaringClass()); + ResolvedJavaType[] signature = resolveJavaTypes(m.getSignature().toParameterTypes(null), m.getDeclaringClass()); MetaAccessProvider metaAccess = providers.getMetaAccess(); for (int i = 0; i < signature.length; i++) { - if (c.getParameterAnnotation(InjectedNodeParameter.class, i) != null) { + if (m.getParameterAnnotation(InjectedNodeParameter.class, i) != null) { injected = injected == null ? new Constant[1] : Arrays.copyOf(injected, injected.length + 1); if (signature[i].equals(metaAccess.lookupJavaType(MetaAccessProvider.class))) { injected[injected.length - 1] = snippetReflection.forObject(metaAccess); @@ -279,24 +282,24 @@ } else if (signature[i].equals(metaAccess.lookupJavaType(SnippetReflectionProvider.class))) { injected[injected.length - 1] = snippetReflection.forObject(snippetReflection); } else { - throw new GraalInternalError("Cannot handle injected argument of type %s in %s", signature[i].toJavaName(), c.format("%H.%n(%p)")); + throw new GraalInternalError("Cannot handle injected argument of type %s in %s", signature[i].toJavaName(), m.format("%H.%n(%p)")); } } else { if (i > 0) { // Chop injected arguments from signature signature = Arrays.copyOfRange(signature, i, signature.length); } - assert !containsInjected(c, i, signature.length); + assert !containsInjected(m, i, signature.length); break; } } if (Arrays.equals(parameterTypes, signature)) { // Exact match - arguments = nodeConstructorArguments; + arguments = nodeFactoryArguments; } else if (signature.length > 0 && signature[signature.length - 1].isArray()) { - // Last constructor parameter is an array, so check if we have a vararg match + // Last parameter is an array, so check if we have a vararg match int fixedArgs = signature.length - 1; if (parameterTypes.length < fixedArgs) { return null; @@ -309,17 +312,17 @@ ResolvedJavaType componentType = signature[fixedArgs].getComponentType(); assert componentType != null; - for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) { + for (int i = fixedArgs; i < nodeFactoryArguments.length; i++) { if (!parameterTypes[i].equals(componentType)) { return null; } } - arguments = Arrays.copyOf(nodeConstructorArguments, fixedArgs + 1); - arguments[fixedArgs] = componentType.newArray(nodeConstructorArguments.length - fixedArgs); + arguments = Arrays.copyOf(nodeFactoryArguments, fixedArgs + 1); + arguments[fixedArgs] = componentType.newArray(nodeFactoryArguments.length - fixedArgs); Object varargs = snippetReflection.asObject(arguments[fixedArgs]); - for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) { - Array.set(varargs, i - fixedArgs, snippetReflection.asBoxedValue(nodeConstructorArguments[i])); + for (int i = fixedArgs; i < nodeFactoryArguments.length; i++) { + Array.set(varargs, i - fixedArgs, snippetReflection.asBoxedValue(nodeFactoryArguments[i])); } } else { return null; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Mon Aug 25 21:15:59 2014 -0700 @@ -36,12 +36,13 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; +import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.java.*; import com.oracle.graal.java.GraphBuilderPhase.Instance; import com.oracle.graal.nodes.*; @@ -428,6 +429,20 @@ } /** + * Calls in snippets to methods matching one of these filters are elided. Only void methods are + * considered for elision. + */ + private static final MethodFilter[] MethodsElidedInSnippets = getMethodsElidedInSnippets(); + + private static MethodFilter[] getMethodsElidedInSnippets() { + String commaSeparatedPatterns = System.getProperty("graal.MethodsElidedInSnippets"); + if (commaSeparatedPatterns != null) { + return MethodFilter.parse(commaSeparatedPatterns); + } + return null; + } + + /** * Creates and preprocesses a graph for a replacement. */ protected class GraphMaker { @@ -554,7 +569,12 @@ final StructuredGraph graph = new StructuredGraph(methodToParse); try (Scope s = Debug.scope("buildInitialGraph", graph)) { MetaAccessProvider metaAccess = providers.getMetaAccess(); - createGraphBuilder(metaAccess, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(graph); + + if (MethodsElidedInSnippets != null && methodToParse.getSignature().getReturnKind() == Kind.Void && MethodFilter.matches(MethodsElidedInSnippets, methodToParse)) { + graph.addAfterFixed(graph.start(), graph.add(ReturnNode.create(null))); + } else { + createGraphBuilder(metaAccess, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(graph); + } new WordTypeVerificationPhase(metaAccess, snippetReflection, target.wordKind).apply(graph); new WordTypeRewriterPhase(metaAccess, snippetReflection, target.wordKind).apply(graph); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,6 +23,7 @@ package com.oracle.graal.replacements; import java.lang.annotation.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.replacements.nodes.*; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Mon Aug 25 21:15:59 2014 -0700 @@ -45,8 +45,9 @@ import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; import com.oracle.graal.graph.Graph.Mark; -import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Node; import com.oracle.graal.loop.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.GuardsStage; import com.oracle.graal.nodes.calc.*; @@ -354,11 +355,16 @@ } } + @NodeInfo static class VarargsPlaceholderNode extends FloatingNode implements ArrayLengthProvider { final Varargs varargs; - public VarargsPlaceholderNode(Varargs varargs, MetaAccessProvider metaAccess) { + public static VarargsPlaceholderNode create(Varargs varargs, MetaAccessProvider metaAccess) { + return USE_GENERATED_NODES ? new SnippetTemplate_VarargsPlaceholderNodeGen(varargs, metaAccess) : new VarargsPlaceholderNode(varargs, metaAccess); + } + + protected VarargsPlaceholderNode(Varargs varargs, MetaAccessProvider metaAccess) { super(StampFactory.exactNonNull(metaAccess.lookupJavaType(varargs.componentType).getArrayClass())); this.varargs = varargs; } @@ -545,7 +551,7 @@ nodeReplacements.put(snippetGraph.getParameter(i), ConstantNode.forConstant(constantArg, metaAccess, snippetCopy)); } else if (args.info.isVarargsParameter(i)) { Varargs varargs = (Varargs) args.values[i]; - VarargsPlaceholderNode placeholder = snippetCopy.unique(new VarargsPlaceholderNode(varargs, providers.getMetaAccess())); + VarargsPlaceholderNode placeholder = snippetCopy.unique(VarargsPlaceholderNode.create(varargs, providers.getMetaAccess())); nodeReplacements.put(snippetGraph.getParameter(i), placeholder); placeholders[i] = placeholder; } @@ -573,7 +579,7 @@ assert parameterCount < 10000; int idx = (i + 1) * 10000 + j; assert idx >= parameterCount : "collision in parameter numbering"; - ParameterNode local = snippetCopy.unique(new ParameterNode(idx, stamp)); + ParameterNode local = snippetCopy.unique(ParameterNode.create(idx, stamp)); params[j] = local; } parameters[i] = params; @@ -584,7 +590,7 @@ if (usage instanceof LoadIndexedNode) { LoadIndexedNode loadIndexed = (LoadIndexedNode) usage; Debug.dump(snippetCopy, "Before replacing %s", loadIndexed); - LoadSnippetVarargParameterNode loadSnippetParameter = snippetCopy.add(new LoadSnippetVarargParameterNode(params, loadIndexed.index(), loadIndexed.stamp())); + LoadSnippetVarargParameterNode loadSnippetParameter = snippetCopy.add(LoadSnippetVarargParameterNode.create(params, loadIndexed.index(), loadIndexed.stamp())); snippetCopy.replaceFixedWithFixed(loadIndexed, loadSnippetParameter); Debug.dump(snippetCopy, "After replacing %s", loadIndexed); } else if (usage instanceof StoreIndexedNode) { @@ -670,7 +676,7 @@ new FloatingReadPhase(false, true, false).apply(snippetCopy); - MemoryAnchorNode memoryAnchor = snippetCopy.add(new MemoryAnchorNode()); + MemoryAnchorNode memoryAnchor = snippetCopy.add(MemoryAnchorNode.create()); snippetCopy.start().replaceAtUsages(InputType.Memory, memoryAnchor); this.snippet = snippetCopy; @@ -689,12 +695,12 @@ } else if (returnNodes.size() == 1) { this.returnNode = returnNodes.get(0); } else { - MergeNode merge = snippet.add(new MergeNode()); + MergeNode merge = snippet.add(MergeNode.create()); List memMaps = returnNodes.stream().map(n -> n.getMemoryMap()).collect(Collectors.toList()); ValueNode returnValue = InliningUtil.mergeReturns(merge, returnNodes, null); - this.returnNode = snippet.add(new ReturnNode(returnValue)); + this.returnNode = snippet.add(ReturnNode.create(returnValue)); MemoryMapImpl mmap = FloatingReadPhase.mergeMemoryMaps(merge, memMaps, false); - MemoryMapNode memoryMap = snippet.unique(new MemoryMapNode(mmap.getMap())); + MemoryMapNode memoryMap = snippet.unique(MemoryMapNode.create(mmap.getMap())); this.returnNode.setMemoryMap(memoryMap); for (MemoryMapNode mm : memMaps) { if (mm != memoryMap && mm.isAlive()) { diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,28 +26,35 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; /** * Compares two arrays with the same length. */ -public class ArrayEqualsNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable, Virtualizable { +@NodeInfo +public class ArrayEqualsNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable, Virtualizable, MemoryAccess { /** {@link Kind} of the arrays to compare. */ private final Kind kind; /** One array to be tested for equality. */ - @Input private ValueNode array1; + @Input ValueNode array1; /** The other array to be tested for equality. */ - @Input private ValueNode array2; + @Input ValueNode array2; /** Length of both arrays. */ - @Input private ValueNode length; + @Input ValueNode length; - public ArrayEqualsNode(ValueNode array1, ValueNode array2, ValueNode length) { + public static ArrayEqualsNode create(ValueNode array1, ValueNode array2, ValueNode length) { + return USE_GENERATED_NODES ? new ArrayEqualsNodeGen(array1, array2, length) : new ArrayEqualsNode(array1, array2, length); + } + + protected ArrayEqualsNode(ValueNode array1, ValueNode array2, ValueNode length) { super(StampFactory.forKind(Kind.Boolean)); assert array1.stamp().equals(array2.stamp()); @@ -132,4 +139,8 @@ Value result = gen.getLIRGeneratorTool().emitArrayEquals(kind, gen.operand(array1), gen.operand(array2), gen.operand(length)); gen.setResult(this, result); } + + public LocationIdentity getLocationIdentity() { + return NamedLocationIdentity.getArrayLocation(kind); + } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/AssertionNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/AssertionNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/AssertionNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -34,14 +35,19 @@ * fail if this has not happened by the time the node is lowered to LIR, while runtime assertions * may need to insert a check. */ +@NodeInfo public class AssertionNode extends FixedWithNextNode implements Lowerable, Canonicalizable, LIRLowerable { - @Input private ValueNode value; + @Input ValueNode value; private final boolean compileTimeAssertion; private final String message; - public AssertionNode(boolean compileTimeAssertion, ValueNode value, String message) { + public static AssertionNode create(boolean compileTimeAssertion, ValueNode value, String message) { + return USE_GENERATED_NODES ? new AssertionNodeGen(compileTimeAssertion, value, message) : new AssertionNode(compileTimeAssertion, value, message); + } + + protected AssertionNode(boolean compileTimeAssertion, ValueNode value, String message) { super(StampFactory.forVoid()); this.value = value; this.compileTimeAssertion = compileTimeAssertion; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,13 +25,19 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public class BitCountNode extends UnaryNode implements LIRLowerable { - public BitCountNode(ValueNode value) { + public static BitCountNode create(ValueNode value) { + return USE_GENERATED_NODES ? new BitCountNodeGen(value) : new BitCountNode(value); + } + + protected BitCountNode(ValueNode value) { super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); assert value.getKind() == Kind.Int || value.getKind() == Kind.Long; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -33,9 +34,14 @@ * Determines the index of the least significant "1" bit. Note that the result is undefined if the * input is zero. */ +@NodeInfo public class BitScanForwardNode extends UnaryNode implements LIRLowerable { - public BitScanForwardNode(ValueNode value) { + public static BitScanForwardNode create(ValueNode value) { + return USE_GENERATED_NODES ? new BitScanForwardNodeGen(value) : new BitScanForwardNode(value); + } + + protected BitScanForwardNode(ValueNode value) { super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); assert value.getKind() == Kind.Int || value.getKind() == Kind.Long; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -33,9 +34,14 @@ * Determines the index of the most significant "1" bit. Note that the result is undefined if the * input is zero. */ +@NodeInfo public class BitScanReverseNode extends UnaryNode implements LIRLowerable { - public BitScanReverseNode(ValueNode value) { + public static BitScanReverseNode create(ValueNode value) { + return USE_GENERATED_NODES ? new BitScanReverseNodeGen(value) : new BitScanReverseNode(value); + } + + protected BitScanReverseNode(ValueNode value) { super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); assert value.getKind() == Kind.Int || value.getKind() == Kind.Long; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.extended.*; @@ -33,15 +34,21 @@ * A special purpose store node that differs from {@link UnsafeStoreNode} in that it is not a * {@link StateSplit} and does not include a write barrier. */ +@NodeInfo public class DirectObjectStoreNode extends FixedWithNextNode implements Lowerable { - @Input private ValueNode object; - @Input private ValueNode value; - @Input private ValueNode offset; + @Input ValueNode object; + @Input ValueNode value; + @Input ValueNode offset; private final int displacement; private final LocationIdentity locationIdentity; - public DirectObjectStoreNode(ValueNode object, int displacement, ValueNode offset, ValueNode value, LocationIdentity locationIdentity) { + public static DirectObjectStoreNode create(ValueNode object, int displacement, ValueNode offset, ValueNode value, LocationIdentity locationIdentity) { + return USE_GENERATED_NODES ? new DirectObjectStoreNodeGen(object, displacement, offset, value, locationIdentity) : new DirectObjectStoreNode(object, displacement, offset, value, + locationIdentity); + } + + protected DirectObjectStoreNode(ValueNode object, int displacement, ValueNode offset, ValueNode value, LocationIdentity locationIdentity) { super(StampFactory.forVoid()); this.object = object; this.value = value; @@ -59,7 +66,7 @@ @Override public void lower(LoweringTool tool) { IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, value.getKind(), displacement, offset, graph(), 1); - JavaWriteNode write = graph().add(new JavaWriteNode(object, value, location, BarrierType.NONE, value.getKind() == Kind.Object, false)); + JavaWriteNode write = graph().add(JavaWriteNode.create(object, value, location, BarrierType.NONE, value.getKind() == Kind.Object, false)); graph().replaceFixedWithFixed(this, write); tool.getLowerer().lower(write, tool); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -34,12 +35,17 @@ * A special purpose store node that differs from {@link UnsafeStoreNode} in that it is not a * {@link StateSplit} and takes a computed address instead of an object. */ +@NodeInfo public class DirectReadNode extends FixedWithNextNode implements LIRLowerable { - @Input private ValueNode address; + @Input protected ValueNode address; private final Kind readKind; - public DirectReadNode(ValueNode address, Kind readKind) { + public static DirectReadNode create(ValueNode address, Kind readKind) { + return USE_GENERATED_NODES ? new DirectReadNodeGen(address, readKind) : new DirectReadNode(address, readKind); + } + + protected DirectReadNode(ValueNode address, Kind readKind) { super(StampFactory.forKind(readKind)); this.address = address; this.readKind = readKind; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -34,13 +35,18 @@ * A special purpose store node that differs from {@link UnsafeStoreNode} in that it is not a * {@link StateSplit} and takes a computed address instead of an object. */ +@NodeInfo public class DirectStoreNode extends FixedWithNextNode implements LIRLowerable { - @Input private ValueNode address; - @Input private ValueNode value; + @Input protected ValueNode address; + @Input protected ValueNode value; private final Kind kind; - public DirectStoreNode(ValueNode address, ValueNode value, Kind kind) { + public static DirectStoreNode create(ValueNode address, ValueNode value, Kind kind) { + return USE_GENERATED_NODES ? new DirectStoreNodeGen(address, value, kind) : new DirectStoreNode(address, value, kind); + } + + protected DirectStoreNode(ValueNode address, ValueNode value, Kind kind) { super(StampFactory.forVoid()); this.address = address; this.value = value; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ExplodeLoopNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ExplodeLoopNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ExplodeLoopNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,36 +26,42 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.replacements.Snippet.VarargsParameter; /** * Placeholder node to denote to snippet preparation that the following loop must be completely * unrolled. - * + * * @see VarargsParameter */ -public final class ExplodeLoopNode extends FixedWithNextNode { +@NodeInfo +public class ExplodeLoopNode extends FixedWithNextNode { - public ExplodeLoopNode() { + public static ExplodeLoopNode create() { + return USE_GENERATED_NODES ? new ExplodeLoopNodeGen() : new ExplodeLoopNode(); + } + + protected ExplodeLoopNode() { super(StampFactory.forVoid()); } public LoopBeginNode findLoopBegin() { - Node next = next(); + Node currentNext = next(); ArrayList succs = new ArrayList<>(); - while (!(next instanceof LoopBeginNode)) { - assert next != null : "cannot find loop after " + this; - for (Node n : next.cfgSuccessors()) { + while (!(currentNext instanceof LoopBeginNode)) { + assert currentNext != null : "cannot find loop after " + this; + for (Node n : currentNext.cfgSuccessors()) { succs.add(n); } if (succs.size() == 1) { - next = succs.get(0); + currentNext = succs.get(0); } else { return null; } } - return (LoopBeginNode) next; + return (LoopBeginNode) currentNext; } /** diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/LoadSnippetVarargParameterNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/LoadSnippetVarargParameterNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/LoadSnippetVarargParameterNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,19 +25,25 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.replacements.Snippet.VarargsParameter; /** * Implements the semantics of {@link VarargsParameter}. */ -public final class LoadSnippetVarargParameterNode extends FixedWithNextNode implements Canonicalizable { +@NodeInfo +public class LoadSnippetVarargParameterNode extends FixedWithNextNode implements Canonicalizable { - @Input private ValueNode index; + @Input ValueNode index; - @Input private final NodeInputList parameters; + @Input NodeInputList parameters; - public LoadSnippetVarargParameterNode(ParameterNode[] locals, ValueNode index, Stamp stamp) { + public static LoadSnippetVarargParameterNode create(ParameterNode[] locals, ValueNode index, Stamp stamp) { + return USE_GENERATED_NODES ? new LoadSnippetVarargParameterNodeGen(locals, index, stamp) : new LoadSnippetVarargParameterNode(locals, index, stamp); + } + + protected LoadSnippetVarargParameterNode(ParameterNode[] locals, ValueNode index, Stamp stamp) { super(stamp); this.index = index; this.parameters = new NodeInputList<>(this, locals); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -30,8 +30,9 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.StructuredGraph.GuardsStage; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; @@ -55,15 +56,20 @@ * possible if the macro node is a {@link MacroStateSplitNode}. * */ +@NodeInfo public class MacroNode extends FixedWithNextNode implements Lowerable { - @Input protected final NodeInputList arguments; + @Input protected NodeInputList arguments; private final int bci; private final ResolvedJavaMethod targetMethod; private final JavaType returnType; private final InvokeKind invokeKind; + public static MacroNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new MacroNodeGen(invoke) : new MacroNode(invoke); + } + protected MacroNode(Invoke invoke) { super(StampFactory.forKind(((MethodCallTargetNode) invoke.callTarget()).targetMethod().getSignature().getReturnKind())); MethodCallTargetNode methodCallTarget = (MethodCallTargetNode) invoke.callTarget(); @@ -182,8 +188,8 @@ } protected InvokeNode createInvoke() { - MethodCallTargetNode callTarget = graph().add(new MethodCallTargetNode(invokeKind, targetMethod, arguments.toArray(new ValueNode[arguments.size()]), returnType)); - InvokeNode invoke = graph().add(new InvokeNode(callTarget, bci)); + MethodCallTargetNode callTarget = graph().add(MethodCallTargetNode.create(invokeKind, targetMethod, arguments.toArray(new ValueNode[arguments.size()]), returnType)); + InvokeNode invoke = graph().add(InvokeNode.create(callTarget, bci)); if (stateAfter() != null) { invoke.setStateAfter(stateAfter().duplicate()); if (getKind() != Kind.Void) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroStateSplitNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroStateSplitNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroStateSplitNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,7 +25,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; @@ -34,9 +34,14 @@ * This is an extension of {@link MacroNode} that is a {@link StateSplit} and a * {@link MemoryCheckpoint}. */ +@NodeInfo public class MacroStateSplitNode extends MacroNode implements StateSplit, MemoryCheckpoint.Single { - @OptionalInput(InputType.State) private FrameState stateAfter; + @OptionalInput(InputType.State) protected FrameState stateAfter; + + public static MacroStateSplitNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new MacroStateSplitNodeGen(invoke) : new MacroStateSplitNode(invoke); + } protected MacroStateSplitNode(Invoke invoke) { super(invoke); @@ -70,7 +75,7 @@ } assert invoke.stateAfter().bci == BytecodeFrame.AFTER_BCI; // Here we need to fix the bci of the invoke - InvokeNode newInvoke = snippetGraph.add(new InvokeNode(invoke.callTarget(), getBci())); + InvokeNode newInvoke = snippetGraph.add(InvokeNode.create(invoke.callTarget(), getBci())); newInvoke.setStateAfter(invoke.stateAfter()); snippetGraph.replaceFixedWithFixed((InvokeNode) invoke.asNode(), newInvoke); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,10 +27,12 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public class MathIntrinsicNode extends UnaryNode implements ArithmeticLIRLowerable { private final Operation operation; @@ -49,7 +51,11 @@ return operation; } - public MathIntrinsicNode(ValueNode value, Operation op) { + public static MathIntrinsicNode create(ValueNode value, Operation op) { + return USE_GENERATED_NODES ? new MathIntrinsicNodeGen(value, op) : new MathIntrinsicNode(value, op); + } + + protected MathIntrinsicNode(ValueNode value, Operation op) { super(StampFactory.forKind(Kind.Double), value); assert value.stamp() instanceof FloatStamp && PrimitiveStamp.getBits(value.stamp()) == 64; this.operation = op; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -32,7 +33,11 @@ @NodeInfo(allowedUsageTypes = {InputType.Memory}) public class MemoryAnchorNode extends FixedWithNextNode implements LIRLowerable, MemoryNode, Canonicalizable { - public MemoryAnchorNode() { + public static MemoryAnchorNode create() { + return USE_GENERATED_NODES ? new MemoryAnchorNodeGen() : new MemoryAnchorNode(); + } + + protected MemoryAnchorNode() { super(StampFactory.forVoid()); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/PureFunctionMacroNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/PureFunctionMacroNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/PureFunctionMacroNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,12 +25,14 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; /** * This node class can be used to create {@link MacroNode}s for simple pure functions like * {@link System#identityHashCode(Object)}. */ +@NodeInfo public abstract class PureFunctionMacroNode extends MacroStateSplitNode implements Canonicalizable { public PureFunctionMacroNode(Invoke invoke) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,7 +25,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -33,7 +33,7 @@ * Access the value of a specific register. */ @NodeInfo(nameTemplate = "ReadRegister %{p#register}") -public final class ReadRegisterNode extends FixedWithNextNode implements LIRLowerable { +public class ReadRegisterNode extends FixedWithNextNode implements LIRLowerable { /** * The fixed register to access. @@ -53,7 +53,11 @@ */ private final boolean incoming; - public ReadRegisterNode(Register register, Kind kind, boolean directUse, boolean incoming) { + public static ReadRegisterNode create(Register register, Kind kind, boolean directUse, boolean incoming) { + return USE_GENERATED_NODES ? new ReadRegisterNodeGen(register, kind, directUse, incoming) : new ReadRegisterNode(register, kind, directUse, incoming); + } + + protected ReadRegisterNode(Register register, Kind kind, boolean directUse, boolean incoming) { super(StampFactory.forKind(kind)); assert register != null; this.register = register; @@ -65,7 +69,11 @@ * Constructor to be used by node intrinsics where the stamp is inferred from the intrinsic * definition. */ - public ReadRegisterNode(Register register, boolean directUse, boolean incoming) { + public static ReadRegisterNode create(Register register, boolean directUse, boolean incoming) { + return USE_GENERATED_NODES ? new ReadRegisterNodeGen(register, directUse, incoming) : new ReadRegisterNode(register, directUse, incoming); + } + + protected ReadRegisterNode(Register register, boolean directUse, boolean incoming) { super(StampFactory.forNodeIntrinsic()); assert register != null; this.register = register; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,14 +25,20 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +@NodeInfo public class ReverseBytesNode extends UnaryNode implements LIRLowerable { - public ReverseBytesNode(ValueNode value) { + public static ReverseBytesNode create(ValueNode value) { + return USE_GENERATED_NODES ? new ReverseBytesNodeGen(value) : new ReverseBytesNode(value); + } + + protected ReverseBytesNode(ValueNode value) { super(StampFactory.forKind(value.getKind()), value); assert getKind() == Kind.Int || getKind() == Kind.Long; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,7 +25,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -33,7 +33,7 @@ * Changes the value of a specific register. */ @NodeInfo(nameTemplate = "WriteRegister %{p#register}") -public final class WriteRegisterNode extends FixedWithNextNode implements LIRLowerable { +public class WriteRegisterNode extends FixedWithNextNode implements LIRLowerable { /** * The fixed register to access. @@ -43,9 +43,13 @@ /** * The new value assigned to the register. */ - @Input private ValueNode value; + @Input ValueNode value; - public WriteRegisterNode(Register register, ValueNode value) { + public static WriteRegisterNode create(Register register, ValueNode value) { + return USE_GENERATED_NODES ? new WriteRegisterNodeGen(register, value) : new WriteRegisterNode(register, value); + } + + protected WriteRegisterNode(Register register, ValueNode value) { super(StampFactory.forVoid()); this.register = register; this.value = value; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Mon Aug 25 21:15:59 2014 -0700 @@ -59,6 +59,7 @@ import com.oracle.truffle.api.CompilerDirectives.SlowPath; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.Node; /** * Implementation of the Truffle runtime when running on top of Graal. @@ -117,9 +118,16 @@ return new OptimizedCallTarget(rootNode, this, TruffleMinInvokeThreshold.getValue(), TruffleCompilationThreshold.getValue(), compilationPolicy, new HotSpotSpeculationLog()); } + public LoopNode createLoopNode(RepeatingNode repeating) { + if (!(repeating instanceof Node)) { + throw new IllegalArgumentException("Repeating node must be of type Node."); + } + return new OptimizedLoopNode(repeating); + } + public DirectCallNode createDirectCallNode(CallTarget target) { if (target instanceof OptimizedCallTarget) { - return OptimizedDirectCallNode.create((OptimizedCallTarget) target); + return new OptimizedDirectCallNode((OptimizedCallTarget) target); } else { throw new IllegalStateException(String.format("Unexpected call target class %s!", target.getClass())); } @@ -231,7 +239,7 @@ MetaAccessProvider metaAccess = providers.getMetaAccess(); SuitesProvider suitesProvider = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites(); Suites suites = suitesProvider.createSuites(); - suites.getHighTier().findPhase(InliningPhase.class).remove(); + removeInliningPhase(suites); StructuredGraph graph = new StructuredGraph(javaMethod); new GraphBuilderPhase.Instance(metaAccess, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); PhaseSuite graphBuilderSuite = suitesProvider.getDefaultGraphBuilderSuite(); @@ -247,6 +255,13 @@ return runtimeProvider.getHostBackend().getProviders(); } + private static void removeInliningPhase(Suites suites) { + ListIterator> inliningPhase = suites.getHighTier().findPhase(InliningPhase.class); + if (inliningPhase != null) { + inliningPhase.remove(); + } + } + @SlowPath @Override public T iterateFrames(FrameInstanceVisitor visitor) { diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -158,7 +158,7 @@ try (Scope s = Debug.scope("Truffle", new DebugDumpScope("Comparison: " + methodName))) { Assumptions assumptions = new Assumptions(false); - StructuredGraph graph = parse(methodName); + StructuredGraph graph = parseEager(methodName); PhaseContext context = new PhaseContext(getProviders(), assumptions); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); canonicalizer.apply(graph, context); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AddTestNode.java diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/BlockTestNode.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/BlockTestNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/BlockTestNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; +@NodeInfo public class BlockTestNode extends AbstractTestNode { @Children private final AbstractTestNode[] statements; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/ConstantTestNode.java diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/ConstantWithAssumptionTestNode.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/ConstantWithAssumptionTestNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/ConstantWithAssumptionTestNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; +@NodeInfo public class ConstantWithAssumptionTestNode extends AbstractTestNode { private final int value; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/LoadLocalTestNode.java diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/LoopTestNode.java diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/RootTestNode.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/RootTestNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/RootTestNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; +@NodeInfo public class RootTestNode extends RootNode { private final String name; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/StoreLocalTestNode.java diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleSplittingStrategyNew.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleSplittingStrategyNew.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleSplittingStrategyNew.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,7 +26,7 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.NodeUtil.*; +import com.oracle.truffle.api.nodes.NodeUtil.NodeCountFilter; public class DefaultTruffleSplittingStrategyNew implements TruffleSplittingStrategy { private static int splitChangeCount; diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java Mon Aug 25 21:15:59 2014 -0700 @@ -81,7 +81,9 @@ } private Object getObjectUnsafe(FrameSlot slot) { - return CompilerDirectives.unsafeGetObject(getLocals(), (long) slot.getIndex() * Unsafe.ARRAY_OBJECT_INDEX_SCALE + Unsafe.ARRAY_OBJECT_BASE_OFFSET, true, slot); + int slotIndex = slot.getIndex(); + return CompilerDirectives.unsafeGetObject(getLocals(), (long) slotIndex * Unsafe.ARRAY_OBJECT_INDEX_SCALE + Unsafe.ARRAY_OBJECT_BASE_OFFSET, + this.getTags()[slotIndex] == FrameSlotKind.Object.ordinal(), slot); } @Override @@ -101,7 +103,9 @@ } private byte getByteUnsafe(FrameSlot slot) { - return CompilerDirectives.unsafeGetByte(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot); + int slotIndex = slot.getIndex(); + return CompilerDirectives.unsafeGetByte(getPrimitiveLocals(), (long) slotIndex * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, + this.getTags()[slotIndex] == FrameSlotKind.Byte.ordinal(), slot); } @Override @@ -121,7 +125,9 @@ } private boolean getBooleanUnsafe(FrameSlot slot) { - return CompilerDirectives.unsafeGetBoolean(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot); + int slotIndex = slot.getIndex(); + return CompilerDirectives.unsafeGetBoolean(getPrimitiveLocals(), (long) slotIndex * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, + this.getTags()[slotIndex] == FrameSlotKind.Boolean.ordinal(), slot); } @Override @@ -141,7 +147,9 @@ } private float getFloatUnsafe(FrameSlot slot) { - return CompilerDirectives.unsafeGetFloat(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot); + int slotIndex = slot.getIndex(); + return CompilerDirectives.unsafeGetFloat(getPrimitiveLocals(), (long) slotIndex * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, + this.getTags()[slotIndex] == FrameSlotKind.Float.ordinal(), slot); } @Override @@ -161,7 +169,9 @@ } private long getLongUnsafe(FrameSlot slot) { - return CompilerDirectives.unsafeGetLong(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot); + int slotIndex = slot.getIndex(); + return CompilerDirectives.unsafeGetLong(getPrimitiveLocals(), (long) slotIndex * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, + this.getTags()[slotIndex] == FrameSlotKind.Long.ordinal(), slot); } @Override @@ -181,7 +191,9 @@ } private int getIntUnsafe(FrameSlot slot) { - return CompilerDirectives.unsafeGetInt(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot); + int slotIndex = slot.getIndex(); + return CompilerDirectives.unsafeGetInt(getPrimitiveLocals(), (long) slotIndex * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, + this.getTags()[slotIndex] == FrameSlotKind.Int.ordinal(), slot); } @Override @@ -201,7 +213,9 @@ } private double getDoubleUnsafe(FrameSlot slot) { - return CompilerDirectives.unsafeGetDouble(getPrimitiveLocals(), (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot); + int slotIndex = slot.getIndex(); + return CompilerDirectives.unsafeGetDouble(getPrimitiveLocals(), (long) slotIndex * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, + this.getTags()[slotIndex] == FrameSlotKind.Double.ordinal(), slot); } @Override diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/MaterializedFrameNotify.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/MaterializedFrameNotify.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/MaterializedFrameNotify.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,7 +22,7 @@ */ package com.oracle.graal.truffle; -import com.oracle.truffle.api.frame.FrameInstance.*; +import com.oracle.truffle.api.frame.FrameInstance.FrameAccess; public interface MaterializedFrameNotify { diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,9 +22,14 @@ */ package com.oracle.graal.truffle; +import static com.oracle.graal.truffle.TruffleCompilerOptions.*; + import java.lang.ref.*; +import java.util.*; +import java.util.stream.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.debug.*; import com.oracle.truffle.api.impl.*; import com.oracle.truffle.api.nodes.*; @@ -52,16 +57,28 @@ @Override public synchronized void invalidate() { if (isValid) { + boolean invalidatedInstalledCode = false; Entry e = first; while (e != null) { InstalledCode installedCode = e.installedCode.get(); if (installedCode != null && installedCode.getVersion() == e.version) { installedCode.invalidate(); + + invalidatedInstalledCode = true; + if (TraceTruffleAssumptions.getValue()) { + logInvalidatedInstalledCode(installedCode); + } } e = e.next; } first = null; isValid = false; + + if (TraceTruffleAssumptions.getValue()) { + if (invalidatedInstalledCode) { + logStackTrace(); + } + } } } @@ -81,4 +98,16 @@ public boolean isValid() { return isValid; } + + private void logInvalidatedInstalledCode(InstalledCode installedCode) { + TTY.out().out().printf("assumption '%s' invalidated installed code '%s'\n", name, installedCode); + } + + private static void logStackTrace() { + final int skip = 1; + final int limit = 20; + StackTraceElement[] stackTrace = new Throwable().getStackTrace(); + String suffix = stackTrace.length > skip + limit ? "\n ..." : ""; + TTY.out().out().println(Arrays.stream(stackTrace).skip(skip).limit(limit).map(StackTraceElement::toString).collect(Collectors.joining("\n ", "", suffix))); + } } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Mon Aug 25 21:15:59 2014 -0700 @@ -217,7 +217,7 @@ logOptimizedInvalidated(this, oldNode, newNode, reason); } cancelInstalledTask(oldNode, newNode, reason); - invalidateInlining(); + // invalidateInlining(); } public void invalidateInlining() { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java Mon Aug 25 21:15:59 2014 -0700 @@ -194,6 +194,7 @@ if (kind == NodeCost.POLYMORPHIC || kind == NodeCost.MEGAMORPHIC) { Map props = new LinkedHashMap<>(); props.put("simpleName", node.getClass().getSimpleName()); + props.put("subtree", "\n" + NodeUtil.printCompactTreeToString(node)); String msg = kind == NodeCost.MEGAMORPHIC ? "megamorphic" : "polymorphic"; log(0, msg, node.toString(), props); } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedDirectCallNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -31,6 +31,7 @@ /** * A call node with a constant {@link CallTarget} that can be optimized by Graal. */ +@NodeInfo public final class OptimizedDirectCallNode extends DirectCallNode implements MaterializedFrameNotify { private int callCount; @@ -42,7 +43,7 @@ private final TruffleSplittingStrategy splittingStrategy; - private OptimizedDirectCallNode(OptimizedCallTarget target) { + public OptimizedDirectCallNode(OptimizedCallTarget target) { super(target); if (TruffleCompilerOptions.TruffleSplittingNew.getValue()) { this.splittingStrategy = new DefaultTruffleSplittingStrategyNew(this); @@ -66,7 +67,7 @@ private void afterInterpreterCall(Object result) { splittingStrategy.afterCall(result); - propagateInliningInvalidations(); + // propagateInliningInvalidations(); } public static Object callProxy(MaterializedFrameNotify notify, CallTarget callTarget, VirtualFrame frame, Object[] arguments, boolean inlined, boolean direct) { @@ -149,7 +150,7 @@ getCurrentCallTarget().incrementKnownCallSites(); } splittingStrategy.beforeCall(arguments); - propagateInliningInvalidations(); + // propagateInliningInvalidations(); } /** Used by the splitting strategy to install new targets. */ @@ -176,6 +177,7 @@ } } + @SuppressWarnings("unused") private void propagateInliningInvalidations() { if (isInlined() && !getCurrentCallTarget().inliningPerformed) { replace(this, "Propagate invalid inlining from " + getCurrentCallTarget().toString()); @@ -197,8 +199,4 @@ splittingStrategy.forceSplitting(); return true; } - - public static OptimizedDirectCallNode create(OptimizedCallTarget target) { - return new OptimizedDirectCallNode(target); - } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedIndirectCallNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedIndirectCallNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedIndirectCallNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -31,6 +31,7 @@ /** * A call node with a constant {@link CallTarget} that can be optimized by Graal. */ +@NodeInfo public final class OptimizedIndirectCallNode extends IndirectCallNode implements MaterializedFrameNotify { @CompilationFinal private FrameAccess outsideFrameAccess = FrameAccess.NONE; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedLoopNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedLoopNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.truffle; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * Temporary node for legacy loop count reporting support as it was most likely done in other + * implementations. + */ +public final class OptimizedLoopNode extends LoopNode { + + @CompilationFinal private int loopCount; + + public OptimizedLoopNode(RepeatingNode body) { + super(body); + } + + @Override + public void executeLoop(VirtualFrame frame) { + try { + do { + } while (executeBody(frame)); + } finally { + loopDone(); + } + } + + private final boolean executeBody(VirtualFrame frame) { + boolean result = executeRepeatNode(frame); + if (CompilerDirectives.inInterpreter()) { + if (result) { + loopCount++; + } + } + return result; + } + + private void loopDone() { + if (CompilerDirectives.inInterpreter()) { + getRootNode().reportLoopCount(loopCount); + loopCount = 0; + } + } +} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Mon Aug 25 21:15:59 2014 -0700 @@ -38,8 +38,8 @@ import com.oracle.graal.graph.Node; import com.oracle.graal.graph.spi.*; import com.oracle.graal.loop.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; @@ -138,7 +138,11 @@ } // EA frame and clean up. - new PartialEscapePhase(true, canonicalizer).apply(graph, tierContext); + try (Scope pe = Debug.scope("TrufflePartialEscape", graph)) { + new PartialEscapePhase(true, canonicalizer).apply(graph, tierContext); + } catch (Throwable t) { + Debug.handle(t); + } new VerifyNoIntrinsicsLeftPhase().apply(graph, false); for (MaterializeFrameNode materializeNode : graph.getNodes(MaterializeFrameNode.class).snapshot()) { materializeNode.replaceAtUsages(materializeNode.getFrame()); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Mon Aug 25 21:15:59 2014 -0700 @@ -37,8 +37,8 @@ import com.oracle.graal.graph.Node; import com.oracle.graal.graph.spi.*; import com.oracle.graal.java.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; @@ -276,7 +276,7 @@ boolean removeAllocation = runtimeExceptionClass.isAssignableFrom(declaringClass) || errorClass.isAssignableFrom(declaringClass); boolean isControlFlowException = controlFlowExceptionClass.isAssignableFrom(exceptionType); if (removeAllocation && !isControlFlowException) { - DeoptimizeNode deoptNode = methodCallTargetNode.graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode)); + DeoptimizeNode deoptNode = methodCallTargetNode.graph().add(DeoptimizeNode.create(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode)); FixedNode invokeNode = methodCallTargetNode.invoke().asNode(); invokeNode.replaceAtPredecessor(deoptNode); GraphUtil.killCFG(invokeNode); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Mon Aug 25 21:15:59 2014 -0700 @@ -69,7 +69,7 @@ @Option(help = "Experimental: Enable the new version of truffle splitting.") public static final OptionValue TruffleSplittingNew = new OptionValue<>(false); @Option(help = "Experimental. New splitting only: Whether or not splitting should be based instance comparisons of non TypedObjects") - public static final OptionValue TruffleSplittingClassInstanceStamps = new OptionValue<>(true); + public static final OptionValue TruffleSplittingClassInstanceStamps = new OptionValue<>(false); @Option(help = "Experimental. New splitting only: Whether or not splitting should be based instance comparisons of TypedObjects") public static final OptionValue TruffleSplittingTypeInstanceStamps = new OptionValue<>(true); @Option(help = "Experimental. New splitting only: The number of calls until splitting is performed. ") @@ -121,6 +121,8 @@ public static final OptionValue 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 ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java Mon Aug 25 21:15:59 2014 -0700 @@ -54,6 +54,7 @@ registerSubstitutions(ExactMath.class, ExactMathSubstitutions.class); registerSubstitutions(OptimizedAssumption.class, OptimizedAssumptionSubstitutions.class); registerSubstitutions(OptimizedCallTarget.class, OptimizedCallTargetSubstitutions.class); + registerSubstitutions(FrameWithoutBoxing.class, FrameWithoutBoxingSubstitutions.class); } @Override diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,15 +27,21 @@ import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.truffle.*; +@NodeInfo public class AssumptionNode extends MacroNode implements com.oracle.graal.graph.IterableNodeType, Simplifiable { - public AssumptionNode(Invoke invoke) { + public static AssumptionNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new AssumptionNodeGen(invoke) : new AssumptionNode(invoke); + } + + protected AssumptionNode(Invoke invoke) { super(invoke); assert super.arguments.size() == 1; } @@ -78,7 +84,7 @@ graph.replaceFixedWithFloating(this, ConstantNode.forBoolean(false, graph())); } else { tool.deleteBranch(this.next()); - this.replaceAndDelete(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.None))); + this.replaceAndDelete(graph.add(DeoptimizeNode.create(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.None))); } } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,13 +25,19 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.nodes.*; +@NodeInfo public class BailoutNode extends MacroNode implements Canonicalizable { - public BailoutNode(Invoke invoke) { + public static BailoutNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new BailoutNodeGen(invoke) : new BailoutNode(invoke); + } + + protected BailoutNode(Invoke invoke) { super(invoke); assert arguments.size() == 1; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/LoadIndexedFinalNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/LoadIndexedFinalNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/LoadIndexedFinalNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; @@ -34,7 +35,8 @@ /** * @see LoadIndexedNode */ -public final class LoadIndexedFinalNode extends AccessIndexedNode implements Canonicalizable { +@NodeInfo +public class LoadIndexedFinalNode extends AccessIndexedNode implements Canonicalizable { /** * Creates a new {@link LoadIndexedFinalNode}. @@ -43,7 +45,11 @@ * @param index the instruction producing the index * @param elementKind the element type */ - public LoadIndexedFinalNode(ValueNode array, ValueNode index, Kind elementKind) { + public static LoadIndexedFinalNode create(ValueNode array, ValueNode index, Kind elementKind) { + return USE_GENERATED_NODES ? new LoadIndexedFinalNodeGen(array, index, elementKind) : new LoadIndexedFinalNode(array, index, elementKind); + } + + protected LoadIndexedFinalNode(ValueNode array, ValueNode index, Kind elementKind) { super(createStamp(array, elementKind), array, index, elementKind); } @@ -74,7 +80,7 @@ @Override public void lower(LoweringTool tool) { - LoadIndexedNode loadIndexedNode = graph().add(new LoadIndexedNode(array(), index(), elementKind())); + LoadIndexedNode loadIndexedNode = graph().add(LoadIndexedNode.create(array(), index(), elementKind())); graph().replaceFixedWithFixed(this, loadIndexedNode); loadIndexedNode.lower(tool); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -35,9 +36,14 @@ * Node representing an exact integer addition that will throw an {@link ArithmeticException} in * case the addition would overflow the 32 bit range. */ +@NodeInfo public class IntegerAddExactNode extends IntegerAddNode implements IntegerExactArithmeticNode { - public IntegerAddExactNode(ValueNode x, ValueNode y) { + public static IntegerAddExactNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new IntegerAddExactNodeGen(x, y) : new IntegerAddExactNode(x, y); + } + + protected IntegerAddExactNode(ValueNode x, ValueNode y) { super(x, y); assert x.stamp().isCompatible(y.stamp()) && x.stamp() instanceof IntegerStamp; } @@ -51,7 +57,7 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { if (forX.isConstant() && !forY.isConstant()) { - return new IntegerAddExactNode(forY, forX); + return IntegerAddExactNode.create(forY, forX); } if (forX.isConstant()) { return canonicalXconstant(forX, forY); @@ -83,7 +89,7 @@ @Override public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) { - return graph().add(new IntegerAddExactSplitNode(stamp(), getX(), getY(), next, deopt)); + return graph().add(IntegerAddExactSplitNode.create(stamp(), getX(), getY(), next, deopt)); } @Override diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,12 +24,18 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public class IntegerAddExactSplitNode extends IntegerExactArithmeticSplitNode { - public IntegerAddExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) { + public static IntegerAddExactSplitNode create(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) { + return USE_GENERATED_NODES ? new IntegerAddExactSplitNodeGen(stamp, x, y, next, overflowSuccessor) : new IntegerAddExactSplitNode(stamp, x, y, next, overflowSuccessor); + } + + protected IntegerAddExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) { super(stamp, x, y, next, overflowSuccessor); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,16 +24,18 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public abstract class IntegerExactArithmeticSplitNode extends ControlSplitNode implements LIRLowerable { - @Successor private BeginNode overflowSuccessor; - @Successor private BeginNode next; - @Input private ValueNode x; - @Input private ValueNode y; + @Successor BeginNode overflowSuccessor; + @Successor BeginNode next; + @Input ValueNode x; + @Input ValueNode y; public IntegerExactArithmeticSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) { super(stamp); @@ -78,8 +80,8 @@ FixedWithNextNode previous = tool.lastFixedNode(); FixedNode next = previous.next(); previous.setNext(null); - DeoptimizeNode deopt = floatingNode.graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.ArithmeticException)); - BeginNode normalBegin = floatingNode.graph().add(new BeginNode()); + DeoptimizeNode deopt = floatingNode.graph().add(DeoptimizeNode.create(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.ArithmeticException)); + BeginNode normalBegin = floatingNode.graph().add(BeginNode.create()); normalBegin.setNext(next); IntegerExactArithmeticSplitNode split = node.createSplit(normalBegin, BeginNode.begin(deopt)); previous.setNext(split); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -34,9 +35,14 @@ * Node representing an exact integer multiplication that will throw an {@link ArithmeticException} * in case the addition would overflow the 32 bit range. */ +@NodeInfo public class IntegerMulExactNode extends IntegerMulNode implements IntegerExactArithmeticNode { - public IntegerMulExactNode(ValueNode x, ValueNode y) { + public static IntegerMulExactNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new IntegerMulExactNodeGen(x, y) : new IntegerMulExactNode(x, y); + } + + protected IntegerMulExactNode(ValueNode x, ValueNode y) { super(x, y); assert x.stamp().isCompatible(y.stamp()) && x.stamp() instanceof IntegerStamp; } @@ -44,7 +50,7 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { if (forX.isConstant() && !forY.isConstant()) { - return new IntegerMulExactNode(forY, forX); + return IntegerMulExactNode.create(forY, forX); } if (forX.isConstant()) { return canonicalXconstant(forX, forY); @@ -79,7 +85,7 @@ @Override public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) { - return graph().add(new IntegerMulExactSplitNode(stamp(), getX(), getY(), next, deopt)); + return graph().add(IntegerMulExactSplitNode.create(stamp(), getX(), getY(), next, deopt)); } @Override diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,12 +24,18 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public class IntegerMulExactSplitNode extends IntegerExactArithmeticSplitNode { - public IntegerMulExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) { + public static IntegerMulExactSplitNode create(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) { + return USE_GENERATED_NODES ? new IntegerMulExactSplitNodeGen(stamp, x, y, next, overflowSuccessor) : new IntegerMulExactSplitNode(stamp, x, y, next, overflowSuccessor); + } + + protected IntegerMulExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) { super(stamp, x, y, next, overflowSuccessor); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulHighNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulHighNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulHighNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,9 +27,9 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -38,11 +38,19 @@ @NodeInfo(shortName = "*H") public class IntegerMulHighNode extends IntegerArithmeticNode { - public IntegerMulHighNode(ValueNode x, ValueNode y) { + public static IntegerMulHighNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new IntegerMulHighNodeGen(x, y) : new IntegerMulHighNode(x, y); + } + + protected IntegerMulHighNode(ValueNode x, ValueNode y) { this(x.stamp().unrestricted(), x, y); } - public IntegerMulHighNode(Stamp stamp, ValueNode x, ValueNode y) { + public static IntegerMulHighNode create(Stamp stamp, ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new IntegerMulHighNodeGen(stamp, x, y) : new IntegerMulHighNode(stamp, x, y); + } + + protected IntegerMulHighNode(Stamp stamp, ValueNode x, ValueNode y) { super(stamp, x, y); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -36,9 +37,14 @@ * Node representing an exact integer substraction that will throw an {@link ArithmeticException} in * case the addition would overflow the 32 bit range. */ +@NodeInfo public class IntegerSubExactNode extends IntegerSubNode implements IntegerExactArithmeticNode { - public IntegerSubExactNode(ValueNode x, ValueNode y) { + public static IntegerSubExactNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new IntegerSubExactNodeGen(x, y) : new IntegerSubExactNode(x, y); + } + + protected IntegerSubExactNode(ValueNode x, ValueNode y) { super(x, y); assert x.stamp().isCompatible(y.stamp()) && x.stamp() instanceof IntegerStamp; } @@ -84,7 +90,7 @@ @Override public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) { - return graph().add(new IntegerSubExactSplitNode(stamp(), getX(), getY(), next, deopt)); + return graph().add(IntegerSubExactSplitNode.create(stamp(), getX(), getY(), next, deopt)); } @Override diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,12 +24,18 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public class IntegerSubExactSplitNode extends IntegerExactArithmeticSplitNode { - public IntegerSubExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) { + public static IntegerSubExactSplitNode create(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) { + return USE_GENERATED_NODES ? new IntegerSubExactSplitNodeGen(stamp, x, y, next, overflowSuccessor) : new IntegerSubExactSplitNode(stamp, x, y, next, overflowSuccessor); + } + + protected IntegerSubExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) { super(stamp, x, y, next, overflowSuccessor); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/UnsignedMulHighNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/UnsignedMulHighNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/UnsignedMulHighNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,9 +27,9 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -38,11 +38,19 @@ @NodeInfo(shortName = "|*H|") public class UnsignedMulHighNode extends IntegerArithmeticNode { - public UnsignedMulHighNode(ValueNode x, ValueNode y) { + public static UnsignedMulHighNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new UnsignedMulHighNodeGen(x, y) : new UnsignedMulHighNode(x, y); + } + + protected UnsignedMulHighNode(ValueNode x, ValueNode y) { this(x.stamp().unrestricted(), x, y); } - public UnsignedMulHighNode(Stamp stamp, ValueNode x, ValueNode y) { + public static UnsignedMulHighNode create(Stamp stamp, ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new UnsignedMulHighNodeGen(stamp, x, y) : new UnsignedMulHighNode(stamp, x, y); + } + + protected UnsignedMulHighNode(Stamp stamp, ValueNode x, ValueNode y) { super(stamp, x, y); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/CompilationConstantNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/CompilationConstantNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/CompilationConstantNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,11 +24,17 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +@NodeInfo public class CompilationConstantNode extends NeverPartOfCompilationNode implements Canonicalizable { - public CompilationConstantNode(Invoke invoke) { + public static CompilationConstantNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new CompilationConstantNodeGen(invoke) : new CompilationConstantNode(invoke); + } + + protected CompilationConstantNode(Invoke invoke) { super(invoke, "The value could not be reduced to a compile time constant."); assert arguments.size() == 1; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,13 +22,19 @@ */ package com.oracle.graal.truffle.nodes.asserts; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.nodes.*; +@NodeInfo public class NeverInlineMacroNode extends MacroStateSplitNode implements com.oracle.graal.graph.IterableNodeType { - public NeverInlineMacroNode(Invoke invoke) { + public static NeverInlineMacroNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new NeverInlineMacroNodeGen(invoke) : new NeverInlineMacroNode(invoke); + } + + protected NeverInlineMacroNode(Invoke invoke) { super(invoke); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,18 +23,28 @@ package com.oracle.graal.truffle.nodes.asserts; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.replacements.nodes.*; +@NodeInfo public class NeverPartOfCompilationNode extends MacroStateSplitNode implements IterableNodeType { private final String message; - public NeverPartOfCompilationNode(Invoke invoke) { + public static NeverPartOfCompilationNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new NeverPartOfCompilationNodeGen(invoke) : new NeverPartOfCompilationNode(invoke); + } + + protected NeverPartOfCompilationNode(Invoke invoke) { this(invoke, "This code path should never be part of a compilation."); } - public NeverPartOfCompilationNode(Invoke invoke, String message) { + public static NeverPartOfCompilationNode create(Invoke invoke, String message) { + return USE_GENERATED_NODES ? new NeverPartOfCompilationNodeGen(invoke, message) : new NeverPartOfCompilationNode(invoke, message); + } + + protected NeverPartOfCompilationNode(Invoke invoke, String message) { super(invoke); this.message = message; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/ForceMaterializeNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/ForceMaterializeNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/ForceMaterializeNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,14 +23,20 @@ package com.oracle.graal.truffle.nodes.frame; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +@NodeInfo public class ForceMaterializeNode extends FixedWithNextNode implements LIRLowerable { - @Input private ValueNode object; + @Input ValueNode object; - public ForceMaterializeNode(ValueNode object) { + public static ForceMaterializeNode create(ValueNode object) { + return USE_GENERATED_NODES ? new ForceMaterializeNodeGen(object) : new ForceMaterializeNode(object); + } + + protected ForceMaterializeNode(ValueNode object) { super(StampFactory.forVoid()); this.object = object; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/MaterializeFrameNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/MaterializeFrameNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/MaterializeFrameNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,6 +23,7 @@ package com.oracle.graal.truffle.nodes.frame; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.truffle.*; @@ -32,9 +33,13 @@ @NodeInfo(nameTemplate = "MaterializeFrame{p#frame/s}") public class MaterializeFrameNode extends FixedWithNextNode implements IterableNodeType { - @Input private ValueNode frame; + @Input ValueNode frame; - public MaterializeFrameNode(ValueNode frame) { + public static MaterializeFrameNode create(ValueNode frame) { + return USE_GENERATED_NODES ? new MaterializeFrameNodeGen(frame) : new MaterializeFrameNode(frame); + } + + protected MaterializeFrameNode(ValueNode frame) { super(frame.stamp()); this.frame = frame; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -31,6 +31,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; @@ -44,18 +45,27 @@ * Intrinsic node representing the call for creating a frame in the {@link OptimizedCallTarget} * class. */ +@NodeInfo public class NewFrameNode extends FixedWithNextNode implements IterableNodeType, VirtualizableAllocation, Canonicalizable { - @Input private ValueNode descriptor; - @Input private ValueNode arguments; + @Input ValueNode descriptor; + @Input ValueNode arguments; - public NewFrameNode(Stamp stamp, ValueNode descriptor, ValueNode arguments) { + public static NewFrameNode create(Stamp stamp, ValueNode descriptor, ValueNode arguments) { + return USE_GENERATED_NODES ? new NewFrameNodeGen(stamp, descriptor, arguments) : new NewFrameNode(stamp, descriptor, arguments); + } + + protected NewFrameNode(Stamp stamp, ValueNode descriptor, ValueNode arguments) { super(stamp); this.descriptor = descriptor; this.arguments = arguments; } - public NewFrameNode(ResolvedJavaType frameType, ValueNode descriptor, ValueNode arguments) { + public static NewFrameNode create(ResolvedJavaType frameType, ValueNode descriptor, ValueNode arguments) { + return USE_GENERATED_NODES ? new NewFrameNodeGen(frameType, descriptor, arguments) : new NewFrameNode(frameType, descriptor, arguments); + } + + protected NewFrameNode(ResolvedJavaType frameType, ValueNode descriptor, ValueNode arguments) { this(StampFactory.exactNonNull(frameType), descriptor, arguments); } @@ -93,11 +103,16 @@ throw new RuntimeException("Frame field not found: " + fieldName); } + @NodeInfo public static class VirtualOnlyInstanceNode extends VirtualInstanceNode { private boolean allowMaterialization; - public VirtualOnlyInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields) { + public static VirtualOnlyInstanceNode create(ResolvedJavaType type, ResolvedJavaField[] fields) { + return USE_GENERATED_NODES ? new NewFrameNode_VirtualOnlyInstanceNodeGen(type, fields) : new VirtualOnlyInstanceNode(type, fields); + } + + VirtualOnlyInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields) { super(type, fields, false); } @@ -115,10 +130,10 @@ } public static ValueNode getMaterializedRepresentationHelper(VirtualObjectNode virtualNode, FixedNode fixed) { - if (fixed instanceof MaterializeFrameNode || fixed instanceof AbstractEndNode) { + if (fixed instanceof MaterializeFrameNode || fixed instanceof AbstractEndNode || fixed instanceof ForceMaterializeNode) { // We need to conservatively assume that a materialization of a virtual frame can also // happen at a merge point. - return new AllocatedObjectNode(virtualNode); + return AllocatedObjectNode.create(virtualNode); } String escapeReason; if (fixed instanceof StoreFieldNode) { @@ -151,10 +166,10 @@ ResolvedJavaField primitiveLocalsField = findField(frameFields, "primitiveLocals"); ResolvedJavaField tagsField = findField(frameFields, "tags"); - VirtualObjectNode virtualFrame = new VirtualInstanceNode(frameType, frameFields, false); - VirtualObjectNode virtualFrameObjectArray = new VirtualArrayNode((ResolvedJavaType) localsField.getType().getComponentType(), frameSize); - VirtualObjectNode virtualFramePrimitiveArray = new VirtualArrayNode((ResolvedJavaType) primitiveLocalsField.getType().getComponentType(), frameSize); - VirtualObjectNode virtualFrameTagArray = new VirtualArrayNode((ResolvedJavaType) tagsField.getType().getComponentType(), frameSize); + VirtualObjectNode virtualFrame = VirtualOnlyInstanceNode.create(frameType, frameFields); + VirtualObjectNode virtualFrameObjectArray = VirtualArrayNode.create((ResolvedJavaType) localsField.getType().getComponentType(), frameSize); + VirtualObjectNode virtualFramePrimitiveArray = VirtualArrayNode.create((ResolvedJavaType) primitiveLocalsField.getType().getComponentType(), frameSize); + VirtualObjectNode virtualFrameTagArray = VirtualArrayNode.create((ResolvedJavaType) tagsField.getType().getComponentType(), frameSize); ValueNode[] objectArrayEntryState = new ValueNode[frameSize]; ValueNode[] primitiveArrayEntryState = new ValueNode[frameSize]; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,6 +27,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; @@ -39,14 +40,20 @@ * * Substitution for method {@link CompilerDirectives#unsafeGetFinalObject} and friends. */ +@NodeInfo public class CustomizedUnsafeLoadFinalNode extends FixedWithNextNode implements Canonicalizable, Virtualizable, Lowerable { - @Input private ValueNode object; - @Input private ValueNode offset; - @Input private ValueNode condition; - @Input private ValueNode location; + @Input ValueNode object; + @Input ValueNode offset; + @Input ValueNode condition; + @Input ValueNode location; private final Kind accessKind; - public CustomizedUnsafeLoadFinalNode(ValueNode object, ValueNode offset, ValueNode condition, ValueNode location, Kind accessKind) { + public static CustomizedUnsafeLoadFinalNode create(ValueNode object, ValueNode offset, ValueNode condition, ValueNode location, Kind accessKind) { + return USE_GENERATED_NODES ? new CustomizedUnsafeLoadFinalNodeGen(object, offset, condition, location, accessKind) : new CustomizedUnsafeLoadFinalNode(object, offset, condition, location, + accessKind); + } + + protected CustomizedUnsafeLoadFinalNode(ValueNode object, ValueNode offset, ValueNode condition, ValueNode location, Kind accessKind) { super(StampFactory.forKind(accessKind.getStackKind())); this.object = object; this.offset = offset; @@ -94,7 +101,7 @@ } else { locationIdentity = ObjectLocationIdentity.create(location.asConstant()); } - UnsafeLoadNode result = graph().add(new UnsafeLoadNode(object, offset, accessKind, locationIdentity, compare)); + UnsafeLoadNode result = graph().add(UnsafeLoadNode.create(object, offset, accessKind, locationIdentity, compare)); graph().replaceFixedWithFixed(this, result); result.lower(tool); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; @@ -36,6 +37,7 @@ /** * Macro node for method {@link CompilerDirectives#unsafeCast(Object, Class, boolean)}. */ +@NodeInfo public class CustomizedUnsafeLoadMacroNode extends NeverPartOfCompilationNode implements Canonicalizable { private static final int ARGUMENT_COUNT = 4; @@ -44,7 +46,11 @@ private static final int CONDITION_ARGUMENT_INDEX = 2; private static final int LOCATION_ARGUMENT_INDEX = 3; - public CustomizedUnsafeLoadMacroNode(Invoke invoke) { + public static CustomizedUnsafeLoadMacroNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new CustomizedUnsafeLoadMacroNodeGen(invoke) : new CustomizedUnsafeLoadMacroNode(invoke); + } + + protected CustomizedUnsafeLoadMacroNode(Invoke invoke) { super(invoke, "The location argument could not be resolved to a constant."); assert arguments.size() == ARGUMENT_COUNT; } @@ -64,7 +70,7 @@ } CompareNode compare = CompareNode.createCompareNode(Condition.EQ, conditionArgument, ConstantNode.forBoolean(true)); Kind returnKind = this.getTargetMethod().getSignature().getReturnKind(); - return new UnsafeLoadNode(objectArgument, offsetArgument, returnKind, locationIdentity, compare); + return UnsafeLoadNode.create(objectArgument, offsetArgument, returnKind, locationIdentity, compare); } return this; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.truffle.nodes.*; @@ -34,6 +35,7 @@ /** * Macro node for method {@link CompilerDirectives#unsafeCast(Object, Class, boolean)}. */ +@NodeInfo public class CustomizedUnsafeStoreMacroNode extends NeverPartOfCompilationNode implements Canonicalizable, StateSplit { private static final int ARGUMENT_COUNT = 4; private static final int OBJECT_ARGUMENT_INDEX = 0; @@ -41,7 +43,11 @@ private static final int VALUE_ARGUMENT_INDEX = 2; private static final int LOCATION_ARGUMENT_INDEX = 3; - public CustomizedUnsafeStoreMacroNode(Invoke invoke) { + public static CustomizedUnsafeStoreMacroNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new CustomizedUnsafeStoreMacroNodeGen(invoke) : new CustomizedUnsafeStoreMacroNode(invoke); + } + + protected CustomizedUnsafeStoreMacroNode(Invoke invoke) { super(invoke, "The location argument could not be resolved to a constant."); assert arguments.size() == ARGUMENT_COUNT; } @@ -60,7 +66,7 @@ locationIdentity = ObjectLocationIdentity.create(locationArgument.asConstant()); } - return new UnsafeStoreNode(objectArgument, offsetArgument, valueArgument, this.getTargetMethod().getSignature().getParameterKind(VALUE_ARGUMENT_INDEX), locationIdentity, stateAfter()); + return UnsafeStoreNode.create(objectArgument, offsetArgument, valueArgument, this.getTargetMethod().getSignature().getParameterKind(VALUE_ARGUMENT_INDEX), locationIdentity, stateAfter()); } return this; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.util.*; @@ -35,6 +36,7 @@ /** * Macro node for method {@link CompilerDirectives#unsafeCast(Object, Class, boolean, boolean)}. */ +@NodeInfo public class UnsafeTypeCastMacroNode extends NeverPartOfCompilationNode implements Simplifiable { private static final int OBJECT_ARGUMENT_INDEX = 0; @@ -43,7 +45,11 @@ private static final int NONNULL_ARGUMENT_INDEX = 3; private static final int ARGUMENT_COUNT = 4; - public UnsafeTypeCastMacroNode(Invoke invoke) { + public static UnsafeTypeCastMacroNode create(Invoke invoke) { + return USE_GENERATED_NODES ? new UnsafeTypeCastMacroNodeGen(invoke) : new UnsafeTypeCastMacroNode(invoke); + } + + protected UnsafeTypeCastMacroNode(Invoke invoke) { super(invoke, "The class of the unsafe cast could not be reduced to a compile time constant."); assert arguments.size() == ARGUMENT_COUNT; } @@ -63,8 +69,8 @@ } else { Stamp stamp = StampFactory.declared(lookupJavaType, nonNullArgument.asConstant().asInt() != 0); ConditionAnchorNode valueAnchorNode = graph().add( - new ConditionAnchorNode(CompareNode.createCompareNode(graph(), Condition.EQ, conditionArgument, ConstantNode.forBoolean(true, graph())))); - PiNode piCast = graph().unique(new PiNode(objectArgument, stamp, valueAnchorNode)); + ConditionAnchorNode.create(CompareNode.createCompareNode(graph(), Condition.EQ, conditionArgument, ConstantNode.forBoolean(true, graph())))); + PiNode piCast = graph().unique(PiNode.create(objectArgument, stamp, valueAnchorNode)); replaceAtUsages(piCast); graph().replaceFixedWithFixed(this, valueAnchorNode); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,8 +23,8 @@ package com.oracle.graal.truffle.phases; import com.oracle.graal.debug.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.truffle.substitutions; + +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.truffle.*; +import com.oracle.graal.truffle.nodes.frame.*; +import com.oracle.truffle.api.frame.*; + +@ClassSubstitution(FrameWithoutBoxing.class) +public class FrameWithoutBoxingSubstitutions { + + @MethodSubstitution(isStatic = false) + public static MaterializedFrame materialize(FrameWithoutBoxing frame) { + return MaterializeFrameNode.materialize(frame); + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializedObjectState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializedObjectState.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializedObjectState.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,28 +23,34 @@ package com.oracle.graal.virtual.nodes; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.virtual.*; /** * This class encapsulated the materialized state of an escape analyzed object. */ -public final class MaterializedObjectState extends EscapeObjectState implements Node.ValueNumberable { +@NodeInfo +public class MaterializedObjectState extends EscapeObjectState implements Node.ValueNumberable { - @Input private ValueNode materializedValue; + @Input ValueNode materializedValue; public ValueNode materializedValue() { return materializedValue; } - public MaterializedObjectState(VirtualObjectNode object, ValueNode materializedValue) { + public static MaterializedObjectState create(VirtualObjectNode object, ValueNode materializedValue) { + return USE_GENERATED_NODES ? new MaterializedObjectStateGen(object, materializedValue) : new MaterializedObjectState(object, materializedValue); + } + + protected MaterializedObjectState(VirtualObjectNode object, ValueNode materializedValue) { super(object); this.materializedValue = materializedValue; } @Override public MaterializedObjectState duplicateWithVirtualState() { - return graph().addWithoutUnique(new MaterializedObjectState(object(), materializedValue)); + return graph().addWithoutUnique(MaterializedObjectState.create(object(), materializedValue)); } @Override diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/VirtualObjectState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/VirtualObjectState.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/VirtualObjectState.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,27 +25,37 @@ import java.util.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.virtual.*; /** * This class encapsulated the virtual state of an escape analyzed object. */ -public final class VirtualObjectState extends EscapeObjectState implements Node.ValueNumberable { +@NodeInfo +public class VirtualObjectState extends EscapeObjectState implements Node.ValueNumberable { - @Input private final NodeInputList values; + @Input NodeInputList values; public NodeInputList values() { return values; } - public VirtualObjectState(VirtualObjectNode object, ValueNode[] values) { + public static VirtualObjectState create(VirtualObjectNode object, ValueNode[] values) { + return USE_GENERATED_NODES ? new VirtualObjectStateGen(object, values) : new VirtualObjectState(object, values); + } + + protected VirtualObjectState(VirtualObjectNode object, ValueNode[] values) { super(object); assert object.entryCount() == values.length; this.values = new NodeInputList<>(this, values); } - public VirtualObjectState(VirtualObjectNode object, List values) { + public static VirtualObjectState create(VirtualObjectNode object, List values) { + return USE_GENERATED_NODES ? new VirtualObjectStateGen(object, values) : new VirtualObjectState(object, values); + } + + protected VirtualObjectState(VirtualObjectNode object, List values) { super(object); assert object.entryCount() == values.size(); this.values = new NodeInputList<>(this, values); @@ -53,7 +63,7 @@ @Override public VirtualObjectState duplicateWithVirtualState() { - return graph().addWithoutUnique(new VirtualObjectState(object(), values)); + return graph().addWithoutUnique(VirtualObjectState.create(object(), values)); } @Override diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java Mon Aug 25 21:15:59 2014 -0700 @@ -28,8 +28,8 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; +import com.oracle.graal.graph.Graph.NodeEventScope; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java Mon Aug 25 21:15:59 2014 -0700 @@ -125,7 +125,7 @@ if (initialState.getReadCache().get(entry.getKey()) != entry.getValue()) { ValueNode value = exitState.getReadCache(entry.getKey().object, entry.getKey().identity, this); if (!(value instanceof ProxyNode) || ((ProxyNode) value).proxyPoint() != exitNode) { - ProxyNode proxy = new ValueProxyNode(value, exitNode); + ProxyNode proxy = ValueProxyNode.create(value, exitNode); effects.addFloatingNode(proxy, "readCacheProxy"); entry.setValue(proxy); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java Mon Aug 25 21:15:59 2014 -0700 @@ -90,7 +90,7 @@ if (fixed.predecessor() instanceof CommitAllocationNode) { commit = (CommitAllocationNode) fixed.predecessor(); } else { - commit = graph.add(new CommitAllocationNode()); + commit = graph.add(CommitAllocationNode.create()); graph.addBeforeFixed(fixed, commit); } for (AllocatedObjectNode obj : objects) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Mon Aug 25 21:15:59 2014 -0700 @@ -188,9 +188,9 @@ } } } - v = new VirtualObjectState(obj.virtual, fieldState); + v = VirtualObjectState.create(obj.virtual, fieldState); } else { - v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue()); + v = MaterializedObjectState.create(obj.virtual, obj.getMaterializedValue()); } effects.addVirtualMapping(frameState, v); } @@ -237,7 +237,7 @@ ValueNode value = obj.getEntry(i); if (!(value instanceof VirtualObjectNode || value.isConstant())) { if (exitNode.loopBegin().isPhiAtMerge(value) || initialObj == null || !initialObj.isVirtual() || initialObj.getEntry(i) != value) { - ProxyNode proxy = new ValueProxyNode(value, exitNode); + ProxyNode proxy = ValueProxyNode.create(value, exitNode); obj.setEntry(i, proxy); effects.addFloatingNode(proxy, "virtualProxy"); } @@ -247,7 +247,7 @@ if (initialObj == null || initialObj.isVirtual()) { ProxyNode proxy = proxies.get(obj.virtual); if (proxy == null) { - proxy = new ValueProxyNode(obj.getMaterializedValue(), exitNode); + proxy = ValueProxyNode.create(obj.getMaterializedValue(), exitNode); effects.addFloatingNode(proxy, "proxy"); } else { effects.replaceFirstInput(proxy, proxy.value(), obj.getMaterializedValue()); @@ -282,7 +282,7 @@ protected PhiNode getCachedPhi(T virtual, Stamp stamp) { ValuePhiNode result = materializedPhis.get(virtual); if (result == null) { - result = new ValuePhiNode(stamp, merge); + result = ValuePhiNode.create(stamp, merge); materializedPhis.put(virtual, result); } return result; @@ -456,11 +456,11 @@ for (int i = 1; i < objStates.length; i++) { ValueNode[] fields = objStates[i].getEntries(); if (phis[valueIndex] == null && values[valueIndex] != fields[valueIndex]) { - phis[valueIndex] = new ValuePhiNode(values[valueIndex].stamp().unrestricted(), merge); + phis[valueIndex] = ValuePhiNode.create(values[valueIndex].stamp().unrestricted(), merge); } } if (phis[valueIndex] != null && !phis[valueIndex].stamp().isCompatible(values[valueIndex].stamp())) { - phis[valueIndex] = new ValuePhiNode(values[valueIndex].stamp().unrestricted(), merge); + phis[valueIndex] = ValuePhiNode.create(values[valueIndex].stamp().unrestricted(), merge); } if (twoSlotKinds != null && twoSlotKinds[valueIndex] != null) { // skip an entry after a long/double value that occupies two int slots diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java Mon Aug 25 21:15:59 2014 -0700 @@ -84,6 +84,32 @@ } } + /** + * CacheEntry describing an Unsafe memory reference. The memory location and the location + * identity are separate so both must be considered when looking for optimizable memory + * accesses. + * + */ + static class UnsafeLoadCacheEntry extends CacheEntry { + + private LocationIdentity locationIdentity; + + public UnsafeLoadCacheEntry(ValueNode object, ValueNode location, LocationIdentity locationIdentity) { + super(object, location); + this.locationIdentity = locationIdentity; + } + + @Override + public CacheEntry duplicateWithObject(ValueNode newObject) { + return new UnsafeLoadCacheEntry(newObject, identity, locationIdentity); + } + + @Override + public boolean conflicts(LocationIdentity other) { + return locationIdentity == other; + } + } + static class ReadCacheEntry extends CacheEntry { public ReadCacheEntry(ValueNode object, LocationNode identity) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java Mon Aug 25 21:15:59 2014 -0700 @@ -37,6 +37,7 @@ import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.CacheEntry; import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.LoadCacheEntry; import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.ReadCacheEntry; +import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.UnsafeLoadCacheEntry; public class ReadEliminationClosure extends EffectsClosure { @@ -89,7 +90,7 @@ ValueNode cachedValue = state.getCacheEntry(identifier); if (cachedValue != null) { if (read.getGuard() != null && !(read.getGuard() instanceof FixedNode)) { - effects.addFixedNodeBefore(new ValueAnchorNode((ValueNode) read.getGuard()), read); + effects.addFixedNodeBefore(ValueAnchorNode.create((ValueNode) read.getGuard()), read); } effects.replaceAtUsages(read, cachedValue); addScalarAlias(read, cachedValue); @@ -121,7 +122,7 @@ UnsafeLoadNode load = (UnsafeLoadNode) node; if (load.offset().isConstant() && load.getLocationIdentity() != LocationIdentity.ANY_LOCATION) { ValueNode object = GraphUtil.unproxify(load.object()); - LoadCacheEntry identifier = new LoadCacheEntry(object, load.getLocationIdentity()); + UnsafeLoadCacheEntry identifier = new UnsafeLoadCacheEntry(object, load.offset(), load.getLocationIdentity()); ValueNode cachedValue = state.getCacheEntry(identifier); if (cachedValue != null) { effects.replaceAtUsages(load, cachedValue); @@ -136,7 +137,7 @@ UnsafeStoreNode write = (UnsafeStoreNode) node; if (write.offset().isConstant() && write.getLocationIdentity() != LocationIdentity.ANY_LOCATION) { ValueNode object = GraphUtil.unproxify(write.object()); - LoadCacheEntry identifier = new LoadCacheEntry(object, write.getLocationIdentity()); + UnsafeLoadCacheEntry identifier = new UnsafeLoadCacheEntry(object, write.offset(), write.getLocationIdentity()); ValueNode cachedValue = state.getCacheEntry(identifier); ValueNode value = getScalarAlias(write.value()); @@ -174,7 +175,7 @@ if (exitNode.graph().hasValueProxies()) { for (Map.Entry, ValueNode> entry : exitState.getReadCache().entrySet()) { if (initialState.getReadCache().get(entry.getKey()) != entry.getValue()) { - ProxyNode proxy = new ValueProxyNode(exitState.getCacheEntry(entry.getKey()), exitNode); + ProxyNode proxy = ValueProxyNode.create(exitState.getCacheEntry(entry.getKey()), exitNode); effects.addFloatingNode(proxy, "readCacheProxy"); entry.setValue(proxy); } @@ -203,7 +204,7 @@ protected PhiNode getCachedPhi(T virtual, Stamp stamp) { ValuePhiNode result = materializedPhis.get(virtual); if (result == null) { - result = new ValuePhiNode(stamp, merge); + result = ValuePhiNode.create(stamp, merge); materializedPhis.put(virtual, result); } return result; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -31,6 +31,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -42,27 +43,38 @@ * nodes. Both scale and disp must eventually canonicalize to {@link ConstantNode constants} so that * this node can be canonicalized to a {@link IndexedLocationNode} or {@link ConstantLocationNode}. */ -public final class SnippetLocationNode extends LocationNode implements Canonicalizable { +@NodeInfo +public class SnippetLocationNode extends LocationNode implements Canonicalizable { private final SnippetReflectionProvider snippetReflection; - @Input private ValueNode valueKind; - @Input(InputType.Association) private ValueNode locationIdentity; - @Input private ValueNode displacement; - @Input private ValueNode index; - @Input private ValueNode indexScaling; + @Input ValueNode valueKind; + @Input(InputType.Association) ValueNode locationIdentity; + @Input ValueNode displacement; + @Input ValueNode index; + @Input ValueNode indexScaling; - public static SnippetLocationNode create(SnippetReflectionProvider snippetReflection, ValueNode identity, ValueNode kind, ValueNode displacement, ValueNode index, ValueNode indexScaling, - Graph graph) { - return graph.unique(new SnippetLocationNode(snippetReflection, identity, kind, displacement, index, indexScaling)); + public static SnippetLocationNode create(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode identity, ValueNode kind, ValueNode displacement, ValueNode index, + ValueNode indexScaling, Graph graph) { + return graph.unique(SnippetLocationNode.create(snippetReflection, identity, kind, displacement, index, indexScaling)); } - private SnippetLocationNode(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode kind, ValueNode displacement) { + public static SnippetLocationNode create(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode kind, ValueNode displacement) { + return USE_GENERATED_NODES ? new SnippetLocationNodeGen(snippetReflection, locationIdentity, kind, displacement) : new SnippetLocationNode(snippetReflection, locationIdentity, kind, + displacement); + } + + SnippetLocationNode(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode kind, ValueNode displacement) { this(snippetReflection, locationIdentity, kind, displacement, null, null); } - private SnippetLocationNode(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode kind, ValueNode displacement, ValueNode index, + public static SnippetLocationNode create(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode kind, ValueNode displacement, ValueNode index, ValueNode indexScaling) { + return USE_GENERATED_NODES ? new SnippetLocationNodeGen(snippetReflection, locationIdentity, kind, displacement, index, indexScaling) : new SnippetLocationNode(snippetReflection, + locationIdentity, kind, displacement, index, indexScaling); + } + + SnippetLocationNode(SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode kind, ValueNode displacement, ValueNode index, ValueNode indexScaling) { super(StampFactory.object()); this.snippetReflection = snippetReflection; this.valueKind = kind; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.phases.*; @@ -34,21 +35,26 @@ * Cast between Word and Object that is introduced by the {@link WordTypeRewriterPhase}. It has an * impact on the pointer maps for the GC, so it must not be scheduled or optimized away. */ -public final class WordCastNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable { +@NodeInfo +public class WordCastNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable { - @Input private ValueNode input; + @Input ValueNode input; public static WordCastNode wordToObject(ValueNode input, Kind wordKind) { assert input.getKind() == wordKind; - return new WordCastNode(StampFactory.object(), input); + return WordCastNode.create(StampFactory.object(), input); } public static WordCastNode objectToWord(ValueNode input, Kind wordKind) { assert input.getKind() == Kind.Object; - return new WordCastNode(StampFactory.forKind(wordKind), input); + return WordCastNode.create(StampFactory.forKind(wordKind), input); } - private WordCastNode(Stamp stamp, ValueNode input) { + public static WordCastNode create(Stamp stamp, ValueNode input) { + return USE_GENERATED_NODES ? new WordCastNodeGen(stamp, input) : new WordCastNode(stamp, input); + } + + WordCastNode(Stamp stamp, ValueNode input) { super(stamp); this.input = input; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Mon Aug 25 21:15:59 2014 -0700 @@ -157,9 +157,9 @@ * depends on elementKind. Therefore, just create a new node and replace the old one. */ if (node instanceof LoadIndexedNode) { - graph.replaceFixedWithFixed(node, graph.add(new LoadIndexedNode(node.array(), node.index(), wordKind))); + graph.replaceFixedWithFixed(node, graph.add(LoadIndexedNode.create(node.array(), node.index(), wordKind))); } else if (node instanceof StoreIndexedNode) { - graph.replaceFixedWithFixed(node, graph.add(new StoreIndexedNode(node.array(), node.index(), wordKind, ((StoreIndexedNode) node).value()))); + graph.replaceFixedWithFixed(node, graph.add(StoreIndexedNode.create(node.array(), node.index(), wordKind, ((StoreIndexedNode) node).value()))); } else { throw GraalInternalError.shouldNotReachHere(); } @@ -213,7 +213,7 @@ case NOT: assert arguments.size() == 1; - replace(invoke, graph.unique(new XorNode(arguments.get(0), ConstantNode.forIntegerKind(wordKind, -1, graph)))); + replace(invoke, graph.unique(XorNode.create(arguments.get(0), ConstantNode.forIntegerKind(wordKind, -1, graph)))); break; case READ_POINTER: @@ -282,7 +282,7 @@ case FROM_ARRAY: assert arguments.size() == 2; - replace(invoke, graph.unique(new ComputeAddressNode(arguments.get(0), arguments.get(1), StampFactory.forKind(wordKind)))); + replace(invoke, graph.unique(ComputeAddressNode.create(arguments.get(0), arguments.get(1), StampFactory.forKind(wordKind)))); break; case TO_OBJECT: @@ -316,14 +316,14 @@ if (toKind == Kind.Int) { assert value.getKind() == Kind.Long; - return graph.unique(new NarrowNode(value, 32)); + return graph.unique(NarrowNode.create(value, 32)); } else { assert toKind == Kind.Long; assert value.getKind().getStackKind() == Kind.Int; if (unsigned) { - return graph.unique(new ZeroExtendNode(value, 64)); + return graph.unique(ZeroExtendNode.create(value, 64)); } else { - return graph.unique(new SignExtendNode(value, 64)); + return graph.unique(SignExtendNode.create(value, 64)); } } } @@ -335,8 +335,8 @@ */ private static ValueNode createBinaryNodeInstance(Class nodeClass, ValueNode left, ValueNode right) { try { - Constructor constructor = nodeClass.getConstructor(ValueNode.class, ValueNode.class); - return constructor.newInstance(left, right); + Method factory = nodeClass.getDeclaredMethod("create", ValueNode.class, ValueNode.class); + return (ValueNode) factory.invoke(null, left, right); } catch (Throwable ex) { throw new GraalInternalError(ex).addContext(nodeClass.getName()); } @@ -353,11 +353,11 @@ CompareNode comparison; if (condition == Condition.EQ || condition == Condition.NE) { - comparison = new IntegerEqualsNode(a, b); + comparison = IntegerEqualsNode.create(a, b); } else if (condition.isUnsigned()) { - comparison = new IntegerBelowNode(a, b); + comparison = IntegerBelowNode.create(a, b); } else { - comparison = new IntegerLessThanNode(a, b); + comparison = IntegerLessThanNode.create(a, b); } ConstantNode trueValue = ConstantNode.forInt(1, graph); @@ -368,7 +368,7 @@ trueValue = falseValue; falseValue = temp; } - ConditionalNode materialize = graph.unique(new ConditionalNode(graph.unique(comparison), trueValue, falseValue)); + ConditionalNode materialize = graph.unique(ConditionalNode.create(graph.unique(comparison), trueValue, falseValue)); return materialize; } @@ -393,7 +393,7 @@ } protected ValueNode readOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location, BarrierType barrierType, boolean compressible) { - JavaReadNode read = graph.add(new JavaReadNode(base, location, barrierType, compressible)); + JavaReadNode read = graph.add(JavaReadNode.create(base, location, barrierType, compressible)); graph.addBeforeFixed(invoke.asNode(), read); /* * The read must not float outside its block otherwise it may float above an explicit zero @@ -408,7 +408,7 @@ final BarrierType barrier = (op == Opcode.WRITE_BARRIERED ? BarrierType.PRECISE : BarrierType.NONE); final boolean compressible = (op == Opcode.WRITE_OBJECT || op == Opcode.WRITE_BARRIERED); final boolean initialize = (op == Opcode.INITIALIZE); - JavaWriteNode write = graph.add(new JavaWriteNode(base, value, location, barrier, compressible, initialize)); + JavaWriteNode write = graph.add(JavaWriteNode.create(base, value, location, barrier, compressible, initialize)); write.setStateAfter(invoke.stateAfter()); graph.addBeforeFixed(invoke.asNode(), write); return write; diff -r ae0f235469db -r f8e60d11c0ec 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 25 21:15:59 2014 -0700 @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.nfi.test; + +import static com.oracle.graal.compiler.common.UnsafeAccess.*; +import static java.io.File.*; +import static java.lang.System.*; +import static org.junit.Assert.*; +import static org.junit.Assume.*; + +import java.io.*; +import java.util.*; + +import org.junit.*; + +import com.oracle.nfi.*; +import com.oracle.nfi.api.*; + +@Ignore +public class NativeFunctionInterfaceTest { + + public final NativeFunctionInterface nfi; + + public NativeFunctionInterfaceTest() { + nfi = NativeFunctionInterfaceRuntime.getNativeFunctionInterface(); + } + + private List 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 ae0f235469db -r f8e60d11c0ec 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 25 21:15:59 2014 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.nfi; + +import com.oracle.nfi.api.*; + +/** + * Class for obtaining the {@link NativeFunctionInterface} (if any) provided by the VM. + */ +public final class NativeFunctionInterfaceRuntime { + private static final NativeFunctionInterface INSTANCE; + + /** + * Creates a new {@link NativeFunctionInterface}. + * + * @throws UnsatisfiedLinkError if not running on a VM that provides a + * {@link NativeFunctionInterface} + */ + private static native NativeFunctionInterface createInterface(); + + /** + * Gets the {@link NativeFunctionInterface} (if any) provided by the VM. + * + * @return null if the VM does not provide a {@link NativeFunctionInterface} + */ + public static NativeFunctionInterface getNativeFunctionInterface() { + return INSTANCE; + } + + static { + NativeFunctionInterface instance; + try { + instance = createInterface(); + } catch (UnsatisfiedLinkError e) { + instance = null; + } + INSTANCE = instance; + } +} diff -r ae0f235469db -r f8e60d11c0ec 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 25 21:15:59 2014 -0700 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.nfi.api; + +/** + * A handle that can be used to {@linkplain #call(Object[]) call} a native function. + */ +public interface NativeFunctionHandle { + + /** + * Calls the native function. + *

    + * 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 ae0f235469db -r f8e60d11c0ec 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 25 21:15:59 2014 -0700 @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.nfi.api; + +/** + * Interface to get a {@linkplain NativeFunctionHandle handle} or {@linkplain NativeFunctionPointer + * pointer} to a native function or a {@linkplain NativeLibraryHandle handle} to an open native + * library. + */ +public interface NativeFunctionInterface { + + /** + * Resolves and returns a handle to an open native library. This method will open the library + * only if it is not already open. + * + * @param libPath the absolute path to the library + * @return the resolved library handle + * @throws UnsatisfiedLinkError if the library could not be found or opened + */ + NativeLibraryHandle getLibraryHandle(String libPath); + + /** + * Determines if the underlying platform/runtime supports the notion of a default library search + * path. For example, on *nix systems, this is typically defined by the {@code LD_LIBRARY_PATH} + * environment variable. + */ + boolean isDefaultLibrarySearchSupported(); + + /** + * Resolves the function pointer {@code NativeFunctionPointer} of a native function. + * + * @param libraries the ordered list of libraries to search for the function + * @param name the name of the function to be resolved + * @return a pointer to the native function + * @throws UnsatisfiedLinkError if the function could not be resolved + */ + NativeFunctionPointer getFunctionPointer(NativeLibraryHandle[] libraries, String name); + + /** + * Resolves a function name to a {@linkplain NativeFunctionHandle handle} that can be called + * with a given signature. The signature contains the types of the arguments that will be passed + * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}. + * + * @param library the handle to a resolved library + * @param name the name of the function to be resolved + * @param returnType the type of the return value + * @param argumentTypes the types of the arguments + * @return the function handle of the native function + * @throws UnsatisfiedLinkError if the function handle could not be resolved + */ + NativeFunctionHandle getFunctionHandle(NativeLibraryHandle library, String name, Class returnType, Class... argumentTypes); + + /** + * Resolves a function pointer to a {@linkplain NativeFunctionHandle handle} that can be called + * with a given signature. The signature contains the types of the arguments that will be passed + * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}. + * + * @param functionPointer a function pointer + * @param returnType the type of the return value + * @param argumentTypes the types of the arguments + * @return the function handle of the native function + * @throws UnsatisfiedLinkError the function handle could not be created + */ + NativeFunctionHandle getFunctionHandle(NativeFunctionPointer functionPointer, Class returnType, Class... argumentTypes); + + /** + * Resolves a function name to a {@linkplain NativeFunctionHandle handle} that can be called + * with a given signature. The signature contains the types of the arguments that will be passed + * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}. + * + * @param libraries the ordered list of libraries to search for the function + * @param name the name of the function to be resolved + * @param returnType the type of the return value + * @param argumentTypes the types of the arguments + * @return the function handle of the native function + * @throws UnsatisfiedLinkError if the function handle could not be created + */ + NativeFunctionHandle getFunctionHandle(NativeLibraryHandle[] libraries, String name, Class returnType, Class... argumentTypes); + + /** + * Resolves a function name to a {@linkplain NativeFunctionHandle handle} that can be called + * with a given signature. The signature contains the types of the arguments that will be passed + * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}. + * + * @param name the name of the function to be resolved + * @param returnType the type of the return value + * @param argumentTypes the types of the arguments + * @return the function handle of the native function + * @throws UnsatisfiedLinkError if default library searching is not + * {@linkplain #isDefaultLibrarySearchSupported() supported} or if the function + * could not be resolved + */ + NativeFunctionHandle getFunctionHandle(String name, Class returnType, Class... argumentTypes); + + /** + * Creates a {@link NativeFunctionPointer} from a raw value. + * + * @param rawValue raw function pointer + * @return {@code NativeFunctionPointer} for {@code rawValue} + */ + NativeFunctionPointer getNativeFunctionPointerFromRawValue(long rawValue); +} diff -r ae0f235469db -r f8e60d11c0ec 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 25 21:15:59 2014 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.nfi.api; + +/** + * An opaque representation of a native function pointer. + *

    + * 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 ae0f235469db -r f8e60d11c0ec 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 25 21:15:59 2014 -0700 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.nfi.api; + +/** + * An opaque representation of a native library handle. A handle is obtained via + * {@link NativeFunctionInterface#getLibraryHandle(String)}. A handle is used to resolve a string to + * a {@linkplain NativeFunctionInterface#getFunctionHandle(String, Class, Class...) handle} or + * {@linkplain NativeFunctionInterface#getFunctionPointer(NativeLibraryHandle[], String) pointer}. + */ +public interface NativeLibraryHandle { + /** + * Gets a name for this library. This may be the path for the file from which the library was + * loaded. + */ + String getName(); +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AssumptionsTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AssumptionsTest.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AssumptionsTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -48,15 +48,16 @@ @NodeAssumptions("assumption") abstract static class SingleAssumptionNode extends ValueNode { - @Specialization(order = 0, assumptions = "assumption") - int doInt() { + @Specialization(assumptions = "assumption") + int do2() { return 42; } - @Specialization - Object doObject() { + @Fallback + Object doFallBack() { return "42"; } + } @Test @@ -67,9 +68,9 @@ Assert.assertEquals(42, TestHelper.executeWith(root)); assumption2.invalidate(); - Assert.assertEquals("42", TestHelper.executeWith(root)); + Assert.assertEquals("41", TestHelper.executeWith(root)); assumption1.invalidate(); - Assert.assertEquals("43", TestHelper.executeWith(root)); + Assert.assertEquals("42", TestHelper.executeWith(root)); } @NodeAssumptions({"assumption1", "assumption2"}) @@ -82,12 +83,12 @@ @Specialization(assumptions = "assumption1") Object doObject() { - return "42"; + return "41"; } - @Generic - Object doGeneric() { - return "43"; + @Fallback + Object doFallBack() { + return "42"; } } @@ -107,10 +108,11 @@ @NodeAssumptions({"additionalAssumption"}) abstract static class DerivedAssumptionNode extends SingleAssumptionNode { - @Specialization(order = 1, assumptions = "additionalAssumption") + @Specialization(assumptions = "additionalAssumption") int doIntDerived() { return 43; } + } @Test @@ -129,7 +131,7 @@ @NodeAssumptions({"additionalAssumption", "assumption"}) abstract static class DerivedAssumptionRedeclaredNode extends SingleAssumptionNode { - @Specialization(order = 1, assumptions = "additionalAssumption") + @Specialization(assumptions = "additionalAssumption") int doIntDerived() { return 43; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BinaryNodeTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BinaryNodeTest.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BinaryNodeTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -60,7 +60,7 @@ return left + right; } - @Generic + @Fallback Object add(Object left, Object right) { return convertDouble(left) + convertDouble(right); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -28,6 +28,9 @@ import com.oracle.truffle.api.dsl.test.CodeFormatTestFactory.LineWrappingTestFactory; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; +/** + * Tests the generated code compiles without warnings for unusual large guard names. + */ public class CodeFormatTest { @Test diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,643 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl.test; + +import static com.oracle.truffle.api.dsl.test.TestHelper.*; +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.internal.*; +import com.oracle.truffle.api.dsl.test.ContainsTestFactory.Contains1Factory; +import com.oracle.truffle.api.dsl.test.ContainsTestFactory.Contains2Factory; +import com.oracle.truffle.api.dsl.test.ContainsTestFactory.Contains3Factory; +import com.oracle.truffle.api.dsl.test.ContainsTestFactory.Contains4Factory; +import com.oracle.truffle.api.dsl.test.ContainsTestFactory.PolymorphicToMonomorphic0Factory; +import com.oracle.truffle.api.dsl.test.TestHelper.ExecutionListener; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; +import com.oracle.truffle.api.nodes.*; + +@SuppressWarnings("unused") +public class ContainsTest { + + /* + * Tests a simple monomorphic inclusion. + */ + @Test + public void testContains1() { + assertRuns(Contains1Factory.getInstance(), // + array(1, "a", 2, "b"), // + array(2, "aa", 3, "ba"),// + new ExecutionListener() { + public void afterExecution(TestRootNode node, int index, Object value, Object expectedResult, Object actualResult, boolean last) { + if (value instanceof String) { + // assert that the final specialization is always Object + Assert.assertEquals(Object.class, ((DSLNode) node.getNode()).getMetadata0().getSpecializedTypes()[0]); + } + } + }); + } + + @NodeChild("a") + abstract static class Contains1 extends ValueNode { + + @Specialization + int f1(int a) { + return a + 1; + } + + @Specialization(contains = "f1") + Object f2(Object a) { + if (a instanceof Integer) { + return ((Integer) a) + 1; + } + return a + "a"; + } + } + + /* + * Tests an inclusion in within a polymorphic chain. + */ + @Test + public void testContains2() { + assertRuns(Contains2Factory.getInstance(), // + array(true, 1, 0, false), // + array(false, -1, 1, true) // + ); + } + + @NodeChild("a") + abstract static class Contains2 extends ValueNode { + + static boolean isZero(int a) { + return a == 0; + } + + @Specialization(guards = "isZero") + int f1(int a) { + return a + 1; + } + + @Specialization(contains = "f1") + int f2(int a) { + if (a == 0) { + return a + 1; + } + return -a; + } + + @Specialization + boolean f3(boolean a) { + return !a; + } + } + + /* + * Tests transitive monomorphic inclusion. + */ + @Test + public void testContains3() { + assertRuns(Contains3Factory.getInstance(), // + array(2, 1, 2, -3, -4), // + array(-2, 2, -2, -3, -4),// + new ExecutionListener() { + public void afterExecution(TestRootNode node, int index, Object value, Object expectedResult, Object actualResult, boolean last) { + // assert that we are always monomorphic + Assert.assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost()); + } + }); + } + + @NodeChild("a") + abstract static class Contains3 extends ValueNode { + + static boolean isGreaterZero(int a) { + return a > 0; + } + + @Implies("isGreaterZero") + static boolean isOne(int a) { + return a == 1; + } + + @Specialization(guards = {"isOne"}) + int f1(int a) { + return a + 1; + } + + @Specialization(contains = "f1", guards = {"isGreaterZero"}) + int f2(int a) { + if (a == 1) { + return 2; + } + return -a; + } + + @Specialization(contains = "f2") + int f3(int a) { + if (a > 0) { + return a == 1 ? 2 : -a; + } else { + return a; + } + } + + } + + /* + * Tests that if it can be derived that two specializations actually a as powerful as the latter + * we can combine them. Therefore operation should always become monomorphic in the end. + */ + @Test + public void testContains4() { + assertRuns(Contains4Factory.getInstance(), // + array(-1, 0, 1, 2), // + array(1, 0, 1, 2),// + new ExecutionListener() { + public void afterExecution(TestRootNode node, int index, Object value, Object expectedResult, Object actualResult, boolean last) { + Assert.assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost()); + } + }); + } + + @NodeChild("a") + abstract static class Contains4 extends ValueNode { + + static boolean isGreaterEqualZero(int a) { + return a >= 0; + } + + @Implies("isGreaterEqualZero") + static boolean isOne(int a) { + return a == 1; + } + + @Specialization(guards = {"isOne"}) + int f0(int a) { + return 1; + } + + @Specialization(contains = "f0", guards = {"isGreaterEqualZero"}) + int f1(int a) { + return a; + } + + @Specialization(contains = {"f1"}) + int f2(int a) { + return Math.abs(a); + } + + } + + @NodeChild("a") + abstract static class ContainsError1 extends ValueNode { + @ExpectError("The contained specialization 'f1' must be declared before the containing specialization.") + @Specialization(contains = "f1") + int f0(int a) { + return a; + } + + @Specialization + Object f1(String a) { + return a; + } + } + + @NodeChild("a") + abstract static class ContainsError2 extends ValueNode { + + @ExpectError("The referenced specialization 'does not exist' could not be found.") + @Specialization(contains = "does not exist") + int f0(int a) { + return a; + } + } + + @NodeChild("a") + abstract static class ContainsError3 extends ValueNode { + + @Specialization + int f0(int a) { + return a; + } + + @ExpectError("Duplicate contains declaration 'f0'.") + @Specialization(contains = {"f0", "f0"}) + Object f1(double a) { + return a; + } + } + + @NodeChild("a") + abstract static class ContainsError4 extends ValueNode { + + @ExpectError("Circular contained specialization 'f1(double)' found.") + @Specialization(contains = {"f1"}) + Object f1(double a) { + return a; + } + } + + @NodeChild("a") + abstract static class ContainsError5 extends ValueNode { + + @ExpectError({"Circular contained specialization 'f0(int)' found.", "Circular contained specialization 'f1(double)' found.", + "The contained specialization 'f1' must be declared before the containing specialization."}) + @Specialization(contains = "f1") + int f0(int a) { + return a; + } + + @ExpectError("Circular contained specialization 'f1(double)' found.") + @Specialization(contains = {"f0"}) + Object f1(double a) { + return a; + } + } + + @NodeChild("a") + abstract static class ContainsType1 extends ValueNode { + @Specialization + int f0(int a) { + return a; + } + + @ExpectError("Specialization is not reachable. It is shadowed by f0(int).") + @Specialization(contains = "f0") + Object f1(int a) { + return a; + } + } + + @NodeChild("a") + abstract static class ContainsType2 extends ValueNode { + @Specialization + int f0(int a) { + return a; + } + + @Specialization(contains = "f0") + Object f1(Object a) { + return a; + } + } + + @NodeChild("a") + abstract static class ContainsType3 extends ValueNode { + @Specialization + int f0(int a) { + return a; + } + + @Specialization(contains = "f0") + Object f1(double a) { // implicit type + return a; + } + } + + @NodeChild("a") + abstract static class ContainsType4 extends ValueNode { + @Specialization + double f0(double a) { + return a; + } + + @ExpectError({"Specialization is not reachable. It is shadowed by f0(double).", "The contained specialization 'f0' is not fully compatible.%"}) + @Specialization(contains = "f0") + int f1(int a) { // implicit type + return a; + } + } + + @NodeChildren({@NodeChild("a"), @NodeChild("b")}) + abstract static class ContainsType5 extends ValueNode { + @Specialization + Object f0(Object a, int b) { + return a; + } + + @ExpectError("The contained specialization 'f0' is not fully compatible.%") + @Specialization(contains = "f0") + Object f1(int a, Object b) { + return a; + } + } + + @NodeChildren({@NodeChild("a"), @NodeChild("b")}) + abstract static class ContainsType6 extends ValueNode { + @Specialization + Object f0(double a, int b) { + return a; + } + + @ExpectError("The contained specialization 'f0' is not fully compatible.%") + @Specialization(contains = "f0") + Object f1(int a, double b) { // implicit type + return a; + } + } + + abstract static class ContainsGuard1 extends ValueNode { + + boolean g1() { + return true; + } + + @Specialization(guards = "g1") + Object f0() { + return null; + } + + @Specialization(contains = "f0") + Object f1() { + return null; + } + } + + abstract static class ContainsGuard2 extends ValueNode { + + boolean g1() { + return true; + } + + @Specialization + Object f0() { + return null; + } + + @ExpectError({"Specialization is not reachable. It is shadowed by f0().", "The contained specialization 'f0' is not fully compatible.%"}) + @Specialization(guards = "g1", contains = "f0") + Object f1() { + return null; + } + } + + abstract static class ContainsGuard3 extends ValueNode { + + boolean g1() { + return true; + } + + @Specialization(guards = "g1") + Object f0() { + return null; + } + + @ExpectError({"The contained specialization 'f0' is not fully compatible.%"}) + @Specialization(guards = "!g1", contains = "f0") + Object f1() { + return null; + } + } + + abstract static class ContainsGuard4 extends ValueNode { + + boolean g1() { + return true; + } + + boolean g2() { + return true; + } + + @Specialization(guards = "g1") + Object f0() { + return null; + } + + @ExpectError({"The contained specialization 'f0' is not fully compatible.%"}) + @Specialization(guards = "g2", contains = "f0") + Object f1() { + return null; + } + } + + abstract static class ContainsGuard5 extends ValueNode { + + @Implies("g2") + boolean g1() { + return true; + } + + boolean g2() { + return true; + } + + @Specialization(guards = "g1") + Object f0() { + return null; + } + + @Specialization(guards = "g2", contains = "f0") + Object f1() { + return null; + } + } + + abstract static class ContainsGuard6 extends ValueNode { + + @Implies("!g2") + boolean g1() { + return true; + } + + boolean g2() { + return true; + } + + @Specialization(guards = "g1") + Object f0() { + return null; + } + + @Specialization(guards = "!g2", contains = "f0") + Object f1() { + return null; + } + } + + abstract static class ContainsGuard7 extends ValueNode { + + boolean g1() { + return true; + } + + boolean g2() { + return true; + } + + @Specialization(guards = {"g1", "g2"}) + Object f0() { + return null; + } + + @Specialization(guards = "g2", contains = "f0") + Object f1() { + return null; + } + } + + @NodeAssumptions("a1") + abstract static class ContainsAssumption1 extends ValueNode { + + @Specialization(assumptions = "a1") + Object f0() { + return null; + } + + @Specialization(contains = "f0") + Object f1() { + return null; + } + } + + @NodeAssumptions("a1") + abstract static class ContainsAssumption2 extends ValueNode { + + @Specialization + Object f0() { + return null; + } + + @ExpectError({"Specialization is not reachable. It is shadowed by f0().", "The contained specialization 'f0' is not fully compatible.%"}) + @Specialization(contains = "f0", assumptions = "a1") + Object f1() { + return null; + } + } + + @NodeAssumptions({"a1", "a2"}) + abstract static class ContainsAssumption3 extends ValueNode { + + @Specialization(assumptions = "a1") + Object f0() { + return null; + } + + @ExpectError({"The contained specialization 'f0' is not fully compatible.%"}) + @Specialization(contains = "f0", assumptions = "a2") + Object f1() { + return null; + } + } + + @NodeAssumptions({"a1", "a2"}) + abstract static class ContainsAssumption4 extends ValueNode { + + @Specialization(assumptions = {"a1", "a2"}) + Object f0() { + return null; + } + + @Specialization(contains = "f0", assumptions = "a1") + Object f1() { + return null; + } + } + + @NodeAssumptions({"a1", "a2"}) + abstract static class ContainsAssumption5 extends ValueNode { + + @Specialization(assumptions = {"a2", "a1"}) + Object f0() { + return null; + } + + @Specialization(contains = "f0", assumptions = "a1") + Object f1() { + return null; + } + } + + abstract static class ContainsThrowable1 extends ValueNode { + + @Specialization(rewriteOn = RuntimeException.class) + Object f0() throws RuntimeException { + throw new RuntimeException(); + } + + @Specialization(contains = "f0") + Object f1() { + return null; + } + } + + abstract static class ContainsThrowable2 extends ValueNode { + + @Specialization(rewriteOn = RuntimeException.class) + Object f0() throws RuntimeException { + throw new RuntimeException(); + } + + @Specialization(contains = "f0", rewriteOn = RuntimeException.class) + Object f1() throws RuntimeException { + throw new RuntimeException(); + } + + @Specialization(contains = "f1") + Object f2() { + return null; + } + } + + @Test + public void testPolymorphicToMonomorphic0() { + TestRootNode root = createRoot(PolymorphicToMonomorphic0Factory.getInstance()); + assertThat((int) executeWith(root, 1), is(1)); + assertThat((int) executeWith(root, 2), is(2)); + assertThat((int) executeWith(root, 3), is(3)); + assertThat(root.getNode().getCost(), is(NodeCost.MONOMORPHIC)); + } + + @NodeChild("a") + static class PolymorphicToMonomorphic0 extends ValueNode { + + boolean isOne(int a) { + return a == 1; + } + + boolean isTwo(int a) { + return a == 2; + } + + @Specialization(guards = "isOne") + int do1(int a) { + return a; + } + + @Specialization(guards = "isTwo") + int do2(int a) { + return a; + } + + @Specialization(contains = {"do1", "do2"}) + int do3(int a) { + return a; + } + + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl.test; + +import static com.oracle.truffle.api.dsl.test.TestHelper.*; + +import org.junit.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.FallbackTestFactory.Fallback1Factory; +import com.oracle.truffle.api.dsl.test.FallbackTestFactory.Fallback2Factory; +import com.oracle.truffle.api.dsl.test.FallbackTestFactory.Fallback3Factory; +import com.oracle.truffle.api.dsl.test.FallbackTestFactory.Fallback4Factory; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.*; +import com.oracle.truffle.api.nodes.*; + +public class FallbackTest { + + private static final Object UNKNOWN_OBJECT = new Object() { + }; + + @Test + public void testFallback1() { + assertRuns(Fallback1Factory.getInstance(), // + array(42, UNKNOWN_OBJECT), // + array("(int)", "(fallback)")); + } + + /** + * test with fallback handler defined + */ + @SuppressWarnings("unused") + @NodeChild("a") + abstract static class Fallback1 extends ValueNode { + + @Specialization + String f1(int a) { + return "(int)"; + } + + @Fallback + String f2(Object a) { + return "(fallback)"; + } + } + + @Test + public void testFallback2() { + assertRuns(Fallback2Factory.getInstance(), // + array(42, UNKNOWN_OBJECT), // + array("(int)", UnsupportedSpecializationException.class)); + } + + /** + * test without fallback handler defined + */ + @SuppressWarnings("unused") + @NodeChild("a") + abstract static class Fallback2 extends ValueNode { + + @Specialization + String f1(int a) { + return "(int)"; + } + + } + + @Test + public void testFallback3() { + assertRuns(Fallback3Factory.getInstance(), // + array(42, 43, UNKNOWN_OBJECT, "somestring"), // + array("(int)", "(int)", "(object)", "(object)")); + } + + /** + * test without fallback handler and unreachable + */ + @SuppressWarnings("unused") + @NodeChild("a") + abstract static class Fallback3 extends ValueNode { + + @Specialization + String f1(int a) { + return "(int)"; + } + + @Specialization(guards = "notInt") + String f2(Object a) { + return "(object)"; + } + + boolean notInt(Object value) { + return !(value instanceof Integer); + } + + } + + /** + * Tests the contents of the {@link UnsupportedSpecializationException} contents in polymorphic + * nodes. + */ + @Test + public void testFallback4() { + TestRootNode node = createRoot(Fallback4Factory.getInstance()); + + Assert.assertEquals("(int)", executeWith(node, 1)); + Assert.assertEquals("(boolean)", executeWith(node, true)); + try { + executeWith(node, UNKNOWN_OBJECT); + Assert.fail(); + } catch (UnsupportedSpecializationException e) { + Assert.assertEquals(node.getNode(), e.getNode()); + Assert.assertArrayEquals(NodeUtil.findNodeChildren(node.getNode()).subList(0, 1).toArray(new Node[0]), e.getSuppliedNodes()); + Assert.assertArrayEquals(new Object[]{UNKNOWN_OBJECT}, e.getSuppliedValues()); + } + } + + /** + * test without fallback handler and unreachable + */ + @SuppressWarnings("unused") + @NodeChild("a") + abstract static class Fallback4 extends ValueNode { + + @Specialization + String f1(int a) { + return "(int)"; + } + + @Specialization + String f2(boolean a) { + return "(boolean)"; + } + } + + /** + * Tests the contents of the {@link UnsupportedSpecializationException} contents in monomorphic + * nodes. + */ + @Test + public void testFallback5() { + TestRootNode node = createRoot(Fallback4Factory.getInstance()); + + Assert.assertEquals("(int)", executeWith(node, 1)); + try { + executeWith(node, UNKNOWN_OBJECT); + Assert.fail(); + } catch (UnsupportedSpecializationException e) { + Assert.assertEquals(node.getNode(), e.getNode()); + Assert.assertArrayEquals(NodeUtil.findNodeChildren(node.getNode()).subList(0, 1).toArray(new Node[0]), e.getSuppliedNodes()); + Assert.assertArrayEquals(new Object[]{UNKNOWN_OBJECT}, e.getSuppliedValues()); + } + } + + // test without fallback handler and unreachable + @SuppressWarnings("unused") + @NodeChild("a") + abstract static class Fallback5 extends ValueNode { + + @Specialization + String f1(int a) { + return "(int)"; + } + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/GuardsTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/GuardsTest.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,315 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.api.dsl.test; - -import static com.oracle.truffle.api.dsl.test.TestHelper.*; -import static org.junit.Assert.*; - -import org.junit.*; - -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GlobalFlagGuardFactory; -import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GuardWithBaseClassFactory; -import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GuardWithBaseInterfaceFactory; -import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GuardWithBoxedPrimitiveFactory; -import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GuardWithObjectFactory; -import com.oracle.truffle.api.dsl.test.GuardsTestFactory.InvocationGuardFactory; -import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestAbstractGuard1Factory; -import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestGuardResolve1Factory; -import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestGuardResolve2Factory; -import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestGuardResolve3Factory; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.Abstract; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.BExtendsAbstract; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.CExtendsAbstract; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; - -@SuppressWarnings("unused") -public class GuardsTest { - - private static final Object NULL = new Object(); - - @Test - public void testGuardInvocations() { - TestRootNode root = createRoot(InvocationGuardFactory.getInstance()); - - assertEquals(Integer.MAX_VALUE, executeWith(root, Integer.MAX_VALUE - 1, 1)); - assertEquals(1, InvocationGuard.specializedInvocations); - assertEquals(0, InvocationGuard.genericInvocations); - - assertEquals(42, executeWith(root, Integer.MAX_VALUE, 1)); - assertEquals(1, InvocationGuard.specializedInvocations); - assertEquals(1, InvocationGuard.genericInvocations); - } - - @NodeChildren({@NodeChild("value0"), @NodeChild("value1")}) - public abstract static class InvocationGuard extends ValueNode { - - static int specializedInvocations = 0; - static int genericInvocations = 0; - - boolean guard(int value0, int value1) { - return value0 != Integer.MAX_VALUE; - } - - @Specialization(guards = "guard") - int doSpecialized(int value0, int value1) { - specializedInvocations++; - return value0 + value1; - } - - @Generic - int doGeneric(Object value0, Object value1) { - genericInvocations++; - return 42; // the generic answer to all questions - } - } - - @Test - public void testGuardGlobal() { - TestRootNode root = createRoot(GlobalFlagGuardFactory.getInstance()); - - assertEquals(42, executeWith(root, NULL)); - - GlobalFlagGuard.globalFlag = true; - assertEquals(41, executeWith(root, NULL)); - - GlobalFlagGuard.globalFlag = false; - assertEquals(42, executeWith(root, NULL)); - } - - @NodeChild("expression") - public abstract static class GlobalFlagGuard extends ValueNode { - - static boolean globalFlag = false; - - static boolean globalFlagGuard() { - return globalFlag; - } - - @Specialization(guards = "globalFlagGuard") - int doSpecialized(Object value0) { - return 41; - } - - @Generic - int doGeneric(Object value0) { - return 42; // the generic answer to all questions - } - } - - @Test - public void testGuardWithBaseClass() { - TestRootNode root = createRoot(GuardWithBaseClassFactory.getInstance()); - - assertEquals(42, executeWith(root, new BExtendsAbstract())); - } - - @NodeChild("expression") - public abstract static class GuardWithBaseClass extends ValueNode { - - boolean baseGuard(Abstract base) { - return true; - } - - @Specialization(guards = "baseGuard") - int doSpecialized(BExtendsAbstract value0) { - return 42; - } - } - - @Test - public void testGuardWithBaseInterface() { - TestRootNode root = createRoot(GuardWithBaseInterfaceFactory.getInstance()); - - assertEquals(42, executeWith(root, "anything")); - } - - @NodeChild("expression") - public abstract static class GuardWithBaseInterface extends ValueNode { - - boolean baseGuard(CharSequence base) { - return true; - } - - @Specialization(guards = "baseGuard") - int doSpecialized(String value0) { - return 42; - } - } - - @Test - public void testGuardWithPrimitive() { - TestRootNode root = createRoot(GuardWithBoxedPrimitiveFactory.getInstance()); - - assertEquals(42, executeWith(root, 42)); - } - - @NodeChild("expression") - public abstract static class GuardWithBoxedPrimitive extends ValueNode { - - boolean baseGuard(Integer primitive) { - return true; - } - - @Specialization(guards = "baseGuard") - int doSpecialized(int value0) { - return value0; - } - } - - @Test - public void testGuardWithObject() { - TestRootNode root = createRoot(GuardWithObjectFactory.getInstance()); - - assertEquals(42, executeWith(root, 42)); - } - - @NodeChild("expression") - public abstract static class GuardWithObject extends ValueNode { - - boolean baseGuard(Object primitive) { - return true; - } - - @Specialization(guards = "baseGuard") - int doSpecialized(int value0) { - return value0; - } - } - - @Test - public void testGuardResolve1() { - TestRootNode root = createRoot(TestGuardResolve1Factory.getInstance()); - - assertEquals(42, executeWith(root, 42)); - } - - @NodeChild("expression") - public abstract static class TestGuardResolve1 extends ValueNode { - - boolean guard(Object primitive) { - return false; - } - - boolean guard(int primitive) { - return true; - } - - @Specialization(guards = "guard") - int doSpecialized(int value0) { - return value0; - } - } - - @Test - public void testGuardResolve2() { - TestRootNode root = createRoot(TestGuardResolve2Factory.getInstance()); - assertEquals(42, executeWith(root, new BExtendsAbstract())); - } - - @NodeChild("expression") - public abstract static class TestGuardResolve2 extends ValueNode { - - boolean guard(Object primitive) { - return false; - } - - boolean guard(Abstract primitive) { - return true; - } - - @Specialization(guards = "guard") - int doSpecialized(BExtendsAbstract value0) { - return 42; - } - } - - @Test - public void testGuardResolve3() { - TestRootNode root = createRoot(TestGuardResolve3Factory.getInstance()); - - assertEquals(42, executeWith(root, new BExtendsAbstract())); - } - - @NodeChild("expression") - public abstract static class TestGuardResolve3 extends ValueNode { - - boolean guard(Object primitive) { - return false; - } - - boolean guard(Abstract primitive) { - return false; - } - - boolean guard(BExtendsAbstract primitive) { - return true; - } - - @Specialization(guards = "guard") - int doSpecialized(BExtendsAbstract value0) { - return 42; - } - } - - @NodeChild("expression") - public abstract static class TestGuardResolve4 extends ValueNode { - - boolean guard(Abstract primitive) { - return false; - } - - @Specialization(guards = "guard") - int doSpecialized(BExtendsAbstract value0) { - return 42; - } - } - - @Test - public void testAbstractGuard1() { - TestRootNode root = createRoot(TestAbstractGuard1Factory.getInstance()); - - assertEquals(BExtendsAbstract.INSTANCE, executeWith(root, BExtendsAbstract.INSTANCE)); - assertEquals(CExtendsAbstract.INSTANCE, executeWith(root, CExtendsAbstract.INSTANCE)); - } - - @NodeChild("expression") - public abstract static class TestAbstractGuard1 extends ValueNode { - - boolean guard(Abstract value0) { - return true; - } - - @Specialization(order = 1, guards = "guard") - BExtendsAbstract doSpecialized1(BExtendsAbstract value0) { - return value0; - } - - @Specialization(order = 2, guards = "guard") - CExtendsAbstract doSpecialized2(CExtendsAbstract value0) { - return value0; - } - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -34,7 +34,7 @@ public class ImplicitCastTest { - @TypeSystem({int.class, boolean.class, String.class}) + @TypeSystem({int.class, String.class, boolean.class}) static class ImplicitCast0Types { @ImplicitCast @@ -55,12 +55,12 @@ public abstract Object executeEvaluated(VirtualFrame frame, Object value2); - @Specialization(order = 1) + @Specialization public String op1(String value) { return value; } - @Specialization(order = 2) + @Specialization public boolean op1(boolean value) { return value; } @@ -81,22 +81,21 @@ @TypeSystemReference(ImplicitCast0Types.class) @NodeChild(value = "operand", type = ImplicitCast1Node.class) - // TODO temporary workaround abstract static class ImplicitCast1Node extends ValueNode { public abstract Object executeEvaluated(VirtualFrame frame, Object operand); - @Specialization(order = 0) + @Specialization public String op0(String value) { return value; } - @Specialization(order = 1, rewriteOn = RuntimeException.class) + @Specialization(rewriteOn = RuntimeException.class) public boolean op1(@SuppressWarnings("unused") boolean value) throws RuntimeException { throw new RuntimeException(); } - @Specialization(order = 2) + @Specialization(contains = "op1") public boolean op2(boolean value) { return value; } @@ -120,18 +119,18 @@ // TODO temporary workaround abstract static class ImplicitCast2Node extends ValueNode { - @Specialization(order = 0) + @Specialization public String op0(String v0, String v1) { return v0 + v1; } @SuppressWarnings("unused") - @Specialization(order = 1, rewriteOn = RuntimeException.class) + @Specialization(rewriteOn = RuntimeException.class) public boolean op1(boolean v0, boolean v1) throws RuntimeException { throw new RuntimeException(); } - @Specialization(order = 2) + @Specialization(contains = "op1") public boolean op2(boolean v0, boolean v1) { return v0 && v1; } @@ -156,4 +155,15 @@ Assert.assertEquals(true, root.getNode().executeEvaluated(null, true, true)); } + @TypeSystem({String.class, boolean.class}) + static class ImplicitCastError1 { + + @ImplicitCast + @ExpectError("Target type and source type of an @ImplicitCast must not be the same type.") + String castInvalid(@SuppressWarnings("unused") String value) { + throw new AssertionError(); + } + + } + } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl.test; + +import static com.oracle.truffle.api.dsl.test.TestHelper.*; + +import org.junit.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.ImportGuardsTestFactory.ImportGuards6Factory; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; + +public class ImportGuardsTest { + + @ImportGuards(Imports0.class) + @NodeChild("a") + static class ImportGuards0 extends ValueNode { + + @Specialization(guards = "staticGuard") + int f0(int a) { + return a; + } + } + + @NodeChild("a") + @ImportGuards(Imports0.class) + static class ImportGuards1 extends ValueNode { + + @ExpectError("No compatible guard with method name 'nonStaticGuard' found.") + @Specialization(guards = "nonStaticGuard") + int f1(int a) { + return a; + } + + @ExpectError("No compatible guard with method name 'protectedGuard' found.") + @Specialization(guards = "protectedGuard") + int f2(int a) { + return a; + } + + @ExpectError("No compatible guard with method name 'packageGuard' found.") + @Specialization(guards = "packageGuard") + int f3(int a) { + return a; + } + + @ExpectError("No compatible guard with method name 'privateGuard' found.") + @Specialization(guards = "privateGuard") + int f4(int a) { + return a; + } + } + + public static class Imports0 { + public static boolean staticGuard(int a) { + return a == 0; + } + + public boolean nonStaticGuard(int a) { + return a == 0; + } + + protected static boolean protectedGuard(int a) { + return a == 0; + } + + static boolean packageGuard(int a) { + return a == 0; + } + + @SuppressWarnings("unused") + private static boolean privateGuard(int a) { + return a == 0; + } + + } + + @ExpectError("The specified import guard class 'com.oracle.truffle.api.dsl.test.ImportGuardsTest.Imports1' must be public.") + @NodeChild("a") + @ImportGuards(Imports1.class) + static class ImportGuards2 extends ValueNode { + + int do1(int a) { + return a; + } + } + + static class Imports1 { + + } + + @ExpectError("The specified import guard class 'com.oracle.truffle.api.dsl.test.ImportGuardsTest.Imports2' must be public.") + @NodeChild("a") + @ImportGuards(Imports2.class) + static class ImportGuards3 extends ValueNode { + + int do1(int a) { + return a; + } + } + + @ExpectError("The specified import guard class 'boolean' is not a declared type.") + @NodeChild("a") + @ImportGuards(boolean.class) + static class ImportGuards4 extends ValueNode { + + int do1(int a) { + return a; + } + } + + private static class Imports2 { + + } + + @ExpectError("At least import guard classes must be specified.") + @NodeChild("a") + @ImportGuards({}) + static class ImportGuards5 extends ValueNode { + + int do1(int a) { + return a; + } + } + + @Test + public void testImportGuards6() { + // should use the guar declared in the node instead of the imported one. + assertRuns(ImportGuards6Factory.getInstance(), // + array(1, 1), // + array(1, 1)); + } + + @ImportGuards(Imports0.class) + @NodeChild("a") + static class ImportGuards6 extends ValueNode { + + static boolean staticGuard(int a) { + return a == 1; + } + + @Specialization(guards = "staticGuard") + int f0(int a) { + return a; + } + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/InsertBeforeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/InsertBeforeTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl.test; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; + +public class InsertBeforeTest { + + @NodeChild("a") + static class InsertBefore1Base extends ValueNode { + + boolean g1(int a) { + return a == 1; + } + + boolean g2(int a) { + return a == 2; + } + + @Specialization(guards = "g1") + int f1(int a) { + return a; + } + + @Specialization(guards = "g2") + int f3(int a) { + return a; + } + + } + + @NodeChild("a") + static class InsertBefore1T1 extends InsertBefore1Base { + + @Specialization + int f0(int a) { + return a; + } + + } + + @NodeChild("a") + static class InsertBefore1T2 extends InsertBefore1Base { + + boolean g0(int a) { + return a == 0; + } + + @Specialization(guards = "g0", insertBefore = "f1") + int f0(int a) { + return a; + } + + } + + @NodeChild("a") + static class InsertBefore1T3 extends InsertBefore1Base { + + boolean g0(int a) { + return a == 0; + } + + @Specialization(guards = "g0", insertBefore = "f3") + int f0(int a) { + return a; + } + + } + + @NodeChild("a") + @ExpectError({"Method f3(int) at annotation @Specialization is erroneous: Specialization is not reachable. It is shadowed by f0(int).", + "Method f1(int) at annotation @Specialization is erroneous: Specialization is not reachable. It is shadowed by f0(int)."}) + static class InsertBefore1T4 extends InsertBefore1Base { + + boolean g0(int a) { + return a == 0; + } + + @Specialization(insertBefore = "f1") + int f0(int a) { + return a; + } + + } + + @NodeChild("a") + @ExpectError({"Method f3(int) at annotation @Specialization is erroneous: Specialization is not reachable. It is shadowed by f0(int)."}) + static class InsertBefore1T5 extends InsertBefore1Base { + + boolean g0(int a) { + return a == 0; + } + + @Specialization(insertBefore = "f3") + int f0(int a) { + return a; + } + + } + + @NodeChild("a") + static class InsertBefore1T6_1 extends InsertBefore1Base { + + boolean g0(int a) { + return a == 0; + } + + @Specialization(insertBefore = "f1", guards = "g0") + int f0(int a) { + return a; + } + + } + + @NodeChild("a") + static class InsertBefore1T6_2 extends InsertBefore1T6_1 { + + boolean g(int a) { + return a == 0; + } + + @Specialization(insertBefore = "f0", guards = "g") + int f(int a) { + return a; + } + + } + + @NodeChild("a") + static class InsertBefore1Error1 extends InsertBefore1Base { + + @ExpectError("Specializations can only be inserted before specializations in superclasses.") + @Specialization(insertBefore = "f0") + int f0(int a) { + return a; + } + + } + + @NodeChild("a") + static class InsertBefore1Error2 extends InsertBefore1Base { + + @ExpectError("The referenced specialization 'asdf' could not be found.") + @Specialization(insertBefore = "asdf") + int f0(int a) { + return a; + } + + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl.test; + +import static com.oracle.truffle.api.dsl.test.TestHelper.*; +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.BinaryNodeTest.*; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GlobalFlagGuardFactory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardWithBaseClassFactory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardWithBoxedPrimitiveFactory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardWithObjectFactory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.InvocationGuardFactory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.TestAbstractGuard1Factory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.TestGuardResolve1Factory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.TestGuardResolve2Factory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.TestGuardResolve3Factory; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.*; + +@SuppressWarnings("unused") +public class MethodGuardsTest { + + private static final Object NULL = new Object(); + + @Test + public void testGuardInvocations() { + TestRootNode root = createRoot(InvocationGuardFactory.getInstance()); + + assertEquals(Integer.MAX_VALUE, executeWith(root, Integer.MAX_VALUE - 1, 1)); + assertEquals(1, InvocationGuard.specializedInvocations); + assertEquals(0, InvocationGuard.genericInvocations); + + assertEquals(42, executeWith(root, Integer.MAX_VALUE, 1)); + assertEquals(1, InvocationGuard.specializedInvocations); + assertEquals(1, InvocationGuard.genericInvocations); + } + + @NodeChildren({@NodeChild("value0"), @NodeChild("value1")}) + public abstract static class InvocationGuard extends ValueNode { + + static int specializedInvocations = 0; + static int genericInvocations = 0; + + boolean guard(int value0, int value1) { + return value0 != Integer.MAX_VALUE; + } + + @Specialization(guards = "guard") + int doSpecialized(int value0, int value1) { + specializedInvocations++; + return value0 + value1; + } + + @Fallback + int doGeneric(Object value0, Object value1) { + genericInvocations++; + return 42; // the generic answer to all questions + } + } + + @Test + public void testGuardGlobal() { + TestRootNode root = createRoot(GlobalFlagGuardFactory.getInstance()); + + assertEquals(42, executeWith(root, NULL)); + + GlobalFlagGuard.globalFlag = true; + assertEquals(41, executeWith(root, NULL)); + + GlobalFlagGuard.globalFlag = false; + assertEquals(42, executeWith(root, NULL)); + } + + @NodeChild("expression") + public abstract static class GlobalFlagGuard extends ValueNode { + + static boolean globalFlag = false; + + static boolean globalFlagGuard() { + return globalFlag; + } + + @Specialization(guards = "globalFlagGuard") + int doSpecialized(Object value0) { + return 41; + } + + @Fallback + int doGeneric(Object value0) { + return 42; // the generic answer to all questions + } + } + + @Test + public void testGuardWithBaseClass() { + TestRootNode root = createRoot(GuardWithBaseClassFactory.getInstance()); + + assertEquals(42, executeWith(root, new BExtendsAbstract())); + } + + @NodeChild("expression") + public abstract static class GuardWithBaseClass extends ValueNode { + + boolean baseGuard(Abstract base) { + return true; + } + + @Specialization(guards = "baseGuard") + int doSpecialized(BExtendsAbstract value0) { + return 42; + } + } + + @NodeChild("expression") + public abstract static class GuardWithBaseInterface extends ValueNode { + + boolean baseGuard(CharSequence base) { + return true; + } + + @Specialization(guards = "baseGuard") + @ExpectError("No guard with name 'baseGuard' matched the required signature.%") + int doSpecialized(String value0) { + return 42; + } + } + + @Test + public void testGuardWithPrimitive() { + TestRootNode root = createRoot(GuardWithBoxedPrimitiveFactory.getInstance()); + + assertEquals(42, executeWith(root, 42)); + } + + @NodeChild("expression") + public abstract static class GuardWithBoxedPrimitive extends ValueNode { + + boolean baseGuard(Integer primitive) { + return true; + } + + @Specialization(guards = "baseGuard") + int doSpecialized(int value0) { + return value0; + } + } + + @Test + public void testGuardWithObject() { + TestRootNode root = createRoot(GuardWithObjectFactory.getInstance()); + + assertEquals(42, executeWith(root, 42)); + } + + @NodeChild("expression") + public abstract static class GuardWithObject extends ValueNode { + + boolean baseGuard(Object primitive) { + return true; + } + + @Specialization(guards = "baseGuard") + int doSpecialized(int value0) { + return value0; + } + } + + @Test + public void testGuardResolve1() { + TestRootNode root = createRoot(TestGuardResolve1Factory.getInstance()); + + assertEquals(42, executeWith(root, 42)); + } + + @NodeChild("expression") + public abstract static class TestGuardResolve1 extends ValueNode { + + boolean guard(Object primitive) { + return false; + } + + boolean guard(int primitive) { + return true; + } + + @Specialization(guards = "guard") + int doSpecialized(int value0) { + return value0; + } + } + + @Test + public void testGuardResolve2() { + TestRootNode root = createRoot(TestGuardResolve2Factory.getInstance()); + assertEquals(42, executeWith(root, new BExtendsAbstract())); + } + + @NodeChild("expression") + public abstract static class TestGuardResolve2 extends ValueNode { + + boolean guard(Object primitive) { + return false; + } + + boolean guard(Abstract primitive) { + return true; + } + + @Specialization(guards = "guard") + int doSpecialized(BExtendsAbstract value0) { + return 42; + } + } + + @Test + public void testGuardResolve3() { + TestRootNode root = createRoot(TestGuardResolve3Factory.getInstance()); + + assertEquals(42, executeWith(root, new BExtendsAbstract())); + } + + @NodeChild("expression") + public abstract static class TestGuardResolve3 extends ValueNode { + + boolean guard(Object primitive) { + return false; + } + + boolean guard(Abstract primitive) { + return false; + } + + boolean guard(BExtendsAbstract primitive) { + return true; + } + + @Specialization(guards = "guard") + int doSpecialized(BExtendsAbstract value0) { + return 42; + } + } + + @NodeChild("expression") + public abstract static class TestGuardResolve4 extends ValueNode { + + boolean guard(Abstract primitive) { + return false; + } + + @Specialization(guards = "guard") + int doSpecialized(BExtendsAbstract value0) { + return 42; + } + } + + @NodeChildren({@NodeChild("a"), @NodeChild("b")}) + abstract static class TestGuardResolve5 extends ValueNode { + + @Specialization(guards = "guard") + int add(Interface left, Interface right) { + return 42; + } + + boolean guard(Interface left, Object right) { + return true; + } + } + + @Test + public void testAbstractGuard1() { + TestRootNode root = createRoot(TestAbstractGuard1Factory.getInstance()); + + assertEquals(BExtendsAbstract.INSTANCE, executeWith(root, BExtendsAbstract.INSTANCE)); + assertEquals(CExtendsAbstract.INSTANCE, executeWith(root, CExtendsAbstract.INSTANCE)); + } + + @NodeChild("expression") + public abstract static class TestAbstractGuard1 extends ValueNode { + + boolean guard(Abstract value0) { + return true; + } + + @Specialization(guards = "guard") + BExtendsAbstract do1(BExtendsAbstract value0) { + return value0; + } + + @Specialization(guards = "guard") + CExtendsAbstract do2(CExtendsAbstract value0) { + return value0; + } + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl.test; + +import static com.oracle.truffle.api.dsl.test.TestHelper.*; + +import org.junit.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArguments0Factory; +import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArguments1Factory; +import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsDouble0Factory; +import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsDouble1Factory; +import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsDouble2Factory; +import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsDouble3Factory; +import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsSingle2Factory; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; + +public class MethodGuardsWithArgumentsTest { + + @Test + public void testMArguments0() { + TestRootNode root = createRoot(MArguments0Factory.getInstance()); + Assert.assertEquals(42, executeWith(root)); + } + + abstract static class MArguments0 extends ValueNode { + + static boolean guard() { + return true; + } + + @Specialization(guards = "guard()") + int do1() { + return 42; + } + } + + @Test + public void testMArguments1() { + TestRootNode root = createRoot(MArguments1Factory.getInstance()); + Assert.assertEquals(42, executeWith(root)); + } + + abstract static class MArguments1 extends ValueNode { + + static boolean guard() { + return true; + } + + @Specialization(guards = "guard ()") + int do1() { + return 42; + } + } + + @Test + public void testMArgumentsSingle0() { + TestRootNode root = createRoot(MArguments1Factory.getInstance()); + Assert.assertEquals(42, executeWith(root, 42)); + } + + @NodeChild("a") + abstract static class MArgumentsSingle0 extends ValueNode { + + static boolean guard() { + return true; + } + + @Specialization(guards = "guard()") + int do1(int a) { + return a; + } + } + + @Test + public void testMArgumentsSingle1() { + TestRootNode root = createRoot(MArguments1Factory.getInstance()); + Assert.assertEquals(42, executeWith(root, 42)); + } + + @NodeChild("a") + abstract static class MArgumentsSingle1 extends ValueNode { + + static boolean guard(int a) { + return a == 42; + } + + @Specialization(guards = "guard(a)") + int do1(int a) { + return a; + } + } + + @Test + public void testMArgumentsSingle2() { + TestRootNode root = createRoot(MArgumentsSingle2Factory.getInstance()); + Assert.assertEquals(42, executeWith(root, 42)); + } + + @NodeChild("a") + abstract static class MArgumentsSingle2 extends ValueNode { + + static boolean guard(int a1, int a2) { + return a1 == 42 && a2 == 42; + } + + @Specialization(guards = "guard(a,a)") + int do1(int a) { + return a; + } + } + + @Test + public void testMArgumentsDouble0() { + TestRootNode root = createRoot(MArgumentsDouble0Factory.getInstance()); + Assert.assertEquals(42, executeWith(root, 42, 0)); + } + + @NodeChild("a") + abstract static class MArgumentsDouble0 extends ValueNode { + + static boolean guard(int a1, Object a2) { + return a1 == 42 && a2.equals(new Integer(42)); + } + + @Specialization(guards = "guard(a,a)") + int do1(int a) { + return a; + } + } + + @Test + public void testMArgumentsDouble1() { + TestRootNode root = createRoot(MArgumentsDouble1Factory.getInstance()); + Assert.assertEquals(42, executeWith(root, 42, 41)); + } + + @NodeChildren({@NodeChild("a"), @NodeChild("b")}) + abstract static class MArgumentsDouble1 extends ValueNode { + + static boolean guard(int a1, double a2) { + return a1 == 42 && a2 == 41; + } + + @Specialization(guards = "guard(a,b)") + int do1(int a, @SuppressWarnings("unused") double b) { + return a; + } + } + + @Test + public void testMArgumentsDouble2() { + TestRootNode root = createRoot(MArgumentsDouble2Factory.getInstance()); + Assert.assertEquals(42, executeWith(root, 42, 41.0)); + } + + @NodeChildren({@NodeChild("a"), @NodeChild("b")}) + abstract static class MArgumentsDouble2 extends ValueNode { + + static boolean guard(double a1, int a2) { + return a1 == 41 && a2 == 42; + } + + @Specialization(guards = "guard(b,a)") + int do1(int a, @SuppressWarnings("unused") double b) { + return a; + } + } + + @Test + public void testMArgumentsDouble3() { + TestRootNode root = createRoot(MArgumentsDouble3Factory.getInstance()); + Assert.assertEquals(42, executeWith(root, 42, 41.0)); + } + + @NodeChildren({@NodeChild("a"), @NodeChild("b")}) + abstract static class MArgumentsDouble3 extends ValueNode { + + static boolean guard(Object a1, double a2) { + return new Double(41.0).equals(a1) && a2 == 41; + } + + @Specialization(guards = "guard(b,b)") + int do1(int a, @SuppressWarnings("unused") double b) { + return a; + } + } + + abstract static class MArgumentsError0 extends ValueNode { + + static boolean guard() { + return true; + } + + @ExpectError("No compatible guard with method name 'guard(' found.%") + @Specialization(guards = "guard(") + int do1() { + return 42; + } + } + + abstract static class MArgumentsError1 extends ValueNode { + + static boolean guard() { + return true; + } + + @ExpectError("No compatible guard with method name 'guard)' found.%") + @Specialization(guards = "guard)") + int do1() { + return 42; + } + + } + + abstract static class MArgumentsError2 extends ValueNode { + + static boolean guard() { + return true; + } + + @ExpectError("Guard parameter 'a' for guard 'guard' could not be mapped to a declared child node.") + @Specialization(guards = "guard(a)") + int do1() { + return 42; + } + } + + @NodeChild("b") + abstract static class MArgumentsError3 extends ValueNode { + + static boolean guard() { + return true; + } + + @ExpectError("Guard parameter 'a' for guard 'guard' could not be mapped to a declared child node.") + @Specialization(guards = "guard(a)") + int do1(int b) { + return b; + } + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -45,12 +45,12 @@ return true; } - @Specialization(order = 1, guards = "!guard") + @Specialization(guards = "!guard") int do1() { throw new AssertionError(); } - @Specialization(order = 2) + @Specialization int do2() { return 42; // the generic answer to all questions } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -117,12 +117,12 @@ public abstract String getField(); - @Specialization(order = 1, rewriteOn = RuntimeException.class) + @Specialization(rewriteOn = RuntimeException.class) String alwaysRewrite() { throw new RuntimeException(); } - @Specialization(order = 2) + @Specialization(contains = "alwaysRewrite") String returnField() { return getField(); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -25,11 +25,15 @@ import static com.oracle.truffle.api.dsl.test.TestHelper.*; import static org.junit.Assert.*; +import java.util.*; + import org.junit.*; import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.dsl.test.BinaryNodeTest.BinaryNode; -import com.oracle.truffle.api.dsl.test.PolymorphicTestFactory.Node1Factory; +import com.oracle.truffle.api.dsl.test.PolymorphicTestFactory.Polymorphic1Factory; +import com.oracle.truffle.api.dsl.test.PolymorphicTestFactory.Polymorphic2Factory; +import com.oracle.truffle.api.dsl.test.PolymorphicTestFactory.Polymorphic3Factory; +import com.oracle.truffle.api.dsl.test.TestHelper.ExecutionListener; import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; import com.oracle.truffle.api.nodes.*; @@ -47,103 +51,155 @@ } } + public static void assertNoDuplicates(Node node, Node... ignored) { + assertNoDuplicatesRec(new HashSet<>(Arrays.asList(ignored)), new HashSet>(), node); + } + + private static void assertNoDuplicatesRec(Set ignored, Set> seenClasses, Node current) { + if (!ignored.contains(current)) { + if (seenClasses.contains(current.getClass())) { + Assert.fail(String.format("Multiple occurences of the same class %s. %nTree: %s", current.getClass().getSimpleName(), NodeUtil.printCompactTreeToString(current.getRootNode()))); + } else { + seenClasses.add(current.getClass()); + } + } + + for (Node child : current.getChildren()) { + if (child != null) { + assertNoDuplicatesRec(ignored, seenClasses, child); + } + } + } + @Test - public void testJustSpecialize() { - TestRootNode node = TestHelper.createRoot(Node1Factory.getInstance()); - assertEquals("(int,int)", executeWith(node, 42, 42)); - assertEquals("(boolean,boolean)", executeWith(node, false, false)); - assertEquals("(int,boolean)", executeWith(node, 42, false)); - assertEquals("(boolean,int)", executeWith(node, false, 42)); - assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost()); - assertParent(node.getNode(), node.getNode().getLeft()); - assertParent(node.getNode(), node.getNode().getRight()); + public void testPolymorphic1() { + assertRuns(Polymorphic1Factory.getInstance(), // + array(42, 43, true, false, "a", "b"), // + array(42, 43, true, false, "a", "b"),// + new ExecutionListener() { + public void afterExecution(TestRootNode node, int index, Object value, Object expectedResult, Object actualResult, boolean last) { + Polymorphic1 polymorphic = ((Polymorphic1) node.getNode()); + assertParent(node.getNode(), polymorphic.getA()); + assertNoDuplicates(polymorphic, polymorphic.getA()); + if (index == 0) { + assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost()); + } + } + }); + } + + @NodeChild("a") + abstract static class Polymorphic1 extends ValueNode { + + public abstract ValueNode getA(); + + @Specialization + int add(int a) { + return a; + } + + @Specialization + boolean add(boolean a) { + return a; + } + + @Specialization + String add(String a) { + return a; + } + + @Fallback + String add(Object left) { + throw new AssertionError(left.toString()); + } + } @Test public void testPolymorphic2() { - TestRootNode node = TestHelper.createRoot(Node1Factory.getInstance()); - assertEquals("(int,boolean)", executeWith(node, 42, false)); - assertEquals("(int,int)", executeWith(node, 42, 42)); - assertEquals(NodeCost.POLYMORPHIC, node.getNode().getCost()); - assertParent(node.getNode(), node.getNode().getLeft()); - assertParent(node.getNode(), node.getNode().getRight()); + assertRuns(Polymorphic2Factory.getInstance(), // + array(0, 1, 1, "1", "2", 2, 3), // + array(0, 1, 1, "1", "2", 2, 3),// + new ExecutionListener() { + public void afterExecution(TestRootNode node, int index, Object value, Object expectedResult, Object actualResult, boolean last) { + Polymorphic2 polymorphic = ((Polymorphic2) node.getNode()); + assertParent(node.getNode(), polymorphic.getA()); + assertNoDuplicates(polymorphic, polymorphic.getA()); + if (index == 0) { + assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost()); + } + } + }); + } + + @NodeChild("a") + abstract static class Polymorphic2 extends ValueNode { + + public abstract ValueNode getA(); + + @Specialization + String s2(String a) { + return a; + } + + @Specialization(rewriteOn = RuntimeException.class) + int s0(int a) { + if (a == 1) { + throw new RuntimeException(); + } + return a; + } + + @Specialization + int s1(int a) { + return a; + } + } @Test public void testPolymorphic3() { - TestRootNode node = TestHelper.createRoot(Node1Factory.getInstance()); - assertEquals("(int,boolean)", executeWith(node, 42, false)); - assertEquals("(boolean,boolean)", executeWith(node, true, false)); - assertEquals("(int,int)", executeWith(node, 42, 42)); - assertEquals(NodeCost.POLYMORPHIC, node.getNode().getCost()); - assertParent(node.getNode(), node.getNode().getLeft()); - assertParent(node.getNode(), node.getNode().getRight()); - } - - @Test - public void testGenericLimitReached() { - TestRootNode node = TestHelper.createRoot(Node1Factory.getInstance()); - assertEquals("(boolean,int)", executeWith(node, false, 42)); - assertEquals("(int,boolean)", executeWith(node, 42, false)); - assertEquals("(boolean,boolean)", executeWith(node, true, false)); - assertEquals("(int,int)", executeWith(node, 42, 42)); - assertEquals(NodeCost.MEGAMORPHIC, node.getNode().getCost()); - assertParent(node.getNode(), node.getNode().getLeft()); - assertParent(node.getNode(), node.getNode().getRight()); - } - - @Test - public void testGenericInitial() { - TestRootNode node = TestHelper.createRoot(Node1Factory.getInstance()); - assertEquals("(generic,generic)", executeWith(node, "1", "1")); - assertEquals(NodeCost.MEGAMORPHIC, node.getNode().getCost()); - assertParent(node.getNode(), node.getNode().getLeft()); - assertParent(node.getNode(), node.getNode().getRight()); + assertRuns(Polymorphic3Factory.getInstance(), // + array("0", "1", 1, 1, 2, 2, 3, 3), // + array("0", "1", 1, 1, 2, 2, 3, 3),// + new ExecutionListener() { + public void afterExecution(TestRootNode node, int index, Object value, Object expectedResult, Object actualResult, boolean last) { + Polymorphic3 polymorphic = ((Polymorphic3) node.getNode()); + assertParent(node.getNode(), polymorphic.getA()); + assertNoDuplicates(polymorphic, polymorphic.getA()); + } + }); } - @Test - public void testGenericPolymorphic1() { - TestRootNode node = TestHelper.createRoot(Node1Factory.getInstance()); - assertEquals("(boolean,int)", executeWith(node, false, 42)); - assertEquals("(boolean,boolean)", executeWith(node, false, false)); - assertEquals("(generic,generic)", executeWith(node, "", "")); - assertEquals(NodeCost.MEGAMORPHIC, node.getNode().getCost()); - /* Assertions for bug GRAAL-425 */ - assertParent(node.getNode(), node.getNode().getLeft()); - assertParent(node.getNode(), node.getNode().getRight()); - } + @NodeChild("a") + abstract static class Polymorphic3 extends ValueNode { - @SuppressWarnings("unused") - @PolymorphicLimit(3) - abstract static class Node1 extends BinaryNode { - - public abstract ValueNode getLeft(); + public abstract ValueNode getA(); - public abstract ValueNode getRight(); - - @Specialization(order = 1) - String add(int left, int right) { - return "(int,int)"; + @Specialization + String s2(String a) { + return a; } - @Specialization(order = 2) - String add(boolean left, boolean right) { - return "(boolean,boolean)"; + @Specialization(rewriteOn = RuntimeException.class) + int s0(int a) { + if (a == 1) { + throw new RuntimeException(); + } + return a; } - @Specialization(order = 3) - String add(int left, boolean right) { - return "(int,boolean)"; + @Specialization(rewriteOn = RuntimeException.class) + int s1(int a) { + if (a == 1) { + throw new RuntimeException(); + } + return a; } - @Specialization(order = 4) - String add(boolean left, int right) { - return "(boolean,int)"; - } - - @Generic - String add(Object left, Object right) { - return "(generic,generic)"; + @Specialization + int s2(int a) { + return a; } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java Mon Aug 25 21:15:59 2014 -0700 @@ -29,7 +29,7 @@ import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.dsl.test.BinaryNodeTest.BinaryNode; -import com.oracle.truffle.api.dsl.test.PolymorphicTest2Factory.Node1Factory; +import com.oracle.truffle.api.dsl.test.PolymorphicTest2Factory.Polymorphic1Factory; import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; import com.oracle.truffle.api.nodes.*; @@ -38,7 +38,7 @@ @Test public void testMultipleTypes() { /* Tests the unexpected polymorphic case. */ - TestRootNode node = TestHelper.createRoot(Node1Factory.getInstance()); + TestRootNode node = TestHelper.createRoot(Polymorphic1Factory.getInstance()); assertEquals(21, executeWith(node, false, false)); assertEquals(42, executeWith(node, 21, 21)); assertEquals("(boolean,int)", executeWith(node, false, 42)); @@ -46,8 +46,7 @@ } @SuppressWarnings("unused") - @PolymorphicLimit(3) - abstract static class Node1 extends BinaryNode { + abstract static class Polymorphic1 extends BinaryNode { @Specialization(order = 1) int add(int left, int right) { diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,375 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl.test; + +import java.math.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.*; + +public class ReachabilityTest { + + static class Reachability1 extends ValueNode { + @Specialization + int do2() { + return 2; + } + + @ExpectError("Specialization is not reachable. It is shadowed by do2().") + @Specialization + int do1() { + return 2; + } + } + + @NodeChildren({@NodeChild("a")}) + static class ReachabilityType1 extends ValueNode { + @Specialization + int do2(int a) { + return a; + } + + @ExpectError("Specialization is not reachable. It is shadowed by do2(int).") + @Specialization + int do1(int a) { + return a; + } + } + + @NodeChildren({@NodeChild("a")}) + static class ReachabilityType2 extends ValueNode { + @Specialization + BExtendsAbstract do2(BExtendsAbstract a) { + return a; + } + + @ExpectError("Specialization is not reachable. It is shadowed by do2(BExtendsAbstract).") + @Specialization + BExtendsAbstract do1(BExtendsAbstract a) { + return a; + } + } + + @NodeChildren({@NodeChild("a")}) + static class ReachabilityType3 extends ValueNode { + @Specialization + Abstract do2(Abstract a) { + return a; + } + + @ExpectError("Specialization is not reachable. It is shadowed by do2(Abstract).") + @Specialization + BExtendsAbstract do1(BExtendsAbstract a) { + return a; + } + } + + @NodeChildren({@NodeChild("a")}) + static class ReachabilityType4 extends ValueNode { + + @Specialization + BExtendsAbstract do2(BExtendsAbstract a) { + return a; + } + + @Specialization + Abstract do1(Abstract a) { + return a; + } + + } + + @NodeChildren({@NodeChild("a")}) + static class ReachabilityType5 extends ValueNode { + + @Specialization + double do2(double a) { + return a; + } + + @ExpectError("Specialization is not reachable. It is shadowed by do2(double).") + @Specialization + int do1(int a) { + return a; + } + + } + + @NodeChildren({@NodeChild("a")}) + static class ReachabilityType6 extends ValueNode { + + @Specialization + BigInteger do2(BigInteger a) { + return a; + } + + @ExpectError("Specialization is not reachable. It is shadowed by do2(BigInteger).") + @Specialization + int do1(int a) { + return a; + } + + } + + @NodeChildren({@NodeChild("a")}) + static class ReachabilityType7 extends ValueNode { + + @Specialization + int do2(int a) { + return a; + } + + @Specialization + BigInteger do1(BigInteger a) { + return a; + } + + } + + @NodeChildren({@NodeChild("a")}) + static class ReachabilityType8 extends ValueNode { + + @Specialization + int do2(int a) { + return a; + } + + @Specialization + Object do1(Object a) { + return a; + } + + } + + @NodeChildren({@NodeChild("a")}) + static class ReachabilityType9 extends ValueNode { + + @Specialization + Object do2(Object a) { + return a; + } + + @ExpectError("Specialization is not reachable. It is shadowed by do2(Object).") + @Specialization + int do1(int a) { + return a; + } + } + + static class ReachabilityGuard1 extends ValueNode { + + boolean foo() { + return false; + } + + @Specialization(guards = "foo") + int do2() { + return 1; + } + + @Specialization + int do1() { + return 2; + } + + } + + static class ReachabilityGuard2 extends ValueNode { + + boolean foo() { + return false; + } + + @Specialization + int do2() { + return 2; + } + + @ExpectError("Specialization is not reachable. It is shadowed by do2().") + @Specialization(guards = "foo") + int do1() { + return 1; + } + + } + + static class ReachabilityGuard3 extends ValueNode { + + boolean foo() { + return false; + } + + @Specialization(guards = "foo") + int do2() { + return 1; + } + + @Specialization + int do1() { + return 2; + } + + } + + static class ReachabilityGuard4 extends ValueNode { + + boolean foo() { + return false; + } + + @Specialization(guards = "foo") + int do2() { + return 1; + } + + @ExpectError("Specialization is not reachable. It is shadowed by do2().") + @Specialization(guards = "foo") + int do1() { + return 2; + } + + } + + @NodeAssumptions({"a1"}) + static class ReachabilityAssumption1 extends ValueNode { + + @Specialization(assumptions = "a1") + int do2() { + return 1; + } + + @Specialization + int do1() { + return 2; + } + + } + + @NodeAssumptions({"a1"}) + static class ReachabilityAssumption2 extends ValueNode { + + @Specialization(assumptions = "a1") + int do2() { + return 1; + } + + @ExpectError("Specialization is not reachable. It is shadowed by do2().") + @Specialization(assumptions = "a1") + int do1() { + return 2; + } + + } + + @NodeAssumptions({"a1", "a2"}) + static class ReachabilityAssumption3 extends ValueNode { + + @Specialization(assumptions = {"a1", "a2"}) + int do2() { + return 1; + } + + @Specialization(assumptions = "a1") + int do1() { + return 2; + } + + } + + @NodeAssumptions({"a1", "a2"}) + static class ReachabilityAssumption4 extends ValueNode { + + @Specialization(assumptions = "a1") + int do2() { + return 1; + } + + @Specialization(assumptions = "a2") + int do1() { + return 2; + } + + } + + @NodeAssumptions({"a1", "a2"}) + static class ReachabilityAssumption5 extends ValueNode { + + @Specialization + int do2() { + return 1; + } + + @ExpectError("Specialization is not reachable. It is shadowed by do2().") + @Specialization(assumptions = "a2") + int do1() { + return 2; + } + + } + + @NodeAssumptions({"a1", "a2"}) + static class ReachabilityAssumption6 extends ValueNode { + + @Specialization(assumptions = {"a1"}) + int do2() { + return 1; + } + + @ExpectError("Specialization is not reachable. It is shadowed by do2().") + @Specialization(assumptions = {"a1", "a2"}) + int do1() { + return 2; + } + + } + + static class ReachabilityThrowable1 extends ValueNode { + + @Specialization(rewriteOn = RuntimeException.class) + int do2() throws RuntimeException { + return 1; + } + + @Specialization + int do1() { + return 2; + } + + } + + static class ReachabilityThrowable2 extends ValueNode { + + @Specialization + int do2() { + return 1; + } + + @ExpectError("Specialization is not reachable. It is shadowed by do2().") + @Specialization(rewriteOn = RuntimeException.class) + int do1() throws RuntimeException { + return 2; + } + + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -106,6 +106,26 @@ } + @NodeChildren({@NodeChild("child0"), @NodeChild("child1")}) + @SuppressWarnings("unused") + abstract static class GuardChildNode extends ValueNode { + + @ShortCircuit("child1") + boolean needsChild1(Object a) { + return a.equals(new Integer(42)); + } + + static boolean guard(int a, boolean hasB, int b) { + return false; + } + + @Specialization(guards = "guard") + int doIt(int a, boolean hasB, int b) { + return a + b; + } + + } + @Test public void testVarArgs1() { ArgumentNode arg0 = new ArgumentNode(0); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SlowPathTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SlowPathTest.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.api.dsl.test; - -import org.junit.*; - -import com.oracle.truffle.api.CompilerDirectives.SlowPath; -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.dsl.test.SlowPathTestFactory.SlowPathOnGeneric0Factory; -import com.oracle.truffle.api.dsl.test.SlowPathTestFactory.SlowPathOnGeneric1Factory; -import com.oracle.truffle.api.dsl.test.SlowPathTestFactory.SlowPathOnGeneric2Factory; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; - -/** Tests the generated placement of {@link SlowPath} in generated methods. */ -public class SlowPathTest { - - @Test - public void testSlowPathOnGeneric0() throws NoSuchMethodException, SecurityException { - Node node = SlowPathOnGeneric0Factory.create(null); - Assert.assertNull(node.getClass().getSuperclass().getDeclaredMethod("executeGeneric0", VirtualFrame.class, Object.class).getAnnotation(SlowPath.class)); - } - - @NodeChild - abstract static class SlowPathOnGeneric0 extends ValueNode { - - @Specialization - @SuppressWarnings("unused") - Object doObject0(VirtualFrame frame, int value0) { - throw new AssertionError(); - } - - } - - @Test - public void testSlowPathOnGeneric1() throws NoSuchMethodException, SecurityException { - Node node = SlowPathOnGeneric1Factory.create(null); - Assert.assertNotNull(node.getClass().getSuperclass().getDeclaredMethod("executeGeneric0", Object.class).getAnnotation(SlowPath.class)); - } - - @NodeChild - abstract static class SlowPathOnGeneric1 extends ValueNode { - - @Specialization - @SuppressWarnings("unused") - Object doObject0(int value0) { - throw new AssertionError(); - } - - } - - @Test - public void testSlowPathOnGeneric2() throws NoSuchMethodException, SecurityException { - Node node = SlowPathOnGeneric2Factory.create(null); - Assert.assertNull(node.getClass().getSuperclass().getDeclaredMethod("executeGeneric0", VirtualFrame.class, Object.class).getAnnotation(SlowPath.class)); - } - - @NodeChild - abstract static class SlowPathOnGeneric2 extends ValueNode { - - @Specialization(order = 0) - @SuppressWarnings("unused") - Object doObject0(int value0) { - throw new AssertionError(); - } - - @Specialization(order = 1) - @SuppressWarnings("unused") - Object doObject1(VirtualFrame frame, String value0) { - throw new AssertionError(); - } - - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SourceSectionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SourceSectionTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl.test; + +import static com.oracle.truffle.api.dsl.test.TestHelper.*; +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import org.junit.experimental.theories.*; +import org.junit.runner.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.SourceSectionTestFactory.SourceSection0Factory; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; + +@RunWith(Theories.class) +public class SourceSectionTest { + + @DataPoints public static final int[] data = new int[]{1, 2, 3, 4}; + + @Theory + public void testSourceSections(int value0, int value1, int value2) { + TestRootNode root = createRoot(SourceSection0Factory.getInstance()); + SourceSection section = new NullSourceSection("a", "b"); + root.getNode().assignSourceSection(section); + expectSourceSection(root.getNode(), section); + assertThat((int) executeWith(root, value0), is(value0)); + expectSourceSection(root.getNode(), section); + assertThat((int) executeWith(root, value1), is(value1)); + expectSourceSection(root.getNode(), section); + assertThat((int) executeWith(root, value2), is(value2)); + expectSourceSection(root.getNode(), section); + } + + private void expectSourceSection(Node root, SourceSection section) { + assertThat(root.getSourceSection(), is(sameInstance(section))); + for (Node child : root.getChildren()) { + if (child instanceof ArgumentNode) { + continue; + } + if (child != null) { + expectSourceSection(child, section); + } + } + } + + @NodeChild("a") + static class SourceSection0 extends ValueNode { + + boolean isOne(int a) { + return a == 1; + } + + boolean isTwo(int a) { + return a == 2; + } + + boolean isThree(int a) { + return a == 3; + } + + @Specialization(guards = "isOne") + int do1(int a) { + return a; + } + + @Specialization(guards = "isTwo") + int do2(int a) { + return a; + } + + @Specialization(guards = "isThree") + int do3(int a) { + return a; + } + + @Fallback + Object do4(Object a) { + return a; // the generic answer to all questions + } + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl.test; + +import static com.oracle.truffle.api.dsl.test.TestHelper.*; + +import org.junit.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest0Factory; +import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest1Factory; +import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest2Factory; +import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest3Factory; +import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest4Factory; +import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest5Factory; +import com.oracle.truffle.api.dsl.test.TestHelper.ExecutionListener; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; + +public class SpecializationFallthroughTest { + + @Test + public void testFallthrough0() { + assertRuns(FallthroughTest0Factory.getInstance(), // + array(0, 0, 1, 2), // + array(0, 0, 1, 2),// + new ExecutionListener() { + public void afterExecution(TestRootNode node, int index, Object value, Object expectedResult, Object actualResult, boolean last) { + if (!last) { + return; + } + if (FallthroughTest0.fallthroughCount > 1) { + Assert.fail("The fallthrough case must never be triggered twice. Therfore count must be <= 1, but is not."); + } + } + }); + } + + @NodeChildren({@NodeChild("a")}) + static class FallthroughTest0 extends ValueNode { + + static int fallthroughCount = 0; + + public FallthroughTest0() { + fallthroughCount = 0; + } + + @Specialization(rewriteOn = ArithmeticException.class) + int do1(int a) throws ArithmeticException { + if (a == 0) { + fallthroughCount++; + throw new ArithmeticException(); + } + return a; + } + + @Fallback + Object doFallback(Object a) { + return a; + } + } + + /* + * Tests that the fall through is never triggered twice for monomorphic cases. + */ + @Test + public void testFallthrough1() { + assertRuns(FallthroughTest1Factory.getInstance(), // + array(0, 0, 0, 1, 2), // + array(0, 0, 0, 1, 2),// + new ExecutionListener() { + public void afterExecution(TestRootNode node, int index, Object value, Object expectedResult, Object actualResult, boolean last) { + if (!last) { + return; + } + if (FallthroughTest1.fallthroughCount > 1) { + Assert.fail("The fallthrough case must never be triggered twice. Therfore count must be <= 1, but is not."); + } + } + }); + } + + /* TODO assert falltrough do1 before do2 */ + @NodeChildren({@NodeChild("a")}) + static class FallthroughTest1 extends ValueNode { + + static int fallthroughCount; + + public FallthroughTest1() { + fallthroughCount = 0; + } + + @Specialization(rewriteOn = ArithmeticException.class) + int do1(int a) throws ArithmeticException { + if (a == 0) { + fallthroughCount++; + throw new ArithmeticException(); + } + return a; + } + + @Specialization + int do2(int a) { + return a; + } + + } + + /* + * Tests that the fall through is never triggered twice with two falltrhoughs in one operation. + */ + @Test + public void testFallthrough2() { + assertRuns(FallthroughTest2Factory.getInstance(), // + array(0, 0, 1, 1, 2, 2), // + array(0, 0, 1, 1, 2, 2),// + new ExecutionListener() { + public void afterExecution(TestRootNode node, int index, Object value, Object expectedResult, Object actualResult, boolean last) { + if (!last) { + return; + } + if (FallthroughTest2.fallthrough1 > 1) { + Assert.fail(); + } + if (FallthroughTest2.fallthrough2 > 1) { + Assert.fail(); + } + FallthroughTest2.fallthrough1 = 0; + FallthroughTest2.fallthrough2 = 0; + } + }); + } + + @NodeChildren({@NodeChild("a")}) + static class FallthroughTest2 extends ValueNode { + + static int fallthrough1; + static int fallthrough2; + + @Specialization(order = 1, rewriteOn = ArithmeticException.class) + int do1(int a) throws ArithmeticException { + if (a == 0) { + fallthrough1++; + throw new ArithmeticException(); + } + return a; + } + + @Specialization(order = 2, rewriteOn = ArithmeticException.class) + int do2(int a) throws ArithmeticException { + if (a == 1) { + fallthrough2++; + throw new ArithmeticException(); + } + return a; + } + + @Specialization + int do3(int a) { + return a; + } + } + + /* + * Tests that the fall through is never triggered twice. In this case mixed fallthrough with + * normal specializations. + */ + @Test + public void testFallthrough3() { + assertRuns(FallthroughTest3Factory.getInstance(), // + array(0, 0, 1, 1, 2, 2), // + array(0, 0, 1, 1, 2, 2),// + new ExecutionListener() { + public void afterExecution(TestRootNode node, int index, Object value, Object expectedResult, Object actualResult, boolean last) { + if (!last) { + return; + } + if (FallthroughTest3.fallthrough1 > 1) { + Assert.fail(String.valueOf(FallthroughTest3.fallthrough1)); + } + FallthroughTest3.fallthrough1 = 0; + } + }); + } + + @NodeChildren({@NodeChild("a")}) + static class FallthroughTest3 extends ValueNode { + + static int fallthrough1; + + boolean guard0(int a) { + return a == 1; + } + + @Specialization(guards = "guard0") + int do2(int a) { + return a; + } + + @Specialization(rewriteOn = ArithmeticException.class) + int do1(int a) throws ArithmeticException { + if (a == 0) { + fallthrough1++; + throw new ArithmeticException(); + } + return a; + } + + @Specialization + int do3(int a) { + return a; + } + + } + + @Test + public void testFallthrough4() { + assertRuns(FallthroughTest4Factory.getInstance(), // + array(0, 0, 1, 1, 2, 2), // + array(0, 0, 1, 1, 2, 2),// + new ExecutionListener() { + public void afterExecution(TestRootNode node, int index, Object value, Object expectedResult, Object actualResult, boolean last) { + if (!last) { + return; + } + if (FallthroughTest4.fallthrough1 > 1) { + Assert.fail(String.valueOf(FallthroughTest4.fallthrough1)); + } + if (FallthroughTest4.fallthrough2 > 1) { + Assert.fail(String.valueOf(FallthroughTest4.fallthrough1)); + } + FallthroughTest4.fallthrough1 = 0; + FallthroughTest4.fallthrough2 = 0; + } + }); + } + + @NodeChildren({@NodeChild("a")}) + static class FallthroughTest4 extends ValueNode { + + static int fallthrough1; + static int fallthrough2; + + @Specialization(order = 1, rewriteOn = ArithmeticException.class) + int do1(int a) throws ArithmeticException { + if (a == 0) { + fallthrough1++; + throw new ArithmeticException(); + } + return a; + } + + @Specialization(order = 2, rewriteOn = ArithmeticException.class) + int do2(int a) throws ArithmeticException { + if (a == 1) { + fallthrough2++; + throw new ArithmeticException(); + } + return a; + } + + @Specialization + int do3(int a) { + return a; + } + + } + + @Test + public void testFallthrough5() { + assertRuns(FallthroughTest5Factory.getInstance(), // + array(0, 0, 1, 1, 2, 2), // + array(0, 0, 1, 1, 2, 2),// + new ExecutionListener() { + public void afterExecution(TestRootNode node, int index, Object value, Object expectedResult, Object actualResult, boolean last) { + if (!last) { + return; + } + if (FallthroughTest5.fallthrough1 > 1) { + Assert.fail(String.valueOf(FallthroughTest5.fallthrough1)); + } + FallthroughTest5.fallthrough1 = 0; + } + }); + } + + @NodeChildren({@NodeChild("a")}) + static class FallthroughTest5 extends ValueNode { + + static int fallthrough1; + + @Specialization(guards = "isDo1", rewriteOn = ArithmeticException.class) + int do1(int a) throws ArithmeticException { + if (a == 0) { + fallthrough1++; + throw new ArithmeticException(); + } + return a; + } + + protected static boolean isDo1(int a) { + return a == 0 || a == 1; + } + + @Specialization(guards = "isDo1") + int do2(int a) { + return a; + } + + @Specialization + int do3(int a) { + return a; + } + + } + + @NodeChildren({@NodeChild("a")}) + static class FallthroughTest6 extends ValueNode { + + static int fallthrough1; + static int fallthrough2; + static int fallthrough3; + static int fallthrough4; + + @Specialization(order = 1, rewriteOn = ArithmeticException.class) + int do4(int a) throws ArithmeticException { + return a; + } + + @Specialization(order = 2, rewriteOn = ArithmeticException.class) + int do2(int a) throws ArithmeticException { + return a; + } + + @Specialization(order = 3, rewriteOn = ArithmeticException.class) + int do3(int a) throws ArithmeticException { + return a; + } + + @Specialization(order = 4, rewriteOn = ArithmeticException.class) + int do1(int a) throws ArithmeticException { + return a; + } + + @Specialization + double do5(double a) { + return a; + } + + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -48,7 +48,7 @@ MockAssumption a2 = new MockAssumption(false); MockAssumption a3 = new MockAssumption(true); - TestRootNode root = TestHelper.createGenericRoot(TestGroupingFactory.getInstance(), a1, a2, a3); + TestRootNode root = TestHelper.createRoot(TestGroupingFactory.getInstance(), a1, a2, a3); SimpleTypes.intCast = 0; SimpleTypes.intCheck = 0; @@ -59,29 +59,29 @@ TestGrouping.true3 = 0; Assert.assertEquals(42, TestHelper.executeWith(root, 21, 21)); - Assert.assertEquals(1, TestGrouping.true1); - Assert.assertEquals(1, TestGrouping.false1); - Assert.assertEquals(1, TestGrouping.true2); - Assert.assertEquals(1, TestGrouping.false2); - Assert.assertEquals(1, TestGrouping.true3); - Assert.assertEquals(2, SimpleTypes.intCheck); - Assert.assertEquals(2, SimpleTypes.intCast); - Assert.assertEquals(1, a1.checked); - Assert.assertEquals(1, a2.checked); - Assert.assertEquals(1, a3.checked); + Assert.assertEquals(4, TestGrouping.true1); + Assert.assertEquals(0, TestGrouping.false1); + Assert.assertEquals(4, TestGrouping.true2); + Assert.assertEquals(5, TestGrouping.false2); + Assert.assertEquals(5, TestGrouping.true3); + Assert.assertEquals(8, SimpleTypes.intCheck); + Assert.assertEquals(8, SimpleTypes.intCast); + Assert.assertEquals(4, a1.checked); + Assert.assertEquals(0, a2.checked); + Assert.assertEquals(4, a3.checked); Assert.assertEquals(42, TestHelper.executeWith(root, 21, 21)); - Assert.assertEquals(2, TestGrouping.true1); - Assert.assertEquals(2, TestGrouping.false1); - Assert.assertEquals(2, TestGrouping.true2); - Assert.assertEquals(2, TestGrouping.false2); - Assert.assertEquals(2, TestGrouping.true3); + Assert.assertEquals(5, TestGrouping.true1); + Assert.assertEquals(0, TestGrouping.false1); + Assert.assertEquals(5, TestGrouping.true2); + Assert.assertEquals(6, TestGrouping.false2); + Assert.assertEquals(6, TestGrouping.true3); - Assert.assertEquals(2, a1.checked); - Assert.assertEquals(2, a2.checked); - Assert.assertEquals(2, a3.checked); - Assert.assertEquals(4, SimpleTypes.intCheck); - Assert.assertEquals(4, SimpleTypes.intCast); + Assert.assertEquals(5, a1.checked); + Assert.assertEquals(0, a2.checked); + Assert.assertEquals(5, a3.checked); + Assert.assertEquals(8, SimpleTypes.intCheck); + Assert.assertEquals(8, SimpleTypes.intCast); } @@ -121,39 +121,39 @@ return true; } - @Specialization(order = 1) + @Specialization public int fail(int value1, String value2) { throw new AssertionError(); } - @Specialization(order = 2, guards = {"true1", "false1"}) - public int fail1(int value1, int value2) { - throw new AssertionError(); - } - - @Specialization(order = 3, guards = {"true1", "true2"}, assumptions = {"a1", "a2"}) - public int fail2(int value1, int value2) { - throw new AssertionError(); - } - - @Specialization(order = 4, guards = {"true1", "true2"}, assumptions = {"a1", "a3"}, rewriteOn = RuntimeException.class) + @Specialization(guards = {"true1", "true2", "!false2", "true3"}, assumptions = {"a1", "a3"}, rewriteOn = RuntimeException.class) public int throwRewrite(int value1, int value2) { throw new RuntimeException(); } - @Specialization(order = 5, guards = {"true1", "true2", "false2"}, assumptions = {"a1", "a3"}) + @Specialization(guards = {"true1", "true2", "!false2", "true3"}, contains = "throwRewrite", assumptions = {"a1", "a3"}) + public int success(int value1, int value2) { + return value1 + value2; + } + + @Specialization(guards = {"true1", "true2", "!false2", "!true3"}, assumptions = {"a1", "a3"}) + public int fail5(int value1, int value2) { + throw new AssertionError(); + } + + @Specialization(guards = {"true1", "true2", "false2"}, assumptions = {"a1", "a3"}) public int fail4(int value1, int value2) { throw new AssertionError(); } - @Specialization(order = 6, guards = {"true1", "true2", "!false2", "!true3"}, assumptions = {"a1", "a3"}) - public int fail5(int value1, int value2) { + @Specialization(guards = {"true1", "true2"}, assumptions = {"a1", "a3"}) + public int fail2break(int value1, int value2) { throw new AssertionError(); } - @Specialization(order = 7, guards = {"true1", "true2", "!false2", "true3"}, assumptions = {"a1", "a3"}) - public int success(int value1, int value2) { - return value1 + value2; + @Specialization(guards = {"true1", "false1"}) + public int fail1(int value1, int value2) { + throw new AssertionError(); } } @@ -168,18 +168,18 @@ @NodeChild(value = "genericChild", type = GenericInt.class) public abstract static class TestElseConnectionBug1 extends ValueNode { - @Specialization(order = 1, rewriteOn = {SlowPathException.class}, guards = "isInitialized") - public int doInteger(int value) throws SlowPathException { + @Specialization(rewriteOn = {SlowPathException.class}, guards = "isInitialized") + public int do1(int value) throws SlowPathException { throw new SlowPathException(); } - @Specialization(order = 3, guards = "isInitialized") - public int doObject(int value) { + @Specialization(contains = "do1", guards = "isInitialized") + public int do2(int value) { return value == 42 ? value : 0; } - @Specialization(order = 4, guards = "!isInitialized") - public Object doUninitialized(int value) { + @Specialization(guards = "!isInitialized") + public Object do3(int value) { throw new AssertionError(); } @@ -204,25 +204,25 @@ @Test public void testElseConnectionBug2() { - TestHelper.assertRuns(TestElseConnectionBug2Factory.getInstance(), 42, 42); + TestHelper.assertRuns(TestElseConnectionBug2Factory.getInstance(), new Object[]{42}, new Object[]{42}); } @SuppressWarnings("unused") @NodeChild public abstract static class TestElseConnectionBug2 extends ValueNode { - @Specialization(order = 2, guards = "guard0") - public int doGuard0(int value) { + @Specialization(guards = "guard0") + public int do1(int value) { throw new AssertionError(); } - @Specialization(order = 3, guards = "guard1") - public int doGuard1(int value) { + @Specialization(guards = "guard1") + public int do2(int value) { throw new AssertionError(); } - @Specialization(order = 4, guards = "!guard0") - public int doUninitialized(int value) { + @Specialization(guards = "!guard0") + public int do3(int value) { return value; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java Mon Aug 25 21:15:59 2014 -0700 @@ -98,7 +98,7 @@ return createCallTarget(node).call(values); } - static Object array(Object... val) { + static Object[] array(Object... val) { return val; } @@ -138,29 +138,71 @@ return output; } + static void assertRuns(NodeFactory factory, Object[] testValues, Object[] result) { + assertRuns(factory, testValues, result, null); + } + /* Methods tests all test values in combinational order. */ - static void assertRuns(NodeFactory factory, Object result, Object... testValues) { + static void assertRuns(NodeFactory factory, Object[] testValues, Object[] result, ExecutionListener listener) { // test each run by its own. for (int i = 0; i < testValues.length; i++) { - assertValue(createRoot(factory), result, testValues); + assertValue(createRoot(factory), 0, testValues[i], result[i], listener, true); } // test all combinations of the test values - List> permuts = permutations(Arrays.asList(testValues)); + List testValuesList = Arrays.asList(testValues); + List> permuts = permutations(testValuesList); for (List list : permuts) { TestRootNode root = createRoot(factory); + int index = 0; for (Object object : list) { - assertValue(root, result, object); + assertValue(root, index, object, result[testValuesList.indexOf(object)], listener, index == list.size() - 1); + index++; } } } - static void assertValue(TestRootNode root, Object result, Object testValues) { - if (testValues instanceof Object[]) { - assertEquals(result, executeWith(root, (Object[]) testValues)); + static void assertValue(TestRootNode root, int index, Object value, Object result, ExecutionListener listener, boolean last) { + Object actualResult = null; + if (result instanceof Class && Throwable.class.isAssignableFrom((Class) result)) { + try { + if (value instanceof Object[]) { + actualResult = executeWith(root, (Object[]) value); + } else { + actualResult = executeWith(root, value); + } + fail(String.format("Exception %s expected but not occured.", result.getClass())); + } catch (Throwable e) { + actualResult = e; + if (!e.getClass().isAssignableFrom(((Class) result))) { + e.printStackTrace(); + fail(String.format("Incompatible exception class thrown. Expected %s but was %s.", result.toString(), e.getClass())); + } + } + } else if (value instanceof Object[]) { + actualResult = executeWith(root, (Object[]) value); + assertEquals(result, actualResult); } else { - assertEquals(result, executeWith(root, testValues)); + actualResult = executeWith(root, value); + assertEquals(result, actualResult); + } + if (listener != null) { + listener.afterExecution(root, index, value, result, actualResult, last); } } + public static final class LogListener implements ExecutionListener { + + public void afterExecution(TestRootNode node, int index, Object value, Object expectedResult, Object actualResult, boolean last) { + System.out.printf("Run %3d Node:%-20s Parameters: %10s Expected: %10s Result %10s%n", index, node.getNode().getClass().getSimpleName(), value, expectedResult, actualResult); + } + + } + + interface ExecutionListener { + + void afterExecution(TestRootNode node, int index, Object value, Object expectedResult, Object actualResult, boolean last); + + } + } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,6 +22,8 @@ */ package com.oracle.truffle.api.dsl.test; +import java.math.*; + import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; @@ -29,7 +31,8 @@ public class TypeSystemTest { - @TypeSystem({int.class, boolean.class, String.class, CallTarget.class, BExtendsAbstract.class, CExtendsAbstract.class, Abstract.class, Object[].class}) + @TypeSystem({int.class, double.class, boolean.class, BigInteger.class, String.class, CallTarget.class, BExtendsAbstract.class, CExtendsAbstract.class, Abstract.class, Interface.class, + Object[].class}) static class SimpleTypes { static int intCheck; @@ -47,10 +50,20 @@ return (int) value; } + @ImplicitCast + public double castDouble(int value) { + return value; + } + + @ImplicitCast + public BigInteger castBigInteger(int value) { + return BigInteger.valueOf(value); + } + } @TypeSystemReference(SimpleTypes.class) - public abstract static class ValueNode extends Node { + public static class ValueNode extends Node { public ValueNode() { super(null); @@ -72,6 +85,10 @@ return SimpleTypesGen.SIMPLETYPES.expectObjectArray(execute(frame)); } + public BigInteger executeBigInteger(VirtualFrame frame) throws UnexpectedResultException { + return SimpleTypesGen.SIMPLETYPES.expectBigInteger(execute(frame)); + } + public BExtendsAbstract executeBExtendsAbstract(VirtualFrame frame) throws UnexpectedResultException { return SimpleTypesGen.SIMPLETYPES.expectBExtendsAbstract(execute(frame)); } @@ -80,7 +97,21 @@ return SimpleTypesGen.SIMPLETYPES.expectCExtendsAbstract(execute(frame)); } - public abstract Object execute(VirtualFrame frame); + public Abstract executeAbstract(VirtualFrame frame) throws UnexpectedResultException { + return SimpleTypesGen.SIMPLETYPES.expectAbstract(execute(frame)); + } + + public double executeDouble(VirtualFrame frame) throws UnexpectedResultException { + return SimpleTypesGen.SIMPLETYPES.expectDouble(execute(frame)); + } + + public Interface executeInterface(VirtualFrame frame) throws UnexpectedResultException { + return SimpleTypesGen.SIMPLETYPES.expectInterface(execute(frame)); + } + + public Object execute(@SuppressWarnings("unused") VirtualFrame frame) { + throw new UnsupportedOperationException(); + } @Override public ValueNode copy() { @@ -158,4 +189,6 @@ static final CExtendsAbstract INSTANCE = new CExtendsAbstract(); } + interface Interface { + } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Fallback.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Fallback.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl; + +import java.lang.annotation.*; + +/** + * + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD}) +public @interface Fallback { + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Generic.java --- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Generic.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.api.dsl; - -import java.lang.annotation.*; - -/** - * - */ -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.METHOD}) -public @interface Generic { - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Implies.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Implies.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl; + +import java.lang.annotation.*; + +/* + * Experimental API. + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD}) +public @interface Implies { + + String[] value(); + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ImportGuards.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ImportGuards.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl; + +import java.lang.annotation.*; + +/** + * Imports all public static methods usable as guards for {@link Specialization} annotations to the + * current class. Using this annotation common guards can be shared across nodes. Imported guards + * are derived from super classes. Guards declared in the node type hierarchy are always preferred + * to imported guards. Imported guards for a more concrete type are preferred to guards imported in + * the base class. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface ImportGuards { + + Class[] value(); + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/PolymorphicLimit.java --- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/PolymorphicLimit.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.api.dsl; - -import java.lang.annotation.*; - -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.TYPE}) -public @interface PolymorphicLimit { - - /** Specifies the maximum polymorphic cache depth until it falls back to the generic case. */ - int value(); - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java --- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java Mon Aug 25 21:15:59 2014 -0700 @@ -30,12 +30,36 @@ @Target({ElementType.METHOD}) public @interface Specialization { - int DEFAULT_ORDER = -1; + /** + * @deprecated do not use anymore. Will get removed in the next release. + */ + @Deprecated int DEFAULT_ORDER = -1; + /** + * The order has no effect anymore. The declaration order specialization methods is used + * instead. + * + * @deprecated use declaration order instead. Will get removed in the next release. + */ + @Deprecated int order() default DEFAULT_ORDER; + /** + * Inserts this and all specializations that are declared after this specialization before a + * specialization in the superclass. By default all specializations of the subclass are appended + * to the specializations of the superclass. + */ + String insertBefore() default ""; + Class[] rewriteOn() default {}; + /** + * The contains attribute declares all specializations that are contained by this + * specialization. A containing specialization must be strictly generic as the contained + * specialization. + */ + String[] contains() default {}; + String[] guards() default {}; /** diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeCheck.java --- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeCheck.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeCheck.java Mon Aug 25 21:15:59 2014 -0700 @@ -57,17 +57,17 @@ * * {@literal @}TypeSystem(types = {int.class, BigInteger.class, String.class}, nodeBaseClass = TypedNode.class) * public abstract class Types { - * + * * {@literal @}TypeCheck * public boolean isBigInteger(Object value) { * return value instanceof Integer || value instanceof BigInteger; * } - * + * * {@literal @}TypeCheck * public boolean isBigInteger(int value) { * return true; * } - * + * * } * * diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLMetadata.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLMetadata.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl.internal; + +/** + * This is NOT public API. Do not use directly. This code may change without notice. + */ +public final class DSLMetadata { + + public static final Class[] EMPTY_CLASS_ARRAY = new Class[]{}; + public static final DSLMetadata NONE = new DSLMetadata(null, EMPTY_CLASS_ARRAY, EMPTY_CLASS_ARRAY, EMPTY_CLASS_ARRAY, 0, 0); + + private final Class specializationClass; + private final Class[] includes; + private final Class[] excludedBy; + private final Class[] specializedTypes; + + private final int costs; + private final int order; + + public DSLMetadata(Class specializationClass, Class[] includes, Class[] excludes, Class[] specializedTypes, int costs, int order) { + this.specializationClass = specializationClass; + this.includes = includes; + this.excludedBy = excludes; + this.specializedTypes = specializedTypes; + this.costs = costs; + this.order = order; + } + + public Class getSpecializationClass() { + return specializationClass; + } + + public Class[] getSpecializedTypes() { + return specializedTypes; + } + + Class[] getIncludes() { + return includes; + } + + Class[] getExcludedBy() { + return excludedBy; + } + + int getCosts() { + return costs; + } + + int getOrder() { + return order; + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl.internal; + +import com.oracle.truffle.api.nodes.*; + +/** + * This is NOT public API. Do not use directly. This code may change without notice. + */ +public interface DSLNode { + + DSLMetadata getMetadata0(); + + void adoptChildren0(Node other, Node next); + + void updateTypes0(Class[] types); + + Node getNext0(); + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLShare.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLShare.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl.internal; + +import java.util.*; + +import com.oracle.truffle.api.nodes.*; + +/** Contains utility classes shared across generated DSLNode implementations. */ +public class DSLShare { + + public static boolean isExcluded(Node currentNode, DSLMetadata otherMetadata) { + assert otherMetadata.getExcludedBy().length > 0 : "At least one exclude must be defined for isIncluded."; + Node cur = findRoot(currentNode); + while (cur != null) { + Class curClass = cur.getClass(); + if (curClass == otherMetadata.getSpecializationClass()) { + return true; + } else if (containsClass(otherMetadata.getExcludedBy(), cur)) { + return true; + } + cur = getNext(cur); + } + return false; + } + + private static boolean includes(Node oldNode, DSLNode newNode) { + return containsClass(newNode.getMetadata0().getIncludes(), oldNode); + } + + public static T rewrite(Node thisNode, T newNode, String message) { + assert newNode != null; + if (getNext(thisNode) != null || getPrevious(thisNode) != null) { + // already polymorphic -> append + return appendPolymorphic(findUninitialized(thisNode), newNode); + } else if (includes(thisNode, newNode)) { + // included -> remains monomorphic + newNode.adoptChildren0(thisNode, null); + return thisNode.replace(newNode, message); + } else { + // goto polymorphic + return null; + } + } + + @SuppressWarnings("unchecked") + public static T findRoot(T node) { + Node prev = node; + Node cur; + do { + cur = prev; + prev = getPrevious(cur); + } while (prev != null); + return (T) cur; + } + + private static Node findUninitialized(Node node) { + Node next = node; + Node cur; + do { + cur = next; + next = getNext(cur); + } while (next != null); + return cur; + } + + public static T rewriteUninitialized(Node uninitialized, T newNode) { + Node prev = getPrevious(uninitialized); + if (prev == null) { + newNode.adoptChildren0(uninitialized, null); + return uninitialized.replace(newNode, "Uninitialized monomorphic"); + } else { + return appendPolymorphic(uninitialized, newNode); + } + } + + public static T rewriteToPolymorphic(Node oldNode, DSLNode uninitializedDSL, T polymorphic, DSLNode currentCopy, DSLNode newNodeDSL, String message) { + assert getNext(oldNode) == null; + assert getPrevious(oldNode) == null; + assert newNodeDSL != null; + + Node uninitialized = (Node) uninitializedDSL; + Node newNode = (Node) newNodeDSL; + polymorphic.adoptChildren0(oldNode, (Node) currentCopy); + + updateSourceSection(oldNode, uninitialized); + // new specialization + updateSourceSection(oldNode, newNode); + newNodeDSL.adoptChildren0(null, uninitialized); + currentCopy.adoptChildren0(null, newNode); + + oldNode.replace(polymorphic, message); + + assert polymorphic.getNext0() == currentCopy; + assert newNode != null ? currentCopy.getNext0() == newNode : currentCopy.getNext0() == uninitialized; + assert uninitializedDSL.getNext0() == null; + return polymorphic; + } + + private static void updateSourceSection(Node oldNode, Node newNode) { + if (newNode.getSourceSection() == null) { + newNode.assignSourceSection(oldNode.getSourceSection()); + } + } + + private static Class[] mergeTypes(DSLNode node, Class[] types) { + Class[] specializedTypes = node.getMetadata0().getSpecializedTypes(); + if (specializedTypes.length == 0) { + return null; + } else if (types == null) { + return Arrays.copyOf(specializedTypes, specializedTypes.length); + } else { + for (int i = 0; i < specializedTypes.length; i++) { + if (specializedTypes[i] != types[i]) { + types[i] = Object.class; + } + } + return types; + } + } + + private static T appendPolymorphic(Node uninitialized, T newNode) { + Class[] includes = newNode.getMetadata0().getIncludes(); + Node cur = getPrevious(uninitialized); + Node prev = uninitialized; + int depth = 0; + Class[] types = null; + while (cur != null) { + if (containsClass(includes, cur)) { + cur.replace(prev, "Included in other specialization"); + cur = prev; + } else { + depth++; + types = mergeTypes((DSLNode) cur, types); + } + prev = cur; + cur = getPrevious(cur); + } + assert prev.getCost() == NodeCost.POLYMORPHIC; + + updateSourceSection(prev, newNode); + if (depth <= 1) { + newNode.adoptChildren0(prev, null); + return prev.replace(newNode, "Polymorphic to monomorphic."); + } else { + newNode.adoptChildren0(null, uninitialized); + ((DSLNode) prev).updateTypes0(mergeTypes(newNode, types)); + return uninitialized.replace(newNode, "Appended polymorphic"); + } + } + + private static boolean containsClass(Class[] classList, Node node) { + Class nodeClass = node.getClass(); + for (Class toCheck : classList) { + if (nodeClass == toCheck) { + if (node.getCost() == NodeCost.UNINITIALIZED) { + /* + * In case a specialization is excluded by the fallback specialization the + * uninitialized class is used as exclusion class. Because the fallback field in + * the uninitialized specialization is not accessible we use the costs to check + * if the fallback was reached or not. In case the fallback was reached in the + * uninitialized version the cost is MONOMORPHIC, otherwise it is UNINITIALIZED. + */ + continue; + } + return true; + } + } + return false; + } + + private static Node getNext(Node node) { + return ((DSLNode) node).getNext0(); + } + + private static Node getPrevious(Node node) { + Node parent = node.getParent(); + if (parent instanceof DSLNode && getNext(parent) == node) { + return parent; + } else { + return null; + } + } + +} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/NodeFactoryBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/NodeFactoryBase.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl.internal; + +import java.util.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.nodes.*; + +/** + * This is NOT public API. Do not use directly. This code may change without notice. + */ +public abstract class NodeFactoryBase implements NodeFactory { + + private final Class nodeClass; + private final Class[][] nodeSignatures; + private final Class[] executionSignatures; + + @SuppressWarnings("unchecked") + public NodeFactoryBase(Class nodeClass, Class[] executionSignatures, Class[][] nodeSignatures) { + this.nodeClass = nodeClass; + this.nodeSignatures = nodeSignatures; + this.executionSignatures = (Class[]) executionSignatures; + } + + public abstract T createNode(Object... arguments); + + public final Class getNodeClass() { + return nodeClass; + } + + public final List>> getNodeSignatures() { + List>> signatures = new ArrayList<>(); + for (int i = 0; i < nodeSignatures.length; i++) { + signatures.add(Arrays.asList(nodeSignatures[i])); + } + return signatures; + } + + public final List> getExecutionSignature() { + return Arrays.asList(executionSignatures); + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/InstrumentationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/InstrumentationTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.test; + +import java.util.*; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; + +/** + *

    AST Instrumentation

    + * + * Instrumentation allows the insertion into Truffle ASTs language-specific instances of + * {@link Wrapper} that propagate {@link ExecutionEvents} through a {@link Probe} to any instances + * of {@link Instrument} that might be attached to the particular probe by tools. + *
      + *
    1. Creates a simple add AST
    2. + *
    3. Verifies its structure
    4. + *
    5. "Probes" the add node by adding a {@link Wrapper} and associated {@link Probe}
    6. + *
    7. Attaches a simple {@link Instrument} to the node via its {@link Probe}
    8. + *
    9. Verifies the structure of the probed AST
    10. + *
    11. Verifies the execution of the probed AST
    12. + *
    13. Verifies the results observed by the instrument.
    14. + *
    + * To do these tests, several required classes have been implemented in their most basic form, only + * implementing the methods necessary for the tests to pass, with stubs elsewhere. + */ +public class InstrumentationTest { + + @Test + public void test() { + // Build a tree + TruffleRuntime runtime = Truffle.getRuntime(); + TestChildNode leftChild = new TestChildNode(); + TestChildNode rightChild = new TestChildNode(); + TestSourceSection sourceSection = new TestSourceSection(); + TestAddNode addNode = new TestAddNode(leftChild, rightChild, sourceSection); + TestRootNode rootNode = new TestRootNode(addNode); + + // Have to create a call target before checking parent/child relationships + CallTarget target = runtime.createCallTarget(rootNode); + + // Check tree structure + Assert.assertEquals(addNode, leftChild.getParent()); + Assert.assertEquals(addNode, rightChild.getParent()); + Iterator iterator = addNode.getChildren().iterator(); + Assert.assertEquals(leftChild, iterator.next()); + Assert.assertEquals(rightChild, iterator.next()); + Assert.assertFalse(iterator.hasNext()); + Assert.assertEquals(rootNode, addNode.getParent()); + iterator = rootNode.getChildren().iterator(); + Assert.assertEquals(addNode, iterator.next()); + Assert.assertFalse(iterator.hasNext()); + Object result = target.call(); + Assert.assertEquals(42, result); + + // Create another call target, this time with the "probed" add node + TestExecutionContext context = new TestExecutionContext(); + TestWrapper wrapper = new TestWrapper(addNode, context); + rootNode = new TestRootNode(wrapper); + target = runtime.createCallTarget(rootNode); + + // Check the new tree structure + Assert.assertEquals(addNode, leftChild.getParent()); + Assert.assertEquals(addNode, rightChild.getParent()); + iterator = addNode.getChildren().iterator(); + Assert.assertEquals(leftChild, iterator.next()); + Assert.assertEquals(rightChild, iterator.next()); + Assert.assertFalse(iterator.hasNext()); + Assert.assertEquals(wrapper, addNode.getParent()); + iterator = wrapper.getChildren().iterator(); + Assert.assertEquals(addNode, iterator.next()); + Assert.assertFalse(iterator.hasNext()); + Assert.assertEquals(rootNode, wrapper.getParent()); + iterator = rootNode.getChildren().iterator(); + Assert.assertEquals(wrapper, iterator.next()); + Assert.assertFalse(iterator.hasNext()); + result = target.call(); + Assert.assertEquals(42, result); + + // Create some instruments + final TestInstrument instrumentA = new TestInstrument(); + final TestInstrument instrumentB = new TestInstrument(); + + wrapper.getProbe().addInstrument(instrumentA); + + result = target.call(); + Assert.assertEquals(instrumentA.numInstrumentEnter, 1); + Assert.assertEquals(instrumentA.numInstrumentLeave, 1); + Assert.assertEquals(instrumentB.numInstrumentEnter, 0); + Assert.assertEquals(instrumentB.numInstrumentLeave, 0); + Assert.assertEquals(42, result); + + wrapper.getProbe().addInstrument(instrumentB); + + result = target.call(); + Assert.assertEquals(instrumentA.numInstrumentEnter, 2); + Assert.assertEquals(instrumentA.numInstrumentLeave, 2); + Assert.assertEquals(instrumentB.numInstrumentEnter, 1); + Assert.assertEquals(instrumentB.numInstrumentLeave, 1); + Assert.assertEquals(42, result); + + wrapper.getProbe().removeInstrument(instrumentA); + + result = target.call(); + Assert.assertEquals(instrumentA.numInstrumentEnter, 2); + Assert.assertEquals(instrumentA.numInstrumentLeave, 2); + Assert.assertEquals(instrumentB.numInstrumentEnter, 2); + Assert.assertEquals(instrumentB.numInstrumentLeave, 2); + Assert.assertEquals(42, result); + + } + + private class TestRootNode extends RootNode { + @Child private RootNode child; + + public TestRootNode(RootNode child) { + super(null); + this.child = child; + } + + @Override + public Object execute(VirtualFrame frame) { + return child.execute(frame); + } + } + + private class TestAddNode extends RootNode { + + @Child private TestChildNode left; + @Child private TestChildNode right; + + public TestAddNode(TestChildNode left, TestChildNode right, TestSourceSection sourceSection) { + super(sourceSection); + this.left = left; + this.right = right; + } + + @Override + public Object execute(VirtualFrame frame) { + return left.execute() + right.execute(); + } + } + + private class TestChildNode extends Node { + + public TestChildNode() { + super(null); + } + + public int execute() { + return 21; + } + } + + /** + * The wrapper node class is usually language-specific and inherits from the language-specific + * subclass of {@link Node}, not {@RootNode}. + */ + private class TestWrapper extends RootNode implements Wrapper { + @Child private RootNode child; + private Probe probe; + + public TestWrapper(RootNode child, ExecutionContext context) { + this.child = insert(child); + this.probe = context.createProbe(child.getSourceSection()); + } + + public boolean isTaggedAs(SyntaxTag tag) { + return false; + } + + public Iterable getSyntaxTags() { + return null; + } + + public Node getChild() { + return child; + } + + public Probe getProbe() { + return probe; + } + + @Override + public Object execute(VirtualFrame frame) { + probe.enter(child, frame); + Object result; + + try { + result = child.execute(frame); + probe.leave(child, frame, result); + } catch (Exception e) { + probe.leaveExceptional(child, frame, e); + throw (e); + } + return result; + } + } + + /** + * An "empty" description of the source code that might correspond to a particular AST node. The + * instrumentation framework tracks probes that have been inserted by their source location, + * using this as a key. + */ + private class TestSourceSection implements SourceSection { + + public Source getSource() { + return null; + } + + public int getStartLine() { + return 0; + } + + public LineLocation getLineLocation() { + return null; + } + + public int getStartColumn() { + return 0; + } + + public int getCharIndex() { + return 0; + } + + public int getCharLength() { + return 0; + } + + public int getCharEndIndex() { + return 0; + } + + public String getIdentifier() { + return null; + } + + public String getCode() { + return null; + } + + public String getShortDescription() { + return null; + } + + } + + private class TestExecutionContext extends ExecutionContext { + + @Override + public String getLanguageShortName() { + return "test"; + } + + @Override + protected void setSourceCallback(SourceCallback sourceCallback) { + } + + } + + private class TestInstrument extends Instrument { + + public int numInstrumentEnter = 0; + public int numInstrumentLeave = 0; + + @Override + public void enter(Node astNode, VirtualFrame frame) { + numInstrumentEnter++; + } + + @Override + public void leave(Node astNode, VirtualFrame frame, Object result) { + numInstrumentLeave++; + } + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/package-info.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/package-info.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/package-info.java Mon Aug 25 21:15:59 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,7 @@ *
  11. How to use frames and frame slots to store values local to an activation? {@link com.oracle.truffle.api.test.FrameTest}
  12. *
  13. How to use type specialization and speculation for frame slots? {@link com.oracle.truffle.api.test.FrameSlotTypeSpecializationTest}
  14. *
  15. How to use type specialization and speculation for node return values? {@link com.oracle.truffle.api.test.ReturnTypeSpecializationTest}
  16. + *
  17. How to "instrument" an AST with nodes that can provide access to runtime state from external tools {@link com.oracle.truffle.api.test.InstrumentationTest}
  18. * * * diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/BinaryConditionProfileTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/BinaryConditionProfileTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.test.utilities; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import org.junit.*; +import org.junit.experimental.theories.*; +import org.junit.runner.*; + +import com.oracle.truffle.api.utilities.*; + +@RunWith(Theories.class) +public class BinaryConditionProfileTest { + + @DataPoints public static boolean[] data = new boolean[]{true, false}; + + private BinaryConditionProfile profile; + + @Before + public void create() { + profile = (BinaryConditionProfile) ConditionProfile.createBinaryProfile(); + } + + @Test + public void testInitial() { + assertThat(profile.wasTrue(), is(false)); + assertThat(profile.wasFalse(), is(false)); + } + + @Theory + public void testProfileOne(boolean value) { + boolean result = profile.profile(value); + + assertThat(result, is(value)); + assertThat(profile.wasTrue(), is(value)); + assertThat(profile.wasFalse(), is(!value)); + } + + @Theory + public void testProfileTwo(boolean value0, boolean value1) { + boolean result0 = profile.profile(value0); + boolean result1 = profile.profile(value1); + + assertThat(result0, is(value0)); + assertThat(result1, is(value1)); + assertThat(profile.wasTrue(), is(value0 || value1)); + assertThat(profile.wasFalse(), is(!value0 || !value1)); + } + + @Theory + public void testProfileThree(boolean value0, boolean value1, boolean value2) { + boolean result0 = profile.profile(value0); + boolean result1 = profile.profile(value1); + boolean result2 = profile.profile(value2); + + assertThat(result0, is(value0)); + assertThat(result1, is(value1)); + assertThat(result2, is(value2)); + assertThat(profile.wasTrue(), is(value0 || value1 || value2)); + assertThat(profile.wasFalse(), is(!value0 || !value1 || !value2)); + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/CountingConditionProfileTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/CountingConditionProfileTest.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.test.utilities; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import org.junit.*; +import org.junit.experimental.theories.*; +import org.junit.runner.*; + +import com.oracle.truffle.api.utilities.*; + +@RunWith(Theories.class) +public class CountingConditionProfileTest { + + @DataPoints public static boolean[] data = new boolean[]{true, false}; + + private CountingConditionProfile profile; + + @Before + public void create() { + profile = (CountingConditionProfile) ConditionProfile.createCountingProfile(); + } + + @Test + public void testInitial() { + assertThat(profile.getTrueCount(), is(0)); + assertThat(profile.getFalseCount(), is(0)); + } + + @Theory + public void testProfileOne(boolean value) { + boolean result = profile.profile(value); + + assertThat(result, is(value)); + assertThat(profile.getTrueCount(), is(value ? 1 : 0)); + assertThat(profile.getFalseCount(), is(!value ? 1 : 0)); + } + + @Theory + public void testProfileTwo(boolean value0, boolean value1) { + boolean result0 = profile.profile(value0); + boolean result1 = profile.profile(value1); + + assertThat(result0, is(value0)); + assertThat(result1, is(value1)); + assertThat(profile.getTrueCount(), is((value0 ? 1 : 0) + (value1 ? 1 : 0))); + assertThat(profile.getFalseCount(), is((!value0 ? 1 : 0) + (!value1 ? 1 : 0))); + } + + @Theory + public void testProfileThree(boolean value0, boolean value1, boolean value2) { + boolean result0 = profile.profile(value0); + boolean result1 = profile.profile(value1); + boolean result2 = profile.profile(value2); + + assertThat(result0, is(value0)); + assertThat(result1, is(value1)); + assertThat(result2, is(value2)); + assertThat(profile.getTrueCount(), is((value0 ? 1 : 0) + (value1 ? 1 : 0) + (value2 ? 1 : 0))); + assertThat(profile.getFalseCount(), is((!value0 ? 1 : 0) + (!value1 ? 1 : 0) + (!value2 ? 1 : 0))); + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Assumption.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Assumption.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Assumption.java Mon Aug 25 21:15:59 2014 -0700 @@ -34,6 +34,9 @@ * method. The Truffle compiler has special knowledge of this class in order to produce efficient * machine code for checking an assumption in case the assumption object is a compile time constant. * Therefore, assumptions should be stored in final fields in Truffle nodes. + * + * All instances of classes implementing {@code Assumption} must be held in {@code final} fields for + * compiler optimizations to take effect. */ public interface Assumption { @@ -42,14 +45,14 @@ * longer the case. This method is preferred over the {@link #isValid()} method when writing * guest language interpreter code. The catch block should perform a node rewrite (see * {@link Node#replace(Node)}) with a node that no longer relies on the assumption. - * + * * @throws InvalidAssumptionException If the assumption is no longer valid. */ void check() throws InvalidAssumptionException; /** * Checks whether the assumption is still valid. - * + * * @return a boolean value indicating the validity of the assumption */ boolean isValid(); @@ -61,7 +64,7 @@ /** * A name for the assumption that is used for debug output. - * + * * @return the name of the assumption */ String getName(); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java Mon Aug 25 21:15:59 2014 -0700 @@ -30,7 +30,7 @@ public interface CallTarget { /** - * Calls this target as a root method.. + * Calls this target as a root method. * * @param arguments passed arguments as an object array * @return the return result of the call diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java Mon Aug 25 21:15:59 2014 -0700 @@ -45,6 +45,9 @@ protected ExecutionContext() { } + /** + * Sets up the {@link SourceCallback} for this execution context. + */ public void initialize() { setSourceCallback(new SourceCallback() { @@ -99,23 +102,13 @@ } /** - * Return the (possibly newly created) {@link Probe} uniquely associated with a particular - * source code location. A newly created probe carries no tags. + * Return a newly created, untagged, {@link Probe} associated with a particular source section, + * with no requirement that the association be unique. * - * @return a probe uniquely associated with an extent of guest language source code. + * @return a probe associated with an extent of guest language source code. */ - public final Probe getProbe(SourceSection sourceSection) { - return probeManager.getProbe(sourceSection); - } - - /** - * Has a {@link Probe} been created that is uniquely associated with a particular source code - * location. - * - * @return a probe uniquely associated with an extent of guest language source code. - */ - public final boolean hasProbe(SourceSection sourceSection) { - return probeManager.hasProbe(sourceSection); + public final Probe createProbe(SourceSection source) { + return probeManager.createProbe(source); } /** @@ -127,14 +120,6 @@ } /** - * Returns all existing probes with first character on a specified line; empty collection if no - * probes found. - */ - public final Collection findProbesByLine(LineLocation lineLocation) { - return probeManager.findProbesByLine(lineLocation); - } - - /** * Sets a trap that will make a callback at any AST location where a existing probe holds a * specified tag; only one trap may be set at a time. * diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,6 +24,8 @@ */ package com.oracle.truffle.api; +import java.security.*; + import com.oracle.truffle.api.impl.*; /** @@ -31,7 +33,7 @@ */ public class Truffle { - private static final TruffleRuntime RUNTIME; + private static final TruffleRuntime RUNTIME = initRuntime(); /** * Creates a new {@link TruffleRuntime} instance if the runtime has a specialized @@ -46,13 +48,15 @@ return RUNTIME; } - static { - TruffleRuntime runtime; + private static TruffleRuntime initRuntime() { try { - runtime = createRuntime(); + return AccessController.doPrivileged(new PrivilegedAction() { + public TruffleRuntime run() { + return createRuntime(); + } + }); } catch (UnsatisfiedLinkError e) { - runtime = new DefaultTruffleRuntime(); + return new DefaultTruffleRuntime(); } - RUNTIME = runtime; } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,6 +24,8 @@ */ package com.oracle.truffle.api; +import java.security.*; + import com.oracle.truffle.api.nodes.*; /** @@ -36,7 +38,7 @@ *

    * Can be set with {@code -Dtruffle.TraceRewrites=true}. */ - public static boolean TraceRewrites = Boolean.getBoolean("truffle.TraceRewrites"); + public static boolean TraceRewrites; /** * Enables the generation of detailed rewrite reasons. Enabling this may introduce some overhead @@ -44,7 +46,7 @@ *

    * Can be set with {@code -Dtruffle.DetailedRewriteReasons=true}. */ - public static final boolean DetailedRewriteReasons = Boolean.getBoolean("truffle.DetailedRewriteReasons"); + public static final boolean DetailedRewriteReasons; /** * Filters rewrites that do not contain the given string in the qualified name of the source or @@ -52,7 +54,7 @@ *

    * Can be set with {@code -Dtruffle.TraceRewritesFilterClass=name}. */ - public static String TraceRewritesFilterClass = System.getProperty("truffle.TraceRewritesFilterClass"); + public static String TraceRewritesFilterClass; /** * Filters rewrites which does not contain the {@link NodeCost} in its source {@link NodeInfo}. @@ -61,7 +63,7 @@ * Can be set with * {@code -Dtruffle.TraceRewritesFilterFromCost=NONE|MONOMORPHIC|POLYMORPHIC|MEGAMORPHIC}. */ - public static NodeCost TraceRewritesFilterFromCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterFromCost")); + public static NodeCost TraceRewritesFilterFromCost; /** * Filters rewrites which does not contain the {@link NodeCost} in its target {@link NodeInfo}. @@ -70,14 +72,14 @@ * Can be set with * {@code -Dtruffle.TraceRewritesFilterToKind=UNINITIALIZED|SPECIALIZED|POLYMORPHIC|GENERIC}. */ - public static NodeCost TraceRewritesFilterToCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterToCost")); + public static NodeCost TraceRewritesFilterToCost; /** * Enables the dumping of Node creations and AST rewrites in JSON format. *

    * Can be set with {@code -Dtruffle.TraceASTJSON=true}. */ - public static final boolean TraceASTJSON = Boolean.getBoolean("truffle.TraceASTJSON"); + public static final boolean TraceASTJSON; private static NodeCost parseNodeInfoKind(String kind) { if (kind == null) { @@ -87,4 +89,21 @@ return NodeCost.valueOf(kind); } + static { + final boolean[] values = {false, false}; + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + TraceRewrites = Boolean.getBoolean("truffle.TraceRewrites"); + TraceRewritesFilterClass = System.getProperty("truffle.TraceRewritesFilterClass"); + TraceRewritesFilterFromCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterFromCost")); + TraceRewritesFilterToCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterToCost")); + values[0] = Boolean.getBoolean("truffle.DetailedRewriteReasons"); + values[1] = Boolean.getBoolean("truffle.TraceASTJSON"); + return null; + } + }); + + DetailedRewriteReasons = values[0]; + TraceASTJSON = values[1]; + } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java Mon Aug 25 21:15:59 2014 -0700 @@ -59,6 +59,11 @@ DirectCallNode createDirectCallNode(CallTarget target); /** + * Experimental API. May change without notice. + */ + LoopNode createLoopNode(RepeatingNode body); + + /** * Creates a new runtime specific version of {@link IndirectCallNode}. * * @return the new call node @@ -135,4 +140,5 @@ * Internal API method. Do not use. */ void notifyTransferToInterpreter(); + } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java Mon Aug 25 21:15:59 2014 -0700 @@ -53,13 +53,17 @@ } public FrameSlot addFrameSlot(Object identifier) { - return addFrameSlot(identifier, FrameSlotKind.Illegal); + return addFrameSlot(identifier, null, FrameSlotKind.Illegal); } public FrameSlot addFrameSlot(Object identifier, FrameSlotKind kind) { + return addFrameSlot(identifier, null, kind); + } + + public FrameSlot addFrameSlot(Object identifier, Object info, FrameSlotKind kind) { CompilerAsserts.neverPartOfCompilation("interpreter-only. includes hashmap operations."); assert !identifierToSlotMap.containsKey(identifier); - FrameSlot slot = new FrameSlot(this, identifier, slots.size(), kind); + FrameSlot slot = new FrameSlot(this, identifier, info, slots.size(), kind); slots.add(slot); identifierToSlotMap.put(identifier, slot); updateVersion(); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java Mon Aug 25 21:15:59 2014 -0700 @@ -34,12 +34,14 @@ private final FrameDescriptor descriptor; private final Object identifier; + private final Object info; private final int index; @CompilationFinal private FrameSlotKind kind; - public FrameSlot(FrameDescriptor descriptor, Object identifier, int index, FrameSlotKind kind) { + public FrameSlot(FrameDescriptor descriptor, Object identifier, Object info, int index, FrameSlotKind kind) { this.descriptor = descriptor; this.identifier = identifier; + this.info = info; this.index = index; this.kind = kind; } @@ -48,6 +50,10 @@ return identifier; } + public Object getInfo() { + return info; + } + public int getIndex() { return index; } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultIndirectCallNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -32,10 +32,32 @@ * This is runtime specific API. Do not use in a guest language. */ final class DefaultIndirectCallNode extends IndirectCallNode { + @Override + public Object call(final VirtualFrame frame, final CallTarget target, Object[] arguments) { + DefaultTruffleRuntime truffleRuntime = (DefaultTruffleRuntime) Truffle.getRuntime(); + final CallTarget currentCallTarget = truffleRuntime.getCurrentFrame().getCallTarget(); + FrameInstance frameInstance = new FrameInstance() { + public Frame getFrame(FrameAccess access, boolean slowPath) { + return frame; + } - @Override - public Object call(VirtualFrame frame, CallTarget target, Object[] arguments) { - return target.call(arguments); + public boolean isVirtualFrame() { + return false; + } + + public Node getCallNode() { + return DefaultIndirectCallNode.this; + } + + public CallTarget getCallTarget() { + return currentCallTarget; + } + }; + truffleRuntime.pushFrame(frameInstance); + try { + return target.call(arguments); + } finally { + truffleRuntime.popFrame(); + } } - } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultLoopNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultLoopNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.impl; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public final class DefaultLoopNode extends LoopNode { + + public DefaultLoopNode(RepeatingNode repeatNode) { + super(repeatNode); + } + + @Override + public void executeLoop(VirtualFrame frame) { + do { + } while (executeRepeatNode(frame)); + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java Mon Aug 25 21:15:59 2014 -0700 @@ -138,4 +138,11 @@ public void notifyTransferToInterpreter() { } + + public LoopNode createLoopNode(RepeatingNode repeating) { + if (!(repeating instanceof Node)) { + throw new IllegalArgumentException("Repeating node must be of type Node."); + } + return new DefaultLoopNode(repeating); + } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTNodeProber.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTNodeProber.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTNodeProber.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,11 +27,10 @@ import com.oracle.truffle.api.nodes.*; /** - * Implementation of a policy for instrumenting inserting a {@link Probe} at a Truffle AST - * node. + * Methods for inserting a {@link Probe} at a Truffle AST node. *

    - * Note that this interface is guest language agnostic, but current extensions are - * language-specific. This will be revisited. + * This interface is guest language agnostic, but current extensions are language-specific. This + * will be revisited. *

    * Disclaimer: experimental interface under development. Really! */ diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTPrinter.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTPrinter.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTPrinter.java Mon Aug 25 21:15:59 2014 -0700 @@ -29,7 +29,8 @@ import com.oracle.truffle.api.nodes.*; /** - * Language-agnostic access to AST-based debugging support. + * Access to AST-based debugging support, which is could be language implementation specific in the + * details chosen to be presented. *

    * WARNING: this interface is under development and will change substantially. */ @@ -37,7 +38,7 @@ /** * Prints a textual AST display, one line per node, with nesting. - * + * * @param p * @param node the root node of the display. * @param maxDepth the maximum number of levels to print below the root @@ -47,7 +48,7 @@ /** * Creates a textual AST display, one line per node, with nesting. - * + * * @param node the root node of the display. * @param maxDepth the maximum number of levels to print below the root * @param markNode a node to mark with a textual arrow prefix, if present. @@ -56,7 +57,7 @@ /** * Creates a textual AST display, one line per node, with nesting. - * + * * @param node the root node of the display. * @param maxDepth the maximum number of levels to print below the root */ diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ExecutionEvents.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ExecutionEvents.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ExecutionEvents.java Mon Aug 25 21:15:59 2014 -0700 @@ -28,8 +28,9 @@ import com.oracle.truffle.api.nodes.*; /** - * Normal events during program execution at Truffle AST nodes that are reported via a {@link Probe} - * associated with the node, and made available to the probe's attached {@link Instrument}s. + * Normal events at each Truffle AST {@link Node} that occur during guest language execution, and + * which the {@link Probe} associated with that node, if any, reports to every {@link Instrument} + * attached to the {@link Probe}. *

    * Disclaimer: experimental interface under development. */ diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumentable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumentable.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.instrument; + +import com.oracle.truffle.api.*; + +public interface Instrumentable { + + /** + * Optionally applies instrumentation at a Truffle AST node, depending on guest + * language characteristics and use-case policy. Ideally, the parent node of the guest language + * implements this interface. + *

      + *
    • if no instrumentation is to be applied, returns the AST node unmodified;
    • + *
    • if an AST node is to be instrumented, then creates a new Wrapper that decorates + * the AST node. Additionally, this creates a probe on the wrapper that is to be used for + * attaching instruments. This {@link Probe} is notified of all {@link ExecutionEvents} at the + * wrapped AST node.
    • + *
    + * + * @param context The {@link ExecutionContext} of the guest language used to create probes on + * the wrapper. + * @return The probe that was created. + */ + public Probe probe(ExecutionContext context); +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java Mon Aug 25 21:15:59 2014 -0700 @@ -45,9 +45,6 @@ * attached instruments seldom changes. The assumption is invalidated when instruments are added or * removed, but some instruments may change their internal state in such a way that the assumption * should also be invalidated. - *

    - * Disclaimer: experimental interface under development. In particular, the - * notify methods must be migrated to another interface. * * @see Instrument * @see Wrapper @@ -55,24 +52,34 @@ public interface Probe extends ExecutionEvents, SyntaxTagged { /** - * The source location with which this probe is (presumably uniquely) associated. + * Get the {@link SourceSection} in some Truffle AST associated with this probe. + * + * @return The source associated with this probe. */ SourceSection getSourceLocation(); /** - * Mark this probe as being associated with an AST node in some category useful for debugging - * and other tools. + * Mark this probe as belonging to some tool-related category that can be used to guide tool + * behavior at an associated AST node. For example, a debugger might add the tag + * {@link StandardSyntaxTag#STATEMENT} as a way of configuring where execution should stop when + * stepping. */ void tagAs(SyntaxTag tag); /** - * Adds an instrument to this probe. + * Adds an {@link Instrument} to this probe's collection. No check is made to see if the same + * instrument has already been added. + * + * @param newInstrument The instrument to add to this probe. */ void addInstrument(Instrument newInstrument); /** - * Removes an instrument from this probe. + * Removes the given instrument from the probe's collection. + * + * @param oldInstrument The instrument to remove from this probe. + * @throws RuntimeException if no matching instrument has been attached. */ - void removeInstrument(Instrument oldInstrument); + void removeInstrument(Instrument oldInstrument) throws RuntimeException; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeListener.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeListener.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeListener.java Mon Aug 25 21:15:59 2014 -0700 @@ -39,7 +39,7 @@ * Notifies that a newly created (untagged) {@link Probe} has been inserted into a Truffle AST. * There will be no notification when an existing {@link Probe} is shared by an AST copy. */ - void newProbeInserted(SourceSection location, Probe probe); + void newProbeInserted(SourceSection source, Probe probe); /** * Notifies that a (fully constructed) {@link Probe} has been tagged. A subsequent marking with diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SyntaxTagged.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SyntaxTagged.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SyntaxTagged.java Mon Aug 25 21:15:59 2014 -0700 @@ -36,12 +36,13 @@ public interface SyntaxTagged { /** - * Is this node tagged as belonging to a particular category of language constructs? + * Is this node tagged as belonging to a particular human-sensible category of language + * constructs? */ boolean isTaggedAs(SyntaxTag tag); /** - * In which categories has this node been tagged (empty set if none). + * In which user-sensible categories has this node been tagged (empty set if none). */ Iterable getSyntaxTags(); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -34,9 +34,9 @@ import com.oracle.truffle.api.source.*; /** - * Abstract implementation of Truffle {@link Node} to be used for AST probes and instruments. - *

    - * Coordinates propagation of Truffle AST {@link ExecutionEvents}. + * Abstract implementation of Truffle {@link Node}s used as AST {@link Probe}s and + * {@link Instrument}s. A {@link Probe} manages its attached {@link Instrument}s by appending them + * to a chain through which {@link ExecutionEvents} are propagated. */ public abstract class InstrumentationNode extends Node implements ExecutionEvents { @@ -44,18 +44,12 @@ void newTagAdded(ProbeImpl probe, SyntaxTag tag); } - /** - * Creates a new {@link Probe}, presumed to be unique to a particular {@linkplain SourceSection} - * extent of guest language source code. - * - * @return a new probe - */ - static ProbeImpl createProbe(SourceSection sourceSection, ProbeCallback probeCallback) { - return new ProbeImpl(sourceSection, probeCallback); + static ProbeImpl createProbe(SourceSection source, ProbeCallback probeCallback) { + return new ProbeImpl(source, probeCallback); } /** - * Next in chain. + * Next instrumentation node in chain. */ @Child protected InstrumentationNode next; @@ -71,7 +65,7 @@ } /** - * Add a probe to the end of this probe chain. + * Add an instrument to the end of this instrument chain. */ private void internalAddInstrument(Instrument newInstrument) { if (next == null) { @@ -81,6 +75,12 @@ } } + /** + * Remove an instrument from this instrument chain. If no matching instrument is found, a + * {@link RuntimeException} is thrown. + * + * @param oldInstrument The {@link Instrument} to remove. + */ private void internalRemoveInstrument(Instrument oldInstrument) { if (next == null) { throw new RuntimeException("Couldn't find probe to remove: " + oldInstrument); @@ -109,6 +109,14 @@ } } + /** + * Informs the instrument that execution is just about to enter an AST node with which this + * instrumentation node is associated. This will continue to call + * {@link #internalEnter(Node, VirtualFrame)} to inform all instruments in the chain. + * + * @param astNode The {@link Node} that was entered + * @param frame The {@link VirtualFrame} at the time of entry + */ protected void internalEnter(Node astNode, VirtualFrame frame) { enter(astNode, frame); if (next != null) { @@ -116,6 +124,15 @@ } } + /** + * Informs the instrument that execution has just returned from an AST node with which this + * instrumentation node is associated. This will continue to call + * {@link #internalEnter(Node, VirtualFrame)} to inform all instruments in the chain. In this + * case, there is no return value. + * + * @param astNode The {@link Node} that was entered + * @param frame The {@link VirtualFrame} at the time of exit + */ protected void internalLeave(Node astNode, VirtualFrame frame) { leave(astNode, frame); if (next != null) { @@ -123,6 +140,16 @@ } } + /** + * Informs the instrument that execution has just returned from an AST node with which this + * instrumentation node is associated. This will continue to call + * {@link #internalLeave(Node, VirtualFrame, boolean)} to inform all instruments in the chain. + * In this case, a boolean value was returned. + * + * @param astNode The {@link Node} that was entered + * @param frame The {@link VirtualFrame} at the time of exit + * @param result The boolean result + */ protected void internalLeave(Node astNode, VirtualFrame frame, boolean result) { leave(astNode, frame, result); if (next != null) { @@ -130,6 +157,16 @@ } } + /** + * Informs the instrument that execution has just returned from an AST node with which this + * instrumentation node is associated. This will continue to call + * {@link #internalLeave(Node, VirtualFrame, byte)} to inform all instruments in the chain. In + * this case, a byte value was returned. + * + * @param astNode The {@link Node} that was entered + * @param frame The {@link VirtualFrame} at the time of exit + * @param result The byte result + */ protected void internalLeave(Node astNode, VirtualFrame frame, byte result) { leave(astNode, frame, result); if (next != null) { @@ -137,6 +174,16 @@ } } + /** + * Informs the instrument that execution has just returned from an AST node with which this + * instrumentation node is associated. This will continue to call + * {@link #internalLeave(Node, VirtualFrame, short)} to inform all instruments in the chain. In + * this case, a short value was returned. + * + * @param astNode The {@link Node} that was entered + * @param frame The {@link VirtualFrame} at the time of exit + * @param result The short result + */ protected void internalLeave(Node astNode, VirtualFrame frame, short result) { leave(astNode, frame, result); if (next != null) { @@ -144,6 +191,16 @@ } } + /** + * Informs the instrument that execution has just returned from an AST node with which this + * instrumentation node is associated. This will continue to call + * {@link #internalLeave(Node, VirtualFrame, int)} to inform all instruments in the chain. In + * this case, a int value was returned. + * + * @param astNode The {@link Node} that was entered + * @param frame The {@link VirtualFrame} at the time of exit + * @param result The int result + */ protected void internalLeave(Node astNode, VirtualFrame frame, int result) { leave(astNode, frame, result); if (next != null) { @@ -151,6 +208,16 @@ } } + /** + * Informs the instrument that execution has just returned from an AST node with which this + * instrumentation node is associated. This will continue to call + * {@link #internalLeave(Node, VirtualFrame, long)} to inform all instruments in the chain. In + * this case, a long value was returned. + * + * @param astNode The {@link Node} that was entered + * @param frame The {@link VirtualFrame} at the time of exit + * @param result The long result + */ protected void internalLeave(Node astNode, VirtualFrame frame, long result) { leave(astNode, frame, result); if (next != null) { @@ -158,6 +225,16 @@ } } + /** + * Informs the instrument that execution has just returned from an AST node with which this + * instrumentation node is associated. This will continue to call + * {@link #internalLeave(Node, VirtualFrame, char)} to inform all instruments in the chain. In + * this case, a char value was returned. + * + * @param astNode The {@link Node} that was entered + * @param frame The {@link VirtualFrame} at the time of exit + * @param result The char result + */ protected void internalLeave(Node astNode, VirtualFrame frame, char result) { leave(astNode, frame, result); if (next != null) { @@ -165,6 +242,16 @@ } } + /** + * Informs the instrument that execution has just returned from an AST node with which this + * instrumentation node is associated. This will continue to call + * {@link #internalLeave(Node, VirtualFrame, float)} to inform all instruments in the chain. In + * this case, a float value was returned. + * + * @param astNode The {@link Node} that was entered + * @param frame The {@link VirtualFrame} at the time of exit + * @param result The float result + */ protected void internalLeave(Node astNode, VirtualFrame frame, float result) { leave(astNode, frame, result); if (next != null) { @@ -172,6 +259,16 @@ } } + /** + * Informs the instrument that execution has just returned from an AST node with which this + * instrumentation node is associated. This will continue to call + * {@link #internalLeave(Node, VirtualFrame, double)} to inform all instruments in the chain. In + * this case, a double value was returned. + * + * @param astNode The {@link Node} that was entered + * @param frame The {@link VirtualFrame} at the time of exit + * @param result The double result + */ protected void internalLeave(Node astNode, VirtualFrame frame, double result) { leave(astNode, frame, result); if (next != null) { @@ -179,6 +276,16 @@ } } + /** + * Informs the instrument that execution has just returned from an AST node with which this + * instrumentation node is associated. This will continue to call + * {@link #internalLeave(Node, VirtualFrame, Object)} to inform all instruments in the chain. In + * this case, an Object was returned. + * + * @param astNode The {@link Node} that was entered + * @param frame The {@link VirtualFrame} at the time of exit + * @param result The Object result + */ protected void internalLeave(Node astNode, VirtualFrame frame, Object result) { leave(astNode, frame, result); if (next != null) { @@ -186,6 +293,16 @@ } } + /** + * Informs the instrument that execution has just returned from an AST node with which this + * instrumentation node is associated. This will continue to call + * {@link #internalLeaveExceptional(Node, VirtualFrame, Exception)} to inform all instruments in + * the chain. In this case, a exception (sometimes containing a value) was thrown. + * + * @param astNode The {@link Node} that was entered + * @param frame The {@link VirtualFrame} at the time of exit + * @param e The exception + */ protected void internalLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) { leaveExceptional(astNode, frame, null); if (next != null) { @@ -195,41 +312,66 @@ /** * Holder of a chain of {@linkplain InstrumentationNode instruments}: manages the - * {@link Assumption} that none of the instruments have changed since last checked. + * {@link Assumption} that no {@link Instrument}s have been added or removed and that none of + * the attached instruments have changed state in a way that would require deopt. *

    * An instance is intended to be shared by every clone of the AST node with which it is * originally attached, so it holds no parent pointer. *

    - * May be categorized by one or more {@linkplain SyntaxTag tags}, signifying information useful - * for instrumentation about its AST location(s). + * Each probe is associated with a {@link SourceSection}, not necessarily uniquely, although + * such a policy could be enforced for some uses. + *

    + * Each {@link Probe} be categorized by one or more {@linkplain SyntaxTag tags}, signifying + * information useful for instrumentation about its AST location(s). */ static final class ProbeImpl extends InstrumentationNode implements Probe { private final ProbeCallback probeCallback; - /** - * Source information about the AST node (and its clones) to which this probe is attached. - */ - private final SourceSection probedSourceSection; - // TODO (mlvdv) assumption model broken @CompilerDirectives.CompilationFinal private Assumption probeUnchanged; @CompilerDirectives.CompilationFinal private SyntaxTagTrap trap = null; + /** + * The collection of tags for this instrumentation node + */ private final ArrayList tags = new ArrayList<>(); - private ProbeImpl(SourceSection sourceSection, ProbeCallback probeCallback) { + /** + * The region of source code associated with this probe. Note that this is distinct from + * {@link Node#getSourceSection()}, which is {@code null} for all instances of + * {@link InstrumentationNode} since they have no corresponding source of their own. + */ + private final SourceSection source; + + /** + * Constructor. + * + * @param source The {@link SourceSection} associated with this probe. + * @param probeCallback The {@link ProbeCallback} to inform when tags have been added to + * this probe. + */ + private ProbeImpl(SourceSection source, ProbeCallback probeCallback) { this.probeCallback = probeCallback; - this.probedSourceSection = sourceSection; + this.source = source; this.probeUnchanged = Truffle.getRuntime().createAssumption(); this.next = null; } + /** + * Returns the {@link SourceSection} associated with this probe. + */ public SourceSection getSourceLocation() { - return probedSourceSection; + return source; } + /** + * Tags this probe with the given {@link SyntaxTag}. If the tag already exists, the tag is + * not added. + * + * @param tag The tag to add to this probe. + */ @SlowPath public void tagAs(SyntaxTag tag) { assert tag != null; @@ -239,15 +381,32 @@ } } + /** + * Checks if this probe has been tagged with the given tag. + * + * @param tag The {@link SyntaxTag} to check for. + * @return True if this probe has the given tag, false otherwise. + */ public boolean isTaggedAs(SyntaxTag tag) { assert tag != null; return tags.contains(tag); } + /** + * Returns an iterable collection of all syntax tags on this probe. + * + * @return A collection of {@link SyntaxTag}s. + */ public Iterable getSyntaxTags() { return tags; } + /** + * Adds the given {@link Instrument} to this probe's chain of instruments. This method does + * not check to see if the same instrument has already been added. + * + * @param instrument The instrument to add to this probe. + */ @SlowPath public void addInstrument(Instrument instrument) { probeUnchanged.invalidate(); @@ -255,6 +414,12 @@ probeUnchanged = Truffle.getRuntime().createAssumption(); } + /** + * Removes the given instrument from the chain of instruments. If no matching instrument is + * found, a {@link RuntimeException} is thrown. + * + * @param instrument The instrument to remove from this probe. + */ @SlowPath public void removeInstrument(Instrument instrument) { probeUnchanged.invalidate(); @@ -262,6 +427,9 @@ probeUnchanged = Truffle.getRuntime().createAssumption(); } + /** + * Returns this probe. + */ @Override protected Probe getProbe() { return this; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineLocationToProbeCollectionMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineLocationToProbeCollectionMap.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.instrument.impl; + +import java.util.*; + +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.source.*; + +/** + * A mapping from {@link LineLocation} (a line number in a specific piece of {@link Source} code) to + * a collection of {@link Probe}s whose associated {@link SourceSection} starts on that line. + */ +public class LineLocationToProbeCollectionMap implements ProbeListener { + + /** + * Map: Source line ==> probes associated with source sections starting on the line. + */ + private final Map> lineToProbesMap = new HashMap<>(); + + public LineLocationToProbeCollectionMap() { + } + + public void newProbeInserted(SourceSection source, Probe probe) { + if (source != null && !(source instanceof NullSourceSection)) + this.addProbeToLine(source.getLineLocation(), probe); + } + + public void probeTaggedAs(Probe probe, SyntaxTag tag) { + // This map ignores tags + } + + /** + * Returns the {@link Probe}, if any, associated with source that starts on a specified line; if + * there are more than one, return the one with the first starting character location. + */ + public Probe findLineProbe(LineLocation lineLocation) { + Probe probe = null; + final Collection probes = getProbesAtLine(lineLocation); + for (Probe probeOnLine : probes) { + if (probe == null) { + probe = probeOnLine; + } else if (probeOnLine.getSourceLocation().getCharIndex() < probe.getSourceLocation().getCharIndex()) { + probe = probeOnLine; + } + } + return probe; + } + + /** + * Records creation of a probe whose associated source starts on the given line. + *

    + * If the line already exists in the internal {@link #lineToProbesMap}, this probe will be added + * to the existing collection. If no line already exists in the internal map, then a new key is + * added along with a new collection containing the probe. + *

    + * This class requires that each added line/probe pair hasn't been previously added. However, + * attaching the same probe to a new line location is allowed. + * + * @param line The {@link LineLocation} to attach the probe to. + * @param probe The {@link Probe} to attach for that line location. + */ + protected void addProbeToLine(LineLocation line, Probe probe) { + + if (!lineToProbesMap.containsKey(line)) { + // Key does not exist, add new probe list + final ArrayList newProbeList = new ArrayList<>(2); + newProbeList.add(probe); + lineToProbesMap.put(line, newProbeList); + } else { + // Probe list exists, add to existing + final Collection existingProbeList = lineToProbesMap.get(line); + assert !existingProbeList.contains(probe); + existingProbeList.add(probe); + } + } + + /** + * + * Returns a collection of {@link Probe}s whose associated source begins at the given + * {@link LineLocation}. If there are no probes at that line, an empty list is returned. + * + * @param line The line to check. + * @return A collection of probes at the given line. + */ + public Collection getProbesAtLine(LineLocation line) { + Collection probeList = lineToProbesMap.get(line); + + if (probeList == null) + probeList = new ArrayList<>(1); + + return probeList; + } + + /** + * Convenience method to get probes according to a int line number. Returns a collection of + * {@link Probe}s at the given line number. If there are no probes at that line, a new empty + * list is returned. + * + * @param lineNumber The line number to check. + * @return A iterable collection of probes at the given line. + */ + public Collection getProbesAtLineNumber(int lineNumber) { + ArrayList probes = new ArrayList<>(); + + for (LineLocation line : lineToProbesMap.keySet()) { + if (line.getLineNumber() == lineNumber) + probes.addAll(lineToProbesMap.get(line)); + } + + return probes; + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineLocationToSourceSectionCollectionMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineLocationToSourceSectionCollectionMap.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.instrument.impl; + +import java.util.*; + +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.source.*; + +/** + * A mapping from {@link LineLocation} (a line number in a specific piece of {@link Source} code) to + * a collection of {@link SourceSection}s that exist on that line. This class assumes that all nodes + * are instrumented as it uses the {@link ProbeListener} interface to determine the source sections + * that exist in the file. + */ +public class LineLocationToSourceSectionCollectionMap implements ProbeListener { + + /** + * Map: Source line ==> source sections that exist on the line. + */ + private final Map> lineToSourceSectionsMap = new HashMap<>(); + + public LineLocationToSourceSectionCollectionMap() { + + } + + public void newProbeInserted(SourceSection sourceSection, Probe probe) { + if (sourceSection != null && !(sourceSection instanceof NullSourceSection)) { + this.addSourceSectionToLine(sourceSection.getLineLocation(), sourceSection); + } + } + + public void probeTaggedAs(Probe probe, SyntaxTag tag) { + // This map ignores tags, but this subclasses can override this method to operate on tags. + } + + /** + * Adds a source section to the given line. + *

    + * If the line already exists in the internal {@link #lineToSourceSectionsMap}, this source + * section will be added to the existing collection. If no line already exists in the internal + * map, then a new key is added along with a new collection containing the source section. + *

    + * This class does not check if a source section has already been added to a line. + * + * @param line The {@link LineLocation} to attach the source section to. + * @param sourceSection The {@link SourceSection} to attach for that line location. + */ + protected void addSourceSectionToLine(LineLocation line, SourceSection sourceSection) { + if (!lineToSourceSectionsMap.containsKey(line)) { + // Key does not exist, add new source section list + final ArrayList newSourceSectionList = new ArrayList<>(2); + newSourceSectionList.add(sourceSection); + lineToSourceSectionsMap.put(line, newSourceSectionList); + } else { + // Source section list exists, add to existing + final Collection existingSourceSectionList = lineToSourceSectionsMap.get(line); + existingSourceSectionList.add(sourceSection); + } + } + + /** + * Returns a collection of {@link SourceSection}s at the given {@link LineLocation}. If there + * are no source sections at that line, a new empty list of size 1 is returned. + * + * @param line The line to check. + * @return A iterable collection of source sections at the given line. + */ + public Collection getSourceSectionsAtLine(LineLocation line) { + Collection sourceSectionList = lineToSourceSectionsMap.get(line); + + if (sourceSectionList == null) + sourceSectionList = new ArrayList<>(1); + + return sourceSectionList; + } + + /** + * Convenience method to get source sections according to a int line number. Returns a + * collection of {@link SourceSection}s at the given line number. If there are no source + * sections at that line, a new empty list is returned. + * + * @param lineNumber The line number to check. + * @return A iterable collection of source sections at the given line. + */ + public Collection getSourceSectionsAtLineNumber(int lineNumber) { + ArrayList sourceSections = new ArrayList<>(); + + for (LineLocation line : lineToSourceSectionsMap.keySet()) { + if (line.getLineNumber() == lineNumber) + sourceSections.addAll(lineToSourceSectionsMap.get(line)); + } + + return sourceSections; + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/ProbeManager.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/ProbeManager.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/ProbeManager.java Mon Aug 25 21:15:59 2014 -0700 @@ -36,20 +36,13 @@ */ public final class ProbeManager { - // TODO (mlvdv) use weak references. - /** - * Map: SourceSection ==> probe associated with that source section in an AST. - */ - private final Map srcToProbe = new HashMap<>(); - - // TODO (mlvdv) use weak references. - /** - * Map: Source line ==> probes associated with source sections starting on the line. - */ - private final Map> lineToProbes = new HashMap<>(); - private final List probeListeners = new ArrayList<>(); + private final List allProbes = new ArrayList<>(); + + /** + * Called when a {@link #tagTrap} is activated in a Probe. + */ private final ProbeCallback probeCallback; /** @@ -74,11 +67,17 @@ }; } + /** + * Adds a {@link ProbeListener} to receive events. + */ public void addProbeListener(ProbeListener listener) { assert listener != null; probeListeners.add(listener); } + /** + * Removes a {@link ProbeListener}. Ignored if listener not found. + */ public void removeProbeListener(ProbeListener removeListener) { final List listeners = new ArrayList<>(probeListeners); for (ProbeListener listener : listeners) { @@ -88,45 +87,32 @@ } } - public Probe getProbe(SourceSection sourceSection) { - assert sourceSection != null; - - ProbeImpl probe = srcToProbe.get(sourceSection); - - if (probe != null) { - return probe; - } - probe = InstrumentationNode.createProbe(sourceSection, probeCallback); + /** + * Creates a new {@link Probe} associated with a {@link SourceSection} of code corresponding to + * a Truffle AST node. + */ + public Probe createProbe(SourceSection source) { + assert source != null; - // Register new probe by unique SourceSection - srcToProbe.put(sourceSection, probe); - - // Register new probe by source line, there may be more than one - // Create line location for map key - final LineLocation lineLocation = sourceSection.getLineLocation(); - - Collection probes = lineToProbes.get(lineLocation); - if (probes == null) { - probes = new ArrayList<>(2); - lineToProbes.put(lineLocation, probes); - } - probes.add(probe); + ProbeImpl probe = InstrumentationNode.createProbe(source, probeCallback); + allProbes.add(probe); for (ProbeListener listener : probeListeners) { - listener.newProbeInserted(sourceSection, probe); + listener.newProbeInserted(source, probe); } return probe; } - public boolean hasProbe(SourceSection sourceSection) { - assert sourceSection != null; - return srcToProbe.get(sourceSection) != null; - } - + /** + * Returns the subset of all {@link Probe}s holding a particular {@link SyntaxTag}, or the whole + * collection if the specified tag is {@code null}. + * + * @return A collection of probes containing the given tag. + */ public Collection findProbesTaggedAs(SyntaxTag tag) { final List probes = new ArrayList<>(); - for (Probe probe : srcToProbe.values()) { + for (Probe probe : allProbes) { if (tag == null || probe.isTaggedAs(tag)) { probes.add(probe); } @@ -134,15 +120,16 @@ return probes; } - public Collection findProbesByLine(LineLocation lineLocation) { - final Collection probes = lineToProbes.get(lineLocation); - if (probes == null) { - return Collections.emptyList(); - } - return new ArrayList<>(probes); - } - - public void setTagTrap(SyntaxTagTrap tagTrap) { + /** + * Sets the current "tag trap", which will cause a callback to be triggered whenever execution + * reaches a Probe (existing or subsequently created) with the specified tag. There can only be + * one tag trap set at a time. + *

    + * + * @param tagTrap The {@link SyntaxTagTrap} to set. + * @throws IllegalStateException if a trap is currently set. + */ + public void setTagTrap(SyntaxTagTrap tagTrap) throws IllegalStateException { assert tagTrap != null; if (this.tagTrap != null) { throw new IllegalStateException("trap already set"); @@ -150,18 +137,23 @@ this.tagTrap = tagTrap; SyntaxTag tag = tagTrap.getTag(); - for (ProbeImpl probe : srcToProbe.values()) { + for (ProbeImpl probe : allProbes) { if (probe.isTaggedAs(tag)) { probe.setTrap(tagTrap); } } } + /** + * Clears the current {@link SyntaxTagTrap}. + * + * @throws IllegalStateException if no trap is currently set. + */ public void clearTagTrap() { if (this.tagTrap == null) { throw new IllegalStateException("no trap set"); } - for (ProbeImpl probe : srcToProbe.values()) { + for (ProbeImpl probe : allProbes) { if (probe.isTaggedAs(tagTrap.getTag())) { probe.setTrap(null); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/LoopNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/LoopNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.nodes; + +import com.oracle.truffle.api.frame.*; + +/** + * Experimental API: may change significantly without notice. + */ +public abstract class LoopNode extends Node { + + /* + * TODO Unfortunately we cannot yet use interface typed fields as child fields. + */ + @Child protected Node repeatingNode; + + public LoopNode(RepeatingNode repeatintNode) { + this.repeatingNode = (Node) repeatintNode; + } + + public abstract void executeLoop(VirtualFrame frame); + + protected final boolean executeRepeatNode(VirtualFrame frame) { + return getRepeatNode().executeRepeating(frame); + } + + public final RepeatingNode getRepeatNode() { + return (RepeatingNode) repeatingNode; + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Mon Aug 25 21:15:59 2014 -0700 @@ -299,12 +299,17 @@ } private void reportReplace(Node oldNode, Node newNode, CharSequence reason) { - RootNode rootNode = getRootNode(); - if (rootNode != null) { - CallTarget target = rootNode.getCallTarget(); - if (target instanceof ReplaceObserver) { - ((ReplaceObserver) target).nodeReplaced(oldNode, newNode, reason); + Node node = this; + while (node != null) { + if (node instanceof ReplaceObserver) { + ((ReplaceObserver) node).nodeReplaced(oldNode, newNode, reason); + } else if (node instanceof RootNode) { + CallTarget target = ((RootNode) node).getCallTarget(); + if (target instanceof ReplaceObserver) { + ((ReplaceObserver) target).nodeReplaced(oldNode, newNode, reason); + } } + node = node.getParent(); } if (TruffleOptions.TraceRewrites) { NodeUtil.traceRewrite(this, newNode, reason); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Mon Aug 25 21:15:59 2014 -0700 @@ -27,6 +27,7 @@ import java.io.*; import java.lang.annotation.*; import java.lang.reflect.*; +import java.security.*; import java.util.*; import sun.misc.*; @@ -160,9 +161,13 @@ private static final ClassValue nodeClasses = new ClassValue() { @SuppressWarnings("unchecked") @Override - protected NodeClass computeValue(Class clazz) { + protected NodeClass computeValue(final Class clazz) { assert Node.class.isAssignableFrom(clazz); - return new NodeClass((Class) clazz, unsafeFieldOffsetProvider); + return AccessController.doPrivileged(new PrivilegedAction() { + public NodeClass run() { + return new NodeClass((Class) clazz, unsafeFieldOffsetProvider); + } + }); } }; @@ -840,9 +845,10 @@ if (section != null) { final String srcText = section.getCode(); final StringBuilder sb = new StringBuilder(); - sb.append("source: len=" + srcText.length()); + sb.append("source:"); sb.append(" (" + section.getCharIndex() + "," + (section.getCharEndIndex() - 1) + ")"); - sb.append(" ___" + srcText + "___"); + sb.append(" len=" + srcText.length()); + sb.append(" text=\"" + srcText + "\""); return sb.toString(); } return ""; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RepeatingNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RepeatingNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.nodes; + +import com.oracle.truffle.api.frame.*; + +/** + * Experimental API: may change significantly without notice. + */ +public interface RepeatingNode { + + boolean executeRepeating(VirtualFrame frame); + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BinaryConditionProfile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BinaryConditionProfile.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.utilities; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.*; + +/** + * Utility class to speculate on conditions to be never true or to be never false. Condition + * profiles are intended to be used as part of if conditions. + * + * @see ConditionProfile#createBinaryProfile() + */ +public final class BinaryConditionProfile extends ConditionProfile { + + @CompilationFinal private boolean wasTrue; + @CompilationFinal private boolean wasFalse; + + BinaryConditionProfile() { + /* package protected constructor */ + } + + @Override + public boolean profile(boolean value) { + if (value) { + if (!wasTrue) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + wasTrue = true; + } + } else { + if (!wasFalse) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + wasFalse = true; + } + } + return value; + } + + public boolean wasTrue() { + return wasTrue; + } + + public boolean wasFalse() { + return wasFalse; + } + + @Override + public String toString() { + return String.format("%s(wasTrue=%s, wasFalse=%s)@%x", getClass().getSimpleName(), wasTrue, wasFalse, hashCode()); + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BranchProfile.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BranchProfile.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BranchProfile.java Mon Aug 25 21:15:59 2014 -0700 @@ -32,6 +32,9 @@ * invoked first the optimized code is invalidated and the branch where {@link #enter()} is invoked * is enabled for compilation. Otherwise if the {@link #enter()} method was never invoked the branch * will not get compiled. + * + * All {@code BranchProfile} instances must be held in {@code final} fields for compiler + * optimizations to take effect. */ public final class BranchProfile { @@ -44,6 +47,10 @@ } } + public boolean isVisited() { + return visited; + } + @Override public String toString() { return String.format("%s(%s)@%x", getClass().getSimpleName(), visited ? "visited" : "not-visited", hashCode()); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ConditionProfile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ConditionProfile.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.utilities; + +import com.oracle.truffle.api.*; + +/** + * Abstract utility class to speculate on conditions. Condition profiles are intended to be used as + * part of if conditions. + * + * Example usage: + * + *

    + * private final ConditionProfile zero = ConditionProfile.createBinaryProfile();
    + * 
    + * int value = ...;
    + * if (zero.profile(value == 0)) {
    + *   return 0;
    + * } else {
    + *   return value;
    + * }
    + *
    + * 
    + * + * All instances of {@code ConditionProfile} (and subclasses) must be held in {@code final} fields + * for compiler optimizations to take effect. + * + * @see #createCountingProfile() + * @see #createBinaryProfile() + */ +public abstract class ConditionProfile { + + public abstract boolean profile(boolean value); + + /** + * Returns a {@link ConditionProfile} that speculates on conditions to be never + * true or to be never false. Additionally to a binary profile this + * method returns a condition profile that also counts the number of times the condition was + * true and false. This information is reported to the underlying optimization system using + * {@link CompilerDirectives#injectBranchProbability(double, boolean)}. Condition profiles are + * intended to be used as part of if conditions. + * + * @see ConditionProfile + * @see #createBinaryProfile() + */ + public static ConditionProfile createCountingProfile() { + return new CountingConditionProfile(); + } + + /** + * Returns a {@link ConditionProfile} that speculates on conditions to be never true or to be + * never false. Condition profiles are intended to be used as part of if conditions. + * + * @see ConditionProfile + * @see ConditionProfile#createCountingProfile() + */ + public static ConditionProfile createBinaryProfile() { + return new BinaryConditionProfile(); + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/CountingConditionProfile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/CountingConditionProfile.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.utilities; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.*; + +/** + * Utility class to speculate on conditions to be never true or to be never false. Additionally to + * {@link BinaryConditionProfile} this implementation of {@link ConditionProfile} also counts the + * number of times the condition was true and false. This information is reported to the underlying + * optimization system using {@link CompilerDirectives#injectBranchProbability(double, boolean)}. + * Condition profiles are intended to be used as part of if conditions. + * + * @see ConditionProfile#createCountingProfile() + */ +public final class CountingConditionProfile extends ConditionProfile { + + @CompilationFinal private int trueCount; + @CompilationFinal private int falseCount; + + CountingConditionProfile() { + /* package protected constructor */ + } + + @Override + public boolean profile(boolean value) { + if (value) { + if (trueCount == 0) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + } + if (CompilerDirectives.inInterpreter()) { + trueCount++; + } + } else { + if (falseCount == 0) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + } + if (CompilerDirectives.inInterpreter()) { + falseCount++; + } + } + return CompilerDirectives.injectBranchProbability((double) trueCount / (double) (trueCount + falseCount), value); + } + + public int getTrueCount() { + return trueCount; + } + + public int getFalseCount() { + return falseCount; + } + + @Override + public String toString() { + return String.format("%s(trueCount=%s, falseCount=%s)@%x", getClass().getSimpleName(), trueCount, falseCount, hashCode()); + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractParser.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor; - -import java.lang.annotation.*; -import java.util.*; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; -import javax.tools.Diagnostic.Kind; - -import com.oracle.truffle.dsl.processor.template.*; - -/** - * THIS IS NOT PUBLIC API. - */ -public abstract class AbstractParser { - - protected final ProcessorContext context; - protected final ProcessingEnvironment processingEnv; - protected RoundEnvironment roundEnv; - - protected final Log log; - - public AbstractParser(ProcessorContext c) { - this.context = c; - this.processingEnv = c.getEnvironment(); - this.log = c.getLog(); - } - - public final M parse(RoundEnvironment env, Element element) { - this.roundEnv = env; - M model = null; - try { - AnnotationMirror mirror = null; - if (getAnnotationType() != null) { - mirror = Utils.findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), getAnnotationType()); - } - - if (!context.getTruffleTypes().verify(context, element, mirror)) { - return null; - } - model = parse(element, mirror); - if (model == null) { - return null; - } - - model.emitMessages(context, (TypeElement) element, log); - return filterErrorElements(model); - } catch (CompileErrorException e) { - log.message(Kind.WARNING, element, null, null, "The truffle processor could not parse class due to error: %s", e.getMessage()); - return null; - } finally { - this.roundEnv = null; - } - } - - protected M filterErrorElements(M model) { - return model.hasErrors() ? null : model; - } - - protected abstract M parse(Element element, AnnotationMirror mirror); - - public abstract Class getAnnotationType(); - - public boolean isDelegateToRootDeclaredType() { - return false; - } - - public List> getAllAnnotationTypes() { - List> list = new ArrayList<>(); - if (getAnnotationType() != null) { - list.add(getAnnotationType()); - } - list.addAll(getTypeDelegatedAnnotationTypes()); - return list; - } - - public List> getTypeDelegatedAnnotationTypes() { - return Collections.emptyList(); - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AnnotationProcessor.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AnnotationProcessor.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AnnotationProcessor.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,18 +22,17 @@ */ package com.oracle.truffle.dsl.processor; -import java.io.*; import java.util.*; -import javax.annotation.processing.*; import javax.lang.model.element.*; import javax.lang.model.type.*; -import javax.tools.*; -import com.oracle.truffle.dsl.processor.ast.*; -import com.oracle.truffle.dsl.processor.codewriter.*; -import com.oracle.truffle.dsl.processor.compiler.*; -import com.oracle.truffle.dsl.processor.template.*; +import com.oracle.truffle.dsl.processor.generator.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.java.model.*; +import com.oracle.truffle.dsl.processor.java.transform.*; +import com.oracle.truffle.dsl.processor.model.*; +import com.oracle.truffle.dsl.processor.parser.*; /** * THIS IS NOT PUBLIC API. @@ -41,13 +40,11 @@ class AnnotationProcessor { private final AbstractParser parser; - private final CompilationUnitFactory factory; - private final ProcessorContext context; + private final AbstractCompilationUnitFactory factory; private final Set processedElements = new HashSet<>(); - public AnnotationProcessor(ProcessorContext context, AbstractParser parser, CompilationUnitFactory factory) { - this.context = context; + public AnnotationProcessor(AbstractParser parser, AbstractCompilationUnitFactory factory) { this.parser = parser; this.factory = factory; } @@ -56,23 +53,19 @@ return parser; } - public ProcessorContext getContext() { - return context; - } - @SuppressWarnings({"unchecked"}) - public void process(RoundEnvironment env, Element element, boolean callback) { - + public void process(Element element, boolean callback) { // since it is not guaranteed to be called only once by the compiler // we check for already processed elements to avoid errors when writing files. if (!callback && element instanceof TypeElement) { - String qualifiedName = Utils.getQualifiedName((TypeElement) element); + String qualifiedName = ElementUtils.getQualifiedName((TypeElement) element); if (processedElements.contains(qualifiedName)) { return; } processedElements.add(qualifiedName); } + ProcessorContext context = ProcessorContext.getInstance(); TypeElement type = (TypeElement) element; M model = (M) context.getTemplate(type.asType(), false); @@ -80,7 +73,7 @@ if (firstRun || !callback) { context.registerTemplate(type, null); - model = parser.parse(env, element); + model = parser.parse(element); context.registerTemplate(type, model); if (model != null) { @@ -91,7 +84,7 @@ DeclaredType overrideType = (DeclaredType) context.getType(Override.class); DeclaredType unusedType = (DeclaredType) context.getType(SuppressWarnings.class); unit.accept(new GenerateOverrideVisitor(overrideType), null); - unit.accept(new FixWarningsVisitor(context, unusedType, overrideType), null); + unit.accept(new FixWarningsVisitor(context.getEnvironment(), unusedType, overrideType), null); if (!callback) { unit.accept(new CodeWriter(context.getEnvironment(), element), null); @@ -100,33 +93,4 @@ } } - private static class CodeWriter extends AbstractCodeWriter { - - private final Element originalElement; - private final ProcessingEnvironment env; - - public CodeWriter(ProcessingEnvironment env, Element originalElement) { - this.env = env; - this.originalElement = originalElement; - } - - @Override - protected Writer createWriter(CodeTypeElement clazz) throws IOException { - JavaFileObject jfo = env.getFiler().createSourceFile(clazz.getQualifiedName(), originalElement); - return new BufferedWriter(jfo.openWriter()); - } - - @Override - protected void writeHeader() { - if (env == null) { - return; - } - String comment = CompilerFactory.getCompiler(originalElement).getHeaderComment(env, originalElement); - if (comment != null) { - writeLn(comment); - } - } - - } - } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/CodeWriter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/CodeWriter.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor; + +import java.io.*; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.tools.*; + +import com.oracle.truffle.dsl.processor.java.compiler.*; +import com.oracle.truffle.dsl.processor.java.model.*; +import com.oracle.truffle.dsl.processor.java.transform.*; + +public final class CodeWriter extends AbstractCodeWriter { + + private final Element originalElement; + private final ProcessingEnvironment env; + + public CodeWriter(ProcessingEnvironment env, Element originalElement) { + this.env = env; + this.originalElement = originalElement; + } + + @Override + protected Writer createWriter(CodeTypeElement clazz) throws IOException { + JavaFileObject jfo = env.getFiler().createSourceFile(clazz.getQualifiedName(), originalElement); + return new BufferedWriter(jfo.openWriter()); + } + + @Override + protected void writeHeader() { + if (env == null) { + return; + } + String comment = CompilerFactory.getCompiler(originalElement).getHeaderComment(env, originalElement); + if (comment != null) { + writeLn(comment); + } + } + +} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Log.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Log.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Log.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,7 +26,7 @@ import javax.lang.model.element.*; import javax.tools.Diagnostic.Kind; -import com.oracle.truffle.dsl.processor.ast.*; +import com.oracle.truffle.dsl.processor.java.model.*; /** * THIS IS NOT PUBLIC API. diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,8 +22,6 @@ */ package com.oracle.truffle.dsl.processor; -import static com.oracle.truffle.dsl.processor.Utils.*; - import java.util.*; import javax.annotation.processing.*; @@ -31,9 +29,9 @@ import javax.lang.model.type.*; import javax.lang.model.util.*; -import com.oracle.truffle.dsl.processor.ast.*; -import com.oracle.truffle.dsl.processor.ast.CodeTypeMirror.ArrayCodeTypeMirror; -import com.oracle.truffle.dsl.processor.template.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.java.model.*; +import com.oracle.truffle.dsl.processor.model.*; /** * THIS IS NOT PUBLIC API. @@ -43,13 +41,12 @@ private final ProcessingEnvironment environment; private final Map models = new HashMap<>(); - private final Map> generatedClasses = new HashMap<>(); private final ProcessCallback callback; private final Log log; private final TruffleTypes truffleTypes; - public ProcessorContext(ProcessingEnvironment env, ProcessCallback callback) { + ProcessorContext(ProcessingEnvironment env, ProcessCallback callback) { this.environment = env; this.callback = callback; this.log = new Log(environment); @@ -69,116 +66,25 @@ } public boolean containsTemplate(TypeElement element) { - return models.containsKey(Utils.getQualifiedName(element)); + return models.containsKey(ElementUtils.getQualifiedName(element)); } public void registerTemplate(TypeElement element, Template model) { - models.put(Utils.getQualifiedName(element), model); - } - - public void registerType(TypeElement templateType, TypeMirror generatedTypeMirror) { - String templateQualifiedName = getQualifiedName(templateType); - Map simpleNameToType = generatedClasses.get(templateQualifiedName); - if (simpleNameToType == null) { - simpleNameToType = new HashMap<>(); - generatedClasses.put(templateQualifiedName, simpleNameToType); - } - String generatedSimpleName = getSimpleName(generatedTypeMirror); - simpleNameToType.put(generatedSimpleName, generatedTypeMirror); + models.put(ElementUtils.getQualifiedName(element), model); } public Template getTemplate(TypeMirror templateTypeMirror, boolean invokeCallback) { - String qualifiedName = Utils.getQualifiedName(templateTypeMirror); + String qualifiedName = ElementUtils.getQualifiedName(templateTypeMirror); Template model = models.get(qualifiedName); if (model == null && invokeCallback) { - callback.callback(Utils.fromTypeMirror(templateTypeMirror)); + callback.callback(ElementUtils.fromTypeMirror(templateTypeMirror)); model = models.get(qualifiedName); } return model; } - public TypeMirror resolveNotYetCompiledType(TypeMirror mirror, Template templateHint) { - TypeMirror resolvedType = null; - if (mirror.getKind() == TypeKind.ARRAY) { - TypeMirror originalComponentType = ((ArrayType) mirror).getComponentType(); - TypeMirror resolvedComponent = resolveNotYetCompiledType(originalComponentType, templateHint); - if (resolvedComponent != originalComponentType) { - return new ArrayCodeTypeMirror(resolvedComponent); - } - } - - if (mirror.getKind() == TypeKind.ERROR) { - Element element = ((ErrorType) mirror).asElement(); - ElementKind kind = element.getKind(); - if (kind == ElementKind.CLASS || kind == ElementKind.PARAMETER || kind == ElementKind.ENUM) { - String simpleName = element.getSimpleName().toString(); - resolvedType = findGeneratedClassBySimpleName(simpleName, templateHint); - } - } else { - resolvedType = mirror; - } - - return resolvedType; - } - - public TypeMirror findGeneratedClassBySimpleName(String simpleName, Template templateHint) { - if (templateHint == null) { - // search all - for (String qualifiedTemplateName : generatedClasses.keySet()) { - Map mirrors = generatedClasses.get(qualifiedTemplateName); - if (mirrors.get(simpleName) != null) { - return mirrors.get(simpleName); - } - } - return null; - } else { - String templateQualifiedName = getQualifiedName(templateHint.getTemplateType()); - Map simpleNameToType = generatedClasses.get(templateQualifiedName); - if (simpleNameToType == null) { - return null; - } - return simpleNameToType.get(simpleName); - } - } - - public TypeMirror getType(String className) { - TypeElement element = environment.getElementUtils().getTypeElement(className); - if (element != null) { - return element.asType(); - } - return null; - } - public TypeMirror getType(Class element) { - TypeMirror mirror; - if (element.isPrimitive()) { - if (element == boolean.class) { - mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.BOOLEAN); - } else if (element == byte.class) { - mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.BYTE); - } else if (element == short.class) { - mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.SHORT); - } else if (element == char.class) { - mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.CHAR); - } else if (element == int.class) { - mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.INT); - } else if (element == long.class) { - mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.LONG); - } else if (element == float.class) { - mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.FLOAT); - } else if (element == double.class) { - mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.DOUBLE); - } else if (element == void.class) { - mirror = environment.getTypeUtils().getNoType(TypeKind.VOID); - } else { - assert false; - return null; - } - } else { - TypeElement typeElement = environment.getElementUtils().getTypeElement(element.getCanonicalName()); - mirror = typeElement.asType(); - } - return mirror; + return ElementUtils.getType(environment, element); } public interface ProcessCallback { @@ -191,6 +97,14 @@ return getType(type.getQualifiedName().toString()); } + private TypeMirror getType(String className) { + TypeElement element = environment.getElementUtils().getTypeElement(className); + if (element != null) { + return element.asType(); + } + return null; + } + public TypeMirror reloadType(TypeMirror type) { if (type instanceof CodeTypeMirror) { return type; @@ -209,4 +123,14 @@ } return type; } + + private static final ThreadLocal instance = new ThreadLocal<>(); + + public static void setThreadLocalInstance(ProcessorContext context) { + instance.set(context); + } + + public static ProcessorContext getInstance() { + return instance.get(); + } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleProcessor.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleProcessor.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleProcessor.java Mon Aug 25 21:15:59 2014 -0700 @@ -31,8 +31,9 @@ import javax.tools.Diagnostic.Kind; import com.oracle.truffle.dsl.processor.ProcessorContext.ProcessCallback; -import com.oracle.truffle.dsl.processor.node.*; -import com.oracle.truffle.dsl.processor.typesystem.*; +import com.oracle.truffle.dsl.processor.generator.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.parser.*; /** * THIS IS NOT PUBLIC API. @@ -42,11 +43,8 @@ @SupportedSourceVersion(SourceVersion.RELEASE_7) public class TruffleProcessor extends AbstractProcessor implements ProcessCallback { - private ProcessorContext context; private List> generators; - private RoundEnvironment round; - @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { if (!roundEnv.processingOver()) { @@ -56,15 +54,15 @@ } private void processImpl(RoundEnvironment env) { - this.round = env; // TODO run verifications that other annotations are not processed out of scope of the // operation or typelattice. try { + ProcessorContext.setThreadLocalInstance(new ProcessorContext(processingEnv, this)); for (AnnotationProcessor generator : getGenerators()) { AbstractParser parser = generator.getParser(); if (parser.getAnnotationType() != null) { for (Element e : env.getElementsAnnotatedWith(parser.getAnnotationType())) { - processElement(env, generator, e, false); + processElement(generator, e, false); } } @@ -72,23 +70,23 @@ for (Element e : env.getElementsAnnotatedWith(annotationType)) { TypeElement processedType; if (parser.isDelegateToRootDeclaredType()) { - processedType = Utils.findRootEnclosingType(e); + processedType = ElementUtils.findRootEnclosingType(e); } else { - processedType = Utils.findNearestEnclosingType(e); + processedType = ElementUtils.findNearestEnclosingType(e); } - processElement(env, generator, processedType, false); + processElement(generator, processedType, false); } } } } finally { - this.round = null; + ProcessorContext.setThreadLocalInstance(null); } } - private static void processElement(RoundEnvironment env, AnnotationProcessor generator, Element e, boolean callback) { + private static void processElement(AnnotationProcessor generator, Element e, boolean callback) { try { - generator.process(env, e, callback); + generator.process(e, callback); } catch (Throwable e1) { handleThrowable(generator, e1, e); } @@ -96,7 +94,7 @@ private static void handleThrowable(AnnotationProcessor generator, Throwable t, Element e) { String message = "Uncaught error in " + generator.getClass().getSimpleName() + " while processing " + e; - generator.getContext().getEnvironment().getMessager().printMessage(Kind.ERROR, message + ": " + Utils.printException(t), e); + ProcessorContext.getInstance().getEnvironment().getMessager().printMessage(Kind.ERROR, message + ": " + ElementUtils.printException(t), e); } @Override @@ -106,7 +104,7 @@ if (annotationType != null) { Annotation annotation = template.getAnnotation(annotationType); if (annotation != null) { - processElement(round, generator, template, true); + processElement(generator, template, true); } } } @@ -127,19 +125,12 @@ private List> getGenerators() { if (generators == null && processingEnv != null) { generators = new ArrayList<>(); - generators.add(new AnnotationProcessor<>(getContext(), new TypeSystemParser(getContext()), new TypeSystemCodeGenerator(getContext()))); - generators.add(new AnnotationProcessor<>(getContext(), new NodeParser(getContext()), new NodeCodeGenerator(getContext()))); + generators.add(new AnnotationProcessor<>(new TypeSystemParser(), new TypeSystemCodeGenerator())); + generators.add(new AnnotationProcessor<>(new NodeParser(), new NodeCodeGenerator())); } return generators; } - private ProcessorContext getContext() { - if (context == null) { - context = new ProcessorContext(processingEnv, this); - } - return context; - } - @Override public synchronized void init(ProcessingEnvironment env) { this.processingEnv = env; diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Mon Aug 25 21:15:59 2014 -0700 @@ -32,6 +32,7 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.SlowPath; import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.internal.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.nodes.Node.Child; @@ -61,11 +62,18 @@ private final DeclaredType sourceSection; private final DeclaredType truffleOptions; private final DeclaredType compilationFinal; + private final DeclaredType nodeUtil; + private final DeclaredType dslNode; + private final DeclaredType dslShare; + private final DeclaredType nodeFactory; + private final DeclaredType nodeFactoryBase; + private final DeclaredType dslMetadata; + private final DeclaredType implies; private final TypeElement expectError; private final List errors = new ArrayList<>(); - public TruffleTypes(ProcessorContext context) { + TruffleTypes(ProcessorContext context) { node = getRequired(context, Node.class); nodeArray = context.getEnvironment().getTypeUtils().getArrayType(node); unexpectedValueException = getRequired(context, UnexpectedResultException.class); @@ -82,9 +90,40 @@ sourceSection = getRequired(context, SourceSection.class); truffleOptions = getRequired(context, TruffleOptions.class); compilationFinal = getRequired(context, CompilationFinal.class); + nodeUtil = getRequired(context, NodeUtil.class); + dslNode = getRequired(context, DSLNode.class); + dslShare = getRequired(context, DSLShare.class); + nodeFactory = getRequired(context, NodeFactory.class); + nodeFactoryBase = getRequired(context, NodeFactoryBase.class); + dslMetadata = getRequired(context, DSLMetadata.class); + implies = getRequired(context, Implies.class); expectError = (TypeElement) getRequired(context, ExpectError.class).asElement(); } + public DeclaredType getImplies() { + return implies; + } + + public DeclaredType getDslMetadata() { + return dslMetadata; + } + + public DeclaredType getNodeFactory() { + return nodeFactory; + } + + public DeclaredType getNodeFactoryBase() { + return nodeFactoryBase; + } + + public DeclaredType getDslNode() { + return dslNode; + } + + public DeclaredType getDslShare() { + return dslShare; + } + public DeclaredType getCompilationFinal() { return compilationFinal; } @@ -172,4 +211,8 @@ public DeclaredType getSourceSection() { return sourceSection; } + + public DeclaredType getNodeUtil() { + return nodeUtil; + } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,997 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor; - -import java.io.*; -import java.lang.annotation.*; -import java.util.*; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; - -import com.oracle.truffle.dsl.processor.ast.*; -import com.oracle.truffle.dsl.processor.ast.CodeTypeMirror.DeclaredCodeTypeMirror; -import com.oracle.truffle.dsl.processor.compiler.*; - -/** - * THIS IS NOT PUBLIC API. - */ -public class Utils { - - public static ExecutableElement findExecutableElement(DeclaredType type, String name) { - List elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements()); - for (ExecutableElement executableElement : elements) { - if (executableElement.getSimpleName().toString().equals(name)) { - return executableElement; - } - } - return null; - } - - public static boolean needsCastTo(ProcessorContext context, TypeMirror sourceType, TypeMirror targetType) { - if (typeEquals(sourceType, targetType)) { - return false; - } else if (isObject(targetType)) { - return false; - } else if (isVoid(targetType)) { - return false; - } else if (isAssignable(context, sourceType, targetType)) { - return false; - } - return true; - } - - public static VariableElement findVariableElement(DeclaredType type, String name) { - List elements = ElementFilter.fieldsIn(type.asElement().getEnclosedElements()); - for (VariableElement variableElement : elements) { - if (variableElement.getSimpleName().toString().equals(name)) { - return variableElement; - } - } - return null; - } - - public static String getMethodBody(ProcessingEnvironment env, ExecutableElement method) { - if (method instanceof CodeExecutableElement) { - return ((CodeExecutableElement) method).getBody(); - } else { - return CompilerFactory.getCompiler(method).getMethodBody(env, method); - } - } - - public static TypeMirror boxType(ProcessorContext context, TypeMirror primitiveType) { - TypeMirror boxedType = primitiveType; - if (boxedType.getKind().isPrimitive()) { - boxedType = context.getEnvironment().getTypeUtils().boxedClass((PrimitiveType) boxedType).asType(); - } - return boxedType; - } - - public static List asTypeMirrors(List elements) { - List types = new ArrayList<>(elements.size()); - for (Element element : elements) { - types.add(element.asType()); - } - return types; - } - - public static DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs) { - return new DeclaredCodeTypeMirror(typeElem, Arrays.asList(typeArgs)); - } - - public static List collectAnnotations(ProcessorContext context, AnnotationMirror markerAnnotation, String elementName, Element element, - Class annotationClass) { - List result = new ArrayList<>(); - if (markerAnnotation != null) { - result.addAll(Utils.getAnnotationValueList(AnnotationMirror.class, markerAnnotation, elementName)); - } - AnnotationMirror explicit = Utils.findAnnotationMirror(context.getEnvironment(), element, annotationClass); - if (explicit != null) { - result.add(explicit); - } - return result; - } - - public static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror[] types) { - if (types.length == 0) { - return context.getType(Object.class); - } - TypeMirror prev = types[0]; - for (int i = 1; i < types.length; i++) { - prev = getCommonSuperType(context, prev, types[i]); - } - return prev; - } - - public static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror type1, TypeMirror type2) { - if (typeEquals(type1, type2)) { - return type1; - } - TypeElement element1 = fromTypeMirror(type1); - TypeElement element2 = fromTypeMirror(type2); - if (element1 == null || element2 == null) { - return context.getType(Object.class); - } - - List element1Types = getDirectSuperTypes(element1); - element1Types.add(0, element1); - List element2Types = getDirectSuperTypes(element2); - element2Types.add(0, element2); - - for (TypeElement superType1 : element1Types) { - for (TypeElement superType2 : element2Types) { - if (typeEquals(superType1.asType(), superType2.asType())) { - return superType2.asType(); - } - } - } - return context.getType(Object.class); - } - - public static String getReadableSignature(ExecutableElement method) { - // TODO toString does not guarantee a good signature - return method.toString(); - } - - public static boolean hasError(TypeMirror mirror) { - switch (mirror.getKind()) { - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FLOAT: - case INT: - case SHORT: - case LONG: - case DECLARED: - case VOID: - case TYPEVAR: - return false; - case ARRAY: - return hasError(((ArrayType) mirror).getComponentType()); - case ERROR: - return true; - default: - throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); - } - } - - public static boolean isAssignable(ProcessorContext context, TypeMirror from, TypeMirror to) { - if (!(from instanceof CodeTypeMirror) && !(to instanceof CodeTypeMirror)) { - return context.getEnvironment().getTypeUtils().isAssignable(context.reloadType(from), context.reloadType(to)); - } else { - return isAssignableImpl(context, from, to); - } - } - - private static boolean isAssignableImpl(ProcessorContext context, TypeMirror from, TypeMirror to) { - // JLS 5.1.1 identity conversion - if (Utils.typeEquals(from, to)) { - return true; - } - - if (isObject(to)) { - return true; - } - - // JLS 5.1.2 widening primitives - if (Utils.isPrimitive(from) && Utils.isPrimitive(to)) { - TypeKind fromKind = from.getKind(); - TypeKind toKind = to.getKind(); - switch (fromKind) { - case BYTE: - switch (toKind) { - case SHORT: - case INT: - case LONG: - case FLOAT: - case DOUBLE: - return true; - } - break; - case SHORT: - switch (toKind) { - case INT: - case LONG: - case FLOAT: - case DOUBLE: - return true; - } - break; - case CHAR: - switch (toKind) { - case INT: - case LONG: - case FLOAT: - case DOUBLE: - return true; - } - break; - case INT: - switch (toKind) { - case LONG: - case FLOAT: - case DOUBLE: - return true; - } - break; - case LONG: - switch (toKind) { - case FLOAT: - case DOUBLE: - return true; - } - break; - case FLOAT: - switch (toKind) { - case DOUBLE: - return true; - } - break; - - } - return false; - } else if (Utils.isPrimitive(from) || Utils.isPrimitive(to)) { - return false; - } - - if (from instanceof ArrayType && to instanceof ArrayType) { - return isAssignable(context, ((ArrayType) from).getComponentType(), ((ArrayType) to).getComponentType()); - } - - if (from instanceof ArrayType || to instanceof ArrayType) { - return false; - } - - TypeElement fromType = Utils.fromTypeMirror(from); - TypeElement toType = Utils.fromTypeMirror(to); - if (fromType == null || toType == null) { - return false; - } - // JLS 5.1.6 narrowing reference conversion - - List superTypes = Utils.getSuperTypes(fromType); - for (TypeElement superType : superTypes) { - if (Utils.typeEquals(superType.asType(), to)) { - return true; - } - } - - // TODO more spec - return false; - } - - public static Set modifiers(Modifier... modifier) { - return new LinkedHashSet<>(Arrays.asList(modifier)); - } - - public static String getTypeId(TypeMirror mirror) { - switch (mirror.getKind()) { - case BOOLEAN: - return "Boolean"; - case BYTE: - return "Byte"; - case CHAR: - return "Char"; - case DOUBLE: - return "Double"; - case FLOAT: - return "Float"; - case SHORT: - return "Short"; - case INT: - return "Int"; - case LONG: - return "Long"; - case DECLARED: - return fixECJBinaryNameIssue(((DeclaredType) mirror).asElement().getSimpleName().toString()); - case ARRAY: - return getTypeId(((ArrayType) mirror).getComponentType()) + "Array"; - case VOID: - return "Void"; - case WILDCARD: - StringBuilder b = new StringBuilder(); - WildcardType type = (WildcardType) mirror; - if (type.getExtendsBound() != null) { - b.append("Extends").append(getTypeId(type.getExtendsBound())); - } else if (type.getSuperBound() != null) { - b.append("Super").append(getTypeId(type.getExtendsBound())); - } - return b.toString(); - case TYPEVAR: - return "Any"; - case ERROR: - throw new CompileErrorException("Type error " + mirror); - default: - throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); - } - } - - public static String getSimpleName(TypeElement element) { - return getSimpleName(element.asType()); - } - - public static String getSimpleName(TypeMirror mirror) { - switch (mirror.getKind()) { - case BOOLEAN: - return "boolean"; - case BYTE: - return "byte"; - case CHAR: - return "char"; - case DOUBLE: - return "double"; - case FLOAT: - return "float"; - case SHORT: - return "short"; - case INT: - return "int"; - case LONG: - return "long"; - case DECLARED: - return getDeclaredName((DeclaredType) mirror); - case ARRAY: - return getSimpleName(((ArrayType) mirror).getComponentType()) + "[]"; - case VOID: - return "void"; - case WILDCARD: - return getWildcardName((WildcardType) mirror); - case TYPEVAR: - return "?"; - case ERROR: - throw new CompileErrorException("Type error " + mirror); - default: - throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); - } - } - - private static String getWildcardName(WildcardType type) { - StringBuilder b = new StringBuilder(); - if (type.getExtendsBound() != null) { - b.append("? extends ").append(getSimpleName(type.getExtendsBound())); - } else if (type.getSuperBound() != null) { - b.append("? super ").append(getSimpleName(type.getExtendsBound())); - } - return b.toString(); - } - - private static String getDeclaredName(DeclaredType element) { - String simpleName = fixECJBinaryNameIssue(element.asElement().getSimpleName().toString()); - - if (element.getTypeArguments().size() == 0) { - return simpleName; - } - - StringBuilder b = new StringBuilder(simpleName); - b.append("<"); - if (element.getTypeArguments().size() > 0) { - for (int i = 0; i < element.getTypeArguments().size(); i++) { - b.append(getSimpleName(element.getTypeArguments().get(i))); - if (i < element.getTypeArguments().size() - 1) { - b.append(", "); - } - } - } - b.append(">"); - return b.toString(); - } - - public static String fixECJBinaryNameIssue(String name) { - if (name.contains("$")) { - int lastIndex = name.lastIndexOf('$'); - return name.substring(lastIndex + 1, name.length()); - } - return name; - } - - public static String getQualifiedName(TypeElement element) { - String qualifiedName = element.getQualifiedName().toString(); - if (qualifiedName.contains("$")) { - /* - * If a class gets loaded in its binary form by the ECJ compiler it fails to produce the - * proper canonical class name. It leaves the $ in the qualified name of the class. So - * one instance of a TypeElement may be loaded in binary and one in source form. The - * current type comparison in #typeEquals compares by the qualified name so the - * qualified name must match. This is basically a hack to fix the returned qualified - * name of eclipse. - */ - qualifiedName = qualifiedName.replace('$', '.'); - } - return qualifiedName; - } - - public static String getQualifiedName(TypeMirror mirror) { - switch (mirror.getKind()) { - case BOOLEAN: - return "boolean"; - case BYTE: - return "byte"; - case CHAR: - return "char"; - case DOUBLE: - return "double"; - case SHORT: - return "short"; - case FLOAT: - return "float"; - case INT: - return "int"; - case LONG: - return "long"; - case DECLARED: - return getQualifiedName(fromTypeMirror(mirror)); - case ARRAY: - return getQualifiedName(((ArrayType) mirror).getComponentType()); - case VOID: - return "void"; - case TYPEVAR: - return getSimpleName(mirror); - case ERROR: - throw new CompileErrorException("Type error " + mirror); - case EXECUTABLE: - return ((ExecutableType) mirror).toString(); - case NONE: - return "$none"; - default: - throw new RuntimeException("Unknown type specified " + mirror + " mirror: " + mirror); - } - } - - public static boolean isVoid(TypeMirror mirror) { - return mirror.getKind() == TypeKind.VOID; - } - - public static boolean isPrimitive(TypeMirror mirror) { - return mirror.getKind().isPrimitive(); - } - - public static boolean isPrimitiveOrVoid(TypeMirror mirror) { - return isPrimitive(mirror) || isVoid(mirror); - } - - public static List getQualifiedSuperTypeNames(TypeElement element) { - List types = getSuperTypes(element); - List qualifiedNames = new ArrayList<>(); - for (TypeElement type : types) { - qualifiedNames.add(getQualifiedName(type)); - } - return qualifiedNames; - } - - public static List getDeclaredTypes(TypeElement element) { - return ElementFilter.typesIn(element.getEnclosedElements()); - } - - public static VariableElement findDeclaredField(TypeMirror type, String singletonName) { - List elements = ElementFilter.fieldsIn(fromTypeMirror(type).getEnclosedElements()); - for (VariableElement var : elements) { - if (var.getSimpleName().toString().equals(singletonName)) { - return var; - } - } - return null; - } - - public static TypeElement findRootEnclosingType(Element element) { - List elements = getElementHierarchy(element); - - for (int i = elements.size() - 1; i >= 0; i--) { - if (elements.get(i).getKind().isClass()) { - return (TypeElement) elements.get(i); - } - } - - return null; - } - - public static List getElementHierarchy(Element e) { - List elements = new ArrayList<>(); - elements.add(e); - - Element enclosing = e.getEnclosingElement(); - while (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE) { - elements.add(enclosing); - enclosing = enclosing.getEnclosingElement(); - } - if (enclosing != null) { - elements.add(enclosing); - } - return elements; - } - - public static TypeElement findNearestEnclosingType(Element element) { - List elements = getElementHierarchy(element); - for (Element e : elements) { - if (e.getKind().isClass()) { - return (TypeElement) e; - } - } - return null; - } - - public static List getDirectSuperTypes(TypeElement element) { - List types = new ArrayList<>(); - if (element.getSuperclass() != null) { - TypeElement superElement = fromTypeMirror(element.getSuperclass()); - if (superElement != null) { - types.add(superElement); - types.addAll(getDirectSuperTypes(superElement)); - } - } - - return types; - } - - public static List getAssignableTypes(ProcessorContext context, TypeMirror type) { - if (isPrimitive(type)) { - return Arrays.asList(type, boxType(context, type), context.getType(Object.class)); - } else if (type.getKind() == TypeKind.ARRAY) { - return Arrays.asList(type, context.getType(Object.class)); - } else if (type.getKind() == TypeKind.DECLARED) { - List types = getSuperTypes(fromTypeMirror(type)); - List mirrors = new ArrayList<>(types.size()); - mirrors.add(type); - for (TypeElement typeElement : types) { - mirrors.add(typeElement.asType()); - } - return mirrors; - } else { - return Collections.emptyList(); - } - } - - public static List getSuperTypes(TypeElement element) { - List types = new ArrayList<>(); - List superTypes = null; - List superInterfaces = null; - if (element.getSuperclass() != null) { - TypeElement superElement = fromTypeMirror(element.getSuperclass()); - if (superElement != null) { - types.add(superElement); - superTypes = getSuperTypes(superElement); - } - } - for (TypeMirror interfaceMirror : element.getInterfaces()) { - TypeElement interfaceElement = fromTypeMirror(interfaceMirror); - if (interfaceElement != null) { - types.add(interfaceElement); - superInterfaces = getSuperTypes(interfaceElement); - } - } - - if (superTypes != null) { - types.addAll(superTypes); - } - - if (superInterfaces != null) { - types.addAll(superInterfaces); - } - - return types; - } - - public static String getPackageName(TypeElement element) { - return findPackageElement(element).getQualifiedName().toString(); - } - - public static String getPackageName(TypeMirror mirror) { - switch (mirror.getKind()) { - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FLOAT: - case SHORT: - case INT: - case LONG: - case VOID: - case TYPEVAR: - return null; - case DECLARED: - PackageElement pack = findPackageElement(fromTypeMirror(mirror)); - if (pack == null) { - throw new IllegalArgumentException("No package element found for declared type " + getSimpleName(mirror)); - } - return pack.getQualifiedName().toString(); - case ARRAY: - return getSimpleName(((ArrayType) mirror).getComponentType()); - default: - throw new RuntimeException("Unknown type specified " + mirror.getKind()); - } - } - - public static String createConstantName(String simpleName) { - // TODO use camel case to produce underscores. - return simpleName.toString().toUpperCase(); - } - - public static TypeElement fromTypeMirror(TypeMirror mirror) { - switch (mirror.getKind()) { - case DECLARED: - return (TypeElement) ((DeclaredType) mirror).asElement(); - case ARRAY: - return fromTypeMirror(((ArrayType) mirror).getComponentType()); - default: - return null; - } - } - - @SuppressWarnings("unchecked") - public static List getAnnotationValueList(Class expectedListType, AnnotationMirror mirror, String name) { - List values = getAnnotationValue(List.class, mirror, name); - List result = new ArrayList<>(); - - if (values != null) { - for (AnnotationValue value : values) { - T annotationValue = resolveAnnotationValue(expectedListType, value); - if (annotationValue != null) { - result.add(annotationValue); - } - } - } - return result; - } - - public static T getAnnotationValue(Class expectedType, AnnotationMirror mirror, String name) { - return resolveAnnotationValue(expectedType, getAnnotationValue(mirror, name)); - } - - @SuppressWarnings({"unchecked"}) - private static T resolveAnnotationValue(Class expectedType, AnnotationValue value) { - if (value == null) { - return null; - } - - Object unboxedValue = value.accept(new AnnotationValueVisitorImpl(), null); - if (unboxedValue != null) { - if (expectedType == TypeMirror.class && unboxedValue instanceof String) { - return null; - } - if (!expectedType.isAssignableFrom(unboxedValue.getClass())) { - throw new ClassCastException(unboxedValue.getClass().getName() + " not assignable from " + expectedType.getName()); - } - } - return (T) unboxedValue; - } - - public static AnnotationValue getAnnotationValue(AnnotationMirror mirror, String name) { - ExecutableElement valueMethod = null; - for (ExecutableElement method : ElementFilter.methodsIn(mirror.getAnnotationType().asElement().getEnclosedElements())) { - if (method.getSimpleName().toString().equals(name)) { - valueMethod = method; - break; - } - } - - if (valueMethod == null) { - return null; - } - - AnnotationValue value = mirror.getElementValues().get(valueMethod); - if (value == null) { - value = valueMethod.getDefaultValue(); - } - - return value; - } - - private static class AnnotationValueVisitorImpl extends AbstractAnnotationValueVisitor7 { - - @Override - public Object visitBoolean(boolean b, Void p) { - return Boolean.valueOf(b); - } - - @Override - public Object visitByte(byte b, Void p) { - return Byte.valueOf(b); - } - - @Override - public Object visitChar(char c, Void p) { - return c; - } - - @Override - public Object visitDouble(double d, Void p) { - return d; - } - - @Override - public Object visitFloat(float f, Void p) { - return f; - } - - @Override - public Object visitInt(int i, Void p) { - return i; - } - - @Override - public Object visitLong(long i, Void p) { - return i; - } - - @Override - public Object visitShort(short s, Void p) { - return s; - } - - @Override - public Object visitString(String s, Void p) { - return s; - } - - @Override - public Object visitType(TypeMirror t, Void p) { - return t; - } - - @Override - public Object visitEnumConstant(VariableElement c, Void p) { - return c; - } - - @Override - public Object visitAnnotation(AnnotationMirror a, Void p) { - return a; - } - - @Override - public Object visitArray(List vals, Void p) { - return vals; - } - - } - - public static boolean getAnnotationValueBoolean(AnnotationMirror mirror, String name) { - return (Boolean) getAnnotationValue(mirror, name).getValue(); - } - - public static String printException(Throwable e) { - StringWriter string = new StringWriter(); - PrintWriter writer = new PrintWriter(string); - e.printStackTrace(writer); - writer.flush(); - return e.getMessage() + "\r\n" + string.toString(); - } - - public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, Element element, Class annotationClass) { - return findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), annotationClass); - } - - public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, List mirrors, Class annotationClass) { - TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName()); - return findAnnotationMirror(mirrors, expectedAnnotationType); - } - - public static AnnotationMirror findAnnotationMirror(List mirrors, TypeElement expectedAnnotationType) { - for (AnnotationMirror mirror : mirrors) { - DeclaredType annotationType = mirror.getAnnotationType(); - TypeElement actualAnnotationType = (TypeElement) annotationType.asElement(); - if (actualAnnotationType.equals(expectedAnnotationType)) { - return mirror; - } - } - return null; - } - - private static PackageElement findPackageElement(Element type) { - List hierarchy = getElementHierarchy(type); - for (Element element : hierarchy) { - if (element.getKind() == ElementKind.PACKAGE) { - return (PackageElement) element; - } - } - return null; - } - - public static String firstLetterUpperCase(String name) { - if (name == null || name.isEmpty()) { - return name; - } - return Character.toUpperCase(name.charAt(0)) + name.substring(1, name.length()); - } - - public static String firstLetterLowerCase(String name) { - if (name == null || name.isEmpty()) { - return name; - } - return Character.toLowerCase(name.charAt(0)) + name.substring(1, name.length()); - } - - private static ExecutableElement getDeclaredMethod(TypeElement element, String name, TypeMirror[] params) { - List methods = ElementFilter.methodsIn(element.getEnclosedElements()); - method: for (ExecutableElement method : methods) { - if (!method.getSimpleName().toString().equals(name)) { - continue; - } - if (method.getParameters().size() != params.length) { - continue; - } - for (int i = 0; i < params.length; i++) { - TypeMirror param1 = params[i]; - TypeMirror param2 = method.getParameters().get(i).asType(); - if (param1.getKind() != TypeKind.TYPEVAR && param2.getKind() != TypeKind.TYPEVAR) { - if (!getQualifiedName(param1).equals(getQualifiedName(param2))) { - continue method; - } - } - } - return method; - } - return null; - } - - private static boolean isDeclaredMethod(TypeElement element, String name, TypeMirror[] params) { - return getDeclaredMethod(element, name, params) != null; - } - - public static boolean isDeclaredMethodInSuperType(TypeElement element, String name, TypeMirror[] params) { - List superElements = getSuperTypes(element); - - for (TypeElement typeElement : superElements) { - if (isDeclaredMethod(typeElement, name, params)) { - return true; - } - } - return false; - } - - private static ExecutableElement getDeclaredMethodInSuperType(TypeElement element, String name, TypeMirror[] params) { - List superElements = getSuperTypes(element); - - for (TypeElement typeElement : superElements) { - ExecutableElement declared = getDeclaredMethod(typeElement, name, params); - if (declared != null) { - return declared; - } - } - return null; - } - - public static ExecutableElement getDeclaredMethodRecursive(TypeElement element, String name, TypeMirror[] params) { - ExecutableElement declared = getDeclaredMethod(element, name, params); - if (declared != null) { - return declared; - } - return getDeclaredMethodInSuperType(element, name, params); - } - - public static boolean typeEquals(TypeMirror type1, TypeMirror type2) { - if (type1 == null && type2 == null) { - return true; - } else if (type1 == null || type2 == null) { - return false; - } else if (type1 == type2) { - return true; - } - String qualified1 = getQualifiedName(type1); - String qualified2 = getQualifiedName(type2); - - if (type1.getKind() == TypeKind.ARRAY || type2.getKind() == TypeKind.ARRAY) { - if (type1.getKind() == TypeKind.ARRAY && type2.getKind() == TypeKind.ARRAY) { - return typeEquals(((ArrayType) type1).getComponentType(), ((ArrayType) type2).getComponentType()); - } else { - return false; - } - } - return qualified1.equals(qualified2); - } - - public static int compareByTypeHierarchy(TypeMirror t1, TypeMirror t2) { - if (typeEquals(t1, t2)) { - return 0; - } - Set t1SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t1))); - if (t1SuperSet.contains(getQualifiedName(t2))) { - return -1; - } - - Set t2SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t2))); - if (t2SuperSet.contains(getQualifiedName(t1))) { - return 1; - } - return 0; - } - - public static boolean canThrowType(List thrownTypes, TypeMirror exceptionType) { - if (Utils.containsType(thrownTypes, exceptionType)) { - return true; - } - - if (isRuntimeException(exceptionType)) { - return true; - } - - // search for any super types - TypeElement exceptionTypeElement = fromTypeMirror(exceptionType); - List superTypes = getSuperTypes(exceptionTypeElement); - for (TypeElement typeElement : superTypes) { - if (Utils.containsType(thrownTypes, typeElement.asType())) { - return true; - } - } - - return false; - } - - public static Modifier getVisibility(Set modifier) { - for (Modifier mod : modifier) { - if (mod == Modifier.PUBLIC || mod == Modifier.PRIVATE || mod == Modifier.PROTECTED) { - return mod; - } - } - return null; - } - - private static boolean isRuntimeException(TypeMirror type) { - Set typeSuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(type))); - String typeName = getQualifiedName(type); - if (!typeSuperSet.contains(Throwable.class.getCanonicalName()) && !typeName.equals(Throwable.class.getCanonicalName())) { - throw new IllegalArgumentException("Given type does not extend Throwable."); - } - return typeSuperSet.contains(RuntimeException.class.getCanonicalName()) || typeName.equals(RuntimeException.class.getCanonicalName()); - } - - private static boolean containsType(Collection collection, TypeMirror type) { - for (TypeMirror otherTypeMirror : collection) { - if (typeEquals(otherTypeMirror, type)) { - return true; - } - } - return false; - } - - public static boolean isTopLevelClass(TypeMirror importType) { - TypeElement type = fromTypeMirror(importType); - if (type != null && type.getEnclosingElement() != null) { - return !type.getEnclosingElement().getKind().isClass(); - } - return true; - } - - public static boolean isObject(TypeMirror actualType) { - return actualType.getKind() == TypeKind.DECLARED && getQualifiedName(actualType).equals("java.lang.Object"); - } - - public static boolean isFieldAccessible(Element element, VariableElement variable) { - TypeElement type = Utils.findNearestEnclosingType(element); - TypeElement varType = Utils.findNearestEnclosingType(variable); - - while (type != null) { - if (typeEquals(type.asType(), varType.asType())) { - return true; - } - if (type.getSuperclass() != null) { - type = Utils.fromTypeMirror(type.getSuperclass()); - } else { - type = null; - } - } - return false; - } -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/ExtensionContext.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/ExtensionContext.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.api; - -import javax.annotation.processing.*; - -import com.oracle.truffle.dsl.processor.api.element.*; - -public interface ExtensionContext { - - ProcessingEnvironment getProcessingEnvironment(); - - RoundEnvironment getRoundEnvironment(); - - WritableElementFactory getElementFactory(); - - void addGeneratedElement(WritableElement element); - - void removeGeneratedElement(WritableElement element); - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableAnnotationMirror.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableAnnotationMirror.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.api.element; - -import javax.lang.model.element.*; - -public interface WritableAnnotationMirror extends AnnotationMirror { - - void setElementValue(ExecutableElement valueName, AnnotationValue value); - - AnnotationValue getElementValue(ExecutableElement valueName); - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableElement.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableElement.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.api.element; - -import javax.lang.model.element.*; - -public interface WritableElement extends Element { - - void addAnnotationMirror(AnnotationMirror annotationMirror); - - void removeAnnotationMirror(AnnotationMirror annotationMirror); - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableElementFactory.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableElementFactory.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.api.element; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -public interface WritableElementFactory { - - WritableExecutableElement cloneExecutableElement(ExecutableElement method); - - WritableVariableElement cloneVariableElement(VariableElement parameter); - - WritableAnnotationMirror cloneAnnotationMirror(AnnotationMirror mirror); - - WritableVariableElement createParameter(TypeMirror type, String simpleName); - - WritableExecutableElement createExecutableElement(TypeMirror returnType, String methodName); - - WritableAnnotationMirror createAnnotationMirror(DeclaredType annotationClass); - - Name createName(String name); - - AnnotationValue createAnnotationValue(Object value); - - TypeMirror createTypeMirror(Class javaClass); - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableExecutableElement.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableExecutableElement.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.api.element; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -public interface WritableExecutableElement extends ExecutableElement, WritableElement { - - void setReturnType(TypeMirror type); - - void setDefaultValue(AnnotationValue defaultValue); - - void addParameter(VariableElement parameter); - - void removeParameter(VariableElement parameter); - - void addThrownType(TypeMirror thrownType); - - void removeThrownType(TypeMirror thrownType); - - void setSimpleName(Name name); - - void setVarArgs(boolean varargs); - - void setBody(String body); - - String getBody(); -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableVariableElement.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableVariableElement.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.api.element; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -public interface WritableVariableElement extends VariableElement, WritableElement { - - void setSimpleName(Name name); - - void setType(TypeMirror type); - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeAnnotationMirror.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeAnnotationMirror.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.ast; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.api.element.*; - -public class CodeAnnotationMirror implements WritableAnnotationMirror { - - private final DeclaredType annotationType; - private final Map values = new LinkedHashMap<>(); - - public CodeAnnotationMirror(DeclaredType annotationType) { - this.annotationType = annotationType; - } - - @Override - public DeclaredType getAnnotationType() { - return annotationType; - } - - @Override - public Map getElementValues() { - return values; - } - - @Override - public AnnotationValue getElementValue(ExecutableElement method) { - return values.get(method); - } - - @Override - public void setElementValue(ExecutableElement method, AnnotationValue value) { - values.put(method, value); - } - - public ExecutableElement findExecutableElement(String name) { - return Utils.findExecutableElement(annotationType, name); - } - - public static CodeAnnotationMirror clone(AnnotationMirror mirror) { - CodeAnnotationMirror copy = new CodeAnnotationMirror(mirror.getAnnotationType()); - for (ExecutableElement key : mirror.getElementValues().keySet()) { - copy.setElementValue(key, mirror.getElementValues().get(key)); - } - return copy; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeAnnotationValue.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeAnnotationValue.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.ast; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -public class CodeAnnotationValue implements AnnotationValue { - - private final Object value; - - public CodeAnnotationValue(Object value) { - Objects.requireNonNull(value); - if ((value instanceof AnnotationMirror) || (value instanceof List) || (value instanceof Boolean) || (value instanceof Byte) || (value instanceof Character) || (value instanceof Double) || - (value instanceof VariableElement) || (value instanceof Float) || (value instanceof Integer) || (value instanceof Long) || (value instanceof Short) || - (value instanceof String) || (value instanceof TypeMirror)) { - this.value = value; - } else { - throw new IllegalArgumentException("Invalid annotation value type " + value.getClass().getName()); - } - } - - @Override - public Object getValue() { - return value; - } - - @SuppressWarnings("unchecked") - @Override - public R accept(AnnotationValueVisitor v, P p) { - if (value instanceof AnnotationMirror) { - return v.visitAnnotation((AnnotationMirror) value, p); - } else if (value instanceof List) { - return v.visitArray((List) value, p); - } else if (value instanceof Boolean) { - return v.visitBoolean((boolean) value, p); - } else if (value instanceof Byte) { - return v.visitByte((byte) value, p); - } else if (value instanceof Character) { - return v.visitChar((char) value, p); - } else if (value instanceof Double) { - return v.visitDouble((double) value, p); - } else if (value instanceof VariableElement) { - return v.visitEnumConstant((VariableElement) value, p); - } else if (value instanceof Float) { - return v.visitFloat((float) value, p); - } else if (value instanceof Integer) { - return v.visitInt((int) value, p); - } else if (value instanceof Long) { - return v.visitLong((long) value, p); - } else if (value instanceof Short) { - return v.visitShort((short) value, p); - } else if (value instanceof String) { - return v.visitString((String) value, p); - } else if (value instanceof TypeMirror) { - return v.visitType((TypeMirror) value, p); - } else { - return v.visitUnknown(this, p); - } - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeCompilationUnit.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeCompilationUnit.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.ast; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -public class CodeCompilationUnit extends CodeElement { - - public CodeCompilationUnit() { - super(Collections. emptySet()); - } - - @Override - public TypeMirror asType() { - throw new UnsupportedOperationException(); - } - - @Override - public ElementKind getKind() { - return ElementKind.OTHER; - } - - @Override - public Name getSimpleName() { - throw new UnsupportedOperationException(); - } - - @Override - public R accept(ElementVisitor v, P p) { - for (Element type : getEnclosedElements()) { - if (type.getKind().isClass()) { - type.accept(v, p); - } else { - throw new ClassCastException(type.getClass().getName()); - } - } - return null; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeElement.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeElement.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,367 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.ast; - -import java.io.*; -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; - -import com.oracle.truffle.dsl.processor.api.element.*; -import com.oracle.truffle.dsl.processor.codewriter.*; - -public abstract class CodeElement implements WritableElement, GeneratedElement { - - private final Set modifiers; - private List annotations; - private List enclosedElements; - - private Element enclosingElement; - - private Element generatorElement; - private AnnotationMirror generatorAnnotationMirror; - - public CodeElement() { - this.modifiers = new LinkedHashSet<>(); - } - - @Override - public void setGeneratorAnnotationMirror(AnnotationMirror mirror) { - this.generatorAnnotationMirror = mirror; - } - - @Override - public void setGeneratorElement(Element element) { - this.generatorElement = element; - } - - @Override - public AnnotationMirror getGeneratorAnnotationMirror() { - return generatorAnnotationMirror; - } - - @Override - public Element getGeneratorElement() { - return generatorElement; - } - - public CodeElement(Set modifiers) { - this.modifiers = new LinkedHashSet<>(modifiers); - } - - public E add(E element) { - if (element == null) { - throw new NullPointerException(); - } - getEnclosedElements().add(element); - return element; - } - - public E addOptional(E element) { - if (element != null) { - add(element); - } - return element; - } - - public void remove(E element) { - getEnclosedElements().remove(element); - } - - @Override - public Set getModifiers() { - return modifiers; - } - - @Override - public List getEnclosedElements() { - if (enclosedElements == null) { - enclosedElements = parentableList(this, new ArrayList()); - } - return enclosedElements; - } - - @Override - public List getAnnotationMirrors() { - if (annotations == null) { - annotations = parentableList(this, new ArrayList()); - } - return annotations; - } - - /** - * Support JDK8 langtools. - * - * @param annotationType - */ - public A[] getAnnotationsByType(Class annotationType) { - throw new UnsupportedOperationException(); - } - - /** - * Support for some JDK8 builds. (remove after jdk8 is released) - * - * @param annotationType - */ - public A[] getAnnotations(Class annotationType) { - throw new UnsupportedOperationException(); - } - - /** - * Support for some JDK8 builds. (remove after jdk8 is released) - * - * @param annotationType - */ - public A getAnnotation(Class annotationType) { - throw new UnsupportedOperationException(); - } - - @Override - public void addAnnotationMirror(AnnotationMirror annotationMirror) { - getAnnotationMirrors().add(annotationMirror); - } - - public void removeAnnotationMirror(AnnotationMirror annotationMirror) { - getAnnotationMirrors().remove(annotationMirror); - } - - void setEnclosingElement(Element parent) { - this.enclosingElement = parent; - } - - public Element getEnclosingElement() { - return enclosingElement; - } - - public CodeTypeElement getEnclosingClass() { - Element p = enclosingElement; - while (p != null && p.getKind() != ElementKind.CLASS && p.getKind() != ElementKind.ENUM) { - p = p.getEnclosingElement(); - } - return (CodeTypeElement) p; - } - - List parentableList(Element parent, List list) { - return new ParentableList<>(parent, list); - } - - @Override - public String toString() { - StringBuilderCodeWriter codeWriter = new StringBuilderCodeWriter(); - accept(codeWriter, null); - return codeWriter.getString(); - } - - private static class StringBuilderCodeWriter extends AbstractCodeWriter { - - public StringBuilderCodeWriter() { - this.writer = new CharArrayWriter(); - } - - @Override - protected Writer createWriter(CodeTypeElement clazz) throws IOException { - return writer; - } - - public String getString() { - return new String(((CharArrayWriter) writer).toCharArray()).trim(); - } - - } - - private static class ParentableList implements List { - - private final Element parent; - private final List delegate; - - public ParentableList(Element parent, List delegate) { - this.parent = parent; - this.delegate = delegate; - } - - private void addImpl(T element) { - if (element != null) { - if (element instanceof CodeElement) { - ((CodeElement) element).setEnclosingElement(parent); - } - } - } - - private static void removeImpl(Object element) { - if (element instanceof CodeElement) { - ((CodeElement) element).setEnclosingElement(null); - } - } - - @Override - public int size() { - return delegate.size(); - } - - @Override - public boolean isEmpty() { - return delegate.isEmpty(); - } - - @Override - public boolean contains(Object o) { - return delegate.contains(o); - } - - @Override - public Iterator iterator() { - return delegate.iterator(); - } - - @Override - public Object[] toArray() { - return delegate.toArray(); - } - - @Override - public E[] toArray(E[] a) { - return delegate.toArray(a); - } - - @Override - public boolean add(T e) { - addImpl(e); - return delegate.add(e); - } - - @Override - public boolean remove(Object o) { - boolean removed = delegate.remove(o); - if (removed) { - removeImpl(o); - } - return removed; - } - - @Override - public boolean containsAll(Collection c) { - return delegate.containsAll(c); - } - - @Override - public boolean addAll(Collection c) { - if (c != null) { - for (T t : c) { - addImpl(t); - } - } - return delegate.addAll(c); - } - - @Override - public boolean addAll(int index, Collection c) { - if (c != null) { - for (T t : c) { - addImpl(t); - } - } - return delegate.addAll(index, c); - } - - @Override - public boolean removeAll(Collection c) { - if (c != null) { - for (Object t : c) { - removeImpl(t); - } - } - return delegate.removeAll(c); - } - - @Override - public String toString() { - return delegate.toString(); - } - - @Override - public boolean retainAll(Collection c) { - throw new UnsupportedOperationException("Not supported by parentable list"); - } - - @Override - public void clear() { - for (Object e : this) { - removeImpl(e); - } - delegate.clear(); - } - - @Override - public T get(int index) { - return delegate.get(index); - } - - @Override - public T set(int index, T element) { - removeImpl(delegate.get(index)); - addImpl(element); - return delegate.set(index, element); - } - - @Override - public void add(int index, T element) { - addImpl(element); - delegate.add(index, element); - } - - @Override - public T remove(int index) { - T element = delegate.remove(index); - removeImpl(element); - return element; - } - - @Override - public int indexOf(Object o) { - return delegate.indexOf(o); - } - - @Override - public int lastIndexOf(Object o) { - return delegate.lastIndexOf(o); - } - - @Override - public ListIterator listIterator() { - return delegate.listIterator(); - } - - @Override - public ListIterator listIterator(int index) { - return delegate.listIterator(index); - } - - @Override - public List subList(int fromIndex, int toIndex) { - return new ParentableList<>(parent, delegate.subList(fromIndex, toIndex)); - } - - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeElementScanner.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeElementScanner.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.ast; - -import javax.lang.model.element.*; -import javax.lang.model.util.*; - -public abstract class CodeElementScanner extends ElementScanner7 { - - @Override - public final R visitExecutable(ExecutableElement e, P p) { - return visitExecutable(cast(e, CodeExecutableElement.class), p); - } - - public R visitExecutable(CodeExecutableElement e, P p) { - R ret = super.visitExecutable(e, p); - if (e.getBodyTree() != null) { - visitTree(e.getBodyTree(), p); - } - return ret; - } - - @Override - public R visitPackage(PackageElement e, P p) { - return super.visitPackage(e, p); - } - - @Override - public final R visitType(TypeElement e, P p) { - return visitType(cast(e, CodeTypeElement.class), p); - } - - public R visitType(CodeTypeElement e, P p) { - return super.visitType(e, p); - } - - @Override - public R visitTypeParameter(TypeParameterElement e, P p) { - return super.visitTypeParameter(e, p); - } - - private static E cast(Element element, Class clazz) { - return clazz.cast(element); - } - - public void visitTree(CodeTree e, P p) { - for (CodeTree tree : e.getEnclosedElements()) { - tree.acceptCodeElementScanner(this, p); - } - } - - @SuppressWarnings("unused") - public void visitImport(CodeImport e, P p) { - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeExecutableElement.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeExecutableElement.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.ast; - -import java.util.*; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.api.element.*; - -public class CodeExecutableElement extends CodeElement implements WritableExecutableElement { - - private final List throwables = new ArrayList<>(); - private final List parameters = parentableList(this, new ArrayList()); - - private TypeMirror returnType; - private Name name; - - private CodeTree bodyTree; - private String body; - private AnnotationValue defaultValue; - private boolean varArgs; - - public CodeExecutableElement(TypeMirror returnType, String name) { - super(Utils.modifiers()); - this.returnType = returnType; - this.name = CodeNames.of(name); - } - - public CodeExecutableElement(Set modifiers, TypeMirror returnType, String name, CodeVariableElement... parameters) { - super(modifiers); - this.returnType = returnType; - this.name = CodeNames.of(name); - for (CodeVariableElement codeParameter : parameters) { - addParameter(codeParameter); - } - } - - /* Support JDK8 langtools. */ - public boolean isDefault() { - return false; - } - - @Override - public List getThrownTypes() { - return throwables; - } - - @Override - public TypeMirror asType() { - return returnType; - } - - @Override - public ElementKind getKind() { - if (getReturnType() == null) { - return ElementKind.CONSTRUCTOR; - } else { - return ElementKind.METHOD; - } - } - - @Override - public List getTypeParameters() { - return Collections.emptyList(); - } - - @Override - public void setVarArgs(boolean varargs) { - this.varArgs = varargs; - } - - @Override - public boolean isVarArgs() { - return varArgs; - } - - @Override - public void setDefaultValue(AnnotationValue defaultValue) { - this.defaultValue = defaultValue; - } - - @Override - public AnnotationValue getDefaultValue() { - return defaultValue; - } - - @Override - public Name getSimpleName() { - return name; - } - - public CodeTreeBuilder getBuilder() { - CodeTree tree = this.bodyTree; - return createBuilder().tree(tree); - } - - public CodeTreeBuilder createBuilder() { - CodeTreeBuilder builder = new CodeTreeBuilder(null); - this.bodyTree = builder.getTree(); - this.bodyTree.setEnclosingElement(this); - this.body = null; - return builder; - } - - public void setBodyTree(CodeTree body) { - this.bodyTree = body; - } - - public CodeTree getBodyTree() { - return bodyTree; - } - - public TypeMirror getReturnType() { - return returnType; - } - - @Override - public List getParameters() { - return parameters; - } - - public TypeMirror[] getParameterTypes() { - TypeMirror[] types = new TypeMirror[getParameters().size()]; - for (int i = 0; i < types.length; i++) { - types[i] = parameters.get(i).asType(); - } - return types; - } - - @Override - public void setReturnType(TypeMirror type) { - returnType = type; - } - - @Override - public void addParameter(VariableElement parameter) { - parameters.add(parameter); - } - - @Override - public void removeParameter(VariableElement parameter) { - parameters.remove(parameter); - } - - public void removeParameter(String varName) { - VariableElement remove = null; - for (VariableElement var : getParameters()) { - if (var.getSimpleName().toString().equals(varName)) { - remove = var; - break; - } - } - if (remove != null) { - parameters.remove(remove); - } - } - - @Override - public void addThrownType(TypeMirror thrownType) { - throwables.add(thrownType); - } - - @Override - public void removeThrownType(TypeMirror thrownType) { - throwables.remove(thrownType); - } - - @Override - public void setSimpleName(Name name) { - this.name = name; - } - - @Override - public void setBody(String body) { - this.body = body; - } - - @Override - public String getBody() { - return body; - } - - @Override - public R accept(ElementVisitor v, P p) { - return v.visitExecutable(this, p); - } - - public static CodeExecutableElement clone(@SuppressWarnings("unused") ProcessingEnvironment env, ExecutableElement method) { - CodeExecutableElement copy = new CodeExecutableElement(method.getReturnType(), method.getSimpleName().toString()); - for (TypeMirror thrownType : method.getThrownTypes()) { - copy.addThrownType(thrownType); - } - copy.setDefaultValue(method.getDefaultValue()); - - for (AnnotationMirror mirror : method.getAnnotationMirrors()) { - copy.addAnnotationMirror(mirror); - } - for (VariableElement var : method.getParameters()) { - copy.addParameter(CodeVariableElement.clone(var)); - } - for (Element element : method.getEnclosedElements()) { - copy.add(element); - } - copy.getModifiers().addAll(method.getModifiers()); - copy.setVarArgs(method.isVarArgs()); - return copy; - } - - public TypeMirror getReceiverType() { - throw new UnsupportedOperationException(); - } -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeImport.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeImport.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.ast; - -import javax.lang.model.type.*; - -public class CodeImport implements Comparable { - - private final TypeMirror importType; - private final String importString; - private final boolean staticImport; - - public CodeImport(TypeMirror importedType, String importString, boolean staticImport) { - this.importType = importedType; - this.importString = importString; - this.staticImport = staticImport; - } - - public TypeMirror getImportType() { - return importType; - } - - public boolean isStaticImport() { - return staticImport; - } - - public String getImportString() { - return importString; - } - - @Override - public int compareTo(CodeImport o) { - if (staticImport && !o.staticImport) { - return 1; - } else if (!staticImport && o.staticImport) { - return -1; - } else { - return importString.compareTo(o.getImportString()); - } - } - - public

    void accept(CodeElementScanner s, P p) { - s.visitImport(this, p); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((importString == null) ? 0 : importString.hashCode()); - result = prime * result + (staticImport ? 1231 : 1237); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - CodeImport other = (CodeImport) obj; - if (importString == null) { - if (other.importString != null) { - return false; - } - } else if (!importString.equals(other.importString)) { - return false; - } - if (staticImport != other.staticImport) { - return false; - } - return true; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeNames.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeNames.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.ast; - -import java.util.*; - -import javax.lang.model.element.*; - -public abstract class CodeNames { - - private static Map names = new HashMap<>(); - - public static Name of(String value) { - Name name = names.get(value); - if (name == null) { - name = new NameImpl(value); - names.put(value, name); - } - return name; - } - - private static class NameImpl implements Name { - - private final String name; - - public NameImpl(String name) { - this.name = name; - } - - @Override - public int length() { - return name.length(); - } - - @Override - public char charAt(int index) { - return name.charAt(index); - } - - @Override - public CharSequence subSequence(int start, int end) { - return name.subSequence(start, end); - } - - @Override - public boolean contentEquals(CharSequence cs) { - return name.contentEquals(cs); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Name) { - return ((Name) obj).contentEquals(name); - } - return super.equals(obj); - } - - @Override - public int hashCode() { - return name.hashCode(); - } - - @Override - public String toString() { - return name; - } - - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTree.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTree.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.ast; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -public class CodeTree extends CodeElement { - - private final CodeTreeKind kind; - - private final TypeMirror type; - private final String string; - - public CodeTree(CodeTreeKind kind, TypeMirror type, String string) { - this.kind = kind; - this.type = type; - this.string = string; - } - - public TypeMirror getType() { - return type; - } - - public CodeTreeKind getCodeKind() { - return kind; - } - - public String getString() { - return string; - } - - public

    void acceptCodeElementScanner(CodeElementScanner s, P p) { - s.visitTree(this, p); - } - - @Override - public TypeMirror asType() { - return type; - } - - @Override - public ElementKind getKind() { - return ElementKind.OTHER; - } - - @Override - public Name getSimpleName() { - return CodeNames.of(getString()); - } - - @Override - public R accept(ElementVisitor v, P p) { - if (v instanceof CodeElementScanner) { - acceptCodeElementScanner((CodeElementScanner) v, p); - return null; - } else { - throw new UnsupportedOperationException(); - } - } -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeBuilder.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeBuilder.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,884 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.ast; - -import static com.oracle.truffle.dsl.processor.ast.CodeTreeKind.*; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.*; - -public class CodeTreeBuilder { - - private final CodeTreeBuilder parent; - - private BuilderCodeTree currentElement; - private final BuilderCodeTree root; - - private int treeCount; - - public CodeTreeBuilder(CodeTreeBuilder parent) { - this.root = new BuilderCodeTree(GROUP, null, null); - this.currentElement = root; - this.parent = parent; - } - - @Override - public String toString() { - return root.toString(); - } - - public int getTreeCount() { - return treeCount; - } - - public boolean isEmpty() { - return treeCount == 0; - } - - public CodeTreeBuilder statement(String statement) { - return startStatement().string(statement).end(); - } - - public CodeTreeBuilder statement(CodeTree statement) { - return startStatement().tree(statement).end(); - } - - public static CodeTreeBuilder createBuilder() { - return new CodeTreeBuilder(null); - } - - public static CodeTree singleString(String s) { - return new CodeTreeBuilder(null).string(s).getTree(); - } - - public static CodeTree singleType(TypeMirror s) { - return new CodeTreeBuilder(null).type(s).getTree(); - } - - private CodeTreeBuilder push(CodeTreeKind kind) { - return push(new BuilderCodeTree(kind, null, null)); - } - - private CodeTreeBuilder push(String string) { - return push(new BuilderCodeTree(CodeTreeKind.STRING, null, string)); - } - - private CodeTreeBuilder push(TypeMirror type) { - return push(new BuilderCodeTree(CodeTreeKind.TYPE, type, null)); - } - - private CodeTreeBuilder push(CodeTreeKind kind, TypeMirror type, String string) { - return push(new BuilderCodeTree(kind, type, string)); - } - - private CodeTreeBuilder push(BuilderCodeTree tree) { - if (currentElement != null) { - if (!removeLastIfEnqueued(tree)) { - return this; - } - currentElement.add(tree); - } - switch (tree.getCodeKind()) { - case COMMA_GROUP: - case GROUP: - case INDENT: - currentElement = tree; - break; - } - treeCount++; - return this; - } - - private boolean removeLastIfEnqueued(BuilderCodeTree tree) { - if (tree.getCodeKind() == REMOVE_LAST) { - return !clearLastRec(tree.removeLast, currentElement.getEnclosedElements()); - } - List childTree = tree.getEnclosedElements(); - if (!childTree.isEmpty()) { - CodeTree last = childTree.get(0); - if (last instanceof BuilderCodeTree) { - if (!removeLastIfEnqueued((BuilderCodeTree) last)) { - childTree.remove(0); - } - } - } - return true; - } - - private void clearLast(CodeTreeKind kind) { - if (clearLastRec(kind, currentElement.getEnclosedElements())) { - treeCount--; - } else { - // delay clearing the last - BuilderCodeTree tree = new BuilderCodeTree(REMOVE_LAST, null, null); - tree.removeLast = kind; - push(tree); - } - } - - public CodeTreeBuilder startStatement() { - startGroup(); - registerCallBack(new EndCallback() { - - @Override - public void beforeEnd() { - string(";").newLine(); - } - - @Override - public void afterEnd() { - } - }); - return this; - } - - public CodeTreeBuilder startGroup() { - return push(CodeTreeKind.GROUP); - } - - public CodeTreeBuilder startCommaGroup() { - return push(CodeTreeKind.COMMA_GROUP); - } - - public CodeTreeBuilder startCall(String callSite) { - return startCall((CodeTree) null, callSite); - } - - public CodeTreeBuilder startCall(String receiver, String callSite) { - return startCall(singleString(receiver), callSite); - } - - public CodeTreeBuilder startCall(CodeTree receiver, String callSite) { - if (receiver == null) { - return startGroup().string(callSite).startParanthesesCommaGroup().endAfter(); - } else { - return startGroup().tree(receiver).string(".").string(callSite).startParanthesesCommaGroup().endAfter(); - } - } - - public CodeTreeBuilder startStaticCall(TypeMirror type, String methodName) { - return startGroup().push(CodeTreeKind.STATIC_METHOD_REFERENCE, type, methodName).startParanthesesCommaGroup().endAfter(); - } - - public CodeTreeBuilder startStaticCall(ExecutableElement method) { - return startStaticCall(Utils.findNearestEnclosingType(method).asType(), method.getSimpleName().toString()); - } - - public CodeTreeBuilder staticReference(TypeMirror type, String fieldName) { - return push(CodeTreeKind.STATIC_FIELD_REFERENCE, type, fieldName); - } - - private CodeTreeBuilder endAndWhitespaceAfter() { - registerCallBack(new EndCallback() { - - @Override - public void beforeEnd() { - } - - @Override - public void afterEnd() { - string(" "); - end(); - } - }); - return this; - } - - private CodeTreeBuilder endAfter() { - registerCallBack(new EndCallback() { - - @Override - public void beforeEnd() { - } - - @Override - public void afterEnd() { - end(); - } - }); - return this; - } - - private CodeTreeBuilder startParanthesesCommaGroup() { - startGroup(); - string("(").startCommaGroup(); - registerCallBack(new EndCallback() { - - @Override - public void beforeEnd() { - } - - @Override - public void afterEnd() { - string(")"); - } - }); - endAfter(); - return this; - } - - private CodeTreeBuilder startCurlyBracesCommaGroup() { - startGroup(); - string("{").startCommaGroup(); - registerCallBack(new EndCallback() { - - @Override - public void beforeEnd() { - } - - @Override - public void afterEnd() { - string("}"); - } - }); - endAfter(); - return this; - } - - public CodeTreeBuilder startParantheses() { - startGroup(); - string("(").startGroup(); - registerCallBack(new EndCallback() { - - @Override - public void beforeEnd() { - } - - @Override - public void afterEnd() { - string(")"); - } - }); - endAfter(); - return this; - } - - public CodeTreeBuilder doubleQuote(String s) { - return startGroup().string("\"" + s + "\"").end(); - } - - public CodeTreeBuilder string(String chunk1) { - return push(chunk1); - } - - public CodeTreeBuilder string(String chunk1, String chunk2) { - return push(GROUP).string(chunk1).string(chunk2).end(); - } - - public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3) { - return push(GROUP).string(chunk1).string(chunk2).string(chunk3).end(); - } - - public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4) { - return push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4).end(); - } - - public CodeTreeBuilder tree(CodeTree treeToAdd) { - if (treeToAdd instanceof BuilderCodeTree) { - return push((BuilderCodeTree) treeToAdd).end(); - } else { - BuilderCodeTree tree = new BuilderCodeTree(GROUP, null, null); - tree.add(treeToAdd); - return push(tree).end(); - } - } - - public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4, String... chunks) { - push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4); - for (int i = 0; i < chunks.length; i++) { - string(chunks[i]); - } - return end(); - } - - public CodeTreeBuilder dot() { - return string("."); - } - - public CodeTreeBuilder newLine() { - return push(NEW_LINE); - } - - public CodeTreeBuilder startWhile() { - return startGroup().string("while ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter(); - } - - public CodeTreeBuilder startDoBlock() { - return startGroup().string("do ").startBlock(); - } - - public CodeTreeBuilder startDoWhile() { - clearLast(CodeTreeKind.NEW_LINE); - return startStatement().string(" while ").startParanthesesCommaGroup().endAfter().startGroup().endAfter(); - } - - public CodeTreeBuilder startIf() { - return startGroup().string("if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter(); - } - - public CodeTreeBuilder startFor() { - return startGroup().string("for ").startParantheses().endAndWhitespaceAfter().startGroup().endAfter(); - } - - public boolean startIf(boolean elseIf) { - if (elseIf) { - startElseIf(); - } else { - startIf(); - } - return true; - } - - public CodeTreeBuilder startElseIf() { - clearLast(CodeTreeKind.NEW_LINE); - return startGroup().string(" else if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter(); - } - - public CodeTreeBuilder startElseBlock() { - clearLast(CodeTreeKind.NEW_LINE); - return startGroup().string(" else ").startBlock().endAfter(); - } - - private boolean clearLastRec(CodeTreeKind kind, List children) { - for (int i = children.size() - 1; i >= 0; i--) { - CodeTree child = children.get(i); - if (child.getCodeKind() == kind) { - children.remove(children.get(i)); - return true; - } else { - if (clearLastRec(kind, child.getEnclosedElements())) { - return true; - } - } - } - return false; - } - - public CodeTreeBuilder startCase() { - startGroup().string("case "); - registerCallBack(new EndCallback() { - - @Override - public void beforeEnd() { - string(" :").newLine(); - } - - @Override - public void afterEnd() { - } - }); - return this; - } - - public CodeTreeBuilder caseDefault() { - return startGroup().string("default :").newLine().end(); - } - - public CodeTreeBuilder startSwitch() { - return startGroup().string("switch ").startParanthesesCommaGroup().endAndWhitespaceAfter(); - } - - public CodeTreeBuilder startReturn() { - ExecutableElement method = findMethod(); - if (method != null && Utils.isVoid(method.getReturnType())) { - startGroup(); - registerCallBack(new EndCallback() { - - @Override - public void beforeEnd() { - string(";").newLine(); // complete statement to execute - } - - @Override - public void afterEnd() { - string("return").string(";").newLine(); // emit a return; - } - }); - return this; - } else { - return startStatement().string("return "); - } - } - - public CodeTreeBuilder startAssert() { - return startStatement().string("assert "); - } - - public CodeTreeBuilder startNewArray(ArrayType arrayType, CodeTree size) { - startGroup().string("new ").type(arrayType.getComponentType()).string("["); - if (size != null) { - tree(size); - } - string("]"); - if (size == null) { - string(" "); - startCurlyBracesCommaGroup().endAfter(); - } - return this; - } - - public CodeTreeBuilder startNew(TypeMirror uninializedNodeClass) { - return startGroup().string("new ").type(uninializedNodeClass).startParanthesesCommaGroup().endAfter(); - } - - public CodeTreeBuilder startNew(String typeName) { - return startGroup().string("new ").string(typeName).startParanthesesCommaGroup().endAfter(); - } - - public CodeTreeBuilder startIndention() { - return push(CodeTreeKind.INDENT); - } - - public CodeTreeBuilder end(int times) { - for (int i = 0; i < times; i++) { - end(); - } - return this; - } - - public CodeTreeBuilder end() { - BuilderCodeTree tree = currentElement; - EndCallback callback = tree.getAtEndListener(); - if (callback != null) { - callback.beforeEnd(); - toParent(); - callback.afterEnd(); - } else { - toParent(); - } - return this; - } - - private void toParent() { - Element parentElement = currentElement.getEnclosingElement(); - if (currentElement != root) { - this.currentElement = (BuilderCodeTree) parentElement; - } else { - this.currentElement = root; - } - } - - public CodeTreeBuilder startBlock() { - startGroup(); - string("{").newLine().startIndention(); - registerCallBack(new EndCallback() { - - @Override - public void beforeEnd() { - } - - @Override - public void afterEnd() { - string("}").newLine(); - } - }); - endAfter(); - return this; - } - - private void registerCallBack(EndCallback callback) { - currentElement.registerAtEnd(callback); - } - - public CodeTreeBuilder defaultDeclaration(TypeMirror type, String name) { - if (!Utils.isVoid(type)) { - startStatement(); - type(type); - string(" "); - string(name); - string(" = "); - defaultValue(type); - end(); // statement - } - return this; - } - - public CodeTreeBuilder declaration(TypeMirror type, String name, String init) { - return declaration(type, name, singleString(init)); - } - - public CodeTreeBuilder declaration(String type, String name, CodeTree init) { - startStatement(); - string(type); - string(" "); - string(name); - if (init != null) { - string(" = "); - tree(init); - } - end(); // statement - return this; - } - - public CodeTreeBuilder declaration(String type, String name, String init) { - return declaration(type, name, singleString(init)); - } - - public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTree init) { - if (Utils.isVoid(type)) { - startStatement(); - tree(init); - end(); - } else { - startStatement(); - type(type); - string(" "); - string(name); - if (init != null) { - string(" = "); - tree(init); - } - end(); // statement - } - return this; - } - - public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTreeBuilder init) { - if (init == this) { - throw new IllegalArgumentException("Recursive builder usage."); - } - return declaration(type, name, init.getTree()); - } - - public CodeTreeBuilder declaration(String type, String name, CodeTreeBuilder init) { - if (init == this) { - throw new IllegalArgumentException("Recursive builder usage."); - } - return declaration(type, name, init.getTree()); - } - - public CodeTreeBuilder declaration(TypeMirror type, String name) { - return declaration(type, name, (CodeTree) null); - } - - public CodeTreeBuilder create() { - return new CodeTreeBuilder(this); - } - - public CodeTreeBuilder type(TypeMirror type) { - return push(type); - } - - public CodeTreeBuilder typeLiteral(TypeMirror type) { - return startGroup().type(type).string(".class").end(); - } - - private void assertRoot() { - if (currentElement != root) { - throw new IllegalStateException("CodeTreeBuilder was not ended properly."); - } - } - - public CodeTreeBuilder startCaseBlock() { - return startIndention(); - } - - public CodeTreeBuilder startThrow() { - return startStatement().string("throw "); - } - - public CodeTree getTree() { - assertRoot(); - return root; - } - - public CodeTree getRoot() { - return root; - } - - public CodeTreeBuilder cast(String baseClassName) { - string("(").string(baseClassName).string(") "); - return this; - } - - public CodeTreeBuilder cast(TypeMirror type, CodeTree content) { - if (Utils.isVoid(type)) { - tree(content); - return this; - } else if (type.getKind() == TypeKind.DECLARED && Utils.getQualifiedName(type).equals("java.lang.Object")) { - tree(content); - return this; - } else { - return startGroup().string("(").type(type).string(")").string(" ").tree(content).end(); - } - } - - public CodeTreeBuilder startSuperCall() { - return string("super").startParanthesesCommaGroup(); - } - - public CodeTreeBuilder returnFalse() { - return startReturn().string("false").end(); - } - - public CodeTreeBuilder returnStatement() { - return statement("return"); - } - - public ExecutableElement findMethod() { - Element element = currentElement; - while (element != null && (element.getKind() != ElementKind.METHOD && (element.getKind() != ElementKind.CONSTRUCTOR))) { - element = element.getEnclosingElement(); - } - ExecutableElement found = element != null ? (ExecutableElement) element : null; - if (found == null && parent != null) { - found = parent.findMethod(); - } - return found; - } - - public CodeTreeBuilder returnTrue() { - return startReturn().string("true").end(); - } - - public CodeTreeBuilder instanceOf(CodeTree var, CodeTree type) { - tree(var).string(" instanceof ").tree(type); - return this; - } - - public CodeTreeBuilder instanceOf(String var, String type) { - return instanceOf(singleString(var), singleString(type)); - } - - public CodeTreeBuilder instanceOf(String var, TypeMirror type) { - TypeElement element = Utils.fromTypeMirror(type); - if (element == null) { - throw new IllegalArgumentException("Cannot call instanceof for a non supported type: " + type.getKind()); - } - return instanceOf(singleString(var), singleType(type)); - } - - public CodeTreeBuilder defaultValue(TypeMirror mirror) { - switch (mirror.getKind()) { - case VOID: - return string(""); - case ARRAY: - case DECLARED: - case PACKAGE: - case NULL: - return string("null"); - case BOOLEAN: - return string("false"); - case BYTE: - return string("(byte) 0"); - case CHAR: - return string("(char) 0"); - case DOUBLE: - return string("0.0D"); - case LONG: - return string("0L"); - case INT: - return string("0"); - case FLOAT: - return string("0.0F"); - case SHORT: - return string("(short) 0"); - default: - throw new AssertionError(); - } - } - - public CodeTreeBuilder assertFalse() { - return startAssert().string("false").end(); - } - - public CodeTreeBuilder breakStatement() { - return statement("break"); - } - - public CodeTreeBuilder isNull() { - return string(" == null"); - } - - public CodeTreeBuilder isNotNull() { - return string(" != null"); - } - - public CodeTreeBuilder is(CodeTree tree) { - return string(" == ").tree(tree); - } - - public CodeTreeBuilder startTryBlock() { - return string("try ").startBlock(); - } - - public CodeTreeBuilder startCatchBlock(TypeMirror exceptionType, String localVarName) { - clearLast(CodeTreeKind.NEW_LINE); - string(" catch (").type(exceptionType).string(" ").string(localVarName).string(") "); - return startBlock(); - } - - public CodeTreeBuilder startFinallyBlock() { - clearLast(CodeTreeKind.NEW_LINE); - string(" finally "); - return startBlock(); - } - - public CodeTreeBuilder nullLiteral() { - return string("null"); - } - - private static class BuilderCodeTree extends CodeTree { - - private EndCallback atEndListener; - private CodeTreeKind removeLast; - - public BuilderCodeTree(CodeTreeKind kind, TypeMirror type, String string) { - super(kind, type, string); - } - - public void registerAtEnd(EndCallback atEnd) { - if (this.atEndListener != null) { - this.atEndListener = new CompoundCallback(this.atEndListener, atEnd); - } else { - this.atEndListener = atEnd; - } - } - - public EndCallback getAtEndListener() { - return atEndListener; - } - - @Override - public String toString() { - final StringBuilder b = new StringBuilder(); - acceptCodeElementScanner(new Printer(b), null); - return b.toString(); - } - - private static class CompoundCallback implements EndCallback { - - private final EndCallback callback1; - private final EndCallback callback2; - - public CompoundCallback(EndCallback callback1, EndCallback callback2) { - this.callback1 = callback1; - this.callback2 = callback2; - } - - @Override - public void afterEnd() { - callback1.afterEnd(); - callback2.afterEnd(); - } - - @Override - public void beforeEnd() { - callback1.beforeEnd(); - callback1.beforeEnd(); - } - } - - } - - private interface EndCallback { - - void beforeEnd(); - - void afterEnd(); - } - - private static class Printer extends CodeElementScanner { - - private int indent; - private boolean newLine; - private final String ln = "\n"; - - private final StringBuilder b; - - Printer(StringBuilder b) { - this.b = b; - } - - @Override - public void visitTree(CodeTree e, Void p) { - switch (e.getCodeKind()) { - case COMMA_GROUP: - List children = e.getEnclosedElements(); - for (int i = 0; i < children.size(); i++) { - children.get(i).acceptCodeElementScanner(this, p); - if (i < e.getEnclosedElements().size() - 1) { - b.append(", "); - } - } - break; - case GROUP: - super.visitTree(e, p); - break; - case INDENT: - indent(); - super.visitTree(e, p); - dedent(); - break; - case NEW_LINE: - writeLn(); - break; - case STRING: - if (e.getString() != null) { - write(e.getString()); - } else { - write("null"); - } - break; - case TYPE: - write(Utils.getSimpleName(e.getType())); - break; - default: - assert false; - return; - } - } - - private void indent() { - indent++; - } - - private void dedent() { - indent--; - } - - private void writeLn() { - write(ln); - newLine = true; - } - - private void write(String m) { - if (newLine && m != ln) { - writeIndent(); - newLine = false; - } - b.append(m); - } - - private void writeIndent() { - for (int i = 0; i < indent; i++) { - b.append(" "); - } - } - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeKind.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeKind.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.ast; - -public enum CodeTreeKind { - STATIC_FIELD_REFERENCE, - STATIC_METHOD_REFERENCE, - GROUP, - COMMA_GROUP, - REMOVE_LAST, - INDENT, - STRING, - NEW_LINE, - TYPE; -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTypeElement.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTypeElement.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.ast; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; - -import com.oracle.truffle.dsl.processor.ast.CodeTypeMirror.DeclaredCodeTypeMirror; - -public class CodeTypeElement extends CodeElement implements TypeElement { - - private final List imports = parentableList(this, new ArrayList()); - - private final PackageElement packageElement; - - private final Name simpleName; - private final Name packageName; - private Name qualifiedName; - - private final List implementsInterfaces = new ArrayList<>(); - private final ElementKind kind; - private TypeMirror superClass; - - private final DeclaredCodeTypeMirror mirror = new DeclaredCodeTypeMirror(this); - - public CodeTypeElement(Set modifiers, ElementKind kind, PackageElement packageElement, String simpleName) { - super(modifiers); - this.kind = kind; - this.packageElement = packageElement; - this.simpleName = CodeNames.of(simpleName); - if (this.packageElement != null) { - this.packageName = packageElement.getQualifiedName(); - } else { - this.packageName = CodeNames.of("default"); - } - this.qualifiedName = createQualifiedName(); - } - - @Override - public TypeMirror asType() { - return mirror; - } - - @Override - public ElementKind getKind() { - return kind; - } - - public boolean containsField(String name) { - for (VariableElement field : getFields()) { - if (field.getSimpleName().toString().equals(name)) { - return true; - } - } - return false; - } - - @Override - public NestingKind getNestingKind() { - return isTopLevelClass() ? NestingKind.TOP_LEVEL : NestingKind.LOCAL; - } - - @Override - public Element getEnclosingElement() { - if (isTopLevelClass()) { - return packageElement; - } else { - return super.getEnclosingElement(); - } - } - - @Override - public TypeMirror getSuperclass() { - return superClass; - } - - @Override - public List getInterfaces() { - return implementsInterfaces; - } - - @Override - public List getTypeParameters() { - return Collections.emptyList(); - } - - public boolean isTopLevelClass() { - return super.getEnclosingElement() instanceof CodeCompilationUnit; - } - - public CodeVariableElement getField(String name) { - for (VariableElement field : ElementFilter.fieldsIn(getEnclosedElements())) { - if (field.getSimpleName().toString().equals(name)) { - return (CodeVariableElement) field; - } - } - return null; - } - - private Name createQualifiedName() { - TypeElement enclosingType = getEnclosingClass(); - if (enclosingType == null) { - return CodeNames.of(packageName + "." + simpleName); - } else { - return CodeNames.of(enclosingType.getQualifiedName() + "." + simpleName); - } - } - - @Override - void setEnclosingElement(Element element) { - super.setEnclosingElement(element); - - // update qualified name on container change - this.qualifiedName = createQualifiedName(); - } - - public Name getPackageName() { - return packageName; - } - - @Override - public Name getQualifiedName() { - return qualifiedName; - } - - @Override - public Name getSimpleName() { - return simpleName; - } - - public void setSuperClass(TypeMirror superType) { - this.superClass = superType; - } - - public List getImports() { - return imports; - } - - public List getImplements() { - return implementsInterfaces; - } - - @Override - public int hashCode() { - return getQualifiedName().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } else if (obj instanceof TypeElement) { - return getQualifiedName().equals(((TypeElement) obj).getQualifiedName()); - } - return false; - } - - public List getFields() { - return ElementFilter.fieldsIn(getEnclosedElements()); - } - - public ExecutableElement getMethod(String name) { - for (Element element : getEnclosedElements()) { - if (element.getKind() == ElementKind.METHOD && element.getSimpleName().toString().equals(name)) { - return (ExecutableElement) element; - } - } - return null; - } - - public List getMethods() { - return ElementFilter.methodsIn(getEnclosedElements()); - } - - public List getInnerClasses() { - return ElementFilter.typesIn(getEnclosedElements()); - } - - @Override - public String toString() { - return getQualifiedName().toString(); - } - - @Override - public R accept(ElementVisitor v, P p) { - return v.visitType(this, p); - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTypeMirror.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTypeMirror.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.ast; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -public class CodeTypeMirror implements TypeMirror { - - private final TypeKind kind; - - public CodeTypeMirror(TypeKind kind) { - this.kind = kind; - } - - @Override - public TypeKind getKind() { - return kind; - } - - @Override - public R accept(TypeVisitor v, P p) { - throw new UnsupportedOperationException(); - } - - public static class ArrayCodeTypeMirror extends CodeTypeMirror implements ArrayType { - - private final TypeMirror component; - - public ArrayCodeTypeMirror(TypeMirror component) { - super(TypeKind.ARRAY); - this.component = component; - } - - @Override - public TypeMirror getComponentType() { - return component; - } - - } - - public static class DeclaredCodeTypeMirror extends CodeTypeMirror implements DeclaredType { - - private final TypeElement clazz; - private final List typeArguments; - - public DeclaredCodeTypeMirror(TypeElement clazz) { - this(clazz, Collections. emptyList()); - } - - public DeclaredCodeTypeMirror(TypeElement clazz, List typeArguments) { - super(TypeKind.DECLARED); - this.clazz = clazz; - this.typeArguments = typeArguments; - } - - @Override - public Element asElement() { - return clazz; - } - - @Override - public TypeMirror getEnclosingType() { - return clazz.getEnclosingElement().asType(); - } - - @Override - public List getTypeArguments() { - return typeArguments; - } - - @Override - public String toString() { - return clazz.getQualifiedName().toString(); - } - - } - - public List getAnnotationMirrors() { - throw new UnsupportedOperationException(); - } - - /** - * @param annotationType - */ - public A getAnnotation(Class annotationType) { - throw new UnsupportedOperationException(); - } - - /** - * @param annotationType - */ - public A[] getAnnotationsByType(Class annotationType) { - throw new UnsupportedOperationException(); - } -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeVariableElement.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeVariableElement.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.ast; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.api.element.*; - -public final class CodeVariableElement extends CodeElement implements WritableVariableElement { - - private Name name; - private TypeMirror type; - private Object constantValue; - - private CodeTree init; - - public CodeVariableElement(TypeMirror type, String name) { - super(Utils.modifiers()); - this.type = type; - this.name = CodeNames.of(name); - } - - public CodeVariableElement(Set modifiers, TypeMirror type, String name) { - super(modifiers); - this.type = type; - this.name = CodeNames.of(name); - } - - public CodeVariableElement(Set modifiers, TypeMirror type, String name, String init) { - this(modifiers, type, name); - if (init != null) { - this.init = new CodeTree(CodeTreeKind.STRING, null, init); - } - } - - public CodeTreeBuilder createInitBuilder() { - CodeTreeBuilder builder = new CodeTreeBuilder(null); - init = builder.getTree(); - init.setEnclosingElement(this); - return builder; - } - - public void setInit(CodeTree init) { - this.init = init; - } - - public CodeTree getInit() { - return init; - } - - public Name getSimpleName() { - return name; - } - - public TypeMirror getType() { - return type; - } - - @Override - public TypeMirror asType() { - return type; - } - - @Override - public ElementKind getKind() { - if (getEnclosingElement() instanceof ExecutableElement) { - return ElementKind.PARAMETER; - } else if (getEnclosingElement() instanceof TypeElement) { - return ElementKind.FIELD; - } else { - return ElementKind.PARAMETER; - } - } - - public void setConstantValue(Object constantValue) { - this.constantValue = constantValue; - } - - @Override - public Object getConstantValue() { - return constantValue; - } - - public String getName() { - return getSimpleName().toString(); - } - - @Override - public void setSimpleName(Name name) { - this.name = name; - } - - public void setName(String name) { - this.name = CodeNames.of(name); - } - - @Override - public void setType(TypeMirror type) { - this.type = type; - } - - @Override - public R accept(ElementVisitor v, P p) { - return v.visitVariable(this, p); - } - - public static CodeVariableElement clone(VariableElement var) { - CodeVariableElement copy = new CodeVariableElement(var.getModifiers(), var.asType(), var.getSimpleName().toString()); - copy.setConstantValue(var.getConstantValue()); - for (AnnotationMirror mirror : var.getAnnotationMirrors()) { - copy.addAnnotationMirror(mirror); - } - for (Element element : var.getEnclosedElements()) { - copy.add(element); - } - return copy; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/GeneratedElement.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/GeneratedElement.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.ast; - -import javax.lang.model.element.*; - -public interface GeneratedElement { - - AnnotationMirror getGeneratorAnnotationMirror(); - - void setGeneratorAnnotationMirror(AnnotationMirror mirror); - - Element getGeneratorElement(); - - void setGeneratorElement(Element element); - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/AbstractCodeWriter.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/AbstractCodeWriter.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,764 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.codewriter; - -import static com.oracle.truffle.dsl.processor.Utils.*; - -import java.io.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.ast.*; - -public abstract class AbstractCodeWriter extends CodeElementScanner { - - private static final int MAX_LINE_LENGTH = 200; - private static final int LINE_WRAP_INDENTS = 3; - private static final String IDENT_STRING = " "; - private static final String LN = "\n"; /* unix style */ - - protected Writer writer; - private int indent; - private boolean newLine; - private int lineLength; - private boolean lineWrapping = false; - - private OrganizedImports imports; - - public void visitCompilationUnit(CodeCompilationUnit e) { - for (TypeElement clazz : e.getEnclosedElements()) { - clazz.accept(this, null); - } - } - - protected abstract Writer createWriter(CodeTypeElement clazz) throws IOException; - - @Override - public Void visitType(CodeTypeElement e, Void p) { - if (e.isTopLevelClass()) { - Writer w = null; - try { - imports = OrganizedImports.organize(e); - w = new TrimTrailingSpaceWriter(createWriter(e)); - writer = w; - writeRootClass(e); - } catch (IOException ex) { - throw new RuntimeException(ex); - } finally { - if (w != null) { - try { - w.close(); - } catch (Throwable e1) { - // see eclipse bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=361378 - // TODO temporary suppress errors on close. - } - } - writer = null; - } - } else { - writeClassImpl(e); - } - return null; - } - - private void writeRootClass(CodeTypeElement e) { - writeHeader(); - write("package ").write(e.getPackageName()).write(";").writeLn(); - writeEmptyLn(); - - Set generateImports = imports.generateImports(); - List typeImports = new ArrayList<>(); - List staticImports = new ArrayList<>(); - - for (CodeImport codeImport : generateImports) { - if (codeImport.isStaticImport()) { - staticImports.add(codeImport); - } else { - typeImports.add(codeImport); - } - } - Collections.sort(typeImports); - Collections.sort(staticImports); - - for (CodeImport imp : staticImports) { - imp.accept(this, null); - writeLn(); - } - if (!staticImports.isEmpty()) { - writeEmptyLn(); - } - - for (CodeImport imp : typeImports) { - imp.accept(this, null); - writeLn(); - } - if (!typeImports.isEmpty()) { - writeEmptyLn(); - } - - writeClassImpl(e); - } - - private String useImport(Element enclosedType, TypeMirror type) { - if (imports != null) { - return imports.createTypeReference(enclosedType, type); - } else { - return Utils.getSimpleName(type); - } - } - - private void writeClassImpl(CodeTypeElement e) { - for (AnnotationMirror annotation : e.getAnnotationMirrors()) { - visitAnnotation(e, annotation); - writeLn(); - } - - writeModifiers(e.getModifiers()); - if (e.getKind() == ElementKind.ENUM) { - write("enum "); - } else { - write("class "); - } - write(e.getSimpleName()); - if (e.getSuperclass() != null && !getQualifiedName(e.getSuperclass()).equals("java.lang.Object")) { - write(" extends ").write(useImport(e, e.getSuperclass())); - } - if (e.getImplements().size() > 0) { - write(" implements "); - for (int i = 0; i < e.getImplements().size(); i++) { - write(useImport(e, e.getImplements().get(i))); - if (i < e.getImplements().size() - 1) { - write(", "); - } - } - } - - write(" {").writeLn(); - writeEmptyLn(); - indent(1); - - List staticFields = getStaticFields(e); - List instanceFields = getInstanceFields(e); - - for (int i = 0; i < staticFields.size(); i++) { - VariableElement field = staticFields.get(i); - field.accept(this, null); - if (e.getKind() == ElementKind.ENUM && i < staticFields.size() - 1) { - write(","); - writeLn(); - } else { - write(";"); - writeLn(); - } - } - - if (staticFields.size() > 0) { - writeEmptyLn(); - } - - for (VariableElement field : instanceFields) { - field.accept(this, null); - write(";"); - writeLn(); - } - if (instanceFields.size() > 0) { - writeEmptyLn(); - } - - for (ExecutableElement method : ElementFilter.constructorsIn(e.getEnclosedElements())) { - method.accept(this, null); - } - - for (ExecutableElement method : getInstanceMethods(e)) { - method.accept(this, null); - } - - for (ExecutableElement method : getStaticMethods(e)) { - method.accept(this, null); - } - - for (TypeElement clazz : e.getInnerClasses()) { - clazz.accept(this, null); - } - - dedent(1); - write("}"); - writeEmptyLn(); - } - - private static List getStaticFields(CodeTypeElement clazz) { - List staticFields = new ArrayList<>(); - for (VariableElement field : clazz.getFields()) { - if (field.getModifiers().contains(Modifier.STATIC)) { - staticFields.add(field); - } - } - return staticFields; - } - - private static List getInstanceFields(CodeTypeElement clazz) { - List instanceFields = new ArrayList<>(); - for (VariableElement field : clazz.getFields()) { - if (!field.getModifiers().contains(Modifier.STATIC)) { - instanceFields.add(field); - } - } - return instanceFields; - } - - private static List getStaticMethods(CodeTypeElement clazz) { - List staticMethods = new ArrayList<>(); - for (ExecutableElement method : clazz.getMethods()) { - if (method.getModifiers().contains(Modifier.STATIC)) { - staticMethods.add(method); - } - } - return staticMethods; - } - - private static List getInstanceMethods(CodeTypeElement clazz) { - List instanceMethods = new ArrayList<>(); - for (ExecutableElement method : clazz.getMethods()) { - if (!method.getModifiers().contains(Modifier.STATIC)) { - instanceMethods.add(method); - } - } - return instanceMethods; - } - - @Override - public Void visitVariable(VariableElement f, Void p) { - Element parent = f.getEnclosingElement(); - - for (AnnotationMirror annotation : f.getAnnotationMirrors()) { - visitAnnotation(f, annotation); - write(" "); - } - - CodeTree init = null; - if (f instanceof CodeVariableElement) { - init = ((CodeVariableElement) f).getInit(); - } - - if (parent.getKind() == ElementKind.ENUM && f.getModifiers().contains(Modifier.STATIC)) { - write(f.getSimpleName()); - if (init != null) { - write("("); - init.acceptCodeElementScanner(this, p); - write(")"); - } - } else { - Element enclosing = f.getEnclosingElement(); - writeModifiers(f.getModifiers()); - - boolean varArgs = false; - if (enclosing.getKind() == ElementKind.METHOD) { - ExecutableElement method = (ExecutableElement) enclosing; - if (method.isVarArgs() && method.getParameters().indexOf(f) == method.getParameters().size() - 1) { - varArgs = true; - } - } - - TypeMirror varType = f.asType(); - if (varArgs) { - if (varType.getKind() == TypeKind.ARRAY) { - varType = ((ArrayType) varType).getComponentType(); - } - write(useImport(f, varType)); - write("..."); - } else { - write(useImport(f, varType)); - } - - write(" "); - write(f.getSimpleName()); - if (init != null) { - write(" = "); - init.acceptCodeElementScanner(this, p); - } - } - return null; - } - - public void visitAnnotation(Element enclosedElement, AnnotationMirror e) { - write("@").write(useImport(enclosedElement, e.getAnnotationType())); - - if (!e.getElementValues().isEmpty()) { - write("("); - final ExecutableElement defaultElement = findExecutableElement(e.getAnnotationType(), "value"); - - Map values = e.getElementValues(); - if (defaultElement != null && values.size() == 1 && values.get(defaultElement) != null) { - visitAnnotationValue(enclosedElement, values.get(defaultElement)); - } else { - Set methodsSet = values.keySet(); - List methodsList = new ArrayList<>(); - for (ExecutableElement method : methodsSet) { - if (values.get(method) == null) { - continue; - } - methodsList.add(method); - } - - Collections.sort(methodsList, new Comparator() { - - @Override - public int compare(ExecutableElement o1, ExecutableElement o2) { - return o1.getSimpleName().toString().compareTo(o2.getSimpleName().toString()); - } - }); - - for (int i = 0; i < methodsList.size(); i++) { - ExecutableElement method = methodsList.get(i); - AnnotationValue value = values.get(method); - write(method.getSimpleName().toString()); - write(" = "); - visitAnnotationValue(enclosedElement, value); - - if (i < methodsList.size() - 1) { - write(", "); - } - } - } - - write(")"); - } - } - - public void visitAnnotationValue(Element enclosedElement, AnnotationValue e) { - e.accept(new AnnotationValueWriterVisitor(enclosedElement), null); - } - - private class AnnotationValueWriterVisitor extends AbstractAnnotationValueVisitor7 { - - private final Element enclosedElement; - - public AnnotationValueWriterVisitor(Element enclosedElement) { - this.enclosedElement = enclosedElement; - } - - @Override - public Void visitBoolean(boolean b, Void p) { - write(Boolean.toString(b)); - return null; - } - - @Override - public Void visitByte(byte b, Void p) { - write(Byte.toString(b)); - return null; - } - - @Override - public Void visitChar(char c, Void p) { - write(Character.toString(c)); - return null; - } - - @Override - public Void visitDouble(double d, Void p) { - write(Double.toString(d)); - return null; - } - - @Override - public Void visitFloat(float f, Void p) { - write(Float.toString(f)); - return null; - } - - @Override - public Void visitInt(int i, Void p) { - write(Integer.toString(i)); - return null; - } - - @Override - public Void visitLong(long i, Void p) { - write(Long.toString(i)); - return null; - } - - @Override - public Void visitShort(short s, Void p) { - write(Short.toString(s)); - return null; - } - - @Override - public Void visitString(String s, Void p) { - write("\""); - write(s); - write("\""); - return null; - } - - @Override - public Void visitType(TypeMirror t, Void p) { - write(useImport(enclosedElement, t)); - write(".class"); - return null; - } - - @Override - public Void visitEnumConstant(VariableElement c, Void p) { - write(useImport(enclosedElement, c.asType())); - write("."); - write(c.getSimpleName().toString()); - return null; - } - - @Override - public Void visitAnnotation(AnnotationMirror a, Void p) { - AbstractCodeWriter.this.visitAnnotation(enclosedElement, a); - return null; - } - - @Override - public Void visitArray(List vals, Void p) { - write("{"); - for (int i = 0; i < vals.size(); i++) { - AnnotationValue value = vals.get(i); - AbstractCodeWriter.this.visitAnnotationValue(enclosedElement, value); - if (i < vals.size() - 1) { - write(", "); - } - } - write("}"); - return null; - } - } - - public ExecutableElement findExecutableElement(DeclaredType type, String name) { - List elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements()); - for (ExecutableElement executableElement : elements) { - if (executableElement.getSimpleName().toString().equals(name)) { - return executableElement; - } - } - return null; - } - - @Override - public void visitImport(CodeImport e, Void p) { - if (e.isStaticImport()) { - write("import static ").write(e.getImportString()).write(";"); - } else { - write("import ").write(e.getImportString()).write(";"); - } - } - - @Override - public Void visitExecutable(CodeExecutableElement e, Void p) { - for (AnnotationMirror annotation : e.getAnnotationMirrors()) { - visitAnnotation(e, annotation); - writeLn(); - } - - writeModifiers(e.getModifiers()); - - if (e.getReturnType() != null) { - write(useImport(e, e.getReturnType())); - write(" "); - } - write(e.getSimpleName()); - write("("); - - for (int i = 0; i < e.getParameters().size(); i++) { - VariableElement param = e.getParameters().get(i); - param.accept(this, p); - if (i < e.getParameters().size() - 1) { - write(", "); - } - } - write(")"); - - List throwables = e.getThrownTypes(); - if (throwables.size() > 0) { - write(" throws "); - for (int i = 0; i < throwables.size(); i++) { - write(useImport(e, throwables.get(i))); - if (i < throwables.size() - 1) { - write(", "); - } - } - } - - if (e.getModifiers().contains(Modifier.ABSTRACT)) { - writeLn(";"); - } else if (e.getBodyTree() != null) { - writeLn(" {"); - indent(1); - e.getBodyTree().acceptCodeElementScanner(this, p); - dedent(1); - writeLn("}"); - } else if (e.getBody() != null) { - write(" {"); - write(e.getBody()); - writeLn("}"); - } else { - writeLn("{ }"); - } - writeEmptyLn(); - return null; - } - - @Override - public void visitTree(CodeTree e, Void p) { - CodeTreeKind kind = e.getCodeKind(); - - switch (kind) { - case COMMA_GROUP: - List children = e.getEnclosedElements(); - for (int i = 0; i < children.size(); i++) { - children.get(i).acceptCodeElementScanner(this, p); - if (i < e.getEnclosedElements().size() - 1) { - write(", "); - } - } - break; - case GROUP: - for (CodeTree tree : e.getEnclosedElements()) { - tree.acceptCodeElementScanner(this, p); - } - break; - case INDENT: - indent(1); - for (CodeTree tree : e.getEnclosedElements()) { - tree.acceptCodeElementScanner(this, p); - } - dedent(1); - break; - case NEW_LINE: - writeLn(); - break; - case STRING: - if (e.getString() != null) { - write(e.getString()); - } else { - write("null"); - } - break; - case STATIC_FIELD_REFERENCE: - if (e.getString() != null) { - write(imports.createStaticFieldReference(e, e.getType(), e.getString())); - } else { - write("null"); - } - break; - case STATIC_METHOD_REFERENCE: - if (e.getString() != null) { - write(imports.createStaticMethodReference(e, e.getType(), e.getString())); - } else { - write("null"); - } - break; - case TYPE: - write(useImport(e, e.getType())); - break; - default: - assert false; - return; - } - } - - protected void writeHeader() { - // default implementation does nothing - } - - private void writeModifiers(Set modifiers) { - if (modifiers != null) { - for (Modifier modifier : modifiers) { - write(modifier.toString()); - write(" "); - } - } - } - - protected void indent(int count) { - indent += count; - } - - protected void dedent(int count) { - indent -= count; - } - - protected void writeLn() { - writeLn(""); - } - - protected void writeLn(String text) { - write(text); - write(LN); - lineLength = 0; - newLine = true; - if (lineWrapping) { - dedent(LINE_WRAP_INDENTS); - lineWrapping = false; - } - lineWrapping = false; - } - - protected void writeEmptyLn() { - writeLn(); - } - - private AbstractCodeWriter write(Name name) { - return write(name.toString()); - } - - private AbstractCodeWriter write(String m) { - if (m.isEmpty()) { - return this; - } - try { - String s = m; - lineLength += s.length(); - if (newLine && s != LN) { - writeIndent(); - newLine = false; - } - if (lineLength > MAX_LINE_LENGTH) { - s = wrapLine(s); - } - writer.write(s); - } catch (IOException e) { - throw new RuntimeException(e); - } - return this; - } - - private String wrapLine(String m) throws IOException { - assert !m.isEmpty(); - - char firstCharacter = m.charAt(0); - char lastCharacter = m.charAt(m.length() - 1); - if (firstCharacter == '\"' && lastCharacter == '\"') { - // string line wrapping - String string = m.substring(1, m.length() - 1); - if (string.isEmpty()) { - return m; - } - - // restore original line length - lineLength = lineLength - m.length(); - int size = 0; - for (int i = 0; i < string.length(); i += size) { - if (i != 0) { - write("+ "); - } - - int nextSize = MAX_LINE_LENGTH - lineLength - 2; - if (nextSize <= 0) { - writeLn(); - nextSize = MAX_LINE_LENGTH - lineLength - 2; - } - - int end = Math.min(i + nextSize, string.length()); - - // TODO(CH): fails in normal usage - output ok though - // assert lineLength + (end - i) + 2 < MAX_LINE_LENGTH; - - write("\"" + string.substring(i, end) + "\""); - size = nextSize; - } - - return ""; - } else if (!Character.isAlphabetic(firstCharacter) && firstCharacter != '+') { - return m; - } - - if (!lineWrapping) { - indent(LINE_WRAP_INDENTS); - } - lineWrapping = true; - lineLength = 0; - write(LN); - writeIndent(); - return m; - } - - private void writeIndent() throws IOException { - lineLength += indentSize(); - for (int i = 0; i < indent; i++) { - writer.write(IDENT_STRING); - } - } - - private int indentSize() { - return IDENT_STRING.length() * indent; - } - - private static class TrimTrailingSpaceWriter extends Writer { - - private final Writer delegate; - private final StringBuilder buffer = new StringBuilder(); - - public TrimTrailingSpaceWriter(Writer delegate) { - this.delegate = delegate; - } - - @Override - public void close() throws IOException { - this.delegate.close(); - } - - @Override - public void flush() throws IOException { - this.delegate.flush(); - } - - @Override - public void write(char[] cbuf, int off, int len) throws IOException { - buffer.append(cbuf, off, len); - int newLinePoint = buffer.indexOf(LN); - - if (newLinePoint != -1) { - String lhs = trimTrailing(buffer.substring(0, newLinePoint)); - delegate.write(lhs); - delegate.write(LN); - buffer.delete(0, newLinePoint + 1); - } - } - - private static String trimTrailing(String s) { - int cut = 0; - for (int i = s.length() - 1; i >= 0; i--) { - if (Character.isWhitespace(s.charAt(i))) { - cut++; - } else { - break; - } - } - if (cut > 0) { - return s.substring(0, s.length() - cut); - } - return s; - } - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/FixWarningsVisitor.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/FixWarningsVisitor.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.codewriter; - -import static com.oracle.truffle.dsl.processor.Utils.*; -import static javax.lang.model.element.Modifier.*; - -import java.io.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.ast.*; - -public class FixWarningsVisitor extends CodeElementScanner { - - private final Set symbolsUsed = new HashSet<>(); - - private final ProcessorContext context; - private final DeclaredType unusedAnnotation; - private final DeclaredType overrideType; - - public FixWarningsVisitor(ProcessorContext context, DeclaredType unusedAnnotation, DeclaredType overrideType) { - this.context = context; - this.unusedAnnotation = unusedAnnotation; - this.overrideType = overrideType; - } - - @Override - public Void visitType(CodeTypeElement e, Void p) { - List superTypes = Utils.getSuperTypes(e); - for (TypeElement type : superTypes) { - String qualifiedName = Utils.getQualifiedName(type); - if (qualifiedName.equals(Serializable.class.getCanonicalName())) { - if (!e.containsField("serialVersionUID")) { - e.add(new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), context.getType(long.class), "serialVersionUID", "1L")); - } - break; - } - } - - return super.visitType(e, p); - } - - @Override - public Void visitExecutable(CodeExecutableElement e, Void p) { - if (e.getParameters().isEmpty()) { - return null; - } else if (e.getModifiers().contains(Modifier.ABSTRACT)) { - return null; - } else if (containsOverride(e)) { - return null; - } - - symbolsUsed.clear(); - super.visitExecutable(e, p); - if (e.getBodyTree() == null && e.getBody() != null) { - computeSymbols(e.getBody()); - } - - for (VariableElement parameter : e.getParameters()) { - if (!symbolsUsed.contains(parameter.getSimpleName().toString())) { - e.getAnnotationMirrors().add(createUnusedAnnotationMirror()); - break; - } - } - return null; - } - - private boolean containsOverride(CodeExecutableElement e) { - for (AnnotationMirror mirror : e.getAnnotationMirrors()) { - if (Utils.typeEquals(overrideType, mirror.getAnnotationType())) { - return true; - } - } - return false; - } - - private CodeAnnotationMirror createUnusedAnnotationMirror() { - CodeAnnotationMirror mirror = new CodeAnnotationMirror(unusedAnnotation); - mirror.setElementValue(mirror.findExecutableElement("value"), new CodeAnnotationValue("unused")); - return mirror; - } - - @Override - public void visitTree(CodeTree e, Void p) { - if (e.getString() != null) { - computeSymbols(e.getString()); - } - super.visitTree(e, p); - } - - private void computeSymbols(String s) { - // TODO there should not be any need for a StringTokenizer if we have a real AST for - // method bodies. Also the current solution is not perfect. What if one token - // is spread across multiple CodeTree instances? But for now that works. - StringTokenizer tokenizer = new StringTokenizer(s, ".= :,()[];{}\"\"'' ", false); - while (tokenizer.hasMoreElements()) { - String token = tokenizer.nextToken().trim(); - if (token.length() > 0) { - symbolsUsed.add(token); - } - } - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/GenerateOverrideVisitor.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/GenerateOverrideVisitor.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.codewriter; - -import static com.oracle.truffle.dsl.processor.Utils.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.ast.*; - -public class GenerateOverrideVisitor extends CodeElementScanner { - - private final DeclaredType overrideType; - - public GenerateOverrideVisitor(DeclaredType overrideType) { - this.overrideType = overrideType; - } - - @Override - public Void visitExecutable(CodeExecutableElement e, Void p) { - if (!e.getModifiers().contains(Modifier.STATIC) && !e.getModifiers().contains(Modifier.PRIVATE)) { - String name = e.getSimpleName().toString(); - TypeMirror[] params = e.getParameterTypes(); - - for (AnnotationMirror mirror : e.getAnnotationMirrors()) { - if (Utils.typeEquals(overrideType, mirror.getAnnotationType())) { - // already declared (may happen if method copied from super class) - return super.visitExecutable(e, p); - } - } - - if (isDeclaredMethodInSuperType(e.getEnclosingClass(), name, params)) { - e.addAnnotationMirror(new CodeAnnotationMirror(overrideType)); - } - } - return super.visitExecutable(e, p); - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/OrganizedImports.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/OrganizedImports.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,491 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.codewriter; - -import static com.oracle.truffle.dsl.processor.Utils.*; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.ast.*; - -public final class OrganizedImports { - - private final Set staticImportUsage = new HashSet<>(); - - private final Map simpleNamesUsed = new HashMap<>(); - - private final Set declaredStaticMethods = new HashSet<>(); - private final Set declaredStaticFields = new HashSet<>(); - private final Set ambiguousStaticMethods = new HashSet<>(); - private final Set ambiguousStaticFields = new HashSet<>(); - - private final CodeTypeElement topLevelClass; - - private OrganizedImports(CodeTypeElement topLevelClass) { - this.topLevelClass = topLevelClass; - } - - public static OrganizedImports organize(CodeTypeElement topLevelClass) { - OrganizedImports organized = new OrganizedImports(topLevelClass); - organized.organizeImpl(); - return organized; - } - - private void organizeImpl() { - ImportTypeReferenceVisitor reference = new ImportTypeReferenceVisitor(); - topLevelClass.accept(reference, null); - - processStaticImports(topLevelClass); - List types = Utils.getSuperTypes(topLevelClass); - for (TypeElement typeElement : types) { - processStaticImports(typeElement); - } - - for (TypeMirror type : staticImportUsage) { - TypeElement element = fromTypeMirror(type); - if (element != null) { - // already processed by supertype - if (types.contains(element)) { - continue; - } - processStaticImports(element); - } - } - } - - public String createTypeReference(Element enclosedElement, TypeMirror type) { - switch (type.getKind()) { - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FLOAT: - case SHORT: - case INT: - case LONG: - case VOID: - return Utils.getSimpleName(type); - case DECLARED: - return createDeclaredTypeName(enclosedElement, (DeclaredType) type); - case ARRAY: - return createTypeReference(enclosedElement, ((ArrayType) type).getComponentType()) + "[]"; - case WILDCARD: - return createWildcardName(enclosedElement, (WildcardType) type); - case TYPEVAR: - return "?"; - default: - throw new RuntimeException("Unknown type specified " + type.getKind() + " mirror: " + type); - } - } - - public String createStaticFieldReference(Element enclosedElement, TypeMirror type, String fieldName) { - return createStaticReference(enclosedElement, type, fieldName, ambiguousStaticFields, declaredStaticFields); - } - - public String createStaticMethodReference(Element enclosedElement, TypeMirror type, String methodName) { - return createStaticReference(enclosedElement, type, methodName, ambiguousStaticMethods, declaredStaticMethods); - } - - private String createStaticReference(Element enclosedElement, TypeMirror type, String name, Set ambiguousSymbols, Set declaredSymbols) { - if (ambiguousSymbols.contains(name)) { - // ambiguous import - return createTypeReference(enclosedElement, type) + "." + name; - } else if (!declaredSymbols.contains(name)) { - // not imported at all - return createTypeReference(enclosedElement, type) + "." + name; - } else { - // import declared and not ambiguous - return name; - } - } - - private String createWildcardName(Element enclosedElement, WildcardType type) { - StringBuilder b = new StringBuilder(); - if (type.getExtendsBound() != null) { - b.append("? extends ").append(createTypeReference(enclosedElement, type.getExtendsBound())); - } else if (type.getSuperBound() != null) { - b.append("? super ").append(createTypeReference(enclosedElement, type.getExtendsBound())); - } - return b.toString(); - } - - private String createDeclaredTypeName(Element enclosedElement, DeclaredType type) { - String name = Utils.fixECJBinaryNameIssue(type.asElement().getSimpleName().toString()); - - if (needsImport(enclosedElement, type)) { - TypeMirror usedByType = simpleNamesUsed.get(name); - if (usedByType == null) { - simpleNamesUsed.put(name, type); - usedByType = type; - } - - if (!typeEquals(type, usedByType)) { - name = getQualifiedName(type); - } - } - - if (type.getTypeArguments().size() == 0) { - return name; - } - - StringBuilder b = new StringBuilder(name); - b.append("<"); - if (type.getTypeArguments().size() > 0) { - for (int i = 0; i < type.getTypeArguments().size(); i++) { - b.append(createTypeReference(enclosedElement, type.getTypeArguments().get(i))); - if (i < type.getTypeArguments().size() - 1) { - b.append(", "); - } - } - } - b.append(">"); - return b.toString(); - } - - public Set generateImports() { - Set imports = new HashSet<>(); - - imports.addAll(generateImports(simpleNamesUsed.values())); - imports.addAll(generateStaticImports(staticImportUsage)); - - return imports; - } - - boolean processStaticImports(TypeElement element) { - Set importedMethods = new HashSet<>(); - List methods = ElementFilter.methodsIn(element.getEnclosedElements()); - for (ExecutableElement method : methods) { - if (method.getModifiers().contains(Modifier.STATIC)) { - importedMethods.add(method.getSimpleName().toString()); - } - } - - boolean allMethodsAmbiguous = processStaticImportElements(importedMethods, this.ambiguousStaticMethods, this.declaredStaticMethods); - - Set importedFields = new HashSet<>(); - List fields = ElementFilter.fieldsIn(element.getEnclosedElements()); - for (VariableElement field : fields) { - if (field.getModifiers().contains(Modifier.STATIC)) { - importedFields.add(field.getSimpleName().toString()); - } - } - - boolean allFieldsAmbiguous = processStaticImportElements(importedFields, this.ambiguousStaticFields, this.declaredStaticFields); - - return allMethodsAmbiguous && allFieldsAmbiguous; - } - - private static boolean processStaticImportElements(Set newElements, Set ambiguousElements, Set declaredElements) { - boolean allAmbiguous = false; - if (declaredElements.containsAll(newElements)) { - // all types already declared -> we can remove the import completely -> they will all - // get ambiguous - allAmbiguous = true; - } - Set newAmbiguous = new HashSet<>(); - Set newDeclared = new HashSet<>(); - - for (String newElement : newElements) { - if (declaredElements.contains(newElement)) { - newAmbiguous.add(newElement); - } else if (ambiguousElements.contains(newElement)) { - // nothing to do - } else { - newDeclared.add(newElement); - } - } - - ambiguousElements.addAll(newAmbiguous); - declaredElements.addAll(newDeclared); - return allAmbiguous; - } - - private boolean needsImport(Element enclosedElement, TypeMirror importType) { - String importPackagName = getPackageName(importType); - if (importPackagName == null) { - return false; - } else if (importPackagName.equals("java.lang")) { - return false; - } else if (importPackagName.equals(getPackageName(topLevelClass)) && Utils.isTopLevelClass(importType)) { - return false; // same package name -> no import - } - - List elements = Utils.getElementHierarchy(enclosedElement); - - Set autoImportedTypes = new HashSet<>(); - for (Element element : elements) { - if (element.getKind().isClass()) { - collectSuperTypeImports((TypeElement) element, autoImportedTypes); - collectInnerTypeImports((TypeElement) element, autoImportedTypes); - } - } - - String qualifiedName = getQualifiedName(importType); - if (autoImportedTypes.contains(qualifiedName)) { - return false; - } - - return true; - } - - private static Set generateImports(Collection toGenerate) { - TreeSet importObjects = new TreeSet<>(); - for (TypeMirror importType : toGenerate) { - importObjects.add(new CodeImport(importType, getQualifiedName(importType), false)); - } - return importObjects; - } - - private static void collectInnerTypeImports(TypeElement e, Set autoImportedTypes) { - autoImportedTypes.add(getQualifiedName(e)); - for (TypeElement innerClass : ElementFilter.typesIn(e.getEnclosedElements())) { - collectInnerTypeImports(innerClass, autoImportedTypes); - } - } - - private static void collectSuperTypeImports(TypeElement e, Set autoImportedTypes) { - List superTypes = getSuperTypes(e); - for (TypeElement superType : superTypes) { - List declaredTypes = getDeclaredTypes(superType); - for (TypeElement declaredType : declaredTypes) { - autoImportedTypes.add(getQualifiedName(declaredType)); - } - } - } - - private Set generateStaticImports(Set toGenerate) { - Set autoImportedStaticTypes = new HashSet<>(); - - // if type is declared inside a super type of this class -> no import - autoImportedStaticTypes.add(getQualifiedName(topLevelClass)); - autoImportedStaticTypes.addAll(getQualifiedSuperTypeNames(topLevelClass)); - - TreeSet importObjects = new TreeSet<>(); - for (TypeMirror importType : toGenerate) { - if (getPackageName(importType) == null) { - continue; // no package name -> no import - } - - String qualifiedName = getQualifiedName(importType); - if (autoImportedStaticTypes.contains(qualifiedName)) { - continue; - } - - importObjects.add(new CodeImport(importType, qualifiedName + ".*", true)); - } - - return importObjects; - } - - private abstract static class TypeReferenceVisitor extends CodeElementScanner { - - @Override - public void visitTree(CodeTree e, Void p) { - if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) { - visitStaticFieldReference(e, e.getType(), e.getString()); - } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) { - visitStaticMethodReference(e, e.getType(), e.getString()); - } else if (e.getType() != null) { - visitTypeReference(e, e.getType()); - } - super.visitTree(e, p); - } - - @Override - public Void visitExecutable(CodeExecutableElement e, Void p) { - visitAnnotations(e, e.getAnnotationMirrors()); - if (e.getReturnType() != null) { - visitTypeReference(e, e.getReturnType()); - } - for (TypeMirror type : e.getThrownTypes()) { - visitTypeReference(e, type); - } - return super.visitExecutable(e, p); - } - - @Override - public Void visitType(CodeTypeElement e, Void p) { - visitAnnotations(e, e.getAnnotationMirrors()); - - visitTypeReference(e, e.getSuperclass()); - for (TypeMirror type : e.getImplements()) { - visitTypeReference(e, type); - } - - return super.visitType(e, p); - } - - private void visitAnnotations(Element enclosingElement, List mirrors) { - for (AnnotationMirror mirror : mirrors) { - visitAnnotation(enclosingElement, mirror); - } - } - - public void visitAnnotation(Element enclosingElement, AnnotationMirror e) { - visitTypeReference(enclosingElement, e.getAnnotationType()); - if (!e.getElementValues().isEmpty()) { - Map values = e.getElementValues(); - Set methodsSet = values.keySet(); - List methodsList = new ArrayList<>(); - for (ExecutableElement method : methodsSet) { - if (values.get(method) == null) { - continue; - } - methodsList.add(method); - } - - for (int i = 0; i < methodsList.size(); i++) { - AnnotationValue value = values.get(methodsList.get(i)); - visitAnnotationValue(enclosingElement, value); - } - } - } - - public void visitAnnotationValue(Element enclosingElement, AnnotationValue e) { - e.accept(new AnnotationValueReferenceVisitor(enclosingElement), null); - } - - private class AnnotationValueReferenceVisitor extends AbstractAnnotationValueVisitor7 { - - private final Element enclosingElement; - - public AnnotationValueReferenceVisitor(Element enclosedElement) { - this.enclosingElement = enclosedElement; - } - - @Override - public Void visitBoolean(boolean b, Void p) { - return null; - } - - @Override - public Void visitByte(byte b, Void p) { - return null; - } - - @Override - public Void visitChar(char c, Void p) { - return null; - } - - @Override - public Void visitDouble(double d, Void p) { - return null; - } - - @Override - public Void visitFloat(float f, Void p) { - return null; - } - - @Override - public Void visitInt(int i, Void p) { - return null; - } - - @Override - public Void visitLong(long i, Void p) { - return null; - } - - @Override - public Void visitShort(short s, Void p) { - return null; - } - - @Override - public Void visitString(String s, Void p) { - return null; - } - - @Override - public Void visitType(TypeMirror t, Void p) { - visitTypeReference(enclosingElement, t); - return null; - } - - @Override - public Void visitEnumConstant(VariableElement c, Void p) { - visitTypeReference(enclosingElement, c.asType()); - return null; - } - - @Override - public Void visitAnnotation(AnnotationMirror a, Void p) { - TypeReferenceVisitor.this.visitAnnotation(enclosingElement, a); - return null; - } - - @Override - public Void visitArray(List vals, Void p) { - for (int i = 0; i < vals.size(); i++) { - TypeReferenceVisitor.this.visitAnnotationValue(enclosingElement, vals.get(i)); - } - return null; - } - } - - @Override - public Void visitVariable(VariableElement f, Void p) { - visitAnnotations(f, f.getAnnotationMirrors()); - visitTypeReference(f, f.asType()); - return super.visitVariable(f, p); - } - - @Override - public void visitImport(CodeImport e, Void p) { - } - - public abstract void visitTypeReference(Element enclosedType, TypeMirror type); - - public abstract void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName); - - public abstract void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName); - - } - - private class ImportTypeReferenceVisitor extends TypeReferenceVisitor { - - @Override - public void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName) { - staticImportUsage.add(type); - } - - @Override - public void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName) { - staticImportUsage.add(type); - } - - @Override - public void visitTypeReference(Element enclosedType, TypeMirror type) { - createTypeReference(enclosedType, type); - } - - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/AbstractCompiler.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/AbstractCompiler.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.compiler; - -import java.lang.reflect.*; - -public abstract class AbstractCompiler implements Compiler { - - protected static Object method(Object o, String methodName) throws Exception { - Method method = o.getClass().getMethod(methodName); - method.setAccessible(true); - return method.invoke(o); - } - - protected static Object method(Object o, String methodName, Class[] paramTypes, Object... values) throws Exception { - Method method = o.getClass().getMethod(methodName, paramTypes); - method.setAccessible(true); - return method.invoke(o, values); - } - - protected static Object field(Object o, String fieldName) throws Exception { - if (o == null) { - return null; - } - Field field = o.getClass().getField(fieldName); - field.setAccessible(true); - return field.get(o); - } - - protected static String parseHeader(String content) { - int index = content.indexOf("/*"); - if (index == -1) { - return null; - } - if (!content.substring(0, index).trim().equals("")) { - // just whitespace before - return null; - } - - int endIndex = content.indexOf("*/", index); - if (endIndex == -1) { - return null; - } - return content.substring(index, endIndex + 2); - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/Compiler.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/Compiler.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.compiler; - -import java.util.*; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; - -public interface Compiler { - - String getMethodBody(ProcessingEnvironment env, ExecutableElement method); - - String getHeaderComment(ProcessingEnvironment env, Element type); - - List getEnclosedElementsDeclarationOrder(TypeElement type); - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/CompilerFactory.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/CompilerFactory.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.compiler; - -import javax.lang.model.element.*; - -public class CompilerFactory { - - private static Compiler javac; - private static Compiler jdt; - - public static Compiler getCompiler(Element currentElement) { - if (JavaCCompiler.isValidElement(currentElement)) { - if (javac == null) { - javac = new JavaCCompiler(); - } - return javac; - } else if (JDTCompiler.isValidElement(currentElement)) { - if (jdt == null) { - jdt = new JDTCompiler(); - } - return jdt; - } else { - throw new UnsupportedOperationException("Unsupported compiler for element " + currentElement.getClass().getName() + "."); - } - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JDTCompiler.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JDTCompiler.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,170 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.compiler; - -import java.util.*; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; - -import com.oracle.truffle.dsl.processor.*; - -public class JDTCompiler extends AbstractCompiler { - - public static boolean isValidElement(Element currentElement) { - try { - Class elementClass = Class.forName("org.eclipse.jdt.internal.compiler.apt.model.ElementImpl"); - return elementClass.isAssignableFrom(currentElement.getClass()); - } catch (ClassNotFoundException e) { - return false; - } - } - - public List getEnclosedElementsDeclarationOrder(TypeElement type) { - try { - Object binding = field(type, "_binding"); - - Class sourceTypeBinding = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding"); - - final List declarationOrder; - if (sourceTypeBinding.isAssignableFrom(binding.getClass())) { - declarationOrder = findSourceOrder(binding); - } else { - return null; - } - - List enclosedElements = new ArrayList<>(type.getEnclosedElements()); - Collections.sort(enclosedElements, new Comparator() { - - public int compare(Element o1, Element o2) { - try { - Object o1Binding = field(o1, "_binding"); - Object o2Binding = field(o2, "_binding"); - - int i1 = declarationOrder.indexOf(o1Binding); - int i2 = declarationOrder.indexOf(o2Binding); - - return i1 - i2; - } catch (Exception e) { - return 0; - } - } - - }); - return enclosedElements; - } catch (Exception e) { - return null; - } - } - - private static List findSourceOrder(Object binding) throws Exception { - Object referenceContext = field(field(binding, "scope"), "referenceContext"); - - TreeMap orderedBindings = new TreeMap<>(); - - collectSourceOrder(orderedBindings, referenceContext, "methods"); - collectSourceOrder(orderedBindings, referenceContext, "fields"); - collectSourceOrder(orderedBindings, referenceContext, "memberTypes"); - - return new ArrayList<>(orderedBindings.values()); - } - - private static void collectSourceOrder(TreeMap orderedBindings, Object referenceContext, String fieldName) throws Exception { - Object[] declarations = (Object[]) field(referenceContext, fieldName); - if (declarations != null) { - for (int i = 0; i < declarations.length; i++) { - Integer declarationSourceStart = (Integer) field(declarations[i], "declarationSourceStart"); - orderedBindings.put(declarationSourceStart, field(declarations[i], "binding")); - } - } - } - - @Override - public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) { - try { - - char[] source = getSource(method); - if (source == null) { - return null; - } - - /* - * AbstractMethodDeclaration decl = - * ((MethodBinding)(((ElementImpl)method)._binding)).sourceMethod(); int bodyStart = - * decl.bodyStart; int bodyEnd = decl.bodyEnd; - */ - Object decl = method(field(method, "_binding"), "sourceMethod"); - int bodyStart = (int) field(decl, "bodyStart"); - int bodyEnd = (int) field(decl, "bodyEnd"); - - int length = bodyEnd - bodyStart; - char[] target = new char[length]; - System.arraycopy(source, bodyStart, target, 0, length); - - return new String(target); - } catch (Exception e) { - return Utils.printException(e); - } - } - - private static char[] getSource(Element element) throws Exception { - /* - * Binding binding = ((ElementImpl)element)._binding; char[] source = null; if (binding - * instanceof MethodBinding) { source = ((MethodBinding) - * binding).sourceMethod().compilationResult.getCompilationUnit().getContents(); } else if - * (binding instanceof SourceTypeBinding) { source = - * ((SourceTypeBinding)binding).scope.referenceContext - * .compilationResult.compilationUnit.getContents(); } return source; - */ - - Object binding = field(element, "_binding"); - Class methodBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.MethodBinding"); - Class referenceBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding"); - - char[] source = null; - if (methodBindingClass.isAssignableFrom(binding.getClass())) { - Object sourceMethod = method(binding, "sourceMethod"); - if (sourceMethod == null) { - return null; - } - source = (char[]) method(method(field(sourceMethod, "compilationResult"), "getCompilationUnit"), "getContents"); - } else if (referenceBindingClass.isAssignableFrom(binding.getClass())) { - source = (char[]) method(field(field(field(field(binding, "scope"), "referenceContext"), "compilationResult"), "compilationUnit"), "getContents"); - } - return source; - } - - @Override - public String getHeaderComment(ProcessingEnvironment env, Element type) { - try { - char[] source = getSource(type); - if (source == null) { - return null; - } - return parseHeader(new String(source)); - } catch (Exception e) { - return Utils.printException(e); - } - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JavaCCompiler.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JavaCCompiler.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.compiler; - -import java.util.*; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; - -import com.oracle.truffle.dsl.processor.*; - -public class JavaCCompiler extends AbstractCompiler { - - public static boolean isValidElement(Element currentElement) { - try { - Class elementClass = Class.forName("com.sun.tools.javac.code.Symbol"); - return elementClass.isAssignableFrom(currentElement.getClass()); - } catch (ClassNotFoundException e) { - return false; - } - } - - public List getEnclosedElementsDeclarationOrder(TypeElement type) { - return type.getEnclosedElements(); - } - - private static final Class[] getTreeAndTopLevelSignature = new Class[]{Element.class, AnnotationMirror.class, AnnotationValue.class}; - private static final Class[] getCharContentSignature = new Class[]{boolean.class}; - - @Override - public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) { - try { - /* - * if (false) { Pair treeAndTopLevel = ((JavacElements) - * env.getElementUtils()).getTreeAndTopLevel(method, null, null); JCBlock block = - * ((JCMethodDecl) treeAndTopLevel.fst).getBody(); int startPos = block.pos; int endPos - * = block.endpos; String methodBody = - * treeAndTopLevel.snd.getSourceFile().getCharContent(true).subSequence(startPos + 1, - * endPos).toString(); return methodBody; } - */ - - Object treeAndTopLevel = getTreeAndTopLevel(env, method); - Object block = method(field(treeAndTopLevel, "fst"), "getBody"); - int startPos = (int) field(block, "pos"); - int endPos = (int) field(block, "endpos"); - return getContent(treeAndTopLevel).subSequence(startPos + 1, endPos).toString(); - } catch (Exception e) { - return Utils.printException(e); - } - } - - private static CharSequence getContent(Object treeAndTopLevel) throws Exception { - /* - * CharSequence content = treeAndTopLevel.snd.getSourceFile().getCharContent(true); - */ - return (CharSequence) method(method(field(treeAndTopLevel, "snd"), "getSourceFile"), "getCharContent", getCharContentSignature, true); - } - - private static Object getTreeAndTopLevel(ProcessingEnvironment env, Element element) throws Exception { - /* - * Pair treeAndTopLevel = ((JavacElements) - * env.getElementUtils()).getTreeAndTopLevel(method, null, null); - */ - return method(method(env, "getElementUtils"), "getTreeAndTopLevel", getTreeAndTopLevelSignature, element, null, null); - } - - @Override - public String getHeaderComment(ProcessingEnvironment env, Element type) { - try { - String content = getContent(getTreeAndTopLevel(env, type)).toString(); - return parseHeader(content); - } catch (Exception e) { - return Utils.printException(e); - } - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/AbstractClassElementFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/AbstractClassElementFactory.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.generator; + +import static com.oracle.truffle.dsl.processor.java.ElementUtils.*; +import static javax.lang.model.element.Modifier.*; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.dsl.processor.java.model.*; +import com.oracle.truffle.dsl.processor.model.*; + +public abstract class AbstractClassElementFactory extends AbstractCodeElementFactory { + + @Override + protected abstract CodeTypeElement create(M m); + + @Override + public CodeTypeElement getElement() { + return (CodeTypeElement) super.getElement(); + } + + protected CodeExecutableElement createConstructorUsingFields(Set modifiers, CodeTypeElement clazz) { + CodeExecutableElement method = new CodeExecutableElement(modifiers, null, clazz.getSimpleName().toString()); + CodeTreeBuilder builder = method.createBuilder(); + TypeElement superClass = fromTypeMirror(clazz.getSuperclass()); + ExecutableElement constructor = findConstructor(superClass); + if (constructor != null && constructor.getParameters().size() > 0) { + builder.startStatement(); + builder.startSuperCall(); + for (VariableElement parameter : constructor.getParameters()) { + method.addParameter(new CodeVariableElement(parameter.asType(), parameter.getSimpleName().toString())); + builder.string(parameter.getSimpleName().toString()); + } + builder.end(); // super + builder.end(); // statement + } + + for (VariableElement field : clazz.getFields()) { + if (field.getModifiers().contains(STATIC)) { + continue; + } + String fieldName = field.getSimpleName().toString(); + method.addParameter(new CodeVariableElement(field.asType(), fieldName)); + builder.startStatement(); + builder.string("this."); + builder.string(fieldName); + builder.string(" = "); + if (isAssignable(field.asType(), getContext().getTruffleTypes().getNode())) { + builder.string("adoptChild(").string(fieldName).string(")"); + } else { + builder.string(fieldName); + } + builder.end(); // statement + } + + return method; + } + + private static ExecutableElement findConstructor(TypeElement clazz) { + List constructors = ElementFilter.constructorsIn(clazz.getEnclosedElements()); + if (constructors.isEmpty()) { + return null; + } else { + return constructors.get(0); + } + } + + protected CodeExecutableElement createSuperConstructor(TypeElement type, ExecutableElement element) { + if (element.getModifiers().contains(Modifier.PRIVATE)) { + return null; + } + CodeExecutableElement executable = CodeExecutableElement.clone(getContext().getEnvironment(), element); + executable.setReturnType(null); + executable.setSimpleName(CodeNames.of(type.getSimpleName().toString())); + CodeTreeBuilder b = executable.createBuilder(); + b.startStatement(); + b.startSuperCall(); + for (VariableElement v : element.getParameters()) { + b.string(v.getSimpleName().toString()); + } + b.end(); + b.end(); + + return executable; + } + + protected CodeTypeElement createClass(Template model, Set modifiers, String simpleName, TypeMirror superType, boolean enumType) { + TypeElement templateType = model.getTemplateType(); + + PackageElement pack = getContext().getEnvironment().getElementUtils().getPackageOf(templateType); + CodeTypeElement clazz = new CodeTypeElement(modifiers, enumType ? ElementKind.ENUM : ElementKind.CLASS, pack, simpleName); + TypeMirror resolvedSuperType = superType; + if (resolvedSuperType == null) { + resolvedSuperType = getContext().getType(Object.class); + } + clazz.setSuperClass(resolvedSuperType); + + CodeAnnotationMirror generatedByAnnotation = new CodeAnnotationMirror((DeclaredType) getContext().getType(GeneratedBy.class)); + generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("value"), new CodeAnnotationValue(templateType.asType())); + if (model.getTemplateMethodName() != null) { + generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("methodName"), new CodeAnnotationValue(model.getTemplateMethodName())); + } + + clazz.addAnnotationMirror(generatedByAnnotation); + return clazz; + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/AbstractCodeElementFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/AbstractCodeElementFactory.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.generator; + +import javax.lang.model.element.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.model.*; + +public abstract class AbstractCodeElementFactory { + + protected final ProcessorContext context; + private M model; + + private CodeElement element; + + public AbstractCodeElementFactory() { + this.context = ProcessorContext.getInstance(); + } + + protected abstract CodeElement create(M m); + + @SuppressWarnings("unused") + protected void createChildren(M m) { + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + public CodeElement process(CodeElement parent, M m) { + model = m; + element = (CodeElement) create(model); + if (parent != null) { + parent.add(element); + } + if (element != null) { + createChildren(model); + } + return element; + } + + @SuppressWarnings("rawtypes") + public CodeElement getElement() { + return element; + } + + protected void add(AbstractCodeElementFactory factory, MO m) { + factory.process(this.element, m); + } + + public ProcessorContext getContext() { + return context; + } + + public M getModel() { + return model; + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/AbstractCompilationUnitFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/AbstractCompilationUnitFactory.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.generator; + +import com.oracle.truffle.dsl.processor.java.model.*; + +public abstract class AbstractCompilationUnitFactory extends AbstractCodeElementFactory { + + @Override + public final CodeCompilationUnit create(M m) { + return new CodeCompilationUnit(); + } + + @SuppressWarnings("rawtypes") + @Override + public CodeCompilationUnit process(CodeElement parent, M m) { + return (CodeCompilationUnit) super.process(parent, m); + } + + @Override + protected abstract void createChildren(M m); + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,2952 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.generator; + +import static com.oracle.truffle.dsl.processor.java.ElementUtils.*; +import static javax.lang.model.element.Modifier.*; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.java.model.*; +import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror; +import com.oracle.truffle.dsl.processor.model.*; +import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality; +import com.oracle.truffle.dsl.processor.parser.*; +import com.oracle.truffle.dsl.processor.parser.SpecializationGroup.TypeGuard; + +public class NodeCodeGenerator extends AbstractCompilationUnitFactory { + + private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode"; + + private static final String EXECUTE_CHAINED = "executeChained0"; + private static final String SPECIALIZE = "specialize0"; + private static final String DSLSHARE_REWRITE = "rewrite"; + private static final String DSLSHARE_FIND_ROOT = "findRoot"; + private static final String DSLSHARE_REWRITE_TO_POLYMORHPIC = "rewriteToPolymorphic"; + private static final String EXECUTE_UNINITIALIZED = "executeUninitialized0"; + private static final String REWRITE = "rewrite0"; + private static final String CREATE_INFO = "createInfo0"; + private static final String CONTAINS_FALLBACK = "containsFallback"; + + private static final String FACTORY_METHOD_NAME = "create0"; + private static final String EMPTY_CLASS_ARRAY = "EMPTY_CLASS_ARRAY"; + + private static final String METADATA_FIELD_NAME = "METADATA"; + + private TypeMirror getUnexpectedValueException() { + return getContext().getTruffleTypes().getUnexpectedValueException(); + } + + private static String factoryClassName(NodeData node) { + return node.getNodeId() + "Factory"; + } + + private static String nodeSpecializationClassName(SpecializationData specialization) { + String nodeid = resolveNodeId(specialization.getNode()); + String name = ElementUtils.firstLetterUpperCase(nodeid); + name += ElementUtils.firstLetterUpperCase(specialization.getId()); + name += "Node"; + return name; + } + + private static String nodePolymorphicClassName(NodeData node) { + return ElementUtils.firstLetterUpperCase(resolveNodeId(node)) + "PolymorphicNode"; + } + + private static String resolveNodeId(NodeData node) { + String nodeid = node.getNodeId(); + if (nodeid.endsWith("Node") && !nodeid.equals("Node")) { + nodeid = nodeid.substring(0, nodeid.length() - 4); + } + return nodeid; + } + + private static String valueNameEvaluated(Parameter targetParameter) { + return valueName(targetParameter) + "Evaluated"; + } + + private static String implicitTypeName(Parameter param) { + return param.getLocalName() + "ImplicitType"; + } + + private static String polymorphicTypeName(NodeExecutionData param) { + return param.getName() + "PolymorphicType"; + } + + private static String valueName(Parameter param) { + return param.getLocalName(); + } + + private static CodeTree createAccessChild(NodeExecutionData targetExecution, String thisReference) { + String reference = thisReference; + if (reference == null) { + reference = "this"; + } + CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); + Element accessElement = targetExecution.getChild().getAccessElement(); + if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) { + builder.string(reference).string(".").string(targetExecution.getChild().getName()); + } else if (accessElement.getKind() == ElementKind.FIELD) { + builder.string(reference).string(".").string(accessElement.getSimpleName().toString()); + } else { + throw new AssertionError(); + } + if (targetExecution.isIndexed()) { + builder.string("[" + targetExecution.getIndex() + "]"); + } + return builder.getRoot(); + } + + private static String castValueName(Parameter parameter) { + return valueName(parameter) + "Cast"; + } + + private void addInternalValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame, boolean evaluated) { + if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { + method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue")); + } + for (Parameter parameter : specialization.getParameters()) { + ParameterSpec spec = parameter.getSpecification(); + if (forceFrame && spec.getName().equals("frame")) { + continue; + } + if (spec.isLocal()) { + continue; + } + + String name = valueName(parameter); + if (evaluated && spec.isSignature()) { + name = valueNameEvaluated(parameter); + } + + method.addParameter(new CodeVariableElement(parameter.getType(), name)); + } + } + + private static void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, + Map customNames) { + if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { + builder.string("frameValue"); + } + for (Parameter parameter : specialization.getParameters()) { + ParameterSpec spec = parameter.getSpecification(); + if (forceFrame && spec.getName().equals("frame")) { + continue; + } + + if (parameter.getSpecification().isLocal()) { + continue; + } + + Parameter sourceParameter = source.findParameter(parameter.getLocalName()); + + if (customNames != null && customNames.containsKey(parameter.getLocalName())) { + builder.string(customNames.get(parameter.getLocalName())); + } else if (unexpectedValueName != null && parameter.getLocalName().equals(unexpectedValueName)) { + builder.cast(parameter.getType(), CodeTreeBuilder.singleString("ex.getResult()")); + } else if (sourceParameter != null) { + builder.string(valueName(sourceParameter, parameter)); + } else { + builder.string(valueName(parameter)); + } + } + } + + private static String valueName(Parameter sourceParameter, Parameter targetParameter) { + if (!sourceParameter.getSpecification().isSignature()) { + return valueName(targetParameter); + } else if (sourceParameter.getTypeSystemType() != null && targetParameter.getTypeSystemType() != null) { + if (sourceParameter.getTypeSystemType().needsCastTo(targetParameter.getTypeSystemType())) { + return castValueName(targetParameter); + } + } + return valueName(targetParameter); + } + + private static CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName, + String... customSignatureValueNames) { + CodeTreeBuilder builder = parent.create(); + + boolean castedValues = sourceMethod != targetMethod; + + builder.startGroup(); + ExecutableElement method = targetMethod.getMethod(); + if (method == null) { + throw new UnsupportedOperationException(); + } + TypeElement targetClass = ElementUtils.findNearestEnclosingType(method.getEnclosingElement()); + NodeData node = (NodeData) targetMethod.getTemplate(); + + if (target == null) { + boolean accessible = targetMethod.canBeAccessedByInstanceOf(node.getNodeType()); + if (accessible) { + if (builder.findMethod().getModifiers().contains(STATIC)) { + if (method.getModifiers().contains(STATIC)) { + builder.type(targetClass.asType()); + } else { + builder.string(THIS_NODE_LOCAL_VAR_NAME); + } + } else { + if (targetMethod instanceof ExecutableTypeData) { + builder.string("this"); + } else { + builder.string("super"); + } + } + } else { + if (method.getModifiers().contains(STATIC)) { + builder.type(targetClass.asType()); + } else { + Parameter firstParameter = null; + for (Parameter searchParameter : targetMethod.getParameters()) { + if (searchParameter.getSpecification().isSignature()) { + firstParameter = searchParameter; + break; + } + } + if (firstParameter == null) { + throw new AssertionError(); + } + + Parameter sourceParameter = sourceMethod.findParameter(firstParameter.getLocalName()); + + if (castedValues && sourceParameter != null) { + builder.string(valueName(sourceParameter, firstParameter)); + } else { + builder.string(valueName(firstParameter)); + } + } + } + builder.string("."); + } else { + builder.tree(target); + } + builder.startCall(method.getSimpleName().toString()); + + int signatureIndex = 0; + + for (Parameter targetParameter : targetMethod.getParameters()) { + Parameter valueParameter = null; + if (sourceMethod != null) { + valueParameter = sourceMethod.findParameter(targetParameter.getLocalName()); + } + if (valueParameter == null) { + valueParameter = targetParameter; + } + TypeMirror targetType = targetParameter.getType(); + TypeMirror valueType = null; + if (valueParameter != null) { + valueType = valueParameter.getType(); + } + + if (signatureIndex < customSignatureValueNames.length && targetParameter.getSpecification().isSignature()) { + builder.string(customSignatureValueNames[signatureIndex]); + signatureIndex++; + } else if (targetParameter.getSpecification().isLocal()) { + builder.startGroup(); + if (builder.findMethod().getModifiers().contains(Modifier.STATIC)) { + builder.string(THIS_NODE_LOCAL_VAR_NAME).string("."); + } else { + builder.string("this."); + } + builder.string(targetParameter.getSpecification().getName()); + builder.end(); + } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) { + builder.cast(targetParameter.getType(), CodeTreeBuilder.singleString("ex.getResult()")); + } else if (!ElementUtils.needsCastTo(valueType, targetType)) { + builder.startGroup(); + builder.string(valueName(targetParameter)); + builder.end(); + } else { + builder.string(castValueName(targetParameter)); + } + } + + builder.end().end(); + + return builder.getRoot(); + } + + private static String baseClassName(NodeData node) { + String nodeid = resolveNodeId(node); + String name = ElementUtils.firstLetterUpperCase(nodeid); + name += "BaseNode"; + return name; + } + + private static CodeTree createCallTypeSystemMethod(CodeTreeBuilder parent, NodeData node, String methodName, CodeTree... args) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + startCallTypeSystemMethod(builder, node.getTypeSystem(), methodName); + for (CodeTree arg : args) { + builder.tree(arg); + } + builder.end().end(); + return builder.getRoot(); + } + + private static void startCallTypeSystemMethod(CodeTreeBuilder body, TypeSystemData typeSystem, String methodName) { + GeneratedTypeMirror typeMirror = new GeneratedTypeMirror(ElementUtils.getPackageName(typeSystem.getTemplateType()), TypeSystemCodeGenerator.typeName(typeSystem)); + body.startGroup(); + body.staticReference(typeMirror, TypeSystemCodeGenerator.singletonName(typeSystem)); + body.string(".").startCall(methodName); + } + + /** + *
    +     * variant1 $condition != null
    +     * 
    +     * $type $name = defaultValue($type);
    +     * if ($condition) {
    +     *     $name = $value;
    +     * }
    +     * 
    +     * variant2 $condition != null
    +     * $type $name = $value;
    +     * 
    + * + * . + */ + private static CodeTree createLazyAssignment(CodeTreeBuilder parent, String name, TypeMirror type, CodeTree condition, CodeTree value) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + if (condition == null) { + builder.declaration(type, name, value); + } else { + builder.declaration(type, name, new CodeTreeBuilder(parent).defaultValue(type).getRoot()); + + builder.startIf().tree(condition).end(); + builder.startBlock(); + builder.startStatement(); + builder.string(name); + builder.string(" = "); + builder.tree(value); + builder.end(); // statement + builder.end(); // block + } + return builder.getRoot(); + } + + private void emitEncounteredSynthetic(CodeTreeBuilder builder, TemplateMethod current) { + CodeTreeBuilder nodes = builder.create(); + CodeTreeBuilder arguments = builder.create(); + nodes.startCommaGroup(); + arguments.startCommaGroup(); + boolean empty = true; + for (Parameter parameter : current.getParameters()) { + NodeExecutionData executionData = parameter.getSpecification().getExecution(); + if (executionData != null) { + if (executionData.isShortCircuit()) { + nodes.nullLiteral(); + arguments.string(valueName(parameter.getPreviousParameter())); + } + nodes.tree(createAccessChild(executionData, "rootNode")); + arguments.string(valueName(parameter)); + empty = false; + } + } + nodes.end(); + arguments.end(); + builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end(); + + builder.declaration(baseClassName(getModel()), "rootNode", builder.create().startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_FIND_ROOT).string("this").end()); + builder.startThrow().startNew(getContext().getType(UnsupportedSpecializationException.class)); + builder.string("rootNode"); + builder.startNewArray(getContext().getTruffleTypes().getNodeArray(), null); + builder.tree(nodes.getRoot()); + builder.end(); + if (!empty) { + builder.tree(arguments.getRoot()); + } + builder.end().end(); + } + + private static List findUserConstructors(TypeMirror nodeType) { + List constructors = new ArrayList<>(); + for (ExecutableElement constructor : ElementFilter.constructorsIn(ElementUtils.fromTypeMirror(nodeType).getEnclosedElements())) { + if (constructor.getModifiers().contains(PRIVATE)) { + continue; + } + if (isCopyConstructor(constructor)) { + continue; + } + constructors.add(constructor); + } + + if (constructors.isEmpty()) { + constructors.add(new CodeExecutableElement(null, ElementUtils.getSimpleName(nodeType))); + } + + return constructors; + } + + private static ExecutableElement findCopyConstructor(TypeMirror type) { + for (ExecutableElement constructor : ElementFilter.constructorsIn(ElementUtils.fromTypeMirror(type).getEnclosedElements())) { + if (constructor.getModifiers().contains(PRIVATE)) { + continue; + } + if (isCopyConstructor(constructor)) { + return constructor; + } + } + + return null; + } + + private static boolean isCopyConstructor(ExecutableElement element) { + if (element.getParameters().size() != 1) { + return false; + } + VariableElement var = element.getParameters().get(0); + TypeElement enclosingType = ElementUtils.findNearestEnclosingType(var); + if (ElementUtils.typeEquals(var.asType(), enclosingType.asType())) { + return true; + } + List types = ElementUtils.getDirectSuperTypes(enclosingType); + for (TypeElement type : types) { + if (!(type instanceof CodeTypeElement)) { + // no copy constructors which are not generated types + return false; + } + + if (ElementUtils.typeEquals(var.asType(), type.asType())) { + return true; + } + } + return false; + } + + @Override + @SuppressWarnings("unchecked") + protected void createChildren(NodeData node) { + List casts = new ArrayList<>(getElement().getEnclosedElements()); + getElement().getEnclosedElements().clear(); + + Map> childTypes = new LinkedHashMap<>(); + for (NodeData nodeChild : node.getEnclosingNodes()) { + NodeCodeGenerator generator = new NodeCodeGenerator(); + childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements()); + } + + if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) { + NodeFactoryFactory factory = new NodeFactoryFactory(childTypes); + add(factory, node); + factory.getElement().getEnclosedElements().addAll(casts); + } + } + + private static CodeTree createCastType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) { + if (targetType == null) { + return value; + } else if (sourceType != null && !sourceType.needsCastTo(targetType)) { + return value; + } + + CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); + String targetMethodName; + if (expect) { + targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType); + } else { + targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType); + } + startCallTypeSystemMethod(builder, typeSystem, targetMethodName); + builder.tree(value); + builder.end().end(); + return builder.getRoot(); + } + + private static CodeTree createExpectType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, CodeTree expression) { + return createCastType(typeSystem, sourceType, targetType, true, expression); + } + + private CodeTree createDeoptimize(CodeTreeBuilder parent) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + builder.startStatement(); + builder.startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end(); + builder.end(); + return builder.getRoot(); + } + + private class NodeFactoryFactory extends AbstractClassElementFactory { + + private final Map> childTypes; + private CodeTypeElement generatedNode; + + public NodeFactoryFactory(Map> childElements) { + this.childTypes = childElements; + } + + @Override + protected CodeTypeElement create(NodeData node) { + Modifier visibility = ElementUtils.getVisibility(node.getTemplateType().getModifiers()); + + CodeTypeElement clazz = createClass(node, modifiers(), factoryClassName(node), null, false); + if (visibility != null) { + clazz.getModifiers().add(visibility); + } + clazz.getModifiers().add(Modifier.FINAL); + return clazz; + } + + @Override + protected void createChildren(NodeData node) { + CodeTypeElement clazz = getElement(); + + Modifier createVisibility = ElementUtils.getVisibility(clazz.getModifiers()); + + if (node.needsFactory()) { + NodeBaseFactory factory = new NodeBaseFactory(); + add(factory, node.getGenericSpecialization() == null ? node.getSpecializations().get(0) : node.getGenericSpecialization()); + generatedNode = factory.getElement(); + + createFactoryMethods(node, clazz, createVisibility); + + for (SpecializationData specialization : node.getSpecializations()) { + if (!specialization.isReachable() || specialization.isGeneric()) { + continue; + } + + if (specialization.isPolymorphic() && node.isPolymorphic(context)) { + PolymorphicNodeFactory polymorphicFactory = new PolymorphicNodeFactory(generatedNode); + add(polymorphicFactory, specialization); + continue; + } + + add(new SpecializedNodeFactory(generatedNode), specialization); + } + + TypeMirror nodeFactory = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(getContext().getTruffleTypes().getNodeFactoryBase()), node.getNodeType()); + clazz.setSuperClass(nodeFactory); + clazz.add(createNodeFactoryConstructor(node)); + clazz.add(createCreateNodeMethod(node)); + clazz.add(createGetInstanceMethod(node, createVisibility)); + clazz.add(createInstanceConstant(node, clazz.asType())); + } + + for (NodeData childNode : childTypes.keySet()) { + if (childNode.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { + continue; + } + + for (TypeElement type : childTypes.get(childNode)) { + Set typeModifiers = ((CodeTypeElement) type).getModifiers(); + Modifier visibility = ElementUtils.getVisibility(type.getModifiers()); + typeModifiers.clear(); + if (visibility != null) { + typeModifiers.add(visibility); + } + + typeModifiers.add(Modifier.STATIC); + typeModifiers.add(Modifier.FINAL); + clazz.add(type); + } + } + + List children = node.getNodeDeclaringChildren(); + if (node.getDeclaringNode() == null && children.size() > 0) { + clazz.add(createGetFactories(node)); + } + + } + + private Element createNodeFactoryConstructor(NodeData node) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), null, factoryClassName(node)); + CodeTreeBuilder builder = method.createBuilder(); + builder.startStatement(); + builder.startCall("super"); + + // node type + builder.typeLiteral(node.getNodeType()); + + // execution signature + builder.startGroup(); + if (node.getChildExecutions().isEmpty()) { + builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY); + } else { + builder.startNewArray(new ArrayCodeTypeMirror(context.getType(Class.class)), null); + for (NodeExecutionData execution : node.getChildExecutions()) { + builder.typeLiteral(execution.getNodeType()); + } + builder.end(); + } + builder.end(); + + // node signatures + builder.startGroup(); + builder.startNewArray(new ArrayCodeTypeMirror(new ArrayCodeTypeMirror(context.getType(Class.class))), null); + List constructors = findUserConstructors(generatedNode.asType()); + for (ExecutableElement constructor : constructors) { + builder.startGroup(); + if (constructor.getParameters().isEmpty()) { + builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY); + } else { + builder.startNewArray(new ArrayCodeTypeMirror(context.getType(Class.class)), null); + for (VariableElement var : constructor.getParameters()) { + builder.typeLiteral(var.asType()); + } + builder.end(); + } + builder.end(); + } + builder.end(); + builder.end(); + + builder.end().end().end(); + return method; + } + + private CodeExecutableElement createCreateNodeMethod(NodeData node) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNode"); + CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Object.class), "arguments"); + method.setVarArgs(true); + method.addParameter(arguments); + + CodeTreeBuilder builder = method.createBuilder(); + List signatures = findUserConstructors(generatedNode.asType()); + boolean ifStarted = false; + + for (ExecutableElement element : signatures) { + ifStarted = builder.startIf(ifStarted); + builder.string("arguments.length == " + element.getParameters().size()); + + int index = 0; + for (VariableElement param : element.getParameters()) { + if (ElementUtils.isObject(param.asType())) { + continue; + } + builder.string(" && "); + if (!param.asType().getKind().isPrimitive()) { + builder.string("(arguments[" + index + "] == null || "); + } + builder.string("arguments[" + index + "] instanceof "); + builder.type(ElementUtils.boxType(getContext(), param.asType())); + if (!param.asType().getKind().isPrimitive()) { + builder.string(")"); + } + index++; + } + builder.end(); + builder.startBlock(); + + builder.startReturn().startCall("create"); + index = 0; + for (VariableElement param : element.getParameters()) { + builder.startGroup(); + if (!ElementUtils.isObject(param.asType())) { + builder.string("(").type(param.asType()).string(") "); + } + builder.string("arguments[").string(String.valueOf(index)).string("]"); + builder.end(); + index++; + } + builder.end().end(); + + builder.end(); // block + } + + builder.startElseBlock(); + builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)); + builder.doubleQuote("Invalid create signature."); + builder.end().end(); + builder.end(); // else block + return method; + } + + private ExecutableElement createGetInstanceMethod(NodeData node, Modifier visibility) { + TypeElement nodeFactoryType = ElementUtils.fromTypeMirror(getContext().getType(NodeFactory.class)); + TypeMirror returnType = ElementUtils.getDeclaredType(nodeFactoryType, node.getNodeType()); + + CodeExecutableElement method = new CodeExecutableElement(modifiers(), returnType, "getInstance"); + if (visibility != null) { + method.getModifiers().add(visibility); + } + method.getModifiers().add(Modifier.STATIC); + + String varName = instanceVarName(node); + + CodeTreeBuilder builder = method.createBuilder(); + builder.startIf(); + builder.string(varName).string(" == null"); + builder.end().startBlock(); + + builder.startStatement(); + builder.string(varName); + builder.string(" = "); + builder.startNew(factoryClassName(node)).end(); + builder.end(); + + builder.end(); + builder.startReturn().string(varName).end(); + return method; + } + + private String instanceVarName(NodeData node) { + if (node.getDeclaringNode() != null) { + return ElementUtils.firstLetterLowerCase(factoryClassName(node)) + "Instance"; + } else { + return "instance"; + } + } + + private CodeVariableElement createInstanceConstant(NodeData node, TypeMirror factoryType) { + String varName = instanceVarName(node); + CodeVariableElement var = new CodeVariableElement(modifiers(), factoryType, varName); + var.getModifiers().add(Modifier.PRIVATE); + var.getModifiers().add(Modifier.STATIC); + return var; + } + + private ExecutableElement createGetFactories(NodeData node) { + List children = node.getNodeDeclaringChildren(); + if (node.needsFactory()) { + children.add(node); + } + + List nodeTypesList = new ArrayList<>(); + TypeMirror prev = null; + boolean allSame = true; + for (NodeData child : children) { + nodeTypesList.add(child.getNodeType()); + if (prev != null && !ElementUtils.typeEquals(child.getNodeType(), prev)) { + allSame = false; + } + prev = child.getNodeType(); + } + TypeMirror commonNodeSuperType = ElementUtils.getCommonSuperType(getContext(), nodeTypesList.toArray(new TypeMirror[nodeTypesList.size()])); + + Types types = getContext().getEnvironment().getTypeUtils(); + TypeMirror factoryType = getContext().getType(NodeFactory.class); + TypeMirror baseType; + if (allSame) { + baseType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(factoryType), commonNodeSuperType); + } else { + baseType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null)); + } + TypeMirror listType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(getContext().getType(List.class)), baseType); + + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), listType, "getFactories"); + + CodeTreeBuilder builder = method.createBuilder(); + builder.startReturn(); + builder.startStaticCall(getContext().getType(Arrays.class), "asList"); + + for (NodeData child : children) { + builder.startGroup(); + NodeData childNode = child; + List factories = new ArrayList<>(); + while (childNode.getDeclaringNode() != null) { + factories.add(childNode); + childNode = childNode.getDeclaringNode(); + } + Collections.reverse(factories); + for (NodeData nodeData : factories) { + builder.string(factoryClassName(nodeData)).string("."); + } + builder.string("getInstance()"); + builder.end(); + } + builder.end(); + builder.end(); + return method; + } + + private void createFactoryMethods(NodeData node, CodeTypeElement clazz, Modifier createVisibility) { + List constructors = findUserConstructors(generatedNode.asType()); + for (ExecutableElement constructor : constructors) { + clazz.add(createCreateMethod(node, createVisibility, constructor)); + } + } + + private CodeExecutableElement createCreateMethod(NodeData node, Modifier visibility, ExecutableElement constructor) { + CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), constructor); + method.setSimpleName(CodeNames.of("create")); + method.getModifiers().clear(); + if (visibility != null) { + method.getModifiers().add(visibility); + } + method.getModifiers().add(Modifier.STATIC); + method.setReturnType(node.getNodeType()); + + CodeTreeBuilder body = method.createBuilder(); + body.startReturn(); + if (node.getSpecializations().isEmpty()) { + body.nullLiteral(); + } else { + body.startCall(nodeSpecializationClassName(node.getSpecializations().get(0)), FACTORY_METHOD_NAME); + for (VariableElement var : method.getParameters()) { + body.string(var.getSimpleName().toString()); + } + body.end(); + } + body.end(); + return method; + } + + } + + private class NodeBaseFactory extends AbstractClassElementFactory { + + @Override + protected CodeTypeElement create(SpecializationData specialization) { + NodeData node = specialization.getNode(); + CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, ABSTRACT, STATIC), baseClassName(node), node.getNodeType(), false); + clazz.getImplements().add(context.getTruffleTypes().getDslNode()); + + for (NodeChildData child : node.getChildren()) { + clazz.add(createChildField(child)); + + if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) { + ExecutableElement getter = (ExecutableElement) child.getAccessElement(); + CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), getter); + method.getModifiers().remove(Modifier.ABSTRACT); + CodeTreeBuilder builder = method.createBuilder(); + builder.startReturn().string("this.").string(child.getName()).end(); + clazz.add(method); + } + } + + for (NodeFieldData field : node.getFields()) { + if (!field.isGenerated()) { + continue; + } + + clazz.add(new CodeVariableElement(modifiers(PROTECTED, FINAL), field.getType(), field.getName())); + if (field.getGetter() != null && field.getGetter().getModifiers().contains(Modifier.ABSTRACT)) { + CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), field.getGetter()); + method.getModifiers().remove(Modifier.ABSTRACT); + method.createBuilder().startReturn().string("this.").string(field.getName()).end(); + clazz.add(method); + } + } + + for (String assumption : node.getAssumptions()) { + clazz.add(createAssumptionField(assumption)); + } + + createConstructors(node, clazz); + + return clazz; + } + + @Override + protected void createChildren(SpecializationData specialization) { + NodeData node = specialization.getNode(); + CodeTypeElement clazz = getElement(); + + SpecializationGroup rootGroup = createSpecializationGroups(node); + + if (node.needsRewrites(context)) { + if (node.isPolymorphic(context)) { + + CodeVariableElement var = new CodeVariableElement(modifiers(PROTECTED), clazz.asType(), "next0"); + var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation())); + clazz.add(var); + + CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getPolymorphicSpecialization()); + clazz.add(genericCachedExecute); + + } + + for (CodeExecutableElement method : createImplicitChildrenAccessors()) { + clazz.add(method); + } + clazz.add(createInfoMessage(node)); + clazz.add(createMonomorphicRewrite()); + clazz.add(createCreateSpecializationMethod(node, rootGroup)); + } + + clazz.add(createAdoptChildren0()); + clazz.add(createGetMetadata0(true)); + clazz.add(createUpdateTypes0()); + clazz.add(createGetNext()); + } + + private Element createGetNext() { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), context.getType(Node.class), "getNext0"); + CodeTreeBuilder builder = method.createBuilder(); + NodeData node = getModel().getNode(); + + if (node.isPolymorphic(context)) { + builder.startReturn().string("next0").end(); + } else { + builder.returnNull(); + } + + return method; + } + + protected final CodeExecutableElement createUpdateTypes0() { + ArrayType classArray = new ArrayCodeTypeMirror(context.getType(Class.class)); + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(void.class), "updateTypes0"); + method.getParameters().add(new CodeVariableElement(classArray, "types")); + + if (getModel().isPolymorphic()) { + CodeTreeBuilder builder = method.createBuilder(); + + int index = 0; + for (NodeExecutionData execution : getModel().getNode().getChildExecutions()) { + String fieldName = polymorphicTypeName(execution); + + builder.startStatement(); + builder.string(fieldName).string(" = ").string("types[").string(String.valueOf(index)).string("]"); + builder.end(); + index++; + } + } + + return method; + } + + protected final CodeExecutableElement createGetMetadata0(boolean empty) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getTruffleTypes().getDslMetadata(), "getMetadata0"); + if (empty) { + method.createBuilder().startReturn().staticReference(context.getTruffleTypes().getDslMetadata(), "NONE").end(); + } else { + method.createBuilder().startReturn().string(METADATA_FIELD_NAME).end(); + } + return method; + } + + private CodeExecutableElement createAdoptChildren0() { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), context.getType(void.class), "adoptChildren0"); + method.getParameters().add(new CodeVariableElement(context.getTruffleTypes().getNode(), "other")); + method.getParameters().add(new CodeVariableElement(context.getTruffleTypes().getNode(), "newNext")); + NodeData node = getModel().getNode(); + CodeTreeBuilder builder = method.createBuilder(); + List executions = node.getChildExecutions(); + + if (executions.size() > 0) { + builder.startIf().string("other == null").end().startBlock(); + for (NodeExecutionData execution : executions) { + builder.startStatement().tree(createAccessChild(execution, "this")).string(" = null").end(); + } + builder.end().startElseBlock(); + + String access; + if (executions.size() > 1) { + builder.declaration(baseClassName(node), "otherCast", builder.create().cast(baseClassName(node)).string("other")); + access = "otherCast"; + } else { + assert executions.size() == 1; + access = "((" + baseClassName(node) + ") other)"; + } + for (NodeExecutionData execution : executions) { + builder.startStatement().tree(createAccessChild(execution, "this")).string(" = ").tree(createAccessChild(execution, access)).end(); + } + + builder.end(); + } + + if (getModel().getNode().isPolymorphic(context)) { + builder.startIf().string("newNext == null").end().startBlock(); + builder.statement("this.next0 = null"); + builder.end().startElseBlock(); + builder.statement("this.next0 = (" + baseClassName(getModel().getNode()) + ") newNext"); + builder.end(); + } + + return method; + } + + private List createImplicitChildrenAccessors() { + NodeData node = getModel().getNode(); + List> prototype = Collections.nCopies(node.getGenericSpecialization().getParameters().size(), null); + List> expectTypes = new ArrayList<>(prototype); + + for (ExecutableTypeData executableType : node.getExecutableTypes()) { + for (int i = 0; i < executableType.getEvaluatedCount(); i++) { + Parameter parameter = executableType.getSignatureParameter(i); + if (i >= expectTypes.size()) { + break; + } + Set types = expectTypes.get(i); + if (types == null) { + types = new TreeSet<>(); + expectTypes.set(i, types); + } + types.add(parameter.getTypeSystemType()); + } + } + + List methods = new ArrayList<>(); + List> visitedList = new ArrayList<>(prototype); + for (SpecializationData spec : node.getSpecializations()) { + int signatureIndex = -1; + for (Parameter param : spec.getParameters()) { + if (!param.getSpecification().isSignature()) { + continue; + } + signatureIndex++; + Set visitedTypeData = visitedList.get(signatureIndex); + if (visitedTypeData == null) { + visitedTypeData = new TreeSet<>(); + visitedList.set(signatureIndex, visitedTypeData); + } + + if (visitedTypeData.contains(param.getTypeSystemType())) { + continue; + } + visitedTypeData.add(param.getTypeSystemType()); + + Set expect = expectTypes.get(signatureIndex); + if (expect == null) { + expect = Collections.emptySet(); + } + + methods.addAll(createExecuteChilds(param, expect)); + } + } + return methods; + } + + private CodeTree truffleBooleanOption(CodeTreeBuilder parent, String name) { + CodeTreeBuilder builder = parent.create(); + builder.staticReference(getContext().getTruffleTypes().getTruffleOptions(), name); + return builder.getRoot(); + } + + private Element createInfoMessage(NodeData node) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), getContext().getType(String.class), CREATE_INFO); + method.addParameter(new CodeVariableElement(getContext().getType(String.class), "message")); + addInternalValueParameters(method, node.getGenericSpecialization(), false, false); + + CodeTreeBuilder builder = method.createBuilder(); + + builder.startIf().tree(truffleBooleanOption(builder, TruffleTypes.OPTION_DETAILED_REWRITE_REASONS)).end(); + builder.startBlock(); + + builder.startStatement().string("StringBuilder builder = new StringBuilder(message)").end(); + builder.startStatement().startCall("builder", "append").doubleQuote(" (").end().end(); + + String sep = null; + for (Parameter parameter : node.getGenericSpecialization().getSignatureParameters()) { + builder.startStatement(); + builder.string("builder"); + if (sep != null) { + builder.startCall(".append").doubleQuote(sep).end(); + } + builder.startCall(".append").doubleQuote(parameter.getLocalName()).end(); + builder.startCall(".append").doubleQuote(" = ").end(); + builder.startCall(".append").string(parameter.getLocalName()).end(); + builder.end(); + + if (!ElementUtils.isPrimitive(parameter.getType())) { + builder.startIf().string(parameter.getLocalName() + " != null").end(); + builder.startBlock(); + } + builder.startStatement(); + if (ElementUtils.isPrimitive(parameter.getType())) { + builder.startCall("builder.append").doubleQuote(" (" + ElementUtils.getSimpleName(parameter.getType()) + ")").end(); + } else { + builder.startCall("builder.append").doubleQuote(" (").end(); + builder.startCall(".append").string(parameter.getLocalName() + ".getClass().getSimpleName()").end(); + builder.startCall(".append").doubleQuote(")").end(); + } + builder.end(); + if (!ElementUtils.isPrimitive(parameter.getType())) { + builder.end(); + } + + sep = ", "; + } + + builder.startStatement().startCall("builder", "append").doubleQuote(")").end().end(); + builder.startReturn().string("builder.toString()").end(); + + builder.end(); + builder.startElseBlock(); + builder.startReturn().string("message").end(); + builder.end(); + + return method; + } + + private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph) { + CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), EXECUTE_CHAINED); + addInternalValueParameters(cachedExecute, polymorph, true, false); + + ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0); + boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext()); + if (sourceThrowsUnexpected && sourceExecutableType.getType().equals(node.getGenericSpecialization().getReturnType().getTypeSystemType())) { + sourceThrowsUnexpected = false; + } + if (sourceThrowsUnexpected) { + cachedExecute.getThrownTypes().add(getContext().getType(UnexpectedResultException.class)); + } + return cachedExecute; + + } + + private void createConstructors(NodeData node, CodeTypeElement clazz) { + List constructors = findUserConstructors(node.getNodeType()); + ExecutableElement sourceSectionConstructor = null; + if (constructors.isEmpty()) { + clazz.add(createUserConstructor(clazz, null)); + } else { + for (ExecutableElement constructor : constructors) { + clazz.add(createUserConstructor(clazz, constructor)); + if (NodeParser.isSourceSectionConstructor(context, constructor)) { + sourceSectionConstructor = constructor; + } + } + } + if (node.needsRewrites(getContext())) { + ExecutableElement copyConstructor = findCopyConstructor(node.getNodeType()); + clazz.add(createCopyConstructor(clazz, copyConstructor, sourceSectionConstructor)); + } + } + + private CodeExecutableElement createUserConstructor(CodeTypeElement type, ExecutableElement superConstructor) { + CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString()); + CodeTreeBuilder builder = method.createBuilder(); + + NodeData node = getModel().getNode(); + + if (superConstructor != null) { + for (VariableElement param : superConstructor.getParameters()) { + method.getParameters().add(CodeVariableElement.clone(param)); + } + } + + if (superConstructor != null) { + builder.startStatement().startSuperCall(); + for (VariableElement param : superConstructor.getParameters()) { + builder.string(param.getSimpleName().toString()); + } + builder.end().end(); + } + + for (VariableElement var : type.getFields()) { + if (var.getModifiers().contains(STATIC)) { + continue; + } + NodeChildData child = node.findChild(var.getSimpleName().toString()); + + if (child != null) { + method.getParameters().add(new CodeVariableElement(child.getOriginalType(), child.getName())); + } else { + method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString())); + } + + builder.startStatement(); + String fieldName = var.getSimpleName().toString(); + + CodeTree init = createStaticCast(builder, child, fieldName); + + builder.string("this.").string(fieldName).string(" = ").tree(init); + builder.end(); + } + return method; + } + + private CodeTree createStaticCast(CodeTreeBuilder parent, NodeChildData child, String fieldName) { + NodeData parentNode = getModel().getNode(); + if (child != null) { + CreateCastData createCast = parentNode.findCast(child.getName()); + if (createCast != null) { + return createTemplateMethodCall(parent, null, parentNode.getGenericSpecialization(), createCast, null, fieldName); + } + } + return CodeTreeBuilder.singleString(fieldName); + } + + private CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor, ExecutableElement sourceSectionConstructor) { + CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString()); + CodeTreeBuilder builder = method.createBuilder(); + method.getParameters().add(new CodeVariableElement(type.asType(), "copy")); + + if (superConstructor != null) { + builder.startStatement().startSuperCall().string("copy").end().end(); + } else if (sourceSectionConstructor != null) { + builder.startStatement().startSuperCall().string("copy.getSourceSection()").end().end(); + } + + for (VariableElement var : type.getFields()) { + if (var.getModifiers().contains(STATIC) || !var.getModifiers().contains(FINAL)) { + continue; + } + final String varName = var.getSimpleName().toString(); + final TypeMirror varType = var.asType(); + if (ElementUtils.isAssignable(varType, getContext().getTruffleTypes().getNodeArray())) { + CodeTree size = builder.create().string("copy.", varName, ".length").getRoot(); + builder.startStatement().string("this.").string(varName).string(" = ").startNewArray((ArrayType) varType, size).end().end(); + } else { + builder.startStatement().string("this.", varName, " = copy.", varName).end(); + } + } + + return method; + } + + private CodeVariableElement createAssumptionField(String assumption) { + CodeVariableElement var = new CodeVariableElement(getContext().getTruffleTypes().getAssumption(), assumption); + var.getModifiers().add(Modifier.FINAL); + return var; + } + + private CodeVariableElement createChildField(NodeChildData child) { + TypeMirror type = child.getNodeType(); + CodeVariableElement var = new CodeVariableElement(type, child.getName()); + var.getModifiers().add(Modifier.PROTECTED); + + DeclaredType annotationType; + if (child.getCardinality() == Cardinality.MANY) { + var.getModifiers().add(Modifier.FINAL); + annotationType = getContext().getTruffleTypes().getChildrenAnnotation(); + } else { + annotationType = getContext().getTruffleTypes().getChildAnnotation(); + } + + var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType)); + return var; + } + + private SpecializationGroup createSpecializationGroups(final NodeData node) { + List specializations = node.getSpecializations(); + List filteredSpecializations = new ArrayList<>(); + for (SpecializationData current : specializations) { + if (current.isUninitialized() || current.isPolymorphic() || !current.isReachable()) { + continue; + } + filteredSpecializations.add(current); + } + + return SpecializationGroup.create(filteredSpecializations); + } + + protected final CodeExecutableElement createExecuteUninitialized() { + NodeData node = getModel().getNode(); + SpecializationData generic = node.getGenericSpecialization(); + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), generic.getReturnType().getType(), EXECUTE_UNINITIALIZED); + addInternalValueParameters(method, generic, true, false); + CodeTreeBuilder builder = method.createBuilder(); + + CodeTreeBuilder createSpecializationCall = builder.create(); + createSpecializationCall.startCall(SPECIALIZE); + addInternalValueParameterNames(createSpecializationCall, generic, generic, null, node.needsFrame(getContext()), null); + createSpecializationCall.end(); + builder.declaration(baseClassName(node), "newNode", createSpecializationCall); + + if (generic.isReachable()) { + builder.startIf().string("newNode == null").end().startBlock(); + + builder.startIf().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "inInterpreter").end().end().startBlock(); + builder.statement("containsFallback = true"); + builder.end(); + builder.tree(createGenericInvoke(builder, generic, generic)); + builder.end(); + builder.startElseBlock(); + builder.tree(createDeoptimize(builder)); + builder.end(); + } + + builder.startReturn(); + builder.startStaticCall(context.getTruffleTypes().getDslShare(), "rewriteUninitialized").string("this").string("newNode").end(); + builder.string(".").startCall(EXECUTE_CHAINED); + addInternalValueParameterNames(builder, generic, generic, null, true, null); + builder.end(); + builder.end(); + + if (generic.isReachable()) { + builder.end(); + } + + return method; + } + + private CodeTree createInfoCall(CodeTreeBuilder parent, SpecializationData specialization, String reason) { + CodeTreeBuilder builder = parent.create(); + builder.startCall(CREATE_INFO).string(reason); + addInternalValueParameterNames(builder, specialization, specialization, null, false, null); + builder.end(); + return builder.getRoot(); + } + + private CodeExecutableElement createMonomorphicRewrite() { + NodeData node = getModel().getNode(); + + SpecializationData generic = node.getGenericSpecialization(); + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), generic.getReturnType().getType(), REWRITE); + addInternalValueParameters(method, generic, true, false); + method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason")); + + CodeTreeBuilder builder = method.createBuilder(); + + builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end().end(); + String baseClassName = baseClassName(getModel().getNode()); + CodeTreeBuilder createSpecializationCall = builder.create(); + createSpecializationCall.startCall(SPECIALIZE); + addInternalValueParameterNames(createSpecializationCall, generic, generic, null, node.needsFrame(getContext()), null); + createSpecializationCall.end(); + builder.declaration(baseClassName, "newNode", createSpecializationCall); + + builder.startIf().string("newNode == null").end().startBlock(); + builder.startStatement(); + String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization()); + builder.string("newNode = ").startNew(uninitializedName).string("this").end(); + builder.end(); + if (node.isFallbackReachable()) { + builder.startStatement().string("((", uninitializedName, ") newNode).containsFallback = true").end(); + } + builder.end(); + + builder.startStatement(); + builder.type(getContext().getType(String.class)).string(" message = ").tree(createInfoCall(builder, generic, "reason")); + builder.end(); + + builder.declaration(baseClassName, "returnNode", + builder.create().startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_REWRITE).string("this").string("newNode").string("message").end().getRoot()); + builder.startIf().string("returnNode == null").end().startBlock(); + builder.tree(createRewritePolymorphic(builder, node, "this")); + builder.end(); + + builder.startReturn(); + builder.startCall("returnNode", EXECUTE_CHAINED); + addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, null); + builder.end(); + builder.end(); + + return method; + } + + private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node, String currentNode) { + String polyClassName = nodePolymorphicClassName(node); + CodeTreeBuilder builder = parent.create(); + + builder.startStatement().string("returnNode = "); + builder.startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_REWRITE_TO_POLYMORHPIC); + builder.string("this"); + builder.tree(builder.create().startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string(currentNode).end().getRoot()); + builder.tree(builder.create().startNew(polyClassName).string(currentNode).end().getRoot()); + builder.startGroup().cast(baseClassName(node)).startCall("copy").end().end(); + builder.string("newNode"); + builder.string("message"); + builder.end(); + builder.end(); + + return builder.getRoot(); + } + + private CodeExecutableElement createCreateSpecializationMethod(NodeData node, SpecializationGroup group) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), new GeneratedTypeMirror(ElementUtils.getPackageName(node.getTemplateType()), baseClassName(node)), + SPECIALIZE); + if (!node.needsFrame(getContext())) { + method.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getSlowPath())); + } + + addInternalValueParameters(method, node.getGenericSpecialization(), node.needsFrame(getContext()), false); + final CodeTreeBuilder builder = method.createBuilder(); + builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), group, new CodeBlock() { + + public CodeTree create(CodeTreeBuilder b, SpecializationData current) { + return createCreateSpecializationMethodBody0(builder, current); + } + }, null, false, true, false, true)); + + emitUnreachableSpecializations(builder, node); + + return method; + } + + protected CodeTree createCreateSpecializationMethodBody0(CodeTreeBuilder parent, SpecializationData current) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + if (current.isGeneric()) { + builder.startReturn().nullLiteral().end(); + } else { + String className = nodeSpecializationClassName(current); + if (!current.getExcludedBy().isEmpty()) { + builder.startIf().string("!").startStaticCall(context.getTruffleTypes().getDslShare(), "isExcluded"); + builder.string("this").string(nodeSpecializationClassName(current), ".", METADATA_FIELD_NAME).end().end(); + builder.startBlock(); + } + + if (current.getNode().getGenericSpecialization().isReachable()) { + builder.tree(createDeoptimize(builder)); + } + builder.startReturn(); + builder.cast(baseClassName(getModel().getNode())); + builder.startGroup().startCall(className, FACTORY_METHOD_NAME).string("this"); + for (Parameter param : current.getSignatureParameters()) { + NodeChildData child = param.getSpecification().getExecution().getChild(); + List types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); + if (types.size() > 1) { + builder.string(implicitTypeName(param)); + } + } + builder.end().end(); + builder.end(); + + if (!current.getExcludedBy().isEmpty()) { + builder.end(); + } + } + return builder.getRoot(); + + } + + private void emitUnreachableSpecializations(final CodeTreeBuilder builder, NodeData node) { + for (SpecializationData current : node.getSpecializations()) { + if (current.isReachable()) { + continue; + } + builder.string("// unreachable ").string(current.getId()).newLine(); + } + } + + protected CodeTree createExecuteTree(CodeTreeBuilder outerParent, final SpecializationData source, final SpecializationGroup group, final CodeBlock guardedblock, + final CodeTree elseBlock, boolean forceElse, final boolean emitAssumptions, final boolean typedCasts, final boolean castForGuardsOnly) { + return guard(outerParent, source, group, new CodeBlock() { + + public CodeTree create(CodeTreeBuilder parent, Integer ifCount) { + CodeTreeBuilder builder = parent.create(); + + if (group.getSpecialization() != null) { + builder.tree(guardedblock.create(builder, group.getSpecialization())); + + assert group.getChildren().isEmpty() : "missed a specialization"; + + } else { + for (SpecializationGroup childGroup : group.getChildren()) { + builder.tree(createExecuteTree(builder, source, childGroup, guardedblock, null, false, emitAssumptions, typedCasts, castForGuardsOnly)); + } + } + + return builder.getRoot(); + } + }, elseBlock, forceElse, emitAssumptions, typedCasts, castForGuardsOnly); + } + + private CodeTree guard(CodeTreeBuilder parent, SpecializationData source, SpecializationGroup group, CodeBlock bodyBlock, CodeTree elseBlock, boolean forceElse, + boolean emitAssumptions, boolean typedCasts, boolean castForGuardsOnly) { + CodeTreeBuilder builder = parent.create(); + + int ifCount = emitGuards(builder, source, group, emitAssumptions, typedCasts, castForGuardsOnly); + + if (isReachableGroup(group, ifCount)) { + builder.tree(bodyBlock.create(builder, ifCount)); + } + + builder.end(ifCount); + + if (elseBlock != null) { + if (ifCount > 0 || forceElse) { + builder.tree(elseBlock); + } + } + + return builder.getRoot(); + } + + private boolean isReachableGroup(SpecializationGroup group, int ifCount) { + if (ifCount != 0) { + return true; + } + SpecializationGroup previous = group.getPreviousGroup(); + if (previous == null || previous.findElseConnectableGuards().isEmpty()) { + return true; + } + + /* + * Hacky else case. In this case the specialization is not reachable due to previous + * else branch. This is only true if the minimum state is not checked. + */ + if (previous.getGuards().size() == 1 && previous.getTypeGuards().isEmpty() && previous.getAssumptions().isEmpty() && + (previous.getParent() == null || previous.getMaxSpecializationIndex() != previous.getParent().getMaxSpecializationIndex())) { + return false; + } + + return true; + } + + private int emitGuards(CodeTreeBuilder builder, SpecializationData source, SpecializationGroup group, boolean emitAssumptions, boolean typedCasts, boolean castForGuardsOnly) { + NodeData node = source.getNode(); + + CodeTreeBuilder guardsBuilder = builder.create(); + CodeTreeBuilder castBuilder = builder.create(); + CodeTreeBuilder guardsCastBuilder = builder.create(); + + String guardsAnd = ""; + String guardsCastAnd = ""; + + if (emitAssumptions) { + for (String assumption : group.getAssumptions()) { + guardsBuilder.string(guardsAnd); + guardsBuilder.string("this"); + guardsBuilder.string(".").string(assumption).string(".isValid()"); + guardsAnd = " && "; + } + } + + for (TypeGuard typeGuard : group.getTypeGuards()) { + Parameter valueParam = source.getSignatureParameter(typeGuard.getSignatureIndex()); + + if (valueParam == null) { + /* + * If used inside a execute evaluated method then the value param may not exist. + * In that case we assume that the value is executed generic or of the current + * specialization. + */ + if (group.getSpecialization() != null) { + valueParam = group.getSpecialization().getSignatureParameter(typeGuard.getSignatureIndex()); + } else { + valueParam = node.getGenericSpecialization().getSignatureParameter(typeGuard.getSignatureIndex()); + } + } + + NodeExecutionData execution = valueParam.getSpecification().getExecution(); + CodeTree implicitGuard = createTypeGuard(guardsBuilder, execution, valueParam, typeGuard.getType(), typedCasts); + if (implicitGuard != null) { + guardsBuilder.string(guardsAnd); + guardsBuilder.tree(implicitGuard); + guardsAnd = " && "; + } + + CodeTree implicitGetType = null; + if (castForGuardsOnly) { + implicitGetType = createGetImplicitType(builder, execution, valueParam, typeGuard.getType()); + } + + boolean performCast = true; + if (castForGuardsOnly) { + // if cast for guards we just cast if the type guard is used inside a guard. + performCast = group.isTypeGuardUsedInAnyGuardBelow(context, source, typeGuard); + } + + if (performCast) { + CodeTree cast = createCast(castBuilder, execution, valueParam, typeGuard.getType(), typedCasts); + if (cast != null) { + castBuilder.tree(cast); + } + } + if (implicitGetType != null) { + castBuilder.tree(implicitGetType); + } + } + List elseGuards = group.findElseConnectableGuards(); + + for (GuardExpression guard : group.getGuards()) { + if (elseGuards.contains(guard)) { + continue; + } + + if (needsTypeGuard(source, group, guard)) { + guardsCastBuilder.tree(createMethodGuard(builder, guardsCastAnd, source, guard)); + guardsCastAnd = " && "; + } else { + guardsBuilder.tree(createMethodGuard(builder, guardsAnd, source, guard)); + guardsAnd = " && "; + } + } + + int ifCount = startGuardIf(builder, guardsBuilder, 0, elseGuards); + builder.tree(castBuilder.getRoot()); + ifCount = startGuardIf(builder, guardsCastBuilder, ifCount, elseGuards); + return ifCount; + } + + private int startGuardIf(CodeTreeBuilder builder, CodeTreeBuilder conditionBuilder, int ifCount, List elseGuard) { + int newIfCount = ifCount; + + if (!conditionBuilder.isEmpty()) { + if (ifCount == 0 && !elseGuard.isEmpty()) { + builder.startElseIf(); + } else { + builder.startIf(); + } + builder.tree(conditionBuilder.getRoot()); + builder.end().startBlock(); + newIfCount++; + } else if (ifCount == 0 && !elseGuard.isEmpty()) { + builder.startElseBlock(); + newIfCount++; + } + return newIfCount; + } + + private boolean needsTypeGuard(SpecializationData source, SpecializationGroup group, GuardExpression guard) { + for (Parameter parameter : guard.getResolvedGuard().getParameters()) { + if (!parameter.getSpecification().isSignature()) { + continue; + } + + int signatureIndex = source.getNode().getChildExecutions().indexOf(parameter.getSpecification().getExecution()); + if (signatureIndex == -1) { + continue; + } + + TypeGuard typeGuard = group.findTypeGuard(signatureIndex); + if (typeGuard != null) { + TypeData requiredType = typeGuard.getType(); + + Parameter sourceParameter = source.findParameter(parameter.getLocalName()); + if (sourceParameter == null) { + sourceParameter = source.getNode().getGenericSpecialization().findParameter(parameter.getLocalName()); + } + + if (ElementUtils.needsCastTo(sourceParameter.getType(), requiredType.getPrimitiveType())) { + return true; + } + } + } + return false; + } + + private CodeTree createTypeGuard(CodeTreeBuilder parent, NodeExecutionData execution, Parameter source, TypeData targetType, boolean typedCasts) { + NodeData node = execution.getChild().getNodeData(); + + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + + TypeData sourceType = source.getTypeSystemType(); + + if (!sourceType.needsCastTo(targetType)) { + return null; + } + + builder.startGroup(); + + if (execution.isShortCircuit()) { + Parameter shortCircuit = source.getPreviousParameter(); + assert shortCircuit != null; + builder.string("("); + builder.string("!").string(valueName(shortCircuit)); + builder.string(" || "); + } + + String castMethodName; + String castTypeName = null; + List types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType); + if (types.size() > 1) { + castMethodName = TypeSystemCodeGenerator.isImplicitTypeMethodName(targetType); + if (typedCasts) { + castTypeName = implicitTypeName(source); + } + } else { + castMethodName = TypeSystemCodeGenerator.isTypeMethodName(targetType); + } + + startCallTypeSystemMethod(builder, node.getTypeSystem(), castMethodName); + builder.string(valueName(source)); + if (castTypeName != null) { + builder.string(castTypeName); + } + builder.end().end(); // call + + if (execution.isShortCircuit()) { + builder.string(")"); + } + + builder.end(); // group + + return builder.getRoot(); + } + + // TODO merge redundancies with #createTypeGuard + private CodeTree createCast(CodeTreeBuilder parent, NodeExecutionData execution, Parameter source, TypeData targetType, boolean typedCasts) { + NodeData node = execution.getChild().getNodeData(); + TypeData sourceType = source.getTypeSystemType(); + + if (!sourceType.needsCastTo(targetType)) { + return null; + } + + CodeTree condition = null; + if (execution.isShortCircuit()) { + Parameter shortCircuit = source.getPreviousParameter(); + assert shortCircuit != null; + condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); + } + + String castMethodName; + String castTypeName = null; + List types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType); + if (types.size() > 1) { + castMethodName = TypeSystemCodeGenerator.asImplicitTypeMethodName(targetType); + if (typedCasts) { + castTypeName = implicitTypeName(source); + } + } else { + castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType); + } + + List args = new ArrayList<>(); + args.add(CodeTreeBuilder.singleString(valueName(source))); + if (castTypeName != null) { + args.add(CodeTreeBuilder.singleString(castTypeName)); + } + + CodeTree cast = createCallTypeSystemMethod(parent, node, castMethodName, args.toArray(new CodeTree[0])); + + CodeTreeBuilder builder = parent.create(); + builder.tree(createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, cast)); + + return builder.getRoot(); + } + + private CodeTree createGetImplicitType(CodeTreeBuilder parent, NodeExecutionData execution, Parameter source, TypeData targetType) { + CodeTree condition = null; + if (execution.isShortCircuit()) { + Parameter shortCircuit = source.getPreviousParameter(); + assert shortCircuit != null; + condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); + } + + CodeTreeBuilder builder = parent.create(); + List types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType); + if (types.size() > 1) { + CodeTree castType = createCallTypeSystemMethod(parent, execution.getChild().getNodeData(), TypeSystemCodeGenerator.getImplicitClass(targetType), + CodeTreeBuilder.singleString(valueName(source))); + builder.tree(createLazyAssignment(builder, implicitTypeName(source), getContext().getType(Class.class), condition, castType)); + } + return builder.getRoot(); + } + + private CodeTree createMethodGuard(CodeTreeBuilder parent, String prefix, SpecializationData source, GuardExpression guard) { + CodeTreeBuilder builder = parent.create(); + builder.string(prefix); + if (guard.isNegated()) { + builder.string("!"); + } + builder.tree(createTemplateMethodCall(builder, null, source, guard.getResolvedGuard(), null)); + return builder.getRoot(); + } + + protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + + if (current.getMethod() == null) { + emitEncounteredSynthetic(builder, current); + } else { + builder.startReturn().tree(createTemplateMethodCall(builder, null, source, current, null)).end(); + } + + return encloseThrowsWithFallThrough(parent, current, builder.getRoot()); + } + + private CodeTree encloseThrowsWithFallThrough(CodeTreeBuilder parent, SpecializationData current, CodeTree tree) { + if (current.getExceptions().isEmpty()) { + return tree; + } + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + + builder.startTryBlock(); + builder.tree(tree); + for (SpecializationThrowsData exception : current.getExceptions()) { + builder.end().startCatchBlock(exception.getJavaClass(), "rewriteEx"); + builder.tree(createDeoptimize(builder)); + builder.tree(createCallRewriteMonomorphic(builder, false, current.getNode().getGenericSpecialization().getReturnType().getTypeSystemType(), current, null, + "Thrown " + ElementUtils.getSimpleName(exception.getJavaClass()))); + } + builder.end(); + + return builder.getRoot(); + } + + protected CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) { + TypeData type = executable.getType(); + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + NodeData node = specialization.getNode(); + + TypeData primaryType = castExecutable.getType(); + + boolean needsTry = castExecutable.hasUnexpectedValue(getContext()); + boolean returnVoid = type.isVoid(); + + List executeParameters = new ArrayList<>(); + for (Parameter sourceParameter : executable.getSignatureParameters()) { + Parameter targetParameter = castExecutable.findParameter(sourceParameter.getLocalName()); + if (targetParameter != null) { + executeParameters.add(targetParameter); + } + } + + // execute names are enforced no cast + String[] executeParameterNames = new String[executeParameters.size()]; + for (int i = 0; i < executeParameterNames.length; i++) { + executeParameterNames[i] = valueName(executeParameters.get(i)); + } + + builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null)); + boolean hasUnexpected = executable.hasUnexpectedValue(getContext()); + + CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null, executeParameterNames); + if (needsTry) { + if (!returnVoid) { + builder.declaration(primaryType.getPrimitiveType(), "value"); + } + builder.startTryBlock(); + + if (returnVoid) { + builder.statement(primaryExecuteCall); + } else { + builder.startStatement(); + builder.string("value = "); + builder.tree(primaryExecuteCall); + builder.end(); + } + + builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); + if (returnVoid) { + builder.string("// ignore").newLine(); + } else { + builder.startReturn(); + builder.tree(createExpectExecutableType(node, specialization.getNode().getTypeSystem().getGenericTypeData(), hasUnexpected, executable.getType(), + CodeTreeBuilder.singleString("ex.getResult()"))); + builder.end(); + } + builder.end(); + + if (!returnVoid) { + builder.startReturn(); + builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), hasUnexpected, executable.getType(), CodeTreeBuilder.singleString("value"))); + builder.end(); + } + } else { + if (returnVoid) { + builder.statement(primaryExecuteCall); + } else { + builder.startReturn(); + builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), hasUnexpected, executable.getType(), primaryExecuteCall)); + builder.end(); + } + } + + return builder.getRoot(); + } + + protected CodeTree createExpectExecutableType(NodeData node, TypeData sourceType, boolean hasUnexpected, TypeData exepctedType, CodeTree value) { + return createCastType(node.getTypeSystem(), sourceType, exepctedType, hasUnexpected, value); + } + + protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List targetParameters, + Parameter unexpectedParameter) { + CodeTreeBuilder builder = parent.create(); + for (Parameter targetParameter : targetParameters) { + if (!targetParameter.getSpecification().isSignature()) { + continue; + } + NodeExecutionData execution = targetParameter.getSpecification().getExecution(); + CodeTree executionExpressions = createExecuteChild(builder, execution, sourceExecutable, targetParameter, unexpectedParameter); + CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpressions, specialization, sourceExecutable, targetParameter, execution.isShortCircuit(), unexpectedParameter); + CodeTree shortCircuitTree = createShortCircuitTree(builder, unexpectedTree, specialization, targetParameter, unexpectedParameter); + + if (shortCircuitTree == executionExpressions) { + if (containsNewLine(executionExpressions)) { + builder.declaration(targetParameter.getType(), valueName(targetParameter)); + builder.tree(shortCircuitTree); + } else { + builder.startStatement().type(targetParameter.getType()).string(" ").tree(shortCircuitTree).end(); + } + } else { + builder.tree(shortCircuitTree); + } + + } + return builder.getRoot(); + } + + private ExecutableTypeData resolveExecutableType(NodeExecutionData execution, TypeData type) { + ExecutableTypeData targetExecutable = execution.getChild().findExecutableType(getContext(), type); + if (targetExecutable == null) { + targetExecutable = execution.getChild().findAnyGenericExecutableType(getContext()); + } + return targetExecutable; + } + + private CodeTree createExecuteChild(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData sourceExecutable, Parameter targetParameter, Parameter unexpectedParameter) { + SpecializationData specialization = getModel(); + if (specialization.isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null) { + List possiblePolymorphicTypes = lookupPolymorphicTargetTypes(targetParameter); + if (possiblePolymorphicTypes.size() > 1) { + CodeTreeBuilder builder = parent.create(); + + boolean elseIf = false; + for (TypeData possiblePolymoprhicType : possiblePolymorphicTypes) { + if (possiblePolymoprhicType.isGeneric()) { + continue; + } + elseIf = builder.startIf(elseIf); + + Parameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName()); + TypeData sourceType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null; + builder.string(polymorphicTypeName(targetParameter.getSpecification().getExecution())).string(" == ").typeLiteral(possiblePolymoprhicType.getPrimitiveType()); + builder.end().startBlock(); + builder.startStatement(); + builder.tree(createExecuteChildExpression(parent, execution, sourceType, new Parameter(targetParameter, possiblePolymoprhicType), unexpectedParameter, null)); + builder.end(); + builder.end(); + } + + builder.startElseBlock(); + builder.startStatement().tree(createExecuteChildImplicit(parent, execution, sourceExecutable, targetParameter, unexpectedParameter)).end(); + builder.end(); + + return builder.getRoot(); + } + } + return createExecuteChildImplicit(parent, execution, sourceExecutable, targetParameter, unexpectedParameter); + } + + protected final List getImplicitTypeParameters(SpecializationData model) { + List parameter = new ArrayList<>(); + for (Parameter param : model.getSignatureParameters()) { + NodeChildData child = param.getSpecification().getExecution().getChild(); + List types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); + if (types.size() > 1) { + parameter.add(param); + } + } + return parameter; + } + + protected final List lookupPolymorphicTargetTypes(Parameter param) { + SpecializationData specialization = getModel(); + Set possiblePolymorphicTypes = new HashSet<>(); + for (SpecializationData otherSpecialization : specialization.getNode().getSpecializations()) { + if (!otherSpecialization.isSpecialized()) { + continue; + } + Parameter otherParameter = otherSpecialization.findParameter(param.getLocalName()); + if (otherParameter != null) { + possiblePolymorphicTypes.add(otherParameter.getTypeSystemType()); + } + } + List types = new ArrayList<>(possiblePolymorphicTypes); + Collections.sort(types); + return types; + } + + private CodeTree createExecuteChildImplicit(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData sourceExecutable, Parameter param, Parameter unexpectedParameter) { + CodeTreeBuilder builder = parent.create(); + Parameter sourceParameter = sourceExecutable.findParameter(param.getLocalName()); + String childExecuteName = createExecuteChildMethodName(param, sourceParameter != null); + if (childExecuteName != null) { + builder.string(valueName(param)); + builder.string(" = "); + builder.startCall(childExecuteName); + + for (Parameter parameters : sourceExecutable.getParameters()) { + if (parameters.getSpecification().isSignature()) { + continue; + } + builder.string(parameters.getLocalName()); + } + + if (sourceParameter != null) { + builder.string(valueNameEvaluated(sourceParameter)); + } + + builder.string(implicitTypeName(param)); + + builder.end(); + } else { + List sourceTypes = execution.getChild().getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); + TypeData expectType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null; + if (sourceTypes.size() > 1) { + builder.tree(createExecuteChildImplicitExpressions(parent, param, expectType)); + } else { + builder.tree(createExecuteChildExpression(parent, execution, expectType, param, unexpectedParameter, null)); + } + } + return builder.getRoot(); + } + + private String createExecuteChildMethodName(Parameter param, boolean expect) { + NodeExecutionData execution = param.getSpecification().getExecution(); + NodeChildData child = execution.getChild(); + if (child.getExecuteWith().size() > 0) { + return null; + } + List sourceTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); + if (sourceTypes.size() <= 1) { + return null; + } + String prefix = expect ? "expect" : "execute"; + String suffix = execution.getIndex() > -1 ? String.valueOf(execution.getIndex()) : ""; + return prefix + ElementUtils.firstLetterUpperCase(child.getName()) + ElementUtils.firstLetterUpperCase(ElementUtils.getSimpleName(param.getType())) + suffix; + } + + private List createExecuteChilds(Parameter param, Set expectTypes) { + CodeExecutableElement executeMethod = createExecuteChild(param, null); + if (executeMethod == null) { + return Collections.emptyList(); + } + List childs = new ArrayList<>(); + childs.add(executeMethod); + + for (TypeData expectType : expectTypes) { + CodeExecutableElement method = createExecuteChild(param, expectType); + if (method != null) { + childs.add(method); + } + } + return childs; + } + + private CodeExecutableElement createExecuteChild(Parameter param, TypeData expectType) { + String childExecuteName = createExecuteChildMethodName(param, expectType != null); + if (childExecuteName == null) { + return null; + } + + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, expectType != null ? STATIC : FINAL), param.getType(), childExecuteName); + method.getThrownTypes().add(getContext().getTruffleTypes().getUnexpectedValueException()); + method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue")); + if (expectType != null) { + method.addParameter(new CodeVariableElement(expectType.getPrimitiveType(), valueNameEvaluated(param))); + } + method.addParameter(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param))); + + CodeTreeBuilder builder = method.createBuilder(); + builder.declaration(param.getType(), valueName(param)); + builder.tree(createExecuteChildImplicitExpressions(builder, param, expectType)); + builder.startReturn().string(valueName(param)).end(); + + return method; + } + + private CodeTree createExecuteChildImplicitExpressions(CodeTreeBuilder parent, Parameter targetParameter, TypeData expectType) { + CodeTreeBuilder builder = parent.create(); + NodeData node = getModel().getNode(); + NodeExecutionData execution = targetParameter.getSpecification().getExecution(); + List sourceTypes = node.getTypeSystem().lookupSourceTypes(targetParameter.getTypeSystemType()); + boolean elseIf = false; + int index = 0; + for (TypeData sourceType : sourceTypes) { + if (index < sourceTypes.size() - 1) { + elseIf = builder.startIf(elseIf); + builder.string(implicitTypeName(targetParameter)).string(" == ").typeLiteral(sourceType.getPrimitiveType()); + builder.end(); + builder.startBlock(); + } else { + builder.startElseBlock(); + } + + ExecutableTypeData implictExecutableTypeData = execution.getChild().findExecutableType(getContext(), sourceType); + if (implictExecutableTypeData == null) { + /* + * For children with executeWith.size() > 0 an executable type may not exist so + * use the generic executable type which is guaranteed to exist. An expect call + * is inserted automatically by #createExecuteExpression. + */ + implictExecutableTypeData = execution.getChild().getNodeData().findExecutableType(node.getTypeSystem().getGenericTypeData(), execution.getChild().getExecuteWith().size()); + } + + ImplicitCastData cast = execution.getChild().getNodeData().getTypeSystem().lookupCast(sourceType, targetParameter.getTypeSystemType()); + CodeTree execute = createExecuteChildExpression(builder, execution, expectType, targetParameter, null, cast); + builder.statement(execute); + builder.end(); + index++; + } + return builder.getRoot(); + } + + private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData execution, TypeData sourceParameterType, Parameter targetParameter, Parameter unexpectedParameter, + ImplicitCastData cast) { + // assignments: targetType <- castTargetType <- castSourceType <- sourceType + TypeData sourceType = sourceParameterType; + TypeData targetType = targetParameter.getTypeSystemType(); + TypeData castSourceType = targetType; + TypeData castTargetType = targetType; + + if (cast != null) { + castSourceType = cast.getSourceType(); + castTargetType = cast.getTargetType(); + } + + CodeTree expression; + if (sourceType == null) { + ExecutableTypeData targetExecutable = resolveExecutableType(execution, castSourceType); + expression = createExecuteChildExpression(parent, execution, targetExecutable, unexpectedParameter); + sourceType = targetExecutable.getType(); + } else { + expression = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter)); + } + + // target = expectTargetType(implicitCast(expectCastSourceType(source))) + TypeSystemData typeSystem = execution.getChild().getNodeData().getTypeSystem(); + expression = createExpectType(typeSystem, sourceType, castSourceType, expression); + expression = createImplicitCast(parent, typeSystem, cast, expression); + expression = createExpectType(typeSystem, castTargetType, targetType, expression); + + CodeTreeBuilder builder = parent.create(); + builder.string(valueName(targetParameter)); + builder.string(" = "); + builder.tree(expression); + return builder.getRoot(); + } + + private CodeTree createImplicitCast(CodeTreeBuilder parent, TypeSystemData typeSystem, ImplicitCastData cast, CodeTree expression) { + if (cast == null) { + return expression; + } + CodeTreeBuilder builder = parent.create(); + startCallTypeSystemMethod(builder, typeSystem, cast.getMethodName()); + builder.tree(expression); + builder.end().end(); + return builder.getRoot(); + } + + private boolean containsNewLine(CodeTree tree) { + if (tree.getCodeKind() == CodeTreeKind.NEW_LINE) { + return true; + } + + List enclosing = tree.getEnclosedElements(); + if (enclosing != null) { + for (CodeTree codeTree : enclosing) { + if (containsNewLine(codeTree)) { + return true; + } + } + } + return false; + } + + private boolean hasUnexpected(Parameter sourceParameter, Parameter targetParameter, Parameter unexpectedParameter) { + NodeExecutionData execution = targetParameter.getSpecification().getExecution(); + + if (getModel().isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null) { + // check for other polymorphic types + List polymorphicTargetTypes = lookupPolymorphicTargetTypes(targetParameter); + if (polymorphicTargetTypes.size() > 1) { + for (TypeData polymorphicTargetType : polymorphicTargetTypes) { + if (hasUnexpectedType(execution, sourceParameter, polymorphicTargetType)) { + return true; + } + } + } + } + + if (hasUnexpectedType(execution, sourceParameter, targetParameter.getTypeSystemType())) { + return true; + } + return false; + } + + private boolean hasUnexpectedType(NodeExecutionData execution, Parameter sourceParameter, TypeData targetType) { + List implicitSourceTypes = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType); + + for (TypeData implicitSourceType : implicitSourceTypes) { + TypeData sourceType; + ExecutableTypeData targetExecutable = resolveExecutableType(execution, implicitSourceType); + if (sourceParameter != null) { + sourceType = sourceParameter.getTypeSystemType(); + } else { + if (targetExecutable.hasUnexpectedValue(getContext())) { + return true; + } + sourceType = targetExecutable.getType(); + } + + ImplicitCastData cast = getModel().getNode().getTypeSystem().lookupCast(implicitSourceType, targetType); + if (cast != null) { + if (cast.getSourceType().needsCastTo(targetType)) { + return true; + } + } + + if (sourceType.needsCastTo(targetType)) { + return true; + } + } + return false; + } + + private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, ExecutableTypeData currentExecutable, Parameter param, + boolean shortCircuit, Parameter unexpectedParameter) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + Parameter sourceParameter = currentExecutable.findParameter(param.getLocalName()); + boolean unexpected = hasUnexpected(sourceParameter, param, unexpectedParameter); + if (!unexpected) { + return body; + } + + if (!shortCircuit) { + builder.declaration(param.getType(), valueName(param)); + } + builder.startTryBlock(); + + if (containsNewLine(body)) { + builder.tree(body); + } else { + builder.statement(body); + } + + builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); + SpecializationData generic = specialization.getNode().getGenericSpecialization(); + Parameter genericParameter = generic.findParameter(param.getLocalName()); + + List genericParameters = generic.getParametersAfter(genericParameter); + builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter)); + if (specialization.isPolymorphic()) { + builder.tree(createReturnOptimizeTypes(builder, currentExecutable, specialization, param)); + } else { + builder.tree(createCallRewriteMonomorphic(builder, currentExecutable.hasUnexpectedValue(context), currentExecutable.getType(), specialization, param, + "Expected " + param.getLocalName() + " instanceof " + ElementUtils.getSimpleName(param.getType()))); + } + builder.end(); // catch block + + return builder.getRoot(); + } + + private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, Parameter param) { + NodeData node = specialization.getNode(); + SpecializationData polymorphic = node.getPolymorphicSpecialization(); + + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + builder.startStatement().string(polymorphicTypeName(param.getSpecification().getExecution())).string(" = ").typeLiteral(getContext().getType(Object.class)).end(); + + builder.startReturn(); + + CodeTreeBuilder execute = new CodeTreeBuilder(builder); + execute.startCall("next0", EXECUTE_CHAINED); + addInternalValueParameterNames(execute, specialization, polymorphic, param.getLocalName(), true, null); + execute.end(); + + TypeData sourceType = polymorphic.getReturnType().getTypeSystemType(); + + builder.tree(createExpectExecutableType(node, sourceType, currentExecutable.hasUnexpectedValue(context), currentExecutable.getType(), execute.getRoot())); + + builder.end(); + return builder.getRoot(); + } + + private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData targetExecution, ExecutableTypeData targetExecutable, Parameter unexpectedParameter) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + if (targetExecution != null) { + builder.tree(createAccessChild(targetExecution, null)); + builder.string("."); + } + + builder.startCall(targetExecutable.getMethodName()); + + // TODO this should be merged with #createTemplateMethodCall + int index = 0; + for (Parameter parameter : targetExecutable.getParameters()) { + + if (!parameter.getSpecification().isSignature()) { + builder.string(parameter.getLocalName()); + } else { + + if (index < targetExecution.getChild().getExecuteWith().size()) { + NodeChildData child = targetExecution.getChild().getExecuteWith().get(index); + + ParameterSpec spec = getModel().getSpecification().findParameterSpec(child.getName()); + List specializationParams = getModel().findParameters(spec); + + if (specializationParams.isEmpty()) { + builder.defaultValue(parameter.getType()); + continue; + } + + Parameter specializationParam = specializationParams.get(0); + + TypeData targetType = parameter.getTypeSystemType(); + TypeData sourceType = specializationParam.getTypeSystemType(); + String localName = specializationParam.getLocalName(); + + if (unexpectedParameter != null && unexpectedParameter.getLocalName().equals(specializationParam.getLocalName())) { + localName = "ex.getResult()"; + sourceType = getModel().getNode().getTypeSystem().getGenericTypeData(); + } + + CodeTree value = CodeTreeBuilder.singleString(localName); + + if (sourceType.needsCastTo(targetType)) { + value = createCallTypeSystemMethod(builder, getModel().getNode(), TypeSystemCodeGenerator.asTypeMethodName(targetType), value); + } + builder.tree(value); + } else { + builder.defaultValue(parameter.getType()); + } + index++; + } + } + + builder.end(); + + return builder.getRoot(); + } + + private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, Parameter parameter, Parameter exceptionParam) { + NodeExecutionData execution = parameter.getSpecification().getExecution(); + if (execution == null || !execution.isShortCircuit()) { + return body; + } + + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + Parameter shortCircuitParam = specialization.getPreviousParam(parameter); + builder.tree(createShortCircuitValue(builder, specialization, execution, shortCircuitParam, exceptionParam)); + builder.declaration(parameter.getType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getType())); + builder.startIf().string(shortCircuitParam.getLocalName()).end(); + builder.startBlock(); + + if (containsNewLine(body)) { + builder.tree(body); + } else { + builder.statement(body); + } + builder.end(); + + return builder.getRoot(); + } + + private CodeTree createShortCircuitValue(CodeTreeBuilder parent, SpecializationData specialization, NodeExecutionData execution, Parameter shortCircuitParam, Parameter exceptionParam) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + int shortCircuitIndex = 0; + for (NodeExecutionData otherExectuion : specialization.getNode().getChildExecutions()) { + if (otherExectuion.isShortCircuit()) { + if (otherExectuion == execution) { + break; + } + shortCircuitIndex++; + } + } + + builder.startStatement().type(shortCircuitParam.getType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); + ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex); + builder.tree(createTemplateMethodCall(builder, null, specialization, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null)); + builder.end(); // statement + + return builder.getRoot(); + } + + protected CodeTree createCallRewriteMonomorphic(CodeTreeBuilder parent, boolean hasUnexpected, TypeData returnType, SpecializationData current, Parameter exceptionParam, String reason) { + NodeData node = current.getNode(); + SpecializationData generic = node.getGenericSpecialization(); + CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); + specializeCall.startCall(REWRITE); + addInternalValueParameterNames(specializeCall, generic, node.getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, null); + specializeCall.doubleQuote(reason); + specializeCall.end().end(); + + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + + builder.startReturn(); + builder.tree(createExpectExecutableType(node, generic.getReturnType().getTypeSystemType(), hasUnexpected, returnType, specializeCall.getRoot())); + builder.end(); + + return builder.getRoot(); + } + + } + + private class PolymorphicNodeFactory extends SpecializedNodeFactory { + + public PolymorphicNodeFactory(CodeTypeElement nodeGen) { + super(nodeGen); + } + + @Override + public CodeTypeElement create(SpecializationData polymorph) { + NodeData node = polymorph.getNode(); + TypeMirror baseType = node.getNodeType(); + if (nodeGen != null) { + baseType = nodeGen.asType(); + } + CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodePolymorphicClassName(node), baseType, false); + + clazz.getAnnotationMirrors().add(createNodeInfo(node, NodeCost.POLYMORPHIC)); + + for (Parameter polymorphParameter : polymorph.getSignatureParameters()) { + if (!polymorphParameter.getTypeSystemType().isGeneric()) { + continue; + } + Set types = new HashSet<>(); + for (SpecializationData specialization : node.getSpecializations()) { + if (!specialization.isSpecialized()) { + continue; + } + Parameter parameter = specialization.findParameter(polymorphParameter.getLocalName()); + assert parameter != null; + types.add(parameter.getTypeSystemType()); + } + + } + + for (NodeExecutionData execution : getModel().getNode().getChildExecutions()) { + String fieldName = polymorphicTypeName(execution); + CodeVariableElement var = new CodeVariableElement(modifiers(PRIVATE), getContext().getType(Class.class), fieldName); + var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getCompilationFinal())); + clazz.add(var); + } + + return clazz; + } + + @Override + protected void createChildren(SpecializationData specialization) { + CodeTypeElement clazz = getElement(); + + createConstructors(clazz); + createExecuteMethods(specialization); + + clazz.add(createUpdateTypes0()); + createCachedExecuteMethods(specialization); + } + + } + + private class SpecializedNodeFactory extends NodeBaseFactory { + + protected final CodeTypeElement nodeGen; + + public SpecializedNodeFactory(CodeTypeElement nodeGen) { + this.nodeGen = nodeGen; + } + + @Override + public CodeTypeElement create(SpecializationData specialization) { + NodeData node = specialization.getNode(); + TypeMirror baseType = node.getNodeType(); + if (nodeGen != null) { + baseType = nodeGen.asType(); + } + CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false); + + if (specialization.isSpecialized() || specialization.isUninitialized()) { + clazz.add(createGetMetadata0(false)); + clazz.add(createMetadataLiteral()); + } + + NodeCost cost; + if (specialization.isGeneric()) { + cost = NodeCost.MEGAMORPHIC; + } else if (specialization.isUninitialized()) { + cost = NodeCost.UNINITIALIZED; + } else if (specialization.isPolymorphic()) { + cost = NodeCost.POLYMORPHIC; + } else if (specialization.isSpecialized()) { + cost = NodeCost.MONOMORPHIC; + } else { + throw new AssertionError(); + } + clazz.getAnnotationMirrors().add(createNodeInfo(node, cost)); + + if (specialization.isUninitialized() && node.getGenericSpecialization().isReachable()) { + clazz.add(createUninitializedGetCostOverride()); + } + + return clazz; + } + + private Element createUninitializedGetCostOverride() { + TypeMirror returnType = context.getTruffleTypes().getNodeCost(); + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getCost"); + CodeTreeBuilder builder = method.createBuilder(); + builder.startIf().string(CONTAINS_FALLBACK).end().startBlock(); + builder.startReturn().staticReference(returnType, "MONOMORPHIC").end(); + builder.end(); + builder.startReturn().string("super.getCost()").end(); + return method; + } + + private CodeVariableElement createMetadataLiteral() { + CodeVariableElement includes = new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), context.getTruffleTypes().getDslMetadata(), METADATA_FIELD_NAME); + + CodeTreeBuilder builder = includes.createInitBuilder(); + + SpecializationData specialization = getModel(); + NodeData node = specialization.getNode(); + + Set contains = specialization.getContains(); + if (specialization.isUninitialized()) { + contains = new HashSet<>(); + + SpecializationData polymorphic = node.getPolymorphicSpecialization(); + if (polymorphic != null) { + contains.addAll(polymorphic.getContains()); + } + SpecializationData generic = node.getGenericSpecialization(); + if (generic != null) { + contains.addAll(generic.getContains()); + } + } + + builder.startNew(context.getTruffleTypes().getDslMetadata()); + builder.startGroup().string(nodeSpecializationClassName(getModel()), ".class").end(); + builder.tree(createSpecializationListLiteral(builder, contains)); + builder.tree(createSpecializationListLiteral(builder, getModel().getExcludedBy())); + builder.tree(createSpecializationTypeLiteral(builder, SpecializationData.getSignatureTypes(getModel()))); + builder.string("0").string("0"); + builder.end(); + return includes; + } + + private CodeTree createSpecializationTypeLiteral(CodeTreeBuilder parent, List list) { + ArrayType classArray = new ArrayCodeTypeMirror(context.getType(Class.class)); + CodeTreeBuilder builder = parent.create(); + + if (list.isEmpty()) { + builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY); + } else { + builder.startNewArray(classArray, null); + for (TypeMirror type : list) { + builder.typeLiteral(type); + } + builder.end(); + } + + return builder.getRoot(); + } + + private CodeTree createSpecializationListLiteral(CodeTreeBuilder parent, Set list) { + ArrayType classArray = new ArrayCodeTypeMirror(context.getType(Class.class)); + CodeTreeBuilder builder = parent.create(); + + if (list.isEmpty()) { + builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY); + } else { + builder.startNewArray(classArray, null); + for (SpecializationData specialization : list) { + if (specialization.isGeneric() || specialization.isPolymorphic()) { + specialization = getModel().getNode().getUninitializedSpecialization(); + } + builder.startGroup().string(nodeSpecializationClassName(specialization)).string(".class").end(); + } + builder.end(); + } + + return builder.getRoot(); + } + + protected CodeAnnotationMirror createNodeInfo(NodeData node, NodeCost cost) { + String shortName = node.getShortName(); + CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(getContext().getTruffleTypes().getNodeInfoAnnotation()); + if (shortName != null) { + nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("shortName"), new CodeAnnotationValue(shortName)); + } + + DeclaredType nodeinfoCost = getContext().getTruffleTypes().getNodeCost(); + VariableElement varKind = ElementUtils.findVariableElement(nodeinfoCost, cost.name()); + + nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("cost"), new CodeAnnotationValue(varKind)); + return nodeInfoMirror; + } + + @Override + protected void createChildren(SpecializationData specialization) { + CodeTypeElement clazz = getElement(); + createConstructors(clazz); + + createExecuteMethods(specialization); + createCachedExecuteMethods(specialization); + + if (specialization.isUninitialized()) { + if (specialization.getNode().isFallbackReachable()) { + CodeVariableElement var = new CodeVariableElement(modifiers(Modifier.PRIVATE), context.getType(boolean.class), CONTAINS_FALLBACK); + var.addAnnotationMirror(new CodeAnnotationMirror(context.getTruffleTypes().getCompilationFinal())); + clazz.add(var); + } + clazz.add(createExecuteUninitialized()); + } + + if (!specialization.isUninitialized() && specialization.getNode().needsRewrites(context)) { + clazz.add(createCopyConstructorFactoryMethod(nodeGen.asType(), specialization)); + } else { + for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) { + if (constructor.getParameters().size() == 1 && ((CodeVariableElement) constructor.getParameters().get(0)).getType().equals(nodeGen.asType())) { + // skip copy constructor - not used + continue; + } + clazz.add(createConstructorFactoryMethod(specialization, constructor)); + } + } + } + + protected void createConstructors(CodeTypeElement clazz) { + TypeElement superTypeElement = ElementUtils.fromTypeMirror(clazz.getSuperclass()); + SpecializationData specialization = getModel(); + NodeData node = specialization.getNode(); + for (ExecutableElement constructor : ElementFilter.constructorsIn(superTypeElement.getEnclosedElements())) { + if (specialization.isUninitialized()) { + // ignore copy constructors for uninitialized if not polymorphic + if (isCopyConstructor(constructor) && !node.isPolymorphic(context)) { + continue; + } + } else if (node.getUninitializedSpecialization() != null) { + // ignore others than copy constructors for specialized nodes + if (!isCopyConstructor(constructor)) { + continue; + } + } + + CodeExecutableElement superConstructor = createSuperConstructor(clazz, constructor); + if (superConstructor == null) { + continue; + } + CodeTree body = superConstructor.getBodyTree(); + CodeTreeBuilder builder = superConstructor.createBuilder(); + builder.tree(body); + + if (superConstructor != null) { + for (Parameter param : getImplicitTypeParameters(getModel())) { + clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), implicitTypeName(param))); + superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param))); + + builder.startStatement(); + builder.string("this.").string(implicitTypeName(param)).string(" = ").string(implicitTypeName(param)); + builder.end(); + } + + clazz.add(superConstructor); + } + } + } + + protected void createExecuteMethods(SpecializationData specialization) { + NodeData node = specialization.getNode(); + CodeTypeElement clazz = getElement(); + + List primaryExecutes = null; + int lastEvaluatedCount = -1; + + for (ExecutableTypeData execType : node.getExecutableTypes()) { + if (execType.isFinal()) { + continue; + } + if (execType.getEvaluatedCount() != lastEvaluatedCount) { + lastEvaluatedCount = execType.getEvaluatedCount(); + primaryExecutes = findFunctionalExecutableType(specialization, lastEvaluatedCount); + } + + CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, true); + clazz.add(executeMethod); + CodeTreeBuilder builder = executeMethod.getBuilder(); + CodeTree result = createExecuteBody(builder, specialization, execType, primaryExecutes); + if (result != null) { + builder.tree(result); + } else { + clazz.remove(executeMethod); + } + } + } + + protected void createCachedExecuteMethods(SpecializationData specialization) { + NodeData node = specialization.getNode(); + if (!node.isPolymorphic(context)) { + return; + } + + CodeTypeElement clazz = getElement(); + + final SpecializationData polymorphic = node.getPolymorphicSpecialization(); + ExecutableElement executeCached = nodeGen.getMethod(EXECUTE_CHAINED); + CodeExecutableElement executeMethod = CodeExecutableElement.clone(getContext().getEnvironment(), executeCached); + executeMethod.getModifiers().remove(Modifier.ABSTRACT); + CodeTreeBuilder builder = executeMethod.createBuilder(); + + if (specialization.isPolymorphic()) { + builder.startReturn().startCall("this.next0", EXECUTE_CHAINED); + addInternalValueParameterNames(builder, polymorphic, polymorphic, null, true, null); + builder.end().end(); + } else if (specialization.isUninitialized()) { + builder.tree(createDeoptimizeUninitialized(node, builder)); + builder.startReturn().startCall("this", EXECUTE_UNINITIALIZED); + addInternalValueParameterNames(builder, polymorphic, polymorphic, null, true, null); + builder.end().end(); + } else { + CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder); + elseBuilder.startReturn().startCall("this.next0", EXECUTE_CHAINED); + addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, null); + elseBuilder.end().end(); + + builder.tree(createExecuteTree(builder, polymorphic, SpecializationGroup.create(specialization), new CodeBlock() { + + public CodeTree create(CodeTreeBuilder b, SpecializationData current) { + return createGenericInvoke(b, polymorphic, current); + } + }, elseBuilder.getRoot(), false, true, true, false)); + } + clazz.add(executeMethod); + } + + private CodeTree createDeoptimizeUninitialized(NodeData node, CodeTreeBuilder parent) { + CodeTreeBuilder builder = parent.create(); + if (node.getGenericSpecialization().isReachable()) { + builder.startIf().string("!containsFallback").end().startBlock(); + builder.tree(createDeoptimize(builder)); + builder.end(); + } else { + builder.tree(createDeoptimize(builder)); + } + return builder.getRoot(); + } + + private CodeTree createExecuteBody(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData execType, List primaryExecutes) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + + if (primaryExecutes.contains(execType) || primaryExecutes.isEmpty()) { + builder.tree(createFunctionalExecute(builder, specialization, execType)); + } else if (needsCastingExecuteMethod(execType)) { + assert !primaryExecutes.isEmpty(); + builder.tree(createCastingExecute(builder, specialization, execType, primaryExecutes.get(0))); + } else { + return null; + } + + return builder.getRoot(); + } + + private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType, boolean evaluated) { + CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod()); + + method.getAnnotationMirrors().clear(); + for (VariableElement variable : method.getParameters()) { + variable.getAnnotationMirrors().clear(); + } + + CodeTreeBuilder builder = method.createBuilder(); + int i = 0; + int signatureIndex = -1; + for (VariableElement param : method.getParameters()) { + CodeVariableElement var = CodeVariableElement.clone(param); + Parameter actualParameter = i < execType.getParameters().size() ? execType.getParameters().get(i) : null; + String name; + if (actualParameter != null) { + if (actualParameter.getSpecification().isSignature()) { + signatureIndex++; + } + + if (evaluated && actualParameter.getSpecification().isSignature()) { + name = valueNameEvaluated(actualParameter); + } else { + name = valueName(actualParameter); + } + + int varArgCount = getModel().getSignatureSize() - signatureIndex; + if (evaluated && actualParameter.isTypeVarArgs()) { + Parameter baseVarArgs = actualParameter; + name = valueName(baseVarArgs) + "Args"; + + builder.startAssert().string(name).string(" != null").end(); + builder.startAssert().string(name).string(".length == ").string(String.valueOf(varArgCount)).end(); + if (varArgCount > 0) { + List varArgsParameter = execType.getParameters().subList(i, execType.getParameters().size()); + for (Parameter varArg : varArgsParameter) { + if (varArgCount <= 0) { + break; + } + TypeMirror type = baseVarArgs.getType(); + if (type.getKind() == TypeKind.ARRAY) { + type = ((ArrayType) type).getComponentType(); + } + builder.declaration(type, valueNameEvaluated(varArg), name + "[" + varArg.getTypeVarArgsIndex() + "]"); + varArgCount--; + } + } + } + } else { + name = "arg" + i; + } + var.setName(name); + method.getParameters().set(i, var); + i++; + } + + method.getAnnotationMirrors().clear(); + method.getModifiers().remove(Modifier.ABSTRACT); + return method; + } + + private boolean needsCastingExecuteMethod(ExecutableTypeData execType) { + if (execType.isAbstract()) { + return true; + } + if (execType.getType().isGeneric()) { + return true; + } + return false; + } + + private List findFunctionalExecutableType(SpecializationData specialization, int evaluatedCount) { + TypeData primaryType = specialization.getReturnType().getTypeSystemType(); + List otherTypes = specialization.getNode().getExecutableTypes(evaluatedCount); + + List filteredTypes = new ArrayList<>(); + for (ExecutableTypeData compareType : otherTypes) { + if (ElementUtils.typeEquals(compareType.getType().getPrimitiveType(), primaryType.getPrimitiveType())) { + filteredTypes.add(compareType); + } + } + + // no direct matches found use generic where the type is Object + if (filteredTypes.isEmpty()) { + for (ExecutableTypeData compareType : otherTypes) { + if (compareType.getType().isGeneric() && !compareType.hasUnexpectedValue(getContext())) { + filteredTypes.add(compareType); + } + } + } + + if (filteredTypes.isEmpty()) { + for (ExecutableTypeData compareType : otherTypes) { + if (compareType.getType().isGeneric()) { + filteredTypes.add(compareType); + } + } + } + + return filteredTypes; + } + + private CodeTree createFunctionalExecute(CodeTreeBuilder parent, final SpecializationData specialization, final ExecutableTypeData executable) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + + if (specialization.isUninitialized()) { + builder.tree(createDeoptimizeUninitialized(specialization.getNode(), builder)); + } + + builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null)); + + CodeTree returnSpecialized = null; + + if (specialization.findNextSpecialization() != null) { + CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder); + returnBuilder.tree(createDeoptimize(builder)); + returnBuilder.tree(createCallRewriteMonomorphic(builder, executable.hasUnexpectedValue(context), executable.getType(), specialization, null, + "One of guards " + specialization.getGuards() + " failed")); + returnSpecialized = returnBuilder.getRoot(); + } + + builder.tree(createExecuteTree(builder, specialization, SpecializationGroup.create(specialization), new CodeBlock() { + + public CodeTree create(CodeTreeBuilder b, SpecializationData current) { + return createExecute(b, executable, specialization); + } + }, returnSpecialized, false, false, false, false)); + + return builder.getRoot(); + } + + private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) { + NodeData node = specialization.getNode(); + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + if (!specialization.getExceptions().isEmpty() || !specialization.getAssumptions().isEmpty()) { + builder.startTryBlock(); + } + + for (String assumption : specialization.getAssumptions()) { + builder.startStatement(); + builder.string("this.").string(assumption).string(".check()"); + builder.end(); + } + + CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent); + if (specialization.isPolymorphic()) { + returnBuilder.startCall("next0", EXECUTE_CHAINED); + addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, null); + returnBuilder.end(); + } else if (specialization.isUninitialized()) { + returnBuilder.startCall(EXECUTE_UNINITIALIZED); + addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, null); + returnBuilder.end(); + } else if (specialization.getMethod() == null && !node.needsRewrites(context)) { + emitEncounteredSynthetic(builder, specialization); + } else { + returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null)); + } + + if (!returnBuilder.isEmpty()) { + TypeData targetType = node.getTypeSystem().findTypeData(builder.findMethod().getReturnType()); + TypeData sourceType = specialization.getReturnType().getTypeSystemType(); + + builder.startReturn(); + if (targetType == null || sourceType == null) { + builder.tree(returnBuilder.getRoot()); + } else if (sourceType.needsCastTo(targetType)) { + String castMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType); + if (!executable.hasUnexpectedValue(context)) { + castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType); + } + builder.tree(createCallTypeSystemMethod(parent, node, castMethodName, returnBuilder.getRoot())); + } else { + builder.tree(returnBuilder.getRoot()); + } + builder.end(); + } + + if (!specialization.getExceptions().isEmpty()) { + for (SpecializationThrowsData exception : specialization.getExceptions()) { + builder.end().startCatchBlock(exception.getJavaClass(), "ex"); + builder.tree(createDeoptimize(builder)); + builder.tree(createCallRewriteMonomorphic(parent, executable.hasUnexpectedValue(context), executable.getType(), specialization, null, + "Thrown " + ElementUtils.getSimpleName(exception.getJavaClass()))); + } + builder.end(); + } + if (!specialization.getAssumptions().isEmpty()) { + builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex"); + builder.tree(createCallRewriteMonomorphic(parent, executable.hasUnexpectedValue(context), executable.getType(), specialization, null, "Assumption failed")); + builder.end(); + } + + return builder.getRoot(); + } + + protected CodeExecutableElement createCopyConstructorFactoryMethod(TypeMirror baseType, SpecializationData specialization) { + List implicitTypeParams = getImplicitTypeParameters(specialization); + String baseName = "current"; + CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), FACTORY_METHOD_NAME); + method.addParameter(new CodeVariableElement(specialization.getNode().getNodeType(), baseName)); + for (Parameter implicitTypeParam : implicitTypeParams) { + method.addParameter(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(implicitTypeParam))); + } + CodeTreeBuilder builder = method.createBuilder(); + builder.startReturn(); + builder.startNew(getElement().asType()); + builder.startGroup().cast(baseType, CodeTreeBuilder.singleString(baseName)).end(); + for (Parameter param : implicitTypeParams) { + builder.string(implicitTypeName(param)); + } + builder.end().end(); + return method; + } + + protected CodeExecutableElement createConstructorFactoryMethod(SpecializationData specialization, ExecutableElement constructor) { + List parameters = constructor.getParameters(); + CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), FACTORY_METHOD_NAME, + parameters.toArray(new CodeVariableElement[parameters.size()])); + CodeTreeBuilder builder = method.createBuilder(); + builder.startReturn(); + builder.startNew(getElement().asType()); + for (VariableElement param : parameters) { + builder.string(((CodeVariableElement) param).getName()); + } + builder.end().end(); + return method; + } + } + + private interface CodeBlock { + + CodeTree create(CodeTreeBuilder parent, T value); + + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.generator; + +import static com.oracle.truffle.dsl.processor.java.ElementUtils.*; +import static javax.lang.model.element.Modifier.*; + +import java.util.*; + +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.java.model.*; +import com.oracle.truffle.dsl.processor.model.*; + +public class TypeSystemCodeGenerator extends AbstractCompilationUnitFactory { + + public static String isTypeMethodName(TypeData type) { + return "is" + ElementUtils.getTypeId(type.getBoxedType()); + } + + public static String isImplicitTypeMethodName(TypeData type) { + return "isImplicit" + ElementUtils.getTypeId(type.getBoxedType()); + } + + public static String asTypeMethodName(TypeData type) { + return "as" + ElementUtils.getTypeId(type.getBoxedType()); + } + + public static String asImplicitTypeMethodName(TypeData type) { + return "asImplicit" + ElementUtils.getTypeId(type.getBoxedType()); + } + + public static String getImplicitClass(TypeData type) { + return "getImplicit" + ElementUtils.getTypeId(type.getBoxedType()) + "Class"; + } + + public static String expectTypeMethodName(TypeData type) { + return "expect" + ElementUtils.getTypeId(type.getBoxedType()); + } + + public static String typeName(TypeSystemData typeSystem) { + String name = getSimpleName(typeSystem.getTemplateType()); + return name + "Gen"; + } + + public static String singletonName(TypeSystemData type) { + return createConstantName(getSimpleName(type.getTemplateType().asType())); + } + + @Override + protected void createChildren(TypeSystemData m) { + add(new TypeClassFactory(), m); + } + + private static class TypeClassFactory extends AbstractClassElementFactory { + + private static final String LOCAL_VALUE = "value"; + + @Override + public CodeTypeElement create(TypeSystemData typeSystem) { + String name = typeName(typeSystem); + CodeTypeElement clazz = createClass(typeSystem, modifiers(PUBLIC, FINAL), name, typeSystem.getTemplateType().asType(), false); + + clazz.add(createConstructorUsingFields(modifiers(PROTECTED), clazz)); + CodeVariableElement singleton = createSingleton(clazz); + clazz.add(singleton); + + for (TypeData type : typeSystem.getTypes()) { + if (type.isGeneric() || type.isVoid()) { + continue; + } + clazz.addOptional(createIsTypeMethod(type)); + clazz.addOptional(createAsTypeMethod(type)); + + for (TypeData sourceType : collectExpectSourceTypes(type)) { + clazz.addOptional(createExpectTypeMethod(type, sourceType)); + } + + clazz.addOptional(createAsImplicitTypeMethod(type, true)); + clazz.addOptional(createAsImplicitTypeMethod(type, false)); + clazz.addOptional(createIsImplicitTypeMethod(type, true)); + clazz.addOptional(createIsImplicitTypeMethod(type, false)); + clazz.addOptional(createGetTypeIndex(type)); + } + + return clazz; + } + + private static List collectExpectSourceTypes(TypeData type) { + Set sourceTypes = new HashSet<>(); + sourceTypes.add(type.getTypeSystem().getGenericTypeData()); + for (TypeCastData cast : type.getTypeCasts()) { + sourceTypes.add(cast.getSourceType()); + } + for (TypeCheckData cast : type.getTypeChecks()) { + sourceTypes.add(cast.getCheckedType()); + } + return new ArrayList<>(sourceTypes); + } + + private CodeVariableElement createSingleton(CodeTypeElement clazz) { + CodeVariableElement field = new CodeVariableElement(modifiers(PUBLIC, STATIC, FINAL), clazz.asType(), singletonName(getModel())); + field.createInitBuilder().startNew(clazz.asType()).end(); + return field; + } + + private CodeExecutableElement createIsImplicitTypeMethod(TypeData type, boolean typed) { + TypeSystemData typeSystem = getModel(); + List casts = typeSystem.lookupByTargetType(type); + if (casts.isEmpty()) { + return null; + } + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(boolean.class), TypeSystemCodeGenerator.isImplicitTypeMethodName(type)); + method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); + if (typed) { + method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "typeHint")); + } + CodeTreeBuilder builder = method.createBuilder(); + + List sourceTypes = typeSystem.lookupSourceTypes(type); + + builder.startReturn(); + String sep = ""; + for (TypeData sourceType : sourceTypes) { + builder.string(sep); + if (typed) { + builder.string("(typeHint == ").typeLiteral(sourceType.getPrimitiveType()).string(" && "); + } + builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end(); + if (typed) { + builder.string(")"); + } + if (sourceTypes.lastIndexOf(sourceType) != sourceTypes.size() - 1) { + builder.newLine(); + } + if (sep.equals("")) { + builder.startIndention(); + } + sep = " || "; + } + builder.end(); + builder.end(); + return method; + } + + private CodeExecutableElement createAsImplicitTypeMethod(TypeData type, boolean typed) { + TypeSystemData typeSystem = getModel(); + List casts = typeSystem.lookupByTargetType(type); + if (casts.isEmpty()) { + return null; + } + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asImplicitTypeMethodName(type)); + method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); + if (typed) { + method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "typeHint")); + } + + List sourceTypes = typeSystem.lookupSourceTypes(type); + + CodeTreeBuilder builder = method.createBuilder(); + boolean elseIf = false; + for (TypeData sourceType : sourceTypes) { + elseIf = builder.startIf(elseIf); + if (typed) { + builder.string("typeHint == ").typeLiteral(sourceType.getPrimitiveType()); + } else { + builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end(); + } + + builder.end().startBlock(); + + builder.startReturn(); + ImplicitCastData cast = typeSystem.lookupCast(sourceType, type); + if (cast != null) { + builder.startCall(cast.getMethodName()); + } + builder.startCall(asTypeMethodName(sourceType)).string(LOCAL_VALUE).end(); + if (cast != null) { + builder.end(); + } + builder.end(); + builder.end(); + } + + builder.startElseBlock(); + builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end(); + builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end(); + builder.end(); + return method; + } + + private CodeExecutableElement createGetTypeIndex(TypeData type) { + TypeSystemData typeSystem = getModel(); + List casts = typeSystem.lookupByTargetType(type); + if (casts.isEmpty()) { + return null; + } + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(Class.class), TypeSystemCodeGenerator.getImplicitClass(type)); + method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); + + List sourceTypes = typeSystem.lookupSourceTypes(type); + CodeTreeBuilder builder = method.createBuilder(); + boolean elseIf = false; + for (TypeData sourceType : sourceTypes) { + elseIf = builder.startIf(elseIf); + builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end(); + builder.end().startBlock(); + builder.startReturn().typeLiteral(sourceType.getPrimitiveType()).end(); + builder.end(); + } + + builder.startElseBlock(); + builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end(); + builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end(); + builder.end(); + + return method; + } + + private CodeExecutableElement createIsTypeMethod(TypeData type) { + if (!type.getTypeChecks().isEmpty()) { + return null; + } + + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(boolean.class), TypeSystemCodeGenerator.isTypeMethodName(type)); + method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); + + DeclaredType suppressWarnings = (DeclaredType) getContext().getType(SuppressWarnings.class); + CodeAnnotationMirror annotationMirror = new CodeAnnotationMirror(suppressWarnings); + annotationMirror.setElementValue(annotationMirror.findExecutableElement("value"), new CodeAnnotationValue("static-method")); + method.getAnnotationMirrors().add(annotationMirror); + + CodeTreeBuilder body = method.createBuilder(); + body.startReturn().instanceOf(LOCAL_VALUE, type.getBoxedType()).end(); + + return method; + } + + private CodeExecutableElement createAsTypeMethod(TypeData type) { + if (!type.getTypeCasts().isEmpty()) { + return null; + } + + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asTypeMethodName(type)); + method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); + + CodeTreeBuilder body = method.createBuilder(); + String assertMessage = typeName(getModel()) + "." + asTypeMethodName(type) + ": " + ElementUtils.getSimpleName(type.getBoxedType()) + " expected"; + body.startAssert().startCall(isTypeMethodName(type)).string(LOCAL_VALUE).end().string(" : ").doubleQuote(assertMessage).end(); + body.startReturn().cast(type.getPrimitiveType(), body.create().string(LOCAL_VALUE).getTree()).end(); + + return method; + } + + private CodeExecutableElement createExpectTypeMethod(TypeData expectedType, TypeData sourceType) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), expectedType.getPrimitiveType(), TypeSystemCodeGenerator.expectTypeMethodName(expectedType)); + method.addParameter(new CodeVariableElement(sourceType.getPrimitiveType(), LOCAL_VALUE)); + method.addThrownType(getContext().getTruffleTypes().getUnexpectedValueException()); + + CodeTreeBuilder body = method.createBuilder(); + body.startIf().startCall(TypeSystemCodeGenerator.isTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end().startBlock(); + body.startReturn().startCall(TypeSystemCodeGenerator.asTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end(); + body.end(); // if-block + body.startThrow().startNew(getContext().getTruffleTypes().getUnexpectedValueException()).string(LOCAL_VALUE).end().end(); + + return method; + } + + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,1069 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java; + +import java.io.*; +import java.lang.annotation.*; +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.model.*; +import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror; +import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.WildcardTypeMirror; + +/** + * THIS IS NOT PUBLIC API. + */ +public class ElementUtils { + + public static TypeMirror getType(ProcessingEnvironment processingEnv, Class element) { + if (element.isPrimitive()) { + if (element == void.class) { + return processingEnv.getTypeUtils().getNoType(TypeKind.VOID); + } + TypeKind typeKind; + if (element == boolean.class) { + typeKind = TypeKind.BOOLEAN; + } else if (element == byte.class) { + typeKind = TypeKind.BYTE; + } else if (element == short.class) { + typeKind = TypeKind.SHORT; + } else if (element == char.class) { + typeKind = TypeKind.CHAR; + } else if (element == int.class) { + typeKind = TypeKind.INT; + } else if (element == long.class) { + typeKind = TypeKind.LONG; + } else if (element == float.class) { + typeKind = TypeKind.FLOAT; + } else if (element == double.class) { + typeKind = TypeKind.DOUBLE; + } else { + assert false; + return null; + } + return processingEnv.getTypeUtils().getPrimitiveType(typeKind); + } else { + TypeElement typeElement = processingEnv.getElementUtils().getTypeElement(element.getCanonicalName()); + if (typeElement == null) { + return null; + } + return typeElement.asType(); + } + } + + public static ExecutableElement findExecutableElement(DeclaredType type, String name) { + List elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements()); + for (ExecutableElement executableElement : elements) { + if (executableElement.getSimpleName().toString().equals(name)) { + return executableElement; + } + } + return null; + } + + public static boolean needsCastTo(TypeMirror sourceType, TypeMirror targetType) { + if (typeEquals(sourceType, targetType)) { + return false; + } else if (isObject(targetType)) { + return false; + } else if (isVoid(targetType)) { + return false; + } else if (isAssignable(sourceType, targetType)) { + return false; + } + return true; + } + + public static String createReferenceName(ExecutableElement method) { + StringBuilder b = new StringBuilder(); + + b.append(method.getSimpleName().toString()); + b.append("("); + + String sep = ""; + for (VariableElement parameter : method.getParameters()) { + b.append(sep); + b.append(ElementUtils.getSimpleName(parameter.asType())); + sep = ", "; + } + + b.append(")"); + return b.toString(); + } + + public static VariableElement findVariableElement(DeclaredType type, String name) { + List elements = ElementFilter.fieldsIn(type.asElement().getEnclosedElements()); + for (VariableElement variableElement : elements) { + if (variableElement.getSimpleName().toString().equals(name)) { + return variableElement; + } + } + return null; + } + + public static TypeMirror boxType(ProcessorContext context, TypeMirror primitiveType) { + TypeMirror boxedType = primitiveType; + if (boxedType.getKind().isPrimitive()) { + boxedType = context.getEnvironment().getTypeUtils().boxedClass((PrimitiveType) boxedType).asType(); + } + return boxedType; + } + + public static DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs) { + return new DeclaredCodeTypeMirror(typeElem, Arrays.asList(typeArgs)); + } + + public static List collectAnnotations(ProcessorContext context, AnnotationMirror markerAnnotation, String elementName, Element element, + Class annotationClass) { + List result = new ArrayList<>(); + if (markerAnnotation != null) { + result.addAll(ElementUtils.getAnnotationValueList(AnnotationMirror.class, markerAnnotation, elementName)); + } + AnnotationMirror explicit = ElementUtils.findAnnotationMirror(context.getEnvironment(), element, annotationClass); + if (explicit != null) { + result.add(explicit); + } + return result; + } + + public static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror[] types) { + if (types.length == 0) { + return context.getType(Object.class); + } + TypeMirror prev = types[0]; + for (int i = 1; i < types.length; i++) { + prev = getCommonSuperType(context, prev, types[i]); + } + return prev; + } + + private static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror type1, TypeMirror type2) { + if (typeEquals(type1, type2)) { + return type1; + } + TypeElement element1 = fromTypeMirror(type1); + TypeElement element2 = fromTypeMirror(type2); + if (element1 == null || element2 == null) { + return context.getType(Object.class); + } + + List element1Types = getDirectSuperTypes(element1); + element1Types.add(0, element1); + List element2Types = getDirectSuperTypes(element2); + element2Types.add(0, element2); + + for (TypeElement superType1 : element1Types) { + for (TypeElement superType2 : element2Types) { + if (typeEquals(superType1.asType(), superType2.asType())) { + return superType2.asType(); + } + } + } + return context.getType(Object.class); + } + + public static String getReadableSignature(ExecutableElement method) { + // TODO toString does not guarantee a good signature + return method.toString(); + } + + public static boolean hasError(TypeMirror mirror) { + switch (mirror.getKind()) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case INT: + case SHORT: + case LONG: + case DECLARED: + case VOID: + case TYPEVAR: + return false; + case ARRAY: + return hasError(((ArrayType) mirror).getComponentType()); + case ERROR: + return true; + default: + throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); + } + } + + public static boolean isSubtype(TypeMirror type1, TypeMirror type2) { + if (type1 instanceof CodeTypeMirror && type2 instanceof CodeTypeMirror) { + throw new UnsupportedOperationException(); + } + return ProcessorContext.getInstance().getEnvironment().getTypeUtils().isSubtype(type1, type2); + } + + public static boolean isAssignable(TypeMirror from, TypeMirror to) { + ProcessorContext context = ProcessorContext.getInstance(); + + if (!(from instanceof CodeTypeMirror) && !(to instanceof CodeTypeMirror)) { + return context.getEnvironment().getTypeUtils().isAssignable(context.reloadType(from), context.reloadType(to)); + } else { + return isAssignableImpl(from, to); + } + } + + private static boolean isAssignableImpl(TypeMirror from, TypeMirror to) { + // JLS 5.1.1 identity conversion + if (ElementUtils.typeEquals(from, to)) { + return true; + } + + if (isObject(to)) { + return true; + } + + // JLS 5.1.2 widening primitives + if (ElementUtils.isPrimitive(from) && ElementUtils.isPrimitive(to)) { + TypeKind fromKind = from.getKind(); + TypeKind toKind = to.getKind(); + switch (fromKind) { + case BYTE: + switch (toKind) { + case SHORT: + case INT: + case LONG: + case FLOAT: + case DOUBLE: + return true; + } + break; + case SHORT: + switch (toKind) { + case INT: + case LONG: + case FLOAT: + case DOUBLE: + return true; + } + break; + case CHAR: + switch (toKind) { + case INT: + case LONG: + case FLOAT: + case DOUBLE: + return true; + } + break; + case INT: + switch (toKind) { + case LONG: + case FLOAT: + case DOUBLE: + return true; + } + break; + case LONG: + switch (toKind) { + case FLOAT: + case DOUBLE: + return true; + } + break; + case FLOAT: + switch (toKind) { + case DOUBLE: + return true; + } + break; + + } + return false; + } else if (ElementUtils.isPrimitive(from) || ElementUtils.isPrimitive(to)) { + return false; + } + + if (from instanceof ArrayType && to instanceof ArrayType) { + return isAssignable(((ArrayType) from).getComponentType(), ((ArrayType) to).getComponentType()); + } + + if (from instanceof ArrayType || to instanceof ArrayType) { + return false; + } + + TypeElement fromType = ElementUtils.fromTypeMirror(from); + TypeElement toType = ElementUtils.fromTypeMirror(to); + if (fromType == null || toType == null) { + return false; + } + // JLS 5.1.6 narrowing reference conversion + + List superTypes = ElementUtils.getSuperTypes(fromType); + for (TypeElement superType : superTypes) { + if (ElementUtils.typeEquals(superType.asType(), to)) { + return true; + } + } + + // TODO more spec + return false; + } + + public static Set modifiers(Modifier... modifier) { + return new LinkedHashSet<>(Arrays.asList(modifier)); + } + + public static String getTypeId(TypeMirror mirror) { + switch (mirror.getKind()) { + case BOOLEAN: + return "Boolean"; + case BYTE: + return "Byte"; + case CHAR: + return "Char"; + case DOUBLE: + return "Double"; + case FLOAT: + return "Float"; + case SHORT: + return "Short"; + case INT: + return "Int"; + case LONG: + return "Long"; + case DECLARED: + return fixECJBinaryNameIssue(((DeclaredType) mirror).asElement().getSimpleName().toString()); + case ARRAY: + return getTypeId(((ArrayType) mirror).getComponentType()) + "Array"; + case VOID: + return "Void"; + case WILDCARD: + StringBuilder b = new StringBuilder(); + WildcardType type = (WildcardType) mirror; + if (type.getExtendsBound() != null) { + b.append("Extends").append(getTypeId(type.getExtendsBound())); + } else if (type.getSuperBound() != null) { + b.append("Super").append(getTypeId(type.getExtendsBound())); + } + return b.toString(); + case TYPEVAR: + return "Any"; + case ERROR: + throw new CompileErrorException("Type error " + mirror); + default: + throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); + } + } + + public static String getSimpleName(TypeElement element) { + return getSimpleName(element.asType()); + } + + public static String getSimpleName(TypeMirror mirror) { + switch (mirror.getKind()) { + case BOOLEAN: + return "boolean"; + case BYTE: + return "byte"; + case CHAR: + return "char"; + case DOUBLE: + return "double"; + case FLOAT: + return "float"; + case SHORT: + return "short"; + case INT: + return "int"; + case LONG: + return "long"; + case DECLARED: + return getDeclaredName((DeclaredType) mirror, true); + case ARRAY: + return getSimpleName(((ArrayType) mirror).getComponentType()) + "[]"; + case VOID: + return "void"; + case WILDCARD: + return getWildcardName((WildcardType) mirror); + case TYPEVAR: + return "?"; + case ERROR: + throw new CompileErrorException("Type error " + mirror); + default: + throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); + } + } + + private static String getWildcardName(WildcardType type) { + StringBuilder b = new StringBuilder(); + if (type.getExtendsBound() != null) { + b.append("? extends ").append(getSimpleName(type.getExtendsBound())); + } else if (type.getSuperBound() != null) { + b.append("? super ").append(getSimpleName(type.getExtendsBound())); + } + return b.toString(); + } + + public static String getDeclaredName(DeclaredType element, boolean includeTypeVariables) { + String simpleName = fixECJBinaryNameIssue(element.asElement().getSimpleName().toString()); + + if (!includeTypeVariables || element.getTypeArguments().size() == 0) { + return simpleName; + } + + StringBuilder b = new StringBuilder(simpleName); + b.append("<"); + if (element.getTypeArguments().size() > 0) { + for (int i = 0; i < element.getTypeArguments().size(); i++) { + b.append(getSimpleName(element.getTypeArguments().get(i))); + if (i < element.getTypeArguments().size() - 1) { + b.append(", "); + } + } + } + b.append(">"); + return b.toString(); + } + + public static String fixECJBinaryNameIssue(String name) { + if (name.contains("$")) { + int lastIndex = name.lastIndexOf('$'); + return name.substring(lastIndex + 1, name.length()); + } + return name; + } + + public static String getQualifiedName(TypeElement element) { + String qualifiedName = element.getQualifiedName().toString(); + if (qualifiedName.contains("$")) { + /* + * If a class gets loaded in its binary form by the ECJ compiler it fails to produce the + * proper canonical class name. It leaves the $ in the qualified name of the class. So + * one instance of a TypeElement may be loaded in binary and one in source form. The + * current type comparison in #typeEquals compares by the qualified name so the + * qualified name must match. This is basically a hack to fix the returned qualified + * name of eclipse. + */ + qualifiedName = qualifiedName.replace('$', '.'); + } + return qualifiedName; + } + + public static String getQualifiedName(TypeMirror mirror) { + switch (mirror.getKind()) { + case BOOLEAN: + return "boolean"; + case BYTE: + return "byte"; + case CHAR: + return "char"; + case DOUBLE: + return "double"; + case SHORT: + return "short"; + case FLOAT: + return "float"; + case INT: + return "int"; + case LONG: + return "long"; + case DECLARED: + return getQualifiedName(fromTypeMirror(mirror)); + case ARRAY: + return getQualifiedName(((ArrayType) mirror).getComponentType()); + case VOID: + return "void"; + case TYPEVAR: + return getSimpleName(mirror); + case ERROR: + throw new CompileErrorException("Type error " + mirror); + case EXECUTABLE: + return ((ExecutableType) mirror).toString(); + case NONE: + return "$none"; + default: + throw new RuntimeException("Unknown type specified " + mirror + " mirror: " + mirror); + } + } + + public static boolean isVoid(TypeMirror mirror) { + return mirror != null && mirror.getKind() == TypeKind.VOID; + } + + public static boolean isPrimitive(TypeMirror mirror) { + return mirror != null && mirror.getKind().isPrimitive(); + } + + public static List getQualifiedSuperTypeNames(TypeElement element) { + List types = getSuperTypes(element); + List qualifiedNames = new ArrayList<>(); + for (TypeElement type : types) { + qualifiedNames.add(getQualifiedName(type)); + } + return qualifiedNames; + } + + public static List getDeclaredTypes(TypeElement element) { + return ElementFilter.typesIn(element.getEnclosedElements()); + } + + public static boolean isEnclosedIn(Element enclosedIn, Element element) { + if (element == null) { + return false; + } else if (typeEquals(enclosedIn.asType(), element.asType())) { + return true; + } else { + return isEnclosedIn(enclosedIn, element.getEnclosingElement()); + } + } + + public static TypeElement findRootEnclosingType(Element element) { + List elements = getElementHierarchy(element); + + for (int i = elements.size() - 1; i >= 0; i--) { + if (elements.get(i).getKind().isClass()) { + return (TypeElement) elements.get(i); + } + } + + return null; + } + + public static List getElementHierarchy(Element e) { + List elements = new ArrayList<>(); + elements.add(e); + + Element enclosing = e.getEnclosingElement(); + while (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE) { + elements.add(enclosing); + enclosing = enclosing.getEnclosingElement(); + } + if (enclosing != null) { + elements.add(enclosing); + } + return elements; + } + + public static TypeElement findNearestEnclosingType(Element element) { + List elements = getElementHierarchy(element); + for (Element e : elements) { + if (e.getKind().isClass()) { + return (TypeElement) e; + } + } + return null; + } + + public static List getDirectSuperTypes(TypeElement element) { + List types = new ArrayList<>(); + TypeElement superElement = getSuperType(element); + if (superElement != null) { + types.add(superElement); + types.addAll(getDirectSuperTypes(superElement)); + } + + return types; + } + + public static List getAssignableTypes(ProcessorContext context, TypeMirror type) { + if (isPrimitive(type)) { + return Arrays.asList(type, boxType(context, type), context.getType(Object.class)); + } else if (type.getKind() == TypeKind.ARRAY) { + return Arrays.asList(type, context.getType(Object.class)); + } else if (type.getKind() == TypeKind.DECLARED) { + DeclaredType declaredType = (DeclaredType) type; + TypeElement typeElement = fromTypeMirror(declaredType); + List types = getSuperTypes(typeElement); + List mirrors = new ArrayList<>(types.size()); + mirrors.add(type); + for (TypeElement superTypeElement : types) { + mirrors.add(superTypeElement.asType()); + } + if (typeElement.getKind().isInterface()) { + mirrors.add(getType(context.getEnvironment(), Object.class)); + } + return mirrors; + } else { + return Collections.emptyList(); + } + } + + /** + * Gets the element representing the {@linkplain TypeElement#getSuperclass() super class} of a + * given type element. + */ + public static TypeElement getSuperType(TypeElement element) { + if (element.getSuperclass() != null) { + return fromTypeMirror(element.getSuperclass()); + } + return null; + } + + public static List getSuperTypes(TypeElement element) { + List types = new ArrayList<>(); + List superTypes = null; + List superInterfaces = null; + TypeElement superElement = getSuperType(element); + if (superElement != null) { + types.add(superElement); + superTypes = getSuperTypes(superElement); + } + for (TypeMirror interfaceMirror : element.getInterfaces()) { + TypeElement interfaceElement = fromTypeMirror(interfaceMirror); + if (interfaceElement != null) { + types.add(interfaceElement); + if (superInterfaces == null) { + superInterfaces = getSuperTypes(interfaceElement); + } else { + superInterfaces.addAll(getSuperTypes(interfaceElement)); + } + } + } + + if (superTypes != null) { + types.addAll(superTypes); + } + + if (superInterfaces != null) { + types.addAll(superInterfaces); + } + + return types; + } + + public static String getPackageName(TypeElement element) { + return findPackageElement(element).getQualifiedName().toString(); + } + + public static String getEnclosedQualifiedName(DeclaredType mirror) { + Element e = ((TypeElement) mirror.asElement()).getEnclosingElement(); + if (e.getKind() == ElementKind.PACKAGE) { + return ((PackageElement) e).getQualifiedName().toString(); + } else if (e.getKind().isInterface() || e.getKind().isClass()) { + return getQualifiedName((TypeElement) e); + } else { + return null; + } + } + + public static String getPackageName(TypeMirror mirror) { + switch (mirror.getKind()) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case SHORT: + case INT: + case LONG: + case VOID: + case TYPEVAR: + return null; + case DECLARED: + PackageElement pack = findPackageElement(fromTypeMirror(mirror)); + if (pack == null) { + throw new IllegalArgumentException("No package element found for declared type " + getSimpleName(mirror)); + } + return pack.getQualifiedName().toString(); + case ARRAY: + return getSimpleName(((ArrayType) mirror).getComponentType()); + default: + throw new RuntimeException("Unknown type specified " + mirror.getKind()); + } + } + + public static String createConstantName(String simpleName) { + // TODO use camel case to produce underscores. + return simpleName.toString().toUpperCase(); + } + + public static TypeElement fromTypeMirror(TypeMirror mirror) { + switch (mirror.getKind()) { + case DECLARED: + return (TypeElement) ((DeclaredType) mirror).asElement(); + case ARRAY: + return fromTypeMirror(((ArrayType) mirror).getComponentType()); + default: + return null; + } + } + + @SuppressWarnings("unchecked") + public static List getAnnotationValueList(Class expectedListType, AnnotationMirror mirror, String name) { + List values = getAnnotationValue(List.class, mirror, name); + List result = new ArrayList<>(); + + if (values != null) { + for (AnnotationValue value : values) { + T annotationValue = resolveAnnotationValue(expectedListType, value); + if (annotationValue != null) { + result.add(annotationValue); + } + } + } + return result; + } + + public static T getAnnotationValue(Class expectedType, AnnotationMirror mirror, String name) { + return resolveAnnotationValue(expectedType, getAnnotationValue(mirror, name)); + } + + @SuppressWarnings({"unchecked"}) + private static T resolveAnnotationValue(Class expectedType, AnnotationValue value) { + if (value == null) { + return null; + } + + Object unboxedValue = value.accept(new AnnotationValueVisitorImpl(), null); + if (unboxedValue != null) { + if (expectedType == TypeMirror.class && unboxedValue instanceof String) { + return null; + } + if (!expectedType.isAssignableFrom(unboxedValue.getClass())) { + throw new ClassCastException(unboxedValue.getClass().getName() + " not assignable from " + expectedType.getName()); + } + } + return (T) unboxedValue; + } + + public static AnnotationValue getAnnotationValue(AnnotationMirror mirror, String name) { + ExecutableElement valueMethod = null; + for (ExecutableElement method : ElementFilter.methodsIn(mirror.getAnnotationType().asElement().getEnclosedElements())) { + if (method.getSimpleName().toString().equals(name)) { + valueMethod = method; + break; + } + } + + if (valueMethod == null) { + return null; + } + + AnnotationValue value = mirror.getElementValues().get(valueMethod); + if (value == null) { + value = valueMethod.getDefaultValue(); + } + + return value; + } + + private static class AnnotationValueVisitorImpl extends AbstractAnnotationValueVisitor7 { + + @Override + public Object visitBoolean(boolean b, Void p) { + return Boolean.valueOf(b); + } + + @Override + public Object visitByte(byte b, Void p) { + return Byte.valueOf(b); + } + + @Override + public Object visitChar(char c, Void p) { + return c; + } + + @Override + public Object visitDouble(double d, Void p) { + return d; + } + + @Override + public Object visitFloat(float f, Void p) { + return f; + } + + @Override + public Object visitInt(int i, Void p) { + return i; + } + + @Override + public Object visitLong(long i, Void p) { + return i; + } + + @Override + public Object visitShort(short s, Void p) { + return s; + } + + @Override + public Object visitString(String s, Void p) { + return s; + } + + @Override + public Object visitType(TypeMirror t, Void p) { + return t; + } + + @Override + public Object visitEnumConstant(VariableElement c, Void p) { + return c; + } + + @Override + public Object visitAnnotation(AnnotationMirror a, Void p) { + return a; + } + + @Override + public Object visitArray(List vals, Void p) { + return vals; + } + + } + + public static String printException(Throwable e) { + StringWriter string = new StringWriter(); + PrintWriter writer = new PrintWriter(string); + e.printStackTrace(writer); + writer.flush(); + return e.getMessage() + "\r\n" + string.toString(); + } + + public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, Element element, Class annotationClass) { + return findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), annotationClass); + } + + public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, List mirrors, Class annotationClass) { + TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName()); + return findAnnotationMirror(mirrors, expectedAnnotationType); + } + + public static AnnotationMirror findAnnotationMirror(List mirrors, TypeElement expectedAnnotationType) { + for (AnnotationMirror mirror : mirrors) { + DeclaredType annotationType = mirror.getAnnotationType(); + TypeElement actualAnnotationType = (TypeElement) annotationType.asElement(); + if (actualAnnotationType.equals(expectedAnnotationType)) { + return mirror; + } + } + return null; + } + + public static PackageElement findPackageElement(Element type) { + List hierarchy = getElementHierarchy(type); + for (Element element : hierarchy) { + if (element.getKind() == ElementKind.PACKAGE) { + return (PackageElement) element; + } + } + return null; + } + + public static String firstLetterUpperCase(String name) { + if (name == null || name.isEmpty()) { + return name; + } + return Character.toUpperCase(name.charAt(0)) + name.substring(1, name.length()); + } + + public static String firstLetterLowerCase(String name) { + if (name == null || name.isEmpty()) { + return name; + } + return Character.toLowerCase(name.charAt(0)) + name.substring(1, name.length()); + } + + private static ExecutableElement getDeclaredMethod(TypeElement element, String name, TypeMirror[] params) { + List methods = ElementFilter.methodsIn(element.getEnclosedElements()); + method: for (ExecutableElement method : methods) { + if (!method.getSimpleName().toString().equals(name)) { + continue; + } + if (method.getParameters().size() != params.length) { + continue; + } + for (int i = 0; i < params.length; i++) { + TypeMirror param1 = params[i]; + TypeMirror param2 = method.getParameters().get(i).asType(); + if (param1.getKind() != TypeKind.TYPEVAR && param2.getKind() != TypeKind.TYPEVAR) { + if (!getQualifiedName(param1).equals(getQualifiedName(param2))) { + continue method; + } + } + } + return method; + } + return null; + } + + public static boolean isDeclaredMethodInSuperType(TypeElement element, String name, TypeMirror[] params) { + return !getDeclaredMethodsInSuperTypes(element, name, params).isEmpty(); + } + + /** + * Gets the methods in the super type hierarchy (excluding interfaces) that are overridden by a + * method in a subtype. + * + * @param declaringElement the subtype element declaring the method + * @param name the name of the method + * @param params the signature of the method + */ + public static List getDeclaredMethodsInSuperTypes(TypeElement declaringElement, String name, TypeMirror... params) { + List superMethods = new ArrayList<>(); + List superElements = getSuperTypes(declaringElement); + + for (TypeElement superElement : superElements) { + ExecutableElement superMethod = getDeclaredMethod(superElement, name, params); + if (superMethod != null) { + superMethods.add(superMethod); + } + } + return superMethods; + } + + public static boolean typeEquals(TypeMirror type1, TypeMirror type2) { + if (type1 == type2) { + return true; + } else if (type1 == null || type2 == null) { + return false; + } else { + if (type1.getKind() == type2.getKind()) { + return getUniqueIdentifier(type1).equals(getUniqueIdentifier(type2)); + } else { + return false; + } + } + } + + public static String getUniqueIdentifier(TypeMirror typeMirror) { + if (typeMirror.getKind() == TypeKind.ARRAY) { + return getUniqueIdentifier(((ArrayType) typeMirror).getComponentType()) + "[]"; + } else { + return getQualifiedName(typeMirror); + } + } + + public static int compareByTypeHierarchy(TypeMirror t1, TypeMirror t2) { + if (typeEquals(t1, t2)) { + return 0; + } + Set t1SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t1))); + if (t1SuperSet.contains(getQualifiedName(t2))) { + return -1; + } + + Set t2SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t2))); + if (t2SuperSet.contains(getQualifiedName(t1))) { + return 1; + } + return 0; + } + + public static boolean canThrowType(List thrownTypes, TypeMirror exceptionType) { + if (ElementUtils.containsType(thrownTypes, exceptionType)) { + return true; + } + + if (isRuntimeException(exceptionType)) { + return true; + } + + // search for any super types + TypeElement exceptionTypeElement = fromTypeMirror(exceptionType); + List superTypes = getSuperTypes(exceptionTypeElement); + for (TypeElement typeElement : superTypes) { + if (ElementUtils.containsType(thrownTypes, typeElement.asType())) { + return true; + } + } + + return false; + } + + public static Modifier getVisibility(Set modifier) { + for (Modifier mod : modifier) { + if (mod == Modifier.PUBLIC || mod == Modifier.PRIVATE || mod == Modifier.PROTECTED) { + return mod; + } + } + return null; + } + + private static boolean isRuntimeException(TypeMirror type) { + Set typeSuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(type))); + String typeName = getQualifiedName(type); + if (!typeSuperSet.contains(Throwable.class.getCanonicalName()) && !typeName.equals(Throwable.class.getCanonicalName())) { + throw new IllegalArgumentException("Given type does not extend Throwable."); + } + return typeSuperSet.contains(RuntimeException.class.getCanonicalName()) || typeName.equals(RuntimeException.class.getCanonicalName()); + } + + private static boolean containsType(Collection collection, TypeMirror type) { + for (TypeMirror otherTypeMirror : collection) { + if (typeEquals(otherTypeMirror, type)) { + return true; + } + } + return false; + } + + public static boolean isTopLevelClass(TypeMirror importType) { + TypeElement type = fromTypeMirror(importType); + if (type != null && type.getEnclosingElement() != null) { + return !type.getEnclosingElement().getKind().isClass(); + } + return true; + } + + public static boolean isObject(TypeMirror actualType) { + return actualType.getKind() == TypeKind.DECLARED && getQualifiedName(actualType).equals("java.lang.Object"); + } + + public static TypeMirror fillInGenericWildcards(TypeMirror type) { + if (type.getKind() != TypeKind.DECLARED) { + return type; + } + DeclaredType declaredType = (DeclaredType) type; + TypeElement element = (TypeElement) declaredType.asElement(); + if (element == null) { + return type; + } + int typeParameters = element.getTypeParameters().size(); + if (typeParameters > 0 && declaredType.getTypeArguments().size() != typeParameters) { + List genericTypes = new ArrayList<>(); + for (int i = 0; i < typeParameters; i++) { + genericTypes.add(new WildcardTypeMirror(null, null)); + } + return new DeclaredCodeTypeMirror(element, genericTypes); + } + return type; + } + + public static TypeMirror eraseGenericTypes(TypeMirror type) { + if (type.getKind() != TypeKind.DECLARED) { + return type; + } + DeclaredType declaredType = (DeclaredType) type; + if (declaredType.getTypeArguments().size() == 0) { + return type; + } + return new DeclaredCodeTypeMirror((TypeElement) declaredType.asElement()); + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/AbstractCompiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/AbstractCompiler.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.compiler; + +import java.lang.reflect.*; + +public abstract class AbstractCompiler implements Compiler { + + protected static Object method(Object o, String methodName) throws Exception { + Method method = o.getClass().getMethod(methodName); + method.setAccessible(true); + return method.invoke(o); + } + + protected static Object method(Object o, String methodName, Class[] paramTypes, Object... values) throws Exception { + Method method = o.getClass().getMethod(methodName, paramTypes); + method.setAccessible(true); + return method.invoke(o, values); + } + + protected static Object field(Object o, String fieldName) throws Exception { + if (o == null) { + return null; + } + Class clazz = o.getClass(); + Field field = null; + try { + field = clazz.getField(fieldName); + } catch (NoSuchFieldException e) { + while (clazz != null) { + try { + field = clazz.getDeclaredField(fieldName); + break; + } catch (NoSuchFieldException e1) { + clazz = clazz.getSuperclass(); + } + } + if (field == null) { + throw e; + } + } + field.setAccessible(true); + return field.get(o); + } + + protected static String parseHeader(String content) { + int index = content.indexOf("/*"); + if (index == -1) { + return null; + } + if (!content.substring(0, index).trim().equals("")) { + // just whitespace before + return null; + } + + int endIndex = content.indexOf("*/", index); + if (endIndex == -1) { + return null; + } + return content.substring(index, endIndex + 2); + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/Compiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/Compiler.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.compiler; + +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; + +public interface Compiler { + + String getMethodBody(ProcessingEnvironment env, ExecutableElement method); + + String getHeaderComment(ProcessingEnvironment env, Element type); + + List getEnclosedElementsInDeclarationOrder(TypeElement type); + + List getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type); + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/CompilerFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/CompilerFactory.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.compiler; + +import javax.lang.model.element.*; + +public class CompilerFactory { + + private static Compiler javac; + private static Compiler jdt; + + public static Compiler getCompiler(Element currentElement) { + if (JavaCCompiler.isValidElement(currentElement)) { + if (javac == null) { + javac = new JavaCCompiler(); + } + return javac; + } else if (JDTCompiler.isValidElement(currentElement)) { + if (jdt == null) { + jdt = new JDTCompiler(); + } + return jdt; + } else { + throw new UnsupportedOperationException("Unsupported compiler for element " + currentElement.getClass().getName() + "."); + } + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.compiler; + +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.java.*; + +public class JDTCompiler extends AbstractCompiler { + + public static boolean isValidElement(Element currentElement) { + try { + Class elementClass = Class.forName("org.eclipse.jdt.internal.compiler.apt.model.ElementImpl"); + return elementClass.isAssignableFrom(currentElement.getClass()); + } catch (ClassNotFoundException e) { + return false; + } + } + + public List getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type) { + return sortBySourceOrder(new ArrayList<>(environment.getElementUtils().getAllMembers(type))); + } + + public List getEnclosedElementsInDeclarationOrder(TypeElement type) { + return sortBySourceOrder(new ArrayList<>(type.getEnclosedElements())); + } + + private static List sortBySourceOrder(List elements) { + final Map> declarationOrders = new HashMap<>(); + + Collections.sort(elements, new Comparator() { + public int compare(Element o1, Element o2) { + try { + TypeMirror enclosing1 = o1.getEnclosingElement().asType(); + TypeMirror enclosing2 = o2.getEnclosingElement().asType(); + + if (ElementUtils.typeEquals(enclosing1, enclosing2)) { + List declarationOrder = lookupDeclarationOrder(declarationOrders, (TypeElement) o1.getEnclosingElement()); + if (declarationOrder == null) { + return 0; + } + Object o1Binding = field(o1, "_binding"); + Object o2Binding = field(o2, "_binding"); + + int i1 = declarationOrder.indexOf(o1Binding); + int i2 = declarationOrder.indexOf(o2Binding); + + return i1 - i2; + } else { + if (ElementUtils.isSubtype(enclosing1, enclosing2)) { + return 1; + } else if (ElementUtils.isSubtype(enclosing2, enclosing1)) { + return -1; + } else { + return 0; + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + return elements; + } + + private static List lookupDeclarationOrder(Map> declarationOrders, TypeElement type) throws Exception, ClassNotFoundException { + if (declarationOrders.containsKey(type)) { + return declarationOrders.get(type); + } + + Object binding = field(type, "_binding"); + Class sourceTypeBinding = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding"); + Class binaryTypeBinding = Class.forName("org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding"); + + List declarationOrder = null; + if (sourceTypeBinding.isAssignableFrom(binding.getClass())) { + declarationOrder = findSourceTypeOrder(binding); + } else if (binaryTypeBinding.isAssignableFrom(binding.getClass())) { + declarationOrder = findBinaryTypeOrder(binding); + } + + declarationOrders.put(type, declarationOrder); + + return declarationOrder; + } + + private static List findBinaryTypeOrder(Object binding) throws Exception { + Object binaryType = lookupBinaryType(binding); + final Object[] sortedMethods = (Object[]) method(binaryType, "getMethods"); + + List sortedElements = new ArrayList<>(); + if (sortedMethods != null) { + sortedElements.addAll(Arrays.asList(sortedMethods)); + } + final Object[] sortedFields = (Object[]) method(binaryType, "getFields"); + if (sortedFields != null) { + sortedElements.addAll(Arrays.asList(sortedFields)); + } + final Object[] sortedTypes = (Object[]) method(binaryType, "getMemberTypes", new Class[0]); + if (sortedTypes != null) { + sortedElements.addAll(Arrays.asList(sortedTypes)); + } + + Collections.sort(sortedElements, new Comparator() { + public int compare(Object o1, Object o2) { + try { + int structOffset1 = (int) field(o1, "structOffset"); + int structOffset2 = (int) field(o2, "structOffset"); + return structOffset1 - structOffset2; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + + Class binaryMethod = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryMethod"); + Class binaryField = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryField"); + Class nestedType = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryNestedType"); + + List bindings = new ArrayList<>(); + for (Object sortedElement : sortedElements) { + Class elementClass = sortedElement.getClass(); + if (binaryMethod.isAssignableFrom(elementClass)) { + char[] selector = (char[]) method(sortedElement, "getSelector"); + Object[] foundBindings = (Object[]) method(binding, "getMethods", new Class[]{char[].class}, selector); + if (foundBindings == null || foundBindings.length == 0) { + continue; + } else if (foundBindings.length == 1) { + bindings.add(foundBindings[0]); + } else { + char[] idescriptor = (char[]) method(sortedElement, "getMethodDescriptor"); + for (Object foundBinding : foundBindings) { + char[] descriptor = (char[]) method(foundBinding, "signature"); + if (descriptor == null && idescriptor == null || Arrays.equals(descriptor, idescriptor)) { + bindings.add(foundBinding); + break; + } + } + } + } else if (binaryField.isAssignableFrom(elementClass)) { + char[] selector = (char[]) method(sortedElement, "getName"); + Object foundField = method(binding, "getField", new Class[]{char[].class, boolean.class}, selector, true); + if (foundField != null) { + bindings.add(foundField); + } + } else if (nestedType.isAssignableFrom(elementClass)) { + char[] selector = (char[]) method(sortedElement, "getSourceName"); + Object foundType = method(binding, "getMemberType", new Class[]{char[].class}, selector); + if (foundType != null) { + bindings.add(foundType); + } + } else { + throw new AssertionError("Unexpected encountered type " + elementClass); + } + } + + return bindings; + } + + private static Object lookupBinaryType(Object binding) throws Exception { + Object lookupEnvironment = field(binding, "environment"); + Object compoundClassName = field(binding, "compoundName"); + Object nameEnvironment = field(lookupEnvironment, "nameEnvironment"); + Object nameEnvironmentAnswer = method(nameEnvironment, "findType", new Class[]{char[][].class}, compoundClassName); + Object binaryType = method(nameEnvironmentAnswer, "getBinaryType", new Class[0]); + return binaryType; + } + + private static List findSourceTypeOrder(Object binding) throws Exception { + Object referenceContext = field(field(binding, "scope"), "referenceContext"); + + TreeMap orderedBindings = new TreeMap<>(); + + collectSourceOrder(orderedBindings, referenceContext, "methods"); + collectSourceOrder(orderedBindings, referenceContext, "fields"); + collectSourceOrder(orderedBindings, referenceContext, "memberTypes"); + + return new ArrayList<>(orderedBindings.values()); + } + + private static void collectSourceOrder(TreeMap orderedBindings, Object referenceContext, String fieldName) throws Exception { + Object[] declarations = (Object[]) field(referenceContext, fieldName); + if (declarations != null) { + for (int i = 0; i < declarations.length; i++) { + Integer declarationSourceStart = (Integer) field(declarations[i], "declarationSourceStart"); + orderedBindings.put(declarationSourceStart, field(declarations[i], "binding")); + } + } + } + + @Override + public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) { + try { + + char[] source = getSource(method); + if (source == null) { + return null; + } + + /* + * AbstractMethodDeclaration decl = + * ((MethodBinding)(((ElementImpl)method)._binding)).sourceMethod(); int bodyStart = + * decl.bodyStart; int bodyEnd = decl.bodyEnd; + */ + Object decl = method(field(method, "_binding"), "sourceMethod"); + int bodyStart = (int) field(decl, "bodyStart"); + int bodyEnd = (int) field(decl, "bodyEnd"); + + int length = bodyEnd - bodyStart; + char[] target = new char[length]; + System.arraycopy(source, bodyStart, target, 0, length); + + return new String(target); + } catch (Exception e) { + return ElementUtils.printException(e); + } + } + + private static char[] getSource(Element element) throws Exception { + /* + * Binding binding = ((ElementImpl)element)._binding; char[] source = null; if (binding + * instanceof MethodBinding) { source = ((MethodBinding) + * binding).sourceMethod().compilationResult.getCompilationUnit().getContents(); } else if + * (binding instanceof SourceTypeBinding) { source = + * ((SourceTypeBinding)binding).scope.referenceContext + * .compilationResult.compilationUnit.getContents(); } return source; + */ + + Object binding = field(element, "_binding"); + Class methodBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.MethodBinding"); + Class referenceBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding"); + + char[] source = null; + if (methodBindingClass.isAssignableFrom(binding.getClass())) { + Object sourceMethod = method(binding, "sourceMethod"); + if (sourceMethod == null) { + return null; + } + source = (char[]) method(method(field(sourceMethod, "compilationResult"), "getCompilationUnit"), "getContents"); + } else if (referenceBindingClass.isAssignableFrom(binding.getClass())) { + source = (char[]) method(field(field(field(field(binding, "scope"), "referenceContext"), "compilationResult"), "compilationUnit"), "getContents"); + } + return source; + } + + @Override + public String getHeaderComment(ProcessingEnvironment env, Element type) { + try { + char[] source = getSource(type); + if (source == null) { + return null; + } + return parseHeader(new String(source)); + } catch (Exception e) { + return ElementUtils.printException(e); + } + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JavaCCompiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JavaCCompiler.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.compiler; + +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; + +import com.oracle.truffle.dsl.processor.java.*; + +public class JavaCCompiler extends AbstractCompiler { + + public static boolean isValidElement(Element currentElement) { + try { + Class elementClass = Class.forName("com.sun.tools.javac.code.Symbol"); + return elementClass.isAssignableFrom(currentElement.getClass()); + } catch (ClassNotFoundException e) { + return false; + } + } + + public List getEnclosedElementsInDeclarationOrder(TypeElement type) { + return type.getEnclosedElements(); + } + + public List getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type) { + return environment.getElementUtils().getAllMembers(type); + } + + private static final Class[] getTreeAndTopLevelSignature = new Class[]{Element.class, AnnotationMirror.class, AnnotationValue.class}; + private static final Class[] getCharContentSignature = new Class[]{boolean.class}; + + @Override + public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) { + try { + /* + * if (false) { Pair treeAndTopLevel = ((JavacElements) + * env.getElementUtils()).getTreeAndTopLevel(method, null, null); JCBlock block = + * ((JCMethodDecl) treeAndTopLevel.fst).getBody(); int startPos = block.pos; int endPos + * = block.endpos; String methodBody = + * treeAndTopLevel.snd.getSourceFile().getCharContent(true).subSequence(startPos + 1, + * endPos).toString(); return methodBody; } + */ + + Object treeAndTopLevel = getTreeAndTopLevel(env, method); + Object block = method(field(treeAndTopLevel, "fst"), "getBody"); + int startPos = (int) field(block, "pos"); + int endPos = (int) field(block, "endpos"); + return getContent(treeAndTopLevel).subSequence(startPos + 1, endPos).toString(); + } catch (Exception e) { + return ElementUtils.printException(e); + } + } + + private static CharSequence getContent(Object treeAndTopLevel) throws Exception { + /* + * CharSequence content = treeAndTopLevel.snd.getSourceFile().getCharContent(true); + */ + return (CharSequence) method(method(field(treeAndTopLevel, "snd"), "getSourceFile"), "getCharContent", getCharContentSignature, true); + } + + private static Object getTreeAndTopLevel(ProcessingEnvironment env, Element element) throws Exception { + /* + * Pair treeAndTopLevel = ((JavacElements) + * env.getElementUtils()).getTreeAndTopLevel(method, null, null); + */ + return method(method(env, "getElementUtils"), "getTreeAndTopLevel", getTreeAndTopLevelSignature, element, null, null); + } + + @Override + public String getHeaderComment(ProcessingEnvironment env, Element type) { + try { + String content = getContent(getTreeAndTopLevel(env, type)).toString(); + return parseHeader(content); + } catch (Exception e) { + return ElementUtils.printException(e); + } + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeAnnotationMirror.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeAnnotationMirror.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.model; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.java.*; + +public class CodeAnnotationMirror implements AnnotationMirror { + + private final DeclaredType annotationType; + private final Map values = new LinkedHashMap<>(); + + public CodeAnnotationMirror(DeclaredType annotationType) { + this.annotationType = annotationType; + } + + @Override + public DeclaredType getAnnotationType() { + return annotationType; + } + + @Override + public Map getElementValues() { + return values; + } + + public void setElementValue(ExecutableElement method, AnnotationValue value) { + values.put(method, value); + } + + public ExecutableElement findExecutableElement(String name) { + return ElementUtils.findExecutableElement(annotationType, name); + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeAnnotationValue.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeAnnotationValue.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.model; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public class CodeAnnotationValue implements AnnotationValue { + + private final Object value; + + public CodeAnnotationValue(Object value) { + Objects.requireNonNull(value); + if ((value instanceof AnnotationMirror) || (value instanceof List) || (value instanceof Boolean) || (value instanceof Byte) || (value instanceof Character) || (value instanceof Double) || + (value instanceof VariableElement) || (value instanceof Float) || (value instanceof Integer) || (value instanceof Long) || (value instanceof Short) || + (value instanceof String) || (value instanceof TypeMirror)) { + this.value = value; + } else { + throw new IllegalArgumentException("Invalid annotation value type " + value.getClass().getName()); + } + } + + @Override + public Object getValue() { + return value; + } + + @SuppressWarnings("unchecked") + @Override + public R accept(AnnotationValueVisitor v, P p) { + if (value instanceof AnnotationMirror) { + return v.visitAnnotation((AnnotationMirror) value, p); + } else if (value instanceof List) { + return v.visitArray((List) value, p); + } else if (value instanceof Boolean) { + return v.visitBoolean((boolean) value, p); + } else if (value instanceof Byte) { + return v.visitByte((byte) value, p); + } else if (value instanceof Character) { + return v.visitChar((char) value, p); + } else if (value instanceof Double) { + return v.visitDouble((double) value, p); + } else if (value instanceof VariableElement) { + return v.visitEnumConstant((VariableElement) value, p); + } else if (value instanceof Float) { + return v.visitFloat((float) value, p); + } else if (value instanceof Integer) { + return v.visitInt((int) value, p); + } else if (value instanceof Long) { + return v.visitLong((long) value, p); + } else if (value instanceof Short) { + return v.visitShort((short) value, p); + } else if (value instanceof String) { + return v.visitString((String) value, p); + } else if (value instanceof TypeMirror) { + return v.visitType((TypeMirror) value, p); + } else { + return v.visitUnknown(this, p); + } + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeCompilationUnit.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeCompilationUnit.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.model; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public class CodeCompilationUnit extends CodeElement { + + public CodeCompilationUnit() { + super(Collections. emptySet()); + } + + @Override + public TypeMirror asType() { + throw new UnsupportedOperationException(); + } + + @Override + public ElementKind getKind() { + return ElementKind.OTHER; + } + + @Override + public Name getSimpleName() { + throw new UnsupportedOperationException(); + } + + @Override + public R accept(ElementVisitor v, P p) { + for (Element type : getEnclosedElements()) { + if (type.getKind().isClass()) { + type.accept(v, p); + } else { + throw new ClassCastException(type.getClass().getName()); + } + } + return null; + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeElement.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.model; + +import java.io.*; +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; + +import com.oracle.truffle.dsl.processor.java.transform.*; + +public abstract class CodeElement implements Element, GeneratedElement { + + private final Set modifiers; + private List annotations; + private List enclosedElements; + + private Element enclosingElement; + + private Element generatorElement; + private AnnotationMirror generatorAnnotationMirror; + + public CodeElement(Set modifiers) { + this.modifiers = new LinkedHashSet<>(modifiers); + } + + @Override + public void setGeneratorAnnotationMirror(AnnotationMirror mirror) { + this.generatorAnnotationMirror = mirror; + } + + @Override + public void setGeneratorElement(Element element) { + this.generatorElement = element; + } + + @Override + public AnnotationMirror getGeneratorAnnotationMirror() { + return generatorAnnotationMirror; + } + + @Override + public Element getGeneratorElement() { + return generatorElement; + } + + public E add(E element) { + if (element == null) { + throw new NullPointerException(); + } + getEnclosedElements().add(element); + return element; + } + + public E addOptional(E element) { + if (element != null) { + add(element); + } + return element; + } + + public void remove(E element) { + getEnclosedElements().remove(element); + } + + @Override + public Set getModifiers() { + return modifiers; + } + + @Override + public List getEnclosedElements() { + if (enclosedElements == null) { + enclosedElements = parentableList(this, new ArrayList()); + } + return enclosedElements; + } + + @Override + public List getAnnotationMirrors() { + if (annotations == null) { + annotations = parentableList(this, new ArrayList()); + } + return annotations; + } + + /** + * Support JDK8 langtools. + * + * @param annotationType + */ + public A[] getAnnotationsByType(Class annotationType) { + throw new UnsupportedOperationException(); + } + + /** + * Support for some JDK8 builds. (remove after jdk8 is released) + * + * @param annotationType + */ + public A[] getAnnotations(Class annotationType) { + throw new UnsupportedOperationException(); + } + + /** + * Support for some JDK8 builds. (remove after jdk8 is released) + * + * @param annotationType + */ + public A getAnnotation(Class annotationType) { + throw new UnsupportedOperationException(); + } + + public void addAnnotationMirror(AnnotationMirror annotationMirror) { + getAnnotationMirrors().add(annotationMirror); + } + + public void setEnclosingElement(Element parent) { + this.enclosingElement = parent; + } + + public Element getEnclosingElement() { + return enclosingElement; + } + + public CodeTypeElement getEnclosingClass() { + Element p = enclosingElement; + while (p != null && p.getKind() != ElementKind.CLASS && p.getKind() != ElementKind.ENUM) { + p = p.getEnclosingElement(); + } + return (CodeTypeElement) p; + } + + List parentableList(Element parent, List list) { + return new ParentableList<>(parent, list); + } + + @Override + public String toString() { + StringBuilderCodeWriter codeWriter = new StringBuilderCodeWriter(); + accept(codeWriter, null); + return codeWriter.getString(); + } + + private static class StringBuilderCodeWriter extends AbstractCodeWriter { + + public StringBuilderCodeWriter() { + this.writer = new CharArrayWriter(); + } + + @Override + protected Writer createWriter(CodeTypeElement clazz) throws IOException { + return writer; + } + + public String getString() { + return new String(((CharArrayWriter) writer).toCharArray()).trim(); + } + + } + + private static class ParentableList implements List { + + private final Element parent; + private final List delegate; + + public ParentableList(Element parent, List delegate) { + this.parent = parent; + this.delegate = delegate; + } + + private void addImpl(T element) { + if (element != null) { + if (element instanceof CodeElement) { + ((CodeElement) element).setEnclosingElement(parent); + } + } + } + + private static void removeImpl(Object element) { + if (element instanceof CodeElement) { + ((CodeElement) element).setEnclosingElement(null); + } + } + + @Override + public int size() { + return delegate.size(); + } + + @Override + public boolean isEmpty() { + return delegate.isEmpty(); + } + + @Override + public boolean contains(Object o) { + return delegate.contains(o); + } + + @Override + public Iterator iterator() { + return delegate.iterator(); + } + + @Override + public Object[] toArray() { + return delegate.toArray(); + } + + @Override + public E[] toArray(E[] a) { + return delegate.toArray(a); + } + + @Override + public boolean add(T e) { + addImpl(e); + return delegate.add(e); + } + + @Override + public boolean remove(Object o) { + boolean removed = delegate.remove(o); + if (removed) { + removeImpl(o); + } + return removed; + } + + @Override + public boolean containsAll(Collection c) { + return delegate.containsAll(c); + } + + @Override + public boolean addAll(Collection c) { + if (c != null) { + for (T t : c) { + addImpl(t); + } + } + return delegate.addAll(c); + } + + @Override + public boolean addAll(int index, Collection c) { + if (c != null) { + for (T t : c) { + addImpl(t); + } + } + return delegate.addAll(index, c); + } + + @Override + public boolean removeAll(Collection c) { + if (c != null) { + for (Object t : c) { + removeImpl(t); + } + } + return delegate.removeAll(c); + } + + @Override + public String toString() { + return delegate.toString(); + } + + @Override + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException("Not supported by parentable list"); + } + + @Override + public void clear() { + for (Object e : this) { + removeImpl(e); + } + delegate.clear(); + } + + @Override + public T get(int index) { + return delegate.get(index); + } + + @Override + public T set(int index, T element) { + removeImpl(delegate.get(index)); + addImpl(element); + return delegate.set(index, element); + } + + @Override + public void add(int index, T element) { + addImpl(element); + delegate.add(index, element); + } + + @Override + public T remove(int index) { + T element = delegate.remove(index); + removeImpl(element); + return element; + } + + @Override + public int indexOf(Object o) { + return delegate.indexOf(o); + } + + @Override + public int lastIndexOf(Object o) { + return delegate.lastIndexOf(o); + } + + @Override + public ListIterator listIterator() { + return delegate.listIterator(); + } + + @Override + public ListIterator listIterator(int index) { + return delegate.listIterator(index); + } + + @Override + public List subList(int fromIndex, int toIndex) { + return new ParentableList<>(parent, delegate.subList(fromIndex, toIndex)); + } + + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeElementScanner.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeElementScanner.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.model; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.util.*; + +public abstract class CodeElementScanner extends ElementScanner7 { + + @Override + public final R visitExecutable(ExecutableElement e, P p) { + return visitExecutable(cast(e, CodeExecutableElement.class), p); + } + + public R visitExecutable(CodeExecutableElement e, P p) { + R ret = super.visitExecutable(e, p); + if (e.getBodyTree() != null) { + visitTree(e.getBodyTree(), p, e); + } + return ret; + } + + @Override + public R visitVariable(VariableElement e, P p) { + if (e instanceof CodeVariableElement) { + CodeTree init = ((CodeVariableElement) e).getInit(); + if (init != null) { + visitTree(init, p, e); + } + } + return super.visitVariable(e, p); + } + + @Override + public R visitPackage(PackageElement e, P p) { + return super.visitPackage(e, p); + } + + @Override + public final R visitType(TypeElement e, P p) { + return visitType(cast(e, CodeTypeElement.class), p); + } + + public R visitType(CodeTypeElement e, P p) { + return super.visitType(e, p); + } + + @Override + public R visitTypeParameter(TypeParameterElement e, P p) { + return super.visitTypeParameter(e, p); + } + + private static E cast(Element element, Class clazz) { + return clazz.cast(element); + } + + public void visitTree(CodeTree e, P p, Element parent) { + List elements = e.getEnclosedElements(); + if (elements != null) { + for (CodeTree tree : e.getEnclosedElements()) { + visitTree(tree, p, parent); + } + } + } + + @SuppressWarnings("unused") + public void visitImport(CodeImport e, P p) { + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeExecutableElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeExecutableElement.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.model; + +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.java.*; + +public class CodeExecutableElement extends CodeElement implements ExecutableElement { + + private final List throwables = new ArrayList<>(); + private final List parameters = parentableList(this, new ArrayList()); + + private TypeMirror returnType; + private Name name; + + private CodeTree bodyTree; + private String body; + private AnnotationValue defaultValue; + private boolean varArgs; + + public CodeExecutableElement(TypeMirror returnType, String name) { + super(ElementUtils.modifiers()); + this.returnType = returnType; + this.name = CodeNames.of(name); + } + + public CodeExecutableElement(Set modifiers, TypeMirror returnType, String name, CodeVariableElement... parameters) { + super(modifiers); + this.returnType = returnType; + this.name = CodeNames.of(name); + for (CodeVariableElement codeParameter : parameters) { + addParameter(codeParameter); + } + } + + /* Support JDK8 langtools. */ + public boolean isDefault() { + return false; + } + + @Override + public List getThrownTypes() { + return throwables; + } + + @Override + public TypeMirror asType() { + return returnType; + } + + @Override + public ElementKind getKind() { + if (getReturnType() == null) { + return ElementKind.CONSTRUCTOR; + } else { + return ElementKind.METHOD; + } + } + + @Override + public List getTypeParameters() { + return Collections.emptyList(); + } + + public void setVarArgs(boolean varargs) { + this.varArgs = varargs; + } + + @Override + public boolean isVarArgs() { + return varArgs; + } + + public void setDefaultValue(AnnotationValue defaultValue) { + this.defaultValue = defaultValue; + } + + @Override + public AnnotationValue getDefaultValue() { + return defaultValue; + } + + @Override + public Name getSimpleName() { + return name; + } + + public CodeTreeBuilder getBuilder() { + CodeTree tree = this.bodyTree; + return createBuilder().tree(tree); + } + + public CodeTreeBuilder createBuilder() { + CodeTreeBuilder builder = new CodeTreeBuilder(null); + builder.setEnclosingElement(this); + this.bodyTree = builder.getTree(); + this.body = null; + return builder; + } + + public void setBodyTree(CodeTree body) { + this.bodyTree = body; + } + + public CodeTree getBodyTree() { + return bodyTree; + } + + public TypeMirror getReturnType() { + return returnType; + } + + @Override + public List getParameters() { + return parameters; + } + + public TypeMirror[] getParameterTypes() { + TypeMirror[] types = new TypeMirror[getParameters().size()]; + for (int i = 0; i < types.length; i++) { + types[i] = parameters.get(i).asType(); + } + return types; + } + + public void setReturnType(TypeMirror type) { + returnType = type; + } + + public void addParameter(VariableElement parameter) { + parameters.add(parameter); + } + + public void addThrownType(TypeMirror thrownType) { + throwables.add(thrownType); + } + + public void setSimpleName(Name name) { + this.name = name; + } + + public void setBody(String body) { + this.body = body; + } + + public String getBody() { + return body; + } + + @Override + public R accept(ElementVisitor v, P p) { + return v.visitExecutable(this, p); + } + + public static CodeExecutableElement clone(@SuppressWarnings("unused") ProcessingEnvironment env, ExecutableElement method) { + CodeExecutableElement copy = new CodeExecutableElement(method.getReturnType(), method.getSimpleName().toString()); + for (TypeMirror thrownType : method.getThrownTypes()) { + copy.addThrownType(thrownType); + } + copy.setDefaultValue(method.getDefaultValue()); + + for (AnnotationMirror mirror : method.getAnnotationMirrors()) { + copy.addAnnotationMirror(mirror); + } + for (VariableElement var : method.getParameters()) { + copy.addParameter(CodeVariableElement.clone(var)); + } + for (Element element : method.getEnclosedElements()) { + copy.add(element); + } + copy.getModifiers().addAll(method.getModifiers()); + copy.setVarArgs(method.isVarArgs()); + return copy; + } + + public TypeMirror getReceiverType() { + throw new UnsupportedOperationException(); + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeImport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeImport.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.model; + +import java.util.*; + +public class CodeImport implements Comparable { + + private final String packageName; + private final String symbolName; + private final boolean staticImport; + + public CodeImport(String packageName, String symbolName, boolean staticImport) { + this.packageName = packageName; + this.symbolName = symbolName; + this.staticImport = staticImport; + } + + public String getPackageName() { + return packageName; + } + + public String getSymbolName() { + return symbolName; + } + + public boolean isStaticImport() { + return staticImport; + } + + @Override + public int compareTo(CodeImport o) { + if (staticImport && !o.staticImport) { + return 1; + } else if (!staticImport && o.staticImport) { + return -1; + } else { + int result = getPackageName().compareTo(o.getPackageName()); + if (result == 0) { + return getSymbolName().compareTo(o.getSymbolName()); + } + return result; + } + } + + public

    void accept(CodeElementScanner s, P p) { + s.visitImport(this, p); + } + + @Override + public int hashCode() { + return Objects.hash(packageName, symbolName, staticImport); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof CodeImport) { + CodeImport otherImport = (CodeImport) obj; + return getPackageName().equals(otherImport.getPackageName()) && getSymbolName().equals(otherImport.getSymbolName()) // + && staticImport == otherImport.staticImport; + } + return super.equals(obj); + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeNames.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeNames.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.model; + +import java.util.*; + +import javax.lang.model.element.*; + +public abstract class CodeNames { + + private static Map names = new HashMap<>(); + + public static Name of(String value) { + Name name = names.get(value); + if (name == null) { + name = new NameImpl(value); + names.put(value, name); + } + return name; + } + + private static class NameImpl implements Name { + + private final String name; + + public NameImpl(String name) { + this.name = name; + } + + @Override + public int length() { + return name.length(); + } + + @Override + public char charAt(int index) { + return name.charAt(index); + } + + @Override + public CharSequence subSequence(int start, int end) { + return name.subSequence(start, end); + } + + @Override + public boolean contentEquals(CharSequence cs) { + return name.contentEquals(cs); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Name) { + return ((Name) obj).contentEquals(name); + } + return super.equals(obj); + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public String toString() { + return name; + } + + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTree.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTree.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.model; + +import java.util.*; + +import javax.lang.model.type.*; + +public class CodeTree { + + private final CodeTreeKind kind; + + private CodeTree parent; + + private TypeMirror type; + private final String string; + + private List children; + + CodeTree(CodeTree parent, CodeTreeKind kind, TypeMirror type, String string) { + this.parent = parent; + this.kind = kind; + this.type = type; + this.string = string; + } + + public void setParent(CodeTree parent) { + this.parent = parent; + } + + public CodeTree getParent() { + return parent; + } + + public TypeMirror getType() { + return type; + } + + public void add(CodeTree element) { + if (children == null) { + children = new ArrayList<>(); + } + element.setParent(this); + children.add(element); + } + + public final List getEnclosedElements() { + return children; + } + + public final CodeTreeKind getCodeKind() { + return kind; + } + + public String getString() { + return string; + } + + public void setType(TypeMirror type) { + this.type = type; + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,893 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.model; + +import static com.oracle.truffle.dsl.processor.java.model.CodeTreeKind.*; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.java.*; + +public class CodeTreeBuilder { + + private BuilderCodeTree currentElement; + private final BuilderCodeTree root; + + private int treeCount; + private Element enclosingElement; + + public CodeTreeBuilder(CodeTreeBuilder parent) { + this.root = new BuilderCodeTree(null, GROUP, null, null); + this.currentElement = root; + if (parent != null) { + this.enclosingElement = parent.enclosingElement; + } + } + + public void setEnclosingElement(Element enclosingElement) { + this.enclosingElement = enclosingElement; + } + + @Override + public String toString() { + return root.toString(); + } + + public int getTreeCount() { + return treeCount; + } + + public boolean isEmpty() { + return treeCount == 0; + } + + public CodeTreeBuilder statement(String statement) { + return startStatement().string(statement).end(); + } + + public CodeTreeBuilder statement(CodeTree statement) { + return startStatement().tree(statement).end(); + } + + public static CodeTreeBuilder createBuilder() { + return new CodeTreeBuilder(null); + } + + public static CodeTree singleString(String s) { + return new CodeTreeBuilder(null).string(s).getTree(); + } + + public static CodeTree singleType(TypeMirror s) { + return new CodeTreeBuilder(null).type(s).getTree(); + } + + private CodeTreeBuilder push(CodeTreeKind kind) { + return push(new BuilderCodeTree(currentElement, kind, null, null), kind == NEW_LINE); + } + + private CodeTreeBuilder push(String string) { + return push(new BuilderCodeTree(currentElement, CodeTreeKind.STRING, null, string), false); + } + + private CodeTreeBuilder push(TypeMirror type) { + return push(new BuilderCodeTree(currentElement, CodeTreeKind.TYPE, type, null), false); + } + + private CodeTreeBuilder push(CodeTreeKind kind, TypeMirror type, String string) { + return push(new BuilderCodeTree(currentElement, kind, type, string), kind == NEW_LINE); + } + + private CodeTreeBuilder push(BuilderCodeTree tree, boolean removeLast) { + if (currentElement != null) { + if (removeLast && !removeLastIfEnqueued(tree)) { + return this; + } + currentElement.add(tree); + } + switch (tree.getCodeKind()) { + case COMMA_GROUP: + case GROUP: + case INDENT: + currentElement = tree; + break; + } + treeCount++; + return this; + } + + private boolean removeLastIfEnqueued(BuilderCodeTree tree) { + if (tree.getCodeKind() == REMOVE_LAST) { + return !clearLastRec(tree.removeLast, currentElement.getEnclosedElements()); + } + List childTree = tree.getEnclosedElements(); + if (childTree != null && !childTree.isEmpty()) { + CodeTree last = childTree.get(0); + if (last instanceof BuilderCodeTree) { + if (!removeLastIfEnqueued((BuilderCodeTree) last)) { + childTree.remove(0); + } + } + } + return true; + } + + private void clearLast(CodeTreeKind kind) { + if (clearLastRec(kind, currentElement.getEnclosedElements())) { + treeCount--; + } else { + // delay clearing the last + BuilderCodeTree tree = new BuilderCodeTree(currentElement, REMOVE_LAST, null, null); + tree.removeLast = kind; + push(tree, false); + } + } + + public CodeTreeBuilder startStatement() { + startGroup(); + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + string(";").newLine(); + } + + @Override + public void afterEnd() { + } + }); + return this; + } + + public CodeTreeBuilder startGroup() { + return push(CodeTreeKind.GROUP); + } + + public CodeTreeBuilder startCommaGroup() { + return push(CodeTreeKind.COMMA_GROUP); + } + + public CodeTreeBuilder startCall(String callSite) { + return startCall((CodeTree) null, callSite); + } + + public CodeTreeBuilder startCall(String receiver, String callSite) { + return startCall(singleString(receiver), callSite); + } + + public CodeTreeBuilder startCall(CodeTree receiver, String callSite) { + if (receiver == null) { + return startGroup().string(callSite).startParanthesesCommaGroup().endAfter(); + } else { + return startGroup().tree(receiver).string(".").string(callSite).startParanthesesCommaGroup().endAfter(); + } + } + + public CodeTreeBuilder startStaticCall(TypeMirror type, String methodName) { + return startGroup().push(CodeTreeKind.STATIC_METHOD_REFERENCE, type, methodName).startParanthesesCommaGroup().endAfter(); + } + + public CodeTreeBuilder startStaticCall(ExecutableElement method) { + return startStaticCall(ElementUtils.findNearestEnclosingType(method).asType(), method.getSimpleName().toString()); + } + + public CodeTreeBuilder staticReference(TypeMirror type, String fieldName) { + return push(CodeTreeKind.STATIC_FIELD_REFERENCE, type, fieldName); + } + + private CodeTreeBuilder endAndWhitespaceAfter() { + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + } + + @Override + public void afterEnd() { + string(" "); + end(); + } + }); + return this; + } + + private CodeTreeBuilder endAfter() { + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + } + + @Override + public void afterEnd() { + end(); + } + }); + return this; + } + + private CodeTreeBuilder startParanthesesCommaGroup() { + startGroup(); + string("(").startCommaGroup(); + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + } + + @Override + public void afterEnd() { + string(")"); + } + }); + endAfter(); + return this; + } + + private CodeTreeBuilder startCurlyBracesCommaGroup() { + startGroup(); + string("{").startCommaGroup(); + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + } + + @Override + public void afterEnd() { + string("}"); + } + }); + endAfter(); + return this; + } + + public CodeTreeBuilder startParantheses() { + startGroup(); + string("(").startGroup(); + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + } + + @Override + public void afterEnd() { + string(")"); + } + }); + endAfter(); + return this; + } + + public CodeTreeBuilder doubleQuote(String s) { + return startGroup().string("\"" + s + "\"").end(); + } + + public CodeTreeBuilder string(String chunk1) { + return push(chunk1); + } + + public CodeTreeBuilder string(String chunk1, String chunk2) { + return push(GROUP).string(chunk1).string(chunk2).end(); + } + + public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3) { + return push(GROUP).string(chunk1).string(chunk2).string(chunk3).end(); + } + + public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4) { + return push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4).end(); + } + + public CodeTreeBuilder tree(CodeTree treeToAdd) { + if (treeToAdd instanceof BuilderCodeTree) { + return push((BuilderCodeTree) treeToAdd, true).end(); + } else { + BuilderCodeTree tree = new BuilderCodeTree(currentElement, GROUP, null, null); + currentElement.add(treeToAdd); + return push(tree, true).end(); + } + } + + public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4, String... chunks) { + push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4); + for (int i = 0; i < chunks.length; i++) { + string(chunks[i]); + } + return end(); + } + + public CodeTreeBuilder dot() { + return string("."); + } + + public CodeTreeBuilder newLine() { + return push(NEW_LINE); + } + + public CodeTreeBuilder startWhile() { + return startGroup().string("while ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter(); + } + + public CodeTreeBuilder startDoBlock() { + return startGroup().string("do ").startBlock(); + } + + public CodeTreeBuilder startDoWhile() { + clearLast(CodeTreeKind.NEW_LINE); + return startStatement().string(" while ").startParanthesesCommaGroup().endAfter().startGroup().endAfter(); + } + + public CodeTreeBuilder startIf() { + return startGroup().string("if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter(); + } + + public CodeTreeBuilder startFor() { + return startGroup().string("for ").startParantheses().endAndWhitespaceAfter().startGroup().endAfter(); + } + + public boolean startIf(boolean elseIf) { + if (elseIf) { + startElseIf(); + } else { + startIf(); + } + return true; + } + + public CodeTreeBuilder startElseIf() { + clearLast(CodeTreeKind.NEW_LINE); + return startGroup().string(" else if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter(); + } + + public CodeTreeBuilder startElseBlock() { + clearLast(CodeTreeKind.NEW_LINE); + return startGroup().string(" else ").startBlock().endAfter(); + } + + private boolean clearLastRec(CodeTreeKind kind, List children) { + if (children == null) { + return false; + } + for (int i = children.size() - 1; i >= 0; i--) { + CodeTree child = children.get(i); + if (child.getCodeKind() == kind) { + children.remove(children.get(i)); + return true; + } else { + if (clearLastRec(kind, child.getEnclosedElements())) { + return true; + } + } + } + return false; + } + + public CodeTreeBuilder startCase() { + startGroup().string("case "); + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + string(" :").newLine(); + } + + @Override + public void afterEnd() { + } + }); + return this; + } + + public CodeTreeBuilder caseDefault() { + return startGroup().string("default :").newLine().end(); + } + + public CodeTreeBuilder startSwitch() { + return startGroup().string("switch ").startParanthesesCommaGroup().endAndWhitespaceAfter(); + } + + public CodeTreeBuilder startReturn() { + ExecutableElement method = findMethod(); + if (method != null && ElementUtils.isVoid(method.getReturnType())) { + startGroup(); + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + string(";").newLine(); // complete statement to execute + } + + @Override + public void afterEnd() { + string("return").string(";").newLine(); // emit a return; + } + }); + return this; + } else { + return startStatement().string("return "); + } + } + + public CodeTreeBuilder startAssert() { + return startStatement().string("assert "); + } + + public CodeTreeBuilder startNewArray(ArrayType arrayType, CodeTree size) { + startGroup().string("new ").type(arrayType.getComponentType()).string("["); + if (size != null) { + tree(size); + } + string("]"); + if (size == null) { + string(" "); + startCurlyBracesCommaGroup().endAfter(); + } + return this; + } + + public CodeTreeBuilder startNew(TypeMirror uninializedNodeClass) { + return startGroup().string("new ").type(uninializedNodeClass).startParanthesesCommaGroup().endAfter(); + } + + public CodeTreeBuilder startNew(String typeName) { + return startGroup().string("new ").string(typeName).startParanthesesCommaGroup().endAfter(); + } + + public CodeTreeBuilder startIndention() { + return push(CodeTreeKind.INDENT); + } + + public CodeTreeBuilder end(int times) { + for (int i = 0; i < times; i++) { + end(); + } + return this; + } + + public CodeTreeBuilder end() { + BuilderCodeTree tree = currentElement; + EndCallback callback = tree.getAtEndListener(); + if (callback != null) { + callback.beforeEnd(); + toParent(); + callback.afterEnd(); + } else { + toParent(); + } + return this; + } + + private void toParent() { + CodeTree parentElement = currentElement.getParent(); + if (currentElement != root) { + this.currentElement = (BuilderCodeTree) parentElement; + } else { + this.currentElement = root; + } + } + + public CodeTreeBuilder startBlock() { + startGroup(); + string("{").newLine().startIndention(); + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + } + + @Override + public void afterEnd() { + string("}").newLine(); + } + }); + endAfter(); + return this; + } + + private void registerCallBack(EndCallback callback) { + currentElement.registerAtEnd(callback); + } + + public CodeTreeBuilder defaultDeclaration(TypeMirror type, String name) { + if (!ElementUtils.isVoid(type)) { + startStatement(); + type(type); + string(" "); + string(name); + string(" = "); + defaultValue(type); + end(); // statement + } + return this; + } + + public CodeTreeBuilder declaration(TypeMirror type, String name, String init) { + return declaration(type, name, singleString(init)); + } + + public CodeTreeBuilder declaration(String type, String name, CodeTree init) { + startStatement(); + string(type); + string(" "); + string(name); + if (init != null) { + string(" = "); + tree(init); + } + end(); // statement + return this; + } + + public CodeTreeBuilder declaration(String type, String name, String init) { + return declaration(type, name, singleString(init)); + } + + public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTree init) { + if (ElementUtils.isVoid(type)) { + startStatement(); + tree(init); + end(); + } else { + startStatement(); + type(type); + string(" "); + string(name); + if (init != null) { + string(" = "); + tree(init); + } + end(); // statement + } + return this; + } + + public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTreeBuilder init) { + if (init == this) { + throw new IllegalArgumentException("Recursive builder usage."); + } + return declaration(type, name, init.getTree()); + } + + public CodeTreeBuilder declaration(String type, String name, CodeTreeBuilder init) { + if (init == this) { + throw new IllegalArgumentException("Recursive builder usage."); + } + return declaration(type, name, init.getTree()); + } + + public CodeTreeBuilder declaration(TypeMirror type, String name) { + return declaration(type, name, (CodeTree) null); + } + + public CodeTreeBuilder create() { + return new CodeTreeBuilder(this); + } + + public CodeTreeBuilder type(TypeMirror type) { + return push(type); + } + + public CodeTreeBuilder typeLiteral(TypeMirror type) { + return startGroup().type(ElementUtils.eraseGenericTypes(type)).string(".class").end(); + } + + private void assertRoot() { + if (currentElement != root) { + throw new IllegalStateException("CodeTreeBuilder was not ended properly."); + } + } + + public CodeTreeBuilder startCaseBlock() { + return startIndention(); + } + + public CodeTreeBuilder startThrow() { + return startStatement().string("throw "); + } + + public CodeTree getTree() { + assertRoot(); + return root; + } + + public CodeTree getRoot() { + return root; + } + + public CodeTreeBuilder cast(String baseClassName) { + string("(").string(baseClassName).string(") "); + return this; + } + + public CodeTreeBuilder cast(TypeMirror type, CodeTree content) { + if (ElementUtils.isVoid(type)) { + tree(content); + return this; + } else if (type.getKind() == TypeKind.DECLARED && ElementUtils.getQualifiedName(type).equals("java.lang.Object")) { + tree(content); + return this; + } else { + return startGroup().string("(").type(type).string(")").string(" ").tree(content).end(); + } + } + + public CodeTreeBuilder startSuperCall() { + return string("super").startParanthesesCommaGroup(); + } + + public CodeTreeBuilder returnFalse() { + return startReturn().string("false").end(); + } + + public CodeTreeBuilder returnStatement() { + return statement("return"); + } + + public ExecutableElement findMethod() { + if (enclosingElement != null && (enclosingElement.getKind() == ElementKind.METHOD || enclosingElement.getKind() == ElementKind.CONSTRUCTOR)) { + return (ExecutableElement) enclosingElement; + } + return null; + } + + public CodeTreeBuilder returnNull() { + return startReturn().string("null").end(); + } + + public CodeTreeBuilder returnTrue() { + return startReturn().string("true").end(); + } + + public CodeTreeBuilder instanceOf(CodeTree var, CodeTree type) { + tree(var).string(" instanceof ").tree(type); + return this; + } + + public CodeTreeBuilder instanceOf(String var, String type) { + return instanceOf(singleString(var), singleString(type)); + } + + public CodeTreeBuilder instanceOf(String var, TypeMirror type) { + TypeElement element = ElementUtils.fromTypeMirror(type); + if (element == null) { + throw new IllegalArgumentException("Cannot call instanceof for a non supported type: " + type.getKind()); + } + return instanceOf(singleString(var), singleType(type)); + } + + public CodeTreeBuilder defaultValue(TypeMirror mirror) { + switch (mirror.getKind()) { + case VOID: + return string(""); + case ARRAY: + case DECLARED: + case PACKAGE: + case NULL: + return string("null"); + case BOOLEAN: + return string("false"); + case BYTE: + return string("(byte) 0"); + case CHAR: + return string("(char) 0"); + case DOUBLE: + return string("0.0D"); + case LONG: + return string("0L"); + case INT: + return string("0"); + case FLOAT: + return string("0.0F"); + case SHORT: + return string("(short) 0"); + default: + throw new AssertionError(); + } + } + + public CodeTreeBuilder assertFalse() { + return startAssert().string("false").end(); + } + + public CodeTreeBuilder breakStatement() { + return statement("break"); + } + + public CodeTreeBuilder isNull() { + return string(" == null"); + } + + public CodeTreeBuilder isNotNull() { + return string(" != null"); + } + + public CodeTreeBuilder is(CodeTree tree) { + return string(" == ").tree(tree); + } + + public CodeTreeBuilder startTryBlock() { + return string("try ").startBlock(); + } + + public CodeTreeBuilder startCatchBlock(TypeMirror exceptionType, String localVarName) { + clearLast(CodeTreeKind.NEW_LINE); + string(" catch (").type(exceptionType).string(" ").string(localVarName).string(") "); + return startBlock(); + } + + public CodeTreeBuilder startFinallyBlock() { + clearLast(CodeTreeKind.NEW_LINE); + string(" finally "); + return startBlock(); + } + + public CodeTreeBuilder nullLiteral() { + return string("null"); + } + + private static class BuilderCodeTree extends CodeTree { + + private EndCallback atEndListener; + private CodeTreeKind removeLast; + + public BuilderCodeTree(CodeTree parent, CodeTreeKind kind, TypeMirror type, String string) { + super(parent, kind, type, string); + } + + public void registerAtEnd(EndCallback atEnd) { + if (this.atEndListener != null) { + this.atEndListener = new CompoundCallback(this.atEndListener, atEnd); + } else { + this.atEndListener = atEnd; + } + } + + public EndCallback getAtEndListener() { + return atEndListener; + } + + @Override + public String toString() { + final StringBuilder b = new StringBuilder(); + new Printer(b).visitTree(this, null, null); + return b.toString(); + } + + private static class CompoundCallback implements EndCallback { + + private final EndCallback callback1; + private final EndCallback callback2; + + public CompoundCallback(EndCallback callback1, EndCallback callback2) { + this.callback1 = callback1; + this.callback2 = callback2; + } + + @Override + public void afterEnd() { + callback1.afterEnd(); + callback2.afterEnd(); + } + + @Override + public void beforeEnd() { + callback1.beforeEnd(); + callback1.beforeEnd(); + } + } + + } + + private interface EndCallback { + + void beforeEnd(); + + void afterEnd(); + } + + private static class Printer extends CodeElementScanner { + + private int indent; + private boolean newLine; + private final String ln = "\n"; + + private final StringBuilder b; + + Printer(StringBuilder b) { + this.b = b; + } + + @Override + public void visitTree(CodeTree e, Void p, Element enclosingElement) { + switch (e.getCodeKind()) { + case COMMA_GROUP: + List children = e.getEnclosedElements(); + if (children != null) { + for (int i = 0; i < children.size(); i++) { + visitTree(children.get(i), p, enclosingElement); + if (i < e.getEnclosedElements().size() - 1) { + b.append(", "); + } + } + } + break; + case GROUP: + super.visitTree(e, p, enclosingElement); + break; + case INDENT: + indent(); + super.visitTree(e, p, enclosingElement); + dedent(); + break; + case NEW_LINE: + writeLn(); + break; + case STRING: + if (e.getString() != null) { + write(e.getString()); + } else { + write("null"); + } + break; + case TYPE: + write(ElementUtils.getSimpleName(e.getType())); + break; + default: + assert false; + return; + } + } + + private void indent() { + indent++; + } + + private void dedent() { + indent--; + } + + private void writeLn() { + write(ln); + newLine = true; + } + + private void write(String m) { + if (newLine && m != ln) { + writeIndent(); + newLine = false; + } + b.append(m); + } + + private void writeIndent() { + for (int i = 0; i < indent; i++) { + b.append(" "); + } + } + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeKind.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeKind.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.model; + +public enum CodeTreeKind { + STATIC_FIELD_REFERENCE, + STATIC_METHOD_REFERENCE, + GROUP, + COMMA_GROUP, + REMOVE_LAST, + INDENT, + STRING, + NEW_LINE, + TYPE; +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeElement.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.model; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror; + +public class CodeTypeElement extends CodeElement implements TypeElement { + + private final List imports = parentableList(this, new ArrayList()); + + private final PackageElement packageElement; + + private final Name simpleName; + private final Name packageName; + private Name qualifiedName; + + private final List implementsInterfaces = new ArrayList<>(); + private final ElementKind kind; + private TypeMirror superClass; + + private final DeclaredCodeTypeMirror mirror = new DeclaredCodeTypeMirror(this); + + public CodeTypeElement(Set modifiers, ElementKind kind, PackageElement packageElement, String simpleName) { + super(modifiers); + this.kind = kind; + this.packageElement = packageElement; + this.simpleName = CodeNames.of(simpleName); + if (this.packageElement != null) { + this.packageName = packageElement.getQualifiedName(); + } else { + this.packageName = CodeNames.of("default"); + } + this.qualifiedName = createQualifiedName(); + } + + @Override + public TypeMirror asType() { + return mirror; + } + + @Override + public ElementKind getKind() { + return kind; + } + + public boolean containsField(String name) { + for (VariableElement field : getFields()) { + if (field.getSimpleName().toString().equals(name)) { + return true; + } + } + return false; + } + + @Override + public NestingKind getNestingKind() { + return isTopLevelClass() ? NestingKind.TOP_LEVEL : NestingKind.LOCAL; + } + + @Override + public Element getEnclosingElement() { + if (isTopLevelClass()) { + return packageElement; + } else { + return super.getEnclosingElement(); + } + } + + @Override + public TypeMirror getSuperclass() { + return superClass; + } + + @Override + public List getInterfaces() { + return implementsInterfaces; + } + + @Override + public List getTypeParameters() { + return Collections.emptyList(); + } + + public boolean isTopLevelClass() { + return super.getEnclosingElement() instanceof CodeCompilationUnit; + } + + private Name createQualifiedName() { + TypeElement enclosingType = getEnclosingClass(); + if (enclosingType == null) { + return CodeNames.of(packageName + "." + simpleName); + } else { + return CodeNames.of(enclosingType.getQualifiedName() + "." + simpleName); + } + } + + @Override + public void setEnclosingElement(Element element) { + super.setEnclosingElement(element); + + // update qualified name on container change + this.qualifiedName = createQualifiedName(); + } + + public Name getPackageName() { + return packageName; + } + + @Override + public Name getQualifiedName() { + return qualifiedName; + } + + @Override + public Name getSimpleName() { + return simpleName; + } + + public void setSuperClass(TypeMirror superType) { + this.superClass = superType; + } + + public List getImports() { + return imports; + } + + public List getImplements() { + return implementsInterfaces; + } + + @Override + public int hashCode() { + return getQualifiedName().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (obj instanceof TypeElement) { + return getQualifiedName().equals(((TypeElement) obj).getQualifiedName()); + } + return false; + } + + public List getFields() { + return ElementFilter.fieldsIn(getEnclosedElements()); + } + + public ExecutableElement getMethod(String name) { + for (Element element : getEnclosedElements()) { + if (element.getKind() == ElementKind.METHOD && element.getSimpleName().toString().equals(name)) { + return (ExecutableElement) element; + } + } + return null; + } + + public List getMethods() { + return ElementFilter.methodsIn(getEnclosedElements()); + } + + public List getInnerClasses() { + return ElementFilter.typesIn(getEnclosedElements()); + } + + @Override + public String toString() { + return getQualifiedName().toString(); + } + + @Override + public R accept(ElementVisitor v, P p) { + return v.visitType(this, p); + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeMirror.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeMirror.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.model; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public class CodeTypeMirror implements TypeMirror { + + private final TypeKind kind; + + public CodeTypeMirror(TypeKind kind) { + this.kind = kind; + } + + @Override + public TypeKind getKind() { + return kind; + } + + @Override + public R accept(TypeVisitor v, P p) { + throw new UnsupportedOperationException(); + } + + public static class WildcardTypeMirror extends CodeTypeMirror implements WildcardType { + + private final TypeMirror extendsBounds; + private final TypeMirror superBounds; + + public WildcardTypeMirror(TypeMirror extendsBounds, TypeMirror superBounds) { + super(TypeKind.WILDCARD); + this.extendsBounds = extendsBounds; + this.superBounds = superBounds; + } + + public TypeMirror getExtendsBound() { + return extendsBounds; + } + + public TypeMirror getSuperBound() { + return superBounds; + } + + } + + public static class ArrayCodeTypeMirror extends CodeTypeMirror implements ArrayType { + + private final TypeMirror component; + + public ArrayCodeTypeMirror(TypeMirror component) { + super(TypeKind.ARRAY); + this.component = component; + } + + @Override + public TypeMirror getComponentType() { + return component; + } + + } + + public static class DeclaredCodeTypeMirror extends CodeTypeMirror implements DeclaredType { + + private final TypeElement clazz; + private final List typeArguments; + + public DeclaredCodeTypeMirror(TypeElement clazz) { + this(clazz, Collections. emptyList()); + } + + public DeclaredCodeTypeMirror(TypeElement clazz, List typeArguments) { + super(TypeKind.DECLARED); + this.clazz = clazz; + this.typeArguments = typeArguments; + } + + @Override + public Element asElement() { + return clazz; + } + + @Override + public TypeMirror getEnclosingType() { + return clazz.getEnclosingElement().asType(); + } + + @Override + public List getTypeArguments() { + return typeArguments; + } + + @Override + public String toString() { + return clazz.getQualifiedName().toString(); + } + + } + + public List getAnnotationMirrors() { + throw new UnsupportedOperationException(); + } + + /** + * @param annotationType + */ + public A getAnnotation(Class annotationType) { + throw new UnsupportedOperationException(); + } + + /** + * @param annotationType + */ + public A[] getAnnotationsByType(Class annotationType) { + throw new UnsupportedOperationException(); + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeVariableElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeVariableElement.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.model; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.java.*; + +public final class CodeVariableElement extends CodeElement implements VariableElement { + + private Name name; + private TypeMirror type; + private Object constantValue; + + private CodeTree init; + + public CodeVariableElement(TypeMirror type, String name) { + super(ElementUtils.modifiers()); + this.type = type; + this.name = CodeNames.of(name); + } + + public CodeVariableElement(Set modifiers, TypeMirror type, String name) { + super(modifiers); + this.type = type; + this.name = CodeNames.of(name); + } + + public CodeVariableElement(Set modifiers, TypeMirror type, String name, String init) { + this(modifiers, type, name); + if (init != null) { + this.init = new CodeTree(null, CodeTreeKind.STRING, null, init); + } + } + + public CodeTreeBuilder createInitBuilder() { + CodeTreeBuilder builder = new CodeTreeBuilder(null); + builder.setEnclosingElement(this); + init = builder.getTree(); + return builder; + } + + public void setInit(CodeTree init) { + this.init = init; + } + + public CodeTree getInit() { + return init; + } + + public Name getSimpleName() { + return name; + } + + public TypeMirror getType() { + return type; + } + + @Override + public TypeMirror asType() { + return type; + } + + @Override + public ElementKind getKind() { + if (getEnclosingElement() instanceof ExecutableElement) { + return ElementKind.PARAMETER; + } else if (getEnclosingElement() instanceof TypeElement) { + return ElementKind.FIELD; + } else { + return ElementKind.PARAMETER; + } + } + + public void setConstantValue(Object constantValue) { + this.constantValue = constantValue; + } + + @Override + public Object getConstantValue() { + return constantValue; + } + + public String getName() { + return getSimpleName().toString(); + } + + public void setSimpleName(Name name) { + this.name = name; + } + + public void setName(String name) { + this.name = CodeNames.of(name); + } + + public void setType(TypeMirror type) { + this.type = type; + } + + @Override + public R accept(ElementVisitor v, P p) { + return v.visitVariable(this, p); + } + + public static CodeVariableElement clone(VariableElement var) { + CodeVariableElement copy = new CodeVariableElement(var.getModifiers(), var.asType(), var.getSimpleName().toString()); + copy.setConstantValue(var.getConstantValue()); + for (AnnotationMirror mirror : var.getAnnotationMirrors()) { + copy.addAnnotationMirror(mirror); + } + for (Element element : var.getEnclosedElements()) { + copy.add(element); + } + return copy; + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedElement.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.model; + +import javax.lang.model.element.*; + +public interface GeneratedElement { + + AnnotationMirror getGeneratorAnnotationMirror(); + + void setGeneratorAnnotationMirror(AnnotationMirror mirror); + + Element getGeneratorElement(); + + void setGeneratorElement(Element element); + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedPackageElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedPackageElement.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.model; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public final class GeneratedPackageElement extends CodeElement implements PackageElement { + + private final Name qualifiedName; + private final Name simpleName; + + public GeneratedPackageElement(String qualifiedName) { + super(Collections. emptySet()); + this.qualifiedName = CodeNames.of(qualifiedName); + int lastIndex = qualifiedName.lastIndexOf('.'); + if (lastIndex == -1) { + simpleName = CodeNames.of(""); + } else { + simpleName = CodeNames.of(qualifiedName.substring(lastIndex, qualifiedName.length())); + } + } + + public TypeMirror asType() { + throw new UnsupportedOperationException(); + } + + public ElementKind getKind() { + return ElementKind.PACKAGE; + } + + public R accept(ElementVisitor v, P p) { + return v.visitPackage(this, p); + } + + public Name getQualifiedName() { + return qualifiedName; + } + + public Name getSimpleName() { + return simpleName; + } + + public boolean isUnnamed() { + return simpleName.toString().equals(""); + } + + @Override + public int hashCode() { + return qualifiedName.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof PackageElement) { + return qualifiedName.equals(((PackageElement) obj).getQualifiedName()); + } + return super.equals(obj); + } +} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedTypeElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedTypeElement.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.model; + +import java.util.*; + +import javax.lang.model.element.*; + +public final class GeneratedTypeElement extends CodeTypeElement { + + public GeneratedTypeElement(Set modifiers, ElementKind kind, PackageElement packageElement, String simpleName) { + super(modifiers, kind, packageElement, simpleName); + setEnclosingElement(packageElement); + } + +} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedTypeMirror.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedTypeMirror.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.model; + +import java.util.*; + +import javax.lang.model.element.*; + +import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror; + +public final class GeneratedTypeMirror extends DeclaredCodeTypeMirror { + + public GeneratedTypeMirror(String packageName, String name) { + super(new GeneratedTypeElement(Collections. emptySet(), ElementKind.CLASS, new GeneratedPackageElement(packageName), name)); + } + +} \ No newline at end of file diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/AbstractCodeWriter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/AbstractCodeWriter.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,760 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.transform; + +import static com.oracle.truffle.dsl.processor.java.ElementUtils.*; + +import java.io.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.java.model.*; + +public abstract class AbstractCodeWriter extends CodeElementScanner { + + private static final int MAX_LINE_LENGTH = 200; + private static final int LINE_WRAP_INDENTS = 3; + private static final String IDENT_STRING = " "; + private static final String LN = "\n"; /* unix style */ + + protected Writer writer; + private int indent; + private boolean newLine; + private int lineLength; + private boolean lineWrapping = false; + + private OrganizedImports imports; + + protected abstract Writer createWriter(CodeTypeElement clazz) throws IOException; + + @Override + public Void visitType(CodeTypeElement e, Void p) { + if (e.isTopLevelClass()) { + Writer w = null; + try { + imports = OrganizedImports.organize(e); + w = new TrimTrailingSpaceWriter(createWriter(e)); + writer = w; + writeRootClass(e); + } catch (IOException ex) { + throw new RuntimeException(ex); + } finally { + if (w != null) { + try { + w.close(); + } catch (Throwable e1) { + // see eclipse bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=361378 + // TODO temporary suppress errors on close. + } + } + writer = null; + } + } else { + writeClassImpl(e); + } + return null; + } + + private void writeRootClass(CodeTypeElement e) { + writeHeader(); + write("package ").write(e.getPackageName()).write(";").writeLn(); + writeEmptyLn(); + + Set generateImports = imports.generateImports(); + List typeImports = new ArrayList<>(); + List staticImports = new ArrayList<>(); + + for (CodeImport codeImport : generateImports) { + if (codeImport.isStaticImport()) { + staticImports.add(codeImport); + } else { + typeImports.add(codeImport); + } + } + Collections.sort(typeImports); + Collections.sort(staticImports); + + for (CodeImport imp : staticImports) { + imp.accept(this, null); + writeLn(); + } + if (!staticImports.isEmpty()) { + writeEmptyLn(); + } + + for (CodeImport imp : typeImports) { + imp.accept(this, null); + writeLn(); + } + if (!typeImports.isEmpty()) { + writeEmptyLn(); + } + + writeClassImpl(e); + } + + private String useImport(Element enclosedType, TypeMirror type) { + if (imports != null) { + return imports.createTypeReference(enclosedType, type); + } else { + return ElementUtils.getSimpleName(type); + } + } + + private void writeClassImpl(CodeTypeElement e) { + for (AnnotationMirror annotation : e.getAnnotationMirrors()) { + visitAnnotation(e, annotation); + writeLn(); + } + + writeModifiers(e.getModifiers()); + if (e.getKind() == ElementKind.ENUM) { + write("enum "); + } else { + write("class "); + } + write(e.getSimpleName()); + if (e.getSuperclass() != null && !getQualifiedName(e.getSuperclass()).equals("java.lang.Object")) { + write(" extends ").write(useImport(e, e.getSuperclass())); + } + if (e.getImplements().size() > 0) { + write(" implements "); + for (int i = 0; i < e.getImplements().size(); i++) { + write(useImport(e, e.getImplements().get(i))); + if (i < e.getImplements().size() - 1) { + write(", "); + } + } + } + + write(" {").writeLn(); + writeEmptyLn(); + indent(1); + + List staticFields = getStaticFields(e); + List instanceFields = getInstanceFields(e); + + for (int i = 0; i < staticFields.size(); i++) { + VariableElement field = staticFields.get(i); + field.accept(this, null); + if (e.getKind() == ElementKind.ENUM && i < staticFields.size() - 1) { + write(","); + writeLn(); + } else { + write(";"); + writeLn(); + } + } + + if (staticFields.size() > 0) { + writeEmptyLn(); + } + + for (VariableElement field : instanceFields) { + field.accept(this, null); + write(";"); + writeLn(); + } + if (instanceFields.size() > 0) { + writeEmptyLn(); + } + + for (ExecutableElement method : ElementFilter.constructorsIn(e.getEnclosedElements())) { + method.accept(this, null); + } + + for (ExecutableElement method : getInstanceMethods(e)) { + method.accept(this, null); + } + + for (ExecutableElement method : getStaticMethods(e)) { + method.accept(this, null); + } + + for (TypeElement clazz : e.getInnerClasses()) { + clazz.accept(this, null); + } + + dedent(1); + write("}"); + writeEmptyLn(); + } + + private static List getStaticFields(CodeTypeElement clazz) { + List staticFields = new ArrayList<>(); + for (VariableElement field : clazz.getFields()) { + if (field.getModifiers().contains(Modifier.STATIC)) { + staticFields.add(field); + } + } + return staticFields; + } + + private static List getInstanceFields(CodeTypeElement clazz) { + List instanceFields = new ArrayList<>(); + for (VariableElement field : clazz.getFields()) { + if (!field.getModifiers().contains(Modifier.STATIC)) { + instanceFields.add(field); + } + } + return instanceFields; + } + + private static List getStaticMethods(CodeTypeElement clazz) { + List staticMethods = new ArrayList<>(); + for (ExecutableElement method : clazz.getMethods()) { + if (method.getModifiers().contains(Modifier.STATIC)) { + staticMethods.add(method); + } + } + return staticMethods; + } + + private static List getInstanceMethods(CodeTypeElement clazz) { + List instanceMethods = new ArrayList<>(); + for (ExecutableElement method : clazz.getMethods()) { + if (!method.getModifiers().contains(Modifier.STATIC)) { + instanceMethods.add(method); + } + } + return instanceMethods; + } + + @Override + public Void visitVariable(VariableElement f, Void p) { + Element parent = f.getEnclosingElement(); + + for (AnnotationMirror annotation : f.getAnnotationMirrors()) { + visitAnnotation(f, annotation); + write(" "); + } + + CodeTree init = null; + if (f instanceof CodeVariableElement) { + init = ((CodeVariableElement) f).getInit(); + } + + if (parent.getKind() == ElementKind.ENUM && f.getModifiers().contains(Modifier.STATIC)) { + write(f.getSimpleName()); + if (init != null) { + write("("); + visitTree(init, p, f); + write(")"); + } + } else { + Element enclosing = f.getEnclosingElement(); + writeModifiers(f.getModifiers()); + + boolean varArgs = false; + if (enclosing.getKind() == ElementKind.METHOD) { + ExecutableElement method = (ExecutableElement) enclosing; + if (method.isVarArgs() && method.getParameters().indexOf(f) == method.getParameters().size() - 1) { + varArgs = true; + } + } + + TypeMirror varType = f.asType(); + if (varArgs) { + if (varType.getKind() == TypeKind.ARRAY) { + varType = ((ArrayType) varType).getComponentType(); + } + write(useImport(f, varType)); + write("..."); + } else { + write(useImport(f, varType)); + } + + write(" "); + write(f.getSimpleName()); + if (init != null) { + write(" = "); + visitTree(init, p, f); + } + } + return null; + } + + private void visitAnnotation(Element enclosedElement, AnnotationMirror e) { + write("@").write(useImport(enclosedElement, e.getAnnotationType())); + + if (!e.getElementValues().isEmpty()) { + write("("); + final ExecutableElement defaultElement = findExecutableElement(e.getAnnotationType(), "value"); + + Map values = e.getElementValues(); + if (defaultElement != null && values.size() == 1 && values.get(defaultElement) != null) { + visitAnnotationValue(enclosedElement, values.get(defaultElement)); + } else { + Set methodsSet = values.keySet(); + List methodsList = new ArrayList<>(); + for (ExecutableElement method : methodsSet) { + if (values.get(method) == null) { + continue; + } + methodsList.add(method); + } + + Collections.sort(methodsList, new Comparator() { + + @Override + public int compare(ExecutableElement o1, ExecutableElement o2) { + return o1.getSimpleName().toString().compareTo(o2.getSimpleName().toString()); + } + }); + + for (int i = 0; i < methodsList.size(); i++) { + ExecutableElement method = methodsList.get(i); + AnnotationValue value = values.get(method); + write(method.getSimpleName().toString()); + write(" = "); + visitAnnotationValue(enclosedElement, value); + + if (i < methodsList.size() - 1) { + write(", "); + } + } + } + + write(")"); + } + } + + private void visitAnnotationValue(Element enclosedElement, AnnotationValue e) { + e.accept(new AnnotationValueWriterVisitor(enclosedElement), null); + } + + private class AnnotationValueWriterVisitor extends AbstractAnnotationValueVisitor7 { + + private final Element enclosedElement; + + public AnnotationValueWriterVisitor(Element enclosedElement) { + this.enclosedElement = enclosedElement; + } + + @Override + public Void visitBoolean(boolean b, Void p) { + write(Boolean.toString(b)); + return null; + } + + @Override + public Void visitByte(byte b, Void p) { + write(Byte.toString(b)); + return null; + } + + @Override + public Void visitChar(char c, Void p) { + write(Character.toString(c)); + return null; + } + + @Override + public Void visitDouble(double d, Void p) { + write(Double.toString(d)); + return null; + } + + @Override + public Void visitFloat(float f, Void p) { + write(Float.toString(f)); + return null; + } + + @Override + public Void visitInt(int i, Void p) { + write(Integer.toString(i)); + return null; + } + + @Override + public Void visitLong(long i, Void p) { + write(Long.toString(i)); + return null; + } + + @Override + public Void visitShort(short s, Void p) { + write(Short.toString(s)); + return null; + } + + @Override + public Void visitString(String s, Void p) { + write("\""); + write(s); + write("\""); + return null; + } + + @Override + public Void visitType(TypeMirror t, Void p) { + write(useImport(enclosedElement, t)); + write(".class"); + return null; + } + + @Override + public Void visitEnumConstant(VariableElement c, Void p) { + write(useImport(enclosedElement, c.asType())); + write("."); + write(c.getSimpleName().toString()); + return null; + } + + @Override + public Void visitAnnotation(AnnotationMirror a, Void p) { + AbstractCodeWriter.this.visitAnnotation(enclosedElement, a); + return null; + } + + @Override + public Void visitArray(List vals, Void p) { + write("{"); + for (int i = 0; i < vals.size(); i++) { + AnnotationValue value = vals.get(i); + AbstractCodeWriter.this.visitAnnotationValue(enclosedElement, value); + if (i < vals.size() - 1) { + write(", "); + } + } + write("}"); + return null; + } + } + + private static ExecutableElement findExecutableElement(DeclaredType type, String name) { + List elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements()); + for (ExecutableElement executableElement : elements) { + if (executableElement.getSimpleName().toString().equals(name)) { + return executableElement; + } + } + return null; + } + + @Override + public void visitImport(CodeImport e, Void p) { + write("import "); + if (e.isStaticImport()) { + write("static "); + } + write(e.getPackageName()); + write("."); + write(e.getSymbolName()); + write(";"); + } + + @Override + public Void visitExecutable(CodeExecutableElement e, Void p) { + for (AnnotationMirror annotation : e.getAnnotationMirrors()) { + visitAnnotation(e, annotation); + writeLn(); + } + + writeModifiers(e.getModifiers()); + + if (e.getReturnType() != null) { + write(useImport(e, e.getReturnType())); + write(" "); + } + write(e.getSimpleName()); + write("("); + + for (int i = 0; i < e.getParameters().size(); i++) { + VariableElement param = e.getParameters().get(i); + param.accept(this, p); + if (i < e.getParameters().size() - 1) { + write(", "); + } + } + write(")"); + + List throwables = e.getThrownTypes(); + if (throwables.size() > 0) { + write(" throws "); + for (int i = 0; i < throwables.size(); i++) { + write(useImport(e, throwables.get(i))); + if (i < throwables.size() - 1) { + write(", "); + } + } + } + + if (e.getModifiers().contains(Modifier.ABSTRACT)) { + writeLn(";"); + } else if (e.getBodyTree() != null) { + writeLn(" {"); + indent(1); + visitTree(e.getBodyTree(), p, e); + dedent(1); + writeLn("}"); + } else if (e.getBody() != null) { + write(" {"); + write(e.getBody()); + writeLn("}"); + } else { + writeLn("{ }"); + } + writeEmptyLn(); + return null; + } + + @Override + public void visitTree(CodeTree e, Void p, Element enclosingElement) { + CodeTreeKind kind = e.getCodeKind(); + + switch (kind) { + case COMMA_GROUP: + List children = e.getEnclosedElements(); + if (children != null) { + for (int i = 0; i < children.size(); i++) { + visitTree(children.get(i), p, enclosingElement); + if (i < e.getEnclosedElements().size() - 1) { + write(", "); + } + } + } + break; + case GROUP: + super.visitTree(e, p, enclosingElement); + break; + case INDENT: + indent(1); + super.visitTree(e, p, enclosingElement); + dedent(1); + break; + case NEW_LINE: + writeLn(); + break; + case STRING: + if (e.getString() != null) { + write(e.getString()); + } else { + write("null"); + } + break; + case STATIC_FIELD_REFERENCE: + if (e.getString() != null) { + write(imports.createStaticFieldReference(enclosingElement, e.getType(), e.getString())); + } else { + write("null"); + } + break; + case STATIC_METHOD_REFERENCE: + if (e.getString() != null) { + write(imports.createStaticMethodReference(enclosingElement, e.getType(), e.getString())); + } else { + write("null"); + } + break; + case TYPE: + write(useImport(enclosingElement, e.getType())); + break; + default: + assert false; + return; + } + } + + protected void writeHeader() { + // default implementation does nothing + } + + private void writeModifiers(Set modifiers) { + if (modifiers != null) { + for (Modifier modifier : modifiers) { + write(modifier.toString()); + write(" "); + } + } + } + + private void indent(int count) { + indent += count; + } + + private void dedent(int count) { + indent -= count; + } + + private void writeLn() { + writeLn(""); + } + + protected void writeLn(String text) { + write(text); + write(LN); + lineLength = 0; + newLine = true; + if (lineWrapping) { + dedent(LINE_WRAP_INDENTS); + lineWrapping = false; + } + lineWrapping = false; + } + + private void writeEmptyLn() { + writeLn(); + } + + private AbstractCodeWriter write(Name name) { + return write(name.toString()); + } + + private AbstractCodeWriter write(String m) { + if (m.isEmpty()) { + return this; + } + try { + String s = m; + lineLength += s.length(); + if (newLine && s != LN) { + writeIndent(); + newLine = false; + } + if (lineLength > MAX_LINE_LENGTH) { + s = wrapLine(s); + } + writer.write(s); + } catch (IOException e) { + throw new RuntimeException(e); + } + return this; + } + + private String wrapLine(String m) throws IOException { + assert !m.isEmpty(); + + char firstCharacter = m.charAt(0); + char lastCharacter = m.charAt(m.length() - 1); + if (firstCharacter == '\"' && lastCharacter == '\"') { + // string line wrapping + String string = m.substring(1, m.length() - 1); + if (string.isEmpty()) { + return m; + } + + // restore original line length + lineLength = lineLength - m.length(); + int size = 0; + for (int i = 0; i < string.length(); i += size) { + if (i != 0) { + write("+ "); + } + + int nextSize = MAX_LINE_LENGTH - lineLength - 2; + if (nextSize <= 0) { + writeLn(); + nextSize = MAX_LINE_LENGTH - lineLength - 2; + } + + int end = Math.min(i + nextSize, string.length()); + + // TODO(CH): fails in normal usage - output ok though + // assert lineLength + (end - i) + 2 < MAX_LINE_LENGTH; + write("\""); + write(string.substring(i, end)); + write("\""); + size = nextSize; + } + + return ""; + } else if (!Character.isAlphabetic(firstCharacter) && firstCharacter != '+') { + return m; + } + + if (!lineWrapping) { + indent(LINE_WRAP_INDENTS); + } + lineWrapping = true; + lineLength = 0; + write(LN); + writeIndent(); + return m; + } + + private void writeIndent() throws IOException { + lineLength += indentSize(); + for (int i = 0; i < indent; i++) { + writer.write(IDENT_STRING); + } + } + + private int indentSize() { + return IDENT_STRING.length() * indent; + } + + private static class TrimTrailingSpaceWriter extends Writer { + + private final Writer delegate; + private final StringBuilder buffer = new StringBuilder(); + + public TrimTrailingSpaceWriter(Writer delegate) { + this.delegate = delegate; + } + + @Override + public void close() throws IOException { + this.delegate.close(); + } + + @Override + public void flush() throws IOException { + this.delegate.flush(); + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + buffer.append(cbuf, off, len); + int newLinePoint = buffer.indexOf(LN); + + if (newLinePoint != -1) { + String lhs = trimTrailing(buffer.substring(0, newLinePoint)); + delegate.write(lhs); + delegate.write(LN); + buffer.delete(0, newLinePoint + 1); + } + } + + private static String trimTrailing(String s) { + int cut = 0; + for (int i = s.length() - 1; i >= 0; i--) { + if (Character.isWhitespace(s.charAt(i))) { + cut++; + } else { + break; + } + } + if (cut > 0) { + return s.substring(0, s.length() - cut); + } + return s; + } + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/FixWarningsVisitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/FixWarningsVisitor.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.transform; + +import static com.oracle.truffle.dsl.processor.java.ElementUtils.*; +import static javax.lang.model.element.Modifier.*; + +import java.io.*; +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.java.model.*; + +public class FixWarningsVisitor extends CodeElementScanner { + + private final Set symbolsUsed = new HashSet<>(); + + private final ProcessingEnvironment processingEnv; + private final DeclaredType unusedAnnotation; + private final DeclaredType overrideType; + + public FixWarningsVisitor(ProcessingEnvironment processingEnv, DeclaredType unusedAnnotation, DeclaredType overrideType) { + this.processingEnv = processingEnv; + this.unusedAnnotation = unusedAnnotation; + this.overrideType = overrideType; + } + + @Override + public Void visitType(CodeTypeElement e, Void p) { + List superTypes = ElementUtils.getSuperTypes(e); + for (TypeElement type : superTypes) { + String qualifiedName = ElementUtils.getQualifiedName(type); + if (qualifiedName.equals(Serializable.class.getCanonicalName())) { + if (!e.containsField("serialVersionUID")) { + e.add(new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), ElementUtils.getType(processingEnv, long.class), "serialVersionUID", "1L")); + } + break; + } + } + + return super.visitType(e, p); + } + + @Override + public Void visitExecutable(CodeExecutableElement e, Void p) { + if (e.getParameters().isEmpty()) { + return null; + } else if (e.getModifiers().contains(Modifier.ABSTRACT)) { + return null; + } else if (containsOverride(e)) { + return null; + } + + symbolsUsed.clear(); + super.visitExecutable(e, p); + + for (VariableElement parameter : e.getParameters()) { + if (!symbolsUsed.contains(parameter.getSimpleName().toString())) { + e.getAnnotationMirrors().add(createUnusedAnnotationMirror()); + break; + } + } + return null; + } + + private boolean containsOverride(CodeExecutableElement e) { + for (AnnotationMirror mirror : e.getAnnotationMirrors()) { + if (ElementUtils.typeEquals(overrideType, mirror.getAnnotationType())) { + return true; + } + } + return false; + } + + private CodeAnnotationMirror createUnusedAnnotationMirror() { + CodeAnnotationMirror mirror = new CodeAnnotationMirror(unusedAnnotation); + mirror.setElementValue(mirror.findExecutableElement("value"), new CodeAnnotationValue("unused")); + return mirror; + } + + @Override + public void visitTree(CodeTree e, Void p, Element enclosingElement) { + if (e.getString() != null) { + computeSymbols(e.getString()); + } + super.visitTree(e, p, enclosingElement); + } + + private void computeSymbols(String s) { + // TODO there should not be any need for a StringTokenizer if we have a real AST for + // method bodies. Also the current solution is not perfect. What if one token + // is spread across multiple CodeTree instances? But for now that works. + StringTokenizer tokenizer = new StringTokenizer(s, ".= :,()[];{}\"\"'' ", false); + while (tokenizer.hasMoreElements()) { + String token = tokenizer.nextToken().trim(); + if (token.length() > 0) { + symbolsUsed.add(token); + } + } + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/GenerateOverrideVisitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/GenerateOverrideVisitor.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.transform; + +import static com.oracle.truffle.dsl.processor.java.ElementUtils.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.java.model.*; + +public class GenerateOverrideVisitor extends CodeElementScanner { + + private final DeclaredType overrideType; + + public GenerateOverrideVisitor(DeclaredType overrideType) { + this.overrideType = overrideType; + } + + @Override + public Void visitExecutable(CodeExecutableElement e, Void p) { + if (!e.getModifiers().contains(Modifier.STATIC) && !e.getModifiers().contains(Modifier.PRIVATE)) { + String name = e.getSimpleName().toString(); + TypeMirror[] params = e.getParameterTypes(); + + for (AnnotationMirror mirror : e.getAnnotationMirrors()) { + if (ElementUtils.typeEquals(overrideType, mirror.getAnnotationType())) { + // already declared (may happen if method copied from super class) + return super.visitExecutable(e, p); + } + } + + if (isDeclaredMethodInSuperType(e.getEnclosingClass(), name, params)) { + e.addAnnotationMirror(new CodeAnnotationMirror(overrideType)); + } + } + return super.visitExecutable(e, p); + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/OrganizedImports.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/OrganizedImports.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,484 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.java.transform; + +import static com.oracle.truffle.dsl.processor.java.ElementUtils.*; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.java.model.*; + +public final class OrganizedImports { + + private final Map classImportUsage = new HashMap<>(); + private final Map staticImportUsage = new HashMap<>(); + private final Map> autoImportCache = new HashMap<>(); + + private final CodeTypeElement topLevelClass; + + private OrganizedImports(CodeTypeElement topLevelClass) { + this.topLevelClass = topLevelClass; + } + + public static OrganizedImports organize(CodeTypeElement topLevelClass) { + OrganizedImports organized = new OrganizedImports(topLevelClass); + organized.organizeImpl(); + return organized; + } + + private void organizeImpl() { + ImportTypeReferenceVisitor reference = new ImportTypeReferenceVisitor(); + topLevelClass.accept(reference, null); + + } + + public String createTypeReference(Element enclosedElement, TypeMirror type) { + switch (type.getKind()) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case SHORT: + case INT: + case LONG: + case VOID: + return ElementUtils.getSimpleName(type); + case DECLARED: + return createDeclaredTypeName(enclosedElement, (DeclaredType) type); + case ARRAY: + return createTypeReference(enclosedElement, ((ArrayType) type).getComponentType()) + "[]"; + case WILDCARD: + return createWildcardName(enclosedElement, (WildcardType) type); + case TYPEVAR: + return "?"; + default: + throw new RuntimeException("Unknown type specified " + type.getKind() + " mirror: " + type); + } + } + + public String createStaticFieldReference(Element enclosedElement, TypeMirror type, String fieldName) { + return createStaticReference(enclosedElement, type, fieldName); + } + + public String createStaticMethodReference(Element enclosedElement, TypeMirror type, String methodName) { + return createStaticReference(enclosedElement, type, methodName); + } + + private String createStaticReference(Element enclosedElement, TypeMirror type, String name) { + String qualifiedName = staticImportUsage.get(name); + if (qualifiedName == null) { + // ambiguous import + return createTypeReference(enclosedElement, type) + "." + name; + } else { + // import declared and not ambiguous + return name; + } + } + + private String createWildcardName(Element enclosedElement, WildcardType type) { + StringBuilder b = new StringBuilder(); + if (type.getExtendsBound() != null) { + b.append("? extends ").append(createTypeReference(enclosedElement, type.getExtendsBound())); + } else if (type.getSuperBound() != null) { + b.append("? super ").append(createTypeReference(enclosedElement, type.getExtendsBound())); + } else { + b.append("?"); + } + return b.toString(); + } + + private String createDeclaredTypeName(Element enclosedElement, DeclaredType type) { + String name = ElementUtils.fixECJBinaryNameIssue(type.asElement().getSimpleName().toString()); + if (classImportUsage.containsKey(name)) { + String qualifiedImport = classImportUsage.get(name); + String qualifiedName = ElementUtils.getEnclosedQualifiedName(type); + + if (!qualifiedName.equals(qualifiedImport)) { + name = qualifiedName; + } + } + + List genericTypes = type.getTypeArguments(); + if (genericTypes.size() == 0) { + return name; + } + + StringBuilder b = new StringBuilder(name); + b.append("<"); + for (int i = 0; i < genericTypes.size(); i++) { + TypeMirror genericType = i < genericTypes.size() ? genericTypes.get(i) : null; + if (genericType != null) { + b.append(createTypeReference(enclosedElement, genericType)); + } else { + b.append("?"); + } + + if (i < genericTypes.size() - 1) { + b.append(", "); + } + } + b.append(">"); + return b.toString(); + } + + public Set generateImports() { + Set imports = new HashSet<>(); + + imports.addAll(generateImports(classImportUsage)); + imports.addAll(generateStaticImports(staticImportUsage)); + + return imports; + } + + private boolean needsImport(Element enclosed, TypeMirror importType) { + String importPackagName = getPackageName(importType); + TypeElement enclosedElement = findNearestEnclosingType(enclosed); + if (importPackagName == null) { + return false; + } else if (importPackagName.equals("java.lang")) { + return false; + } else if (importPackagName.equals(getPackageName(topLevelClass)) && ElementUtils.isTopLevelClass(importType)) { + return false; // same package name -> no import + } + + String enclosedElementId = ElementUtils.getUniqueIdentifier(enclosedElement.asType()); + Set autoImportedTypes = autoImportCache.get(enclosedElementId); + if (autoImportedTypes == null) { + List elements = ElementUtils.getElementHierarchy(enclosedElement); + autoImportedTypes = new HashSet<>(); + for (Element element : elements) { + if (element.getKind().isClass()) { + collectSuperTypeImports((TypeElement) element, autoImportedTypes); + collectInnerTypeImports((TypeElement) element, autoImportedTypes); + } + } + autoImportCache.put(enclosedElementId, autoImportedTypes); + } + + String qualifiedName = getQualifiedName(importType); + if (autoImportedTypes.contains(qualifiedName)) { + return false; + } + + return true; + } + + private static Set generateImports(Map symbols) { + TreeSet importObjects = new TreeSet<>(); + for (String symbol : symbols.keySet()) { + String packageName = symbols.get(symbol); + if (packageName != null) { + importObjects.add(new CodeImport(packageName, symbol, false)); + } + } + return importObjects; + } + + private static void collectInnerTypeImports(TypeElement e, Set autoImportedTypes) { + autoImportedTypes.add(getQualifiedName(e)); + for (TypeElement innerClass : ElementFilter.typesIn(e.getEnclosedElements())) { + collectInnerTypeImports(innerClass, autoImportedTypes); + } + } + + private static void collectSuperTypeImports(TypeElement e, Set autoImportedTypes) { + List superTypes = getSuperTypes(e); + for (TypeElement superType : superTypes) { + List declaredTypes = getDeclaredTypes(superType); + for (TypeElement declaredType : declaredTypes) { + autoImportedTypes.add(getQualifiedName(declaredType)); + } + } + } + + private Set generateStaticImports(Map toGenerate) { + Set autoImportedStaticTypes = new HashSet<>(); + + // if type is declared inside a super type of this class -> no import + autoImportedStaticTypes.add(getQualifiedName(topLevelClass)); + autoImportedStaticTypes.addAll(getQualifiedSuperTypeNames(topLevelClass)); + + TreeSet importObjects = new TreeSet<>(); + for (String symbol : toGenerate.keySet()) { + String qualifiedName = toGenerate.get(symbol); + if (qualifiedName == null) { + // ambiguous + continue; + } + // not not import + if (autoImportedStaticTypes.contains(qualifiedName)) { + continue; + } + + importObjects.add(new CodeImport(qualifiedName, symbol, true)); + } + + return importObjects; + } + + private abstract static class TypeReferenceVisitor extends CodeElementScanner { + + @Override + public void visitTree(CodeTree e, Void p, Element enclosing) { + if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) { + visitStaticFieldReference(enclosing, e.getType(), e.getString()); + } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) { + visitStaticMethodReference(enclosing, e.getType(), e.getString()); + } else if (e.getType() != null) { + visitTypeReference(enclosing, e.getType()); + } + super.visitTree(e, p, enclosing); + } + + @Override + public Void visitExecutable(CodeExecutableElement e, Void p) { + visitAnnotations(e, e.getAnnotationMirrors()); + if (e.getReturnType() != null) { + visitTypeReference(e, e.getReturnType()); + } + for (TypeMirror type : e.getThrownTypes()) { + visitTypeReference(e, type); + } + return super.visitExecutable(e, p); + } + + @Override + public Void visitType(CodeTypeElement e, Void p) { + visitAnnotations(e, e.getAnnotationMirrors()); + + visitTypeReference(e, e.getSuperclass()); + for (TypeMirror type : e.getImplements()) { + visitTypeReference(e, type); + } + + return super.visitType(e, p); + } + + private void visitAnnotations(Element enclosingElement, List mirrors) { + for (AnnotationMirror mirror : mirrors) { + visitAnnotation(enclosingElement, mirror); + } + } + + public void visitAnnotation(Element enclosingElement, AnnotationMirror e) { + visitTypeReference(enclosingElement, e.getAnnotationType()); + if (!e.getElementValues().isEmpty()) { + Map values = e.getElementValues(); + Set methodsSet = values.keySet(); + List methodsList = new ArrayList<>(); + for (ExecutableElement method : methodsSet) { + if (values.get(method) == null) { + continue; + } + methodsList.add(method); + } + + for (int i = 0; i < methodsList.size(); i++) { + AnnotationValue value = values.get(methodsList.get(i)); + visitAnnotationValue(enclosingElement, value); + } + } + } + + public void visitAnnotationValue(Element enclosingElement, AnnotationValue e) { + e.accept(new AnnotationValueReferenceVisitor(enclosingElement), null); + } + + private class AnnotationValueReferenceVisitor extends AbstractAnnotationValueVisitor7 { + + private final Element enclosingElement; + + public AnnotationValueReferenceVisitor(Element enclosedElement) { + this.enclosingElement = enclosedElement; + } + + @Override + public Void visitBoolean(boolean b, Void p) { + return null; + } + + @Override + public Void visitByte(byte b, Void p) { + return null; + } + + @Override + public Void visitChar(char c, Void p) { + return null; + } + + @Override + public Void visitDouble(double d, Void p) { + return null; + } + + @Override + public Void visitFloat(float f, Void p) { + return null; + } + + @Override + public Void visitInt(int i, Void p) { + return null; + } + + @Override + public Void visitLong(long i, Void p) { + return null; + } + + @Override + public Void visitShort(short s, Void p) { + return null; + } + + @Override + public Void visitString(String s, Void p) { + return null; + } + + @Override + public Void visitType(TypeMirror t, Void p) { + visitTypeReference(enclosingElement, t); + return null; + } + + @Override + public Void visitEnumConstant(VariableElement c, Void p) { + visitTypeReference(enclosingElement, c.asType()); + return null; + } + + @Override + public Void visitAnnotation(AnnotationMirror a, Void p) { + TypeReferenceVisitor.this.visitAnnotation(enclosingElement, a); + return null; + } + + @Override + public Void visitArray(List vals, Void p) { + for (int i = 0; i < vals.size(); i++) { + TypeReferenceVisitor.this.visitAnnotationValue(enclosingElement, vals.get(i)); + } + return null; + } + } + + @Override + public Void visitVariable(VariableElement f, Void p) { + visitAnnotations(f, f.getAnnotationMirrors()); + visitTypeReference(f, f.asType()); + return super.visitVariable(f, p); + } + + @Override + public void visitImport(CodeImport e, Void p) { + } + + public abstract void visitTypeReference(Element enclosedType, TypeMirror type); + + public abstract void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName); + + public abstract void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName); + + } + + private class ImportTypeReferenceVisitor extends TypeReferenceVisitor { + + @Override + public void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName) { + registerSymbol(staticImportUsage, ElementUtils.getQualifiedName(type), elementName); + } + + @Override + public void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName) { + registerSymbol(staticImportUsage, ElementUtils.getQualifiedName(type), elementName); + } + + @Override + public void visitTypeReference(Element enclosedType, TypeMirror type) { + if (type != null) { + switch (type.getKind()) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case SHORT: + case INT: + case LONG: + case VOID: + return; + case DECLARED: + if (needsImport(enclosedType, type)) { + DeclaredType declard = (DeclaredType) type; + registerSymbol(classImportUsage, ElementUtils.getEnclosedQualifiedName(declard), ElementUtils.getDeclaredName(declard, false)); + } + for (TypeMirror argument : ((DeclaredType) type).getTypeArguments()) { + visitTypeReference(enclosedType, argument); + } + return; + case ARRAY: + visitTypeReference(enclosedType, ((ArrayType) type).getComponentType()); + return; + case WILDCARD: + WildcardType wildcard = (WildcardType) type; + if (wildcard.getExtendsBound() != null) { + visitTypeReference(enclosedType, wildcard.getExtendsBound()); + } else if (wildcard.getSuperBound() != null) { + visitTypeReference(enclosedType, wildcard.getSuperBound()); + } + return; + case TYPEVAR: + return; + default: + throw new RuntimeException("Unknown type specified " + type.getKind() + " mirror: " + type); + } + + } + } + + private void registerSymbol(Map symbolUsage, String elementQualifiedName, String elementName) { + if (symbolUsage.containsKey(elementName)) { + String otherQualifiedName = symbolUsage.get(elementName); + if (otherQualifiedName == null) { + // already registered ambiguous + return; + } + if (!otherQualifiedName.equals(elementQualifiedName)) { + symbolUsage.put(elementName, null); + } + } else { + symbolUsage.put(elementName, elementQualifiedName); + } + } + + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/CreateCastData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/CreateCastData.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import java.util.*; + +public class CreateCastData extends TemplateMethod { + + private final List childNames; + + public CreateCastData(TemplateMethod method, List childNames) { + super(method); + this.childNames = childNames; + } + + public List getChildNames() { + return childNames; + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import javax.lang.model.element.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; + +public class ExecutableTypeData extends TemplateMethod { + + private final TypeSystemData typeSystem; + private final TypeData type; + + public ExecutableTypeData(TemplateMethod method, ExecutableElement executable, TypeSystemData typeSystem, TypeData type) { + super(method, executable); + this.typeSystem = typeSystem; + this.type = type; + if (executable.getParameters().size() < method.getMethod().getParameters().size()) { + throw new IllegalArgumentException(String.format("Method parameter count mismatch %s != %s.", executable.getParameters(), method.getMethod().getParameters())); + } + } + + public TypeData getType() { + return type; + } + + public TypeSystemData getTypeSystem() { + return typeSystem; + } + + public boolean hasUnexpectedValue(ProcessorContext context) { + return ElementUtils.canThrowType(getMethod().getThrownTypes(), context.getTruffleTypes().getUnexpectedValueException()); + } + + public boolean isFinal() { + return getMethod().getModifiers().contains(Modifier.FINAL); + } + + public boolean isAbstract() { + return getMethod().getModifiers().contains(Modifier.ABSTRACT); + } + + public int getEvaluatedCount() { + int count = 0; + for (Parameter parameter : getParameters()) { + if (parameter.getSpecification().isSignature()) { + count++; + } + } + return count; + } + + @Override + public int hashCode() { + return type.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ExecutableTypeData) { + return type.equals(((ExecutableTypeData) obj).type); + } + return super.equals(obj); + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardData.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import java.util.*; + +public class GuardData extends TemplateMethod { + + private List impliesExpressions; + + public GuardData(TemplateMethod method, List impliesExpressions) { + super(method); + this.impliesExpressions = impliesExpressions; + } + + public List getImpliesExpressions() { + return impliesExpressions; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof GuardData) { + GuardData other = (GuardData) obj; + return getMethod().equals(other.getMethod()); + } + return false; + } + + @Override + public int hashCode() { + return getMethod().hashCode(); + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import java.util.*; + +public final class GuardExpression { + + private GuardData resolvedGuard; + private NodeExecutionData[] resolvedChildren; + + private final String guardName; + private final boolean negated; + private final String[] childNames; + + public GuardExpression(String expression, boolean allowArguments) { + String exp = expression; + if (exp.startsWith("!")) { + exp = exp.substring(1, exp.length()); + negated = true; + } else { + negated = false; + } + + int argumentStart = exp.indexOf('('); + int endIndex = exp.lastIndexOf(')'); + if (allowArguments && argumentStart != -1 && endIndex != -1) { + guardName = exp.substring(0, argumentStart).trim(); + String arguments = exp.substring(argumentStart + 1, endIndex); + String[] children = arguments.split(","); + for (int i = 0; i < children.length; i++) { + children[i] = children[i].trim(); + } + if (children.length == 1 && children[0].isEmpty()) { + childNames = new String[0]; + } else { + childNames = children; + } + } else { + guardName = exp; + childNames = null; + } + } + + public String[] getChildNames() { + return childNames; + } + + public boolean isResolved() { + return resolvedGuard != null; + } + + public String getGuardName() { + return guardName; + } + + public NodeExecutionData[] getResolvedChildren() { + return resolvedChildren; + } + + public void setResolvedChildren(NodeExecutionData[] resolvedChildren) { + this.resolvedChildren = resolvedChildren; + } + + public void setResolvedGuard(GuardData guard) { + this.resolvedGuard = guard; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (obj instanceof GuardExpression) { + GuardExpression other = (GuardExpression) obj; + if (isResolved() && other.isResolved()) { + return resolvedGuard.equals(other.resolvedGuard) && negated == other.negated && Arrays.equals(resolvedChildren, other.resolvedChildren); + } else { + boolean equal = guardName.equals(other.guardName) && negated == other.negated; + if (childNames != null && other.childNames != null) { + equal &= Arrays.equals(childNames, other.childNames); + } + return equal; + } + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(guardName, negated, resolvedGuard, resolvedChildren); + } + + public final boolean implies(GuardExpression other) { + if (equals(other)) { + return true; + } + + if (isResolved() && other.isResolved()) { + for (GuardExpression implies : getResolvedGuard().getImpliesExpressions()) { + if (implies.getGuardName().equals(other.getGuardName())) { + if (implies.isNegated() == other.isNegated()) { + return true; + } + } + } + } + return false; + } + + @Override + public String toString() { + return (negated ? "!" : "") + guardName; + } + + public boolean isNegated() { + return negated; + } + + public GuardData getResolvedGuard() { + return resolvedGuard; + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ImplicitCastData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ImplicitCastData.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +public class ImplicitCastData extends TemplateMethod { + + private final TypeData sourceType; + private final TypeData targetType; + + public ImplicitCastData(TemplateMethod method, TypeData sourceType, TypeData targetType) { + super(method); + this.sourceType = sourceType; + this.targetType = targetType; + } + + public TypeData getSourceType() { + return sourceType; + } + + public TypeData getTargetType() { + return targetType; + } + + @Override + public int compareTo(TemplateMethod o) { + if (o instanceof ImplicitCastData && sourceType != null) { + // implicit casts are ordered by source type since + // its also the order in which they are checked. + TypeData otherSourceType = ((ImplicitCastData) o).getSourceType(); + if (otherSourceType != null) { + return this.sourceType.compareTo(otherSourceType); + } + } + return super.compareTo(o); + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MessageContainer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MessageContainer.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.tools.Diagnostic.Kind; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; + +public abstract class MessageContainer implements Iterable { + + private final List messages = new ArrayList<>(); + + public final void addWarning(String text, Object... params) { + getMessages().add(new Message(null, null, this, String.format(text, params), Kind.WARNING)); + } + + public final void addWarning(AnnotationValue value, String text, Object... params) { + getMessages().add(new Message(null, value, this, String.format(text, params), Kind.WARNING)); + } + + public final void addError(String text, Object... params) { + addError(null, text, params); + } + + public final void addError(AnnotationValue value, String text, Object... params) { + getMessages().add(new Message(null, value, this, String.format(text, params), Kind.ERROR)); + } + + public final void addError(AnnotationMirror mirror, AnnotationValue value, String text, Object... params) { + getMessages().add(new Message(mirror, value, this, String.format(text, params), Kind.ERROR)); + } + + protected List findChildContainers() { + return Collections.emptyList(); + } + + public abstract Element getMessageElement(); + + public MessageContainer getBaseContainer() { + return null; + } + + public Iterator iterator() { + return findChildContainers().iterator(); + } + + public final void emitMessages(ProcessorContext context, Log log) { + emitMessagesImpl(context, log, new HashSet(), null); + } + + private void emitMessagesImpl(ProcessorContext context, Log log, Set visitedSinks, List verifiedMessages) { + List childMessages; + if (verifiedMessages == null) { + childMessages = collectMessagesWithElementChildren(new HashSet(), getMessageElement()); + } else { + childMessages = verifiedMessages; + } + verifyExpectedMessages(context, log, childMessages); + + for (int i = getMessages().size() - 1; i >= 0; i--) { + emitDefault(context, log, getMessages().get(i)); + } + + for (MessageContainer sink : findChildContainers()) { + if (visitedSinks.contains(sink)) { + continue; + } + + visitedSinks.add(sink); + if (sink.getMessageElement() == this.getMessageElement()) { + sink.emitMessagesImpl(context, log, visitedSinks, childMessages); + } else { + sink.emitMessagesImpl(context, log, visitedSinks, null); + } + } + } + + private List collectMessagesWithElementChildren(Set visitedSinks, Element e) { + if (visitedSinks.contains(this)) { + return Collections.emptyList(); + } + visitedSinks.add(this); + + List foundMessages = new ArrayList<>(); + if (ElementUtils.typeEquals(getMessageElement().asType(), e.asType())) { + foundMessages.addAll(getMessages()); + } + for (MessageContainer sink : findChildContainers()) { + foundMessages.addAll(sink.collectMessagesWithElementChildren(visitedSinks, e)); + } + return foundMessages; + } + + private void verifyExpectedMessages(ProcessorContext context, Log log, List msgs) { + TypeElement expectError = context.getTruffleTypes().getExpectError(); + if (expectError != null) { + Element element = getMessageElement(); + AnnotationMirror mirror = ElementUtils.findAnnotationMirror(element.getAnnotationMirrors(), expectError); + if (mirror != null) { + List values = ElementUtils.getAnnotationValueList(String.class, mirror, "value"); + if (values == null) { + values = Collections.emptyList(); + } + if (values.size() != msgs.size()) { + log.message(Kind.ERROR, element, mirror, ElementUtils.getAnnotationValue(mirror, "value"), String.format("Error count expected %s but was %s.", values.size(), msgs.size())); + } + } + } + } + + private void emitDefault(ProcessorContext context, Log log, Message message) { + Kind kind = message.getKind(); + + Element messageElement = getMessageElement(); + AnnotationMirror messageAnnotation = getMessageAnnotation(); + AnnotationValue messageValue = getMessageAnnotationValue(); + if (message.getAnnotationValue() != null) { + messageValue = message.getAnnotationValue(); + } + if (message.getAnnotationMirror() != null) { + messageAnnotation = message.getAnnotationMirror(); + } + + String text = message.getText(); + + TypeElement expectError = context.getTruffleTypes().getExpectError(); + if (expectError != null) { + AnnotationMirror mirror = ElementUtils.findAnnotationMirror(messageElement.getAnnotationMirrors(), expectError); + if (mirror != null) { + List expectedTexts = ElementUtils.getAnnotationValueList(String.class, mirror, "value"); + boolean found = false; + for (String expectedText : expectedTexts) { + if (expectedText.endsWith("%") && text.startsWith(expectedText.substring(0, expectedText.length() - 1))) { + found = true; + break; + } else if (text.equals(expectedText)) { + found = true; + break; + } + } + if (!found) { + log.message(kind, messageElement, mirror, ElementUtils.getAnnotationValue(mirror, "value"), "Message expected one of '%s' but was '%s'.", expectedTexts, text); + } else { + return; + } + + } + } + + log.message(kind, messageElement, messageAnnotation, messageValue, text); + } + + public AnnotationMirror getMessageAnnotation() { + return null; + } + + public AnnotationValue getMessageAnnotationValue() { + return null; + } + + public final boolean hasErrors() { + return hasErrorsImpl(new HashSet()); + } + + public final List collectMessages() { + List collectedMessages = new ArrayList<>(); + collectMessagesImpl(collectedMessages, new HashSet()); + return collectedMessages; + } + + private void collectMessagesImpl(List collectedMessages, Set visitedSinks) { + collectedMessages.addAll(getMessages()); + for (MessageContainer sink : findChildContainers()) { + if (visitedSinks.contains(sink)) { + return; + } + + visitedSinks.add(sink); + sink.collectMessagesImpl(collectedMessages, visitedSinks); + } + } + + private boolean hasErrorsImpl(Set visitedSinks) { + for (Message msg : getMessages()) { + if (msg.getKind() == Kind.ERROR) { + return true; + } + } + for (MessageContainer sink : findChildContainers()) { + if (visitedSinks.contains(sink)) { + return false; + } + + visitedSinks.add(sink); + + if (sink.hasErrorsImpl(visitedSinks)) { + return true; + } + } + return false; + } + + public List getMessages() { + return messages; + } + + public static final class Message { + + private final MessageContainer originalContainer; + private final AnnotationMirror annotationMirror; + private final AnnotationValue annotationValue; + private final String text; + private final Kind kind; + + public Message(AnnotationMirror annotationMirror, AnnotationValue annotationValue, MessageContainer originalContainer, String text, Kind kind) { + this.annotationMirror = annotationMirror; + this.annotationValue = annotationValue; + this.originalContainer = originalContainer; + this.text = text; + this.kind = kind; + } + + public AnnotationMirror getAnnotationMirror() { + return annotationMirror; + } + + public AnnotationValue getAnnotationValue() { + return annotationValue; + } + + public MessageContainer getOriginalContainer() { + return originalContainer; + } + + public String getText() { + return text; + } + + public Kind getKind() { + return kind; + } + + @Override + public String toString() { + return kind + ": " + text; + } + + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MethodSpec.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MethodSpec.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import java.util.*; + +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.java.*; + +public class MethodSpec { + + private final ParameterSpec returnType; + private final List optional = new ArrayList<>(); + private final List required = new ArrayList<>(); + + private boolean ignoreAdditionalParameters; + private boolean ignoreAdditionalSpecifications; + private boolean variableRequiredParameters; + + private List typeDefinitions; + + public MethodSpec(ParameterSpec returnType) { + this.returnType = returnType; + } + + public void setVariableRequiredParameters(boolean variableRequiredParameters) { + this.variableRequiredParameters = variableRequiredParameters; + } + + public boolean isVariableRequiredParameters() { + return variableRequiredParameters; + } + + public void setIgnoreAdditionalParameters(boolean ignoreAdditionalParameter) { + this.ignoreAdditionalParameters = ignoreAdditionalParameter; + } + + public boolean isIgnoreAdditionalParameters() { + return ignoreAdditionalParameters; + } + + public void addOptional(ParameterSpec spec) { + optional.add(spec); + } + + public ParameterSpec addRequired(ParameterSpec spec) { + required.add(spec); + return spec; + } + + public ParameterSpec getReturnType() { + return returnType; + } + + public List getRequired() { + return required; + } + + public List getOptional() { + return optional; + } + + public List getAll() { + List specs = new ArrayList<>(); + specs.add(getReturnType()); + specs.addAll(getOptional()); + specs.addAll(getRequired()); + return specs; + } + + public ParameterSpec findParameterSpec(String name) { + for (ParameterSpec spec : getAll()) { + if (spec.getName().equals(name)) { + return spec; + } + } + return null; + } + + public void applyTypeDefinitions(String prefix) { + this.typeDefinitions = createTypeDefinitions(prefix); + } + + private List createTypeDefinitions(String prefix) { + List typeDefs = new ArrayList<>(); + + int defIndex = 0; + for (ParameterSpec spec : getAll()) { + List allowedTypes = spec.getAllowedTypes(); + List types = spec.getAllowedTypes(); + if (types != null && allowedTypes.size() > 1) { + TypeDef foundDef = null; + for (TypeDef def : typeDefs) { + if (allowedTypes.equals(def.getTypes())) { + foundDef = def; + break; + } + } + if (foundDef == null) { + foundDef = new TypeDef(types, prefix + defIndex); + typeDefs.add(foundDef); + defIndex++; + } + + spec.setTypeDefinition(foundDef); + } + } + + return typeDefs; + } + + public String toSignatureString(String methodName) { + StringBuilder b = new StringBuilder(); + b.append(" "); + b.append(createTypeSignature(returnType, true)); + + b.append(" "); + b.append(methodName); + b.append("("); + + String sep = ""; + + for (ParameterSpec optionalSpec : getOptional()) { + b.append(sep); + b.append("["); + b.append(createTypeSignature(optionalSpec, false)); + b.append("]"); + sep = ", "; + } + + for (int i = 0; i < getRequired().size(); i++) { + ParameterSpec requiredSpec = getRequired().get(i); + b.append(sep); + + if (isVariableRequiredParameters() && i == getRequired().size() - 1) { + b.append(("{")); + } + b.append(createTypeSignature(requiredSpec, false)); + if (isVariableRequiredParameters() && i == getRequired().size() - 1) { + b.append(("}")); + } + + sep = ", "; + } + + b.append(")"); + + if (typeDefinitions != null && !typeDefinitions.isEmpty()) { + b.append("\n\n"); + + String lineSep = ""; + for (TypeDef def : typeDefinitions) { + b.append(lineSep); + b.append(" <").append(def.getName()).append(">"); + b.append(" = {"); + String separator = ""; + for (TypeMirror type : def.getTypes()) { + b.append(separator).append(ElementUtils.getSimpleName(type)); + separator = ", "; + } + b.append("}"); + lineSep = "\n"; + + } + } + return b.toString(); + } + + private static String createTypeSignature(ParameterSpec spec, boolean typeOnly) { + StringBuilder builder = new StringBuilder(); + TypeDef foundTypeDef = spec.getTypeDefinition(); + if (foundTypeDef != null) { + builder.append("<" + foundTypeDef.getName() + ">"); + } else if (spec.getAllowedTypes().size() >= 1) { + builder.append(ElementUtils.getSimpleName(spec.getAllowedTypes().get(0))); + } else { + builder.append("void"); + } + if (!typeOnly) { + builder.append(" "); + builder.append(spec.getName()); + } + return builder.toString(); + } + + @Override + public String toString() { + return toSignatureString("methodName"); + } + + static class TypeDef { + + private final List types; + private final String name; + + private TypeDef(List types, String name) { + this.types = types; + this.name = name; + } + + public List getTypes() { + return types; + } + + public String getName() { + return name; + } + } + + public void setIgnoreAdditionalSpecifications(boolean ignoreAdditoinalSpecifications) { + this.ignoreAdditionalSpecifications = ignoreAdditoinalSpecifications; + } + + public boolean isIgnoreAdditionalSpecifications() { + return ignoreAdditionalSpecifications; + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeChildData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeChildData.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.*; + +public class NodeChildData extends MessageContainer { + + public enum Cardinality { + ONE, + MANY; + + public boolean isMany() { + return this == MANY; + } + + public boolean isOne() { + return this == ONE; + } + } + + private final Element sourceElement; + private final AnnotationMirror sourceAnnotationMirror; + private final String name; + private final TypeMirror type; + private final TypeMirror originalType; + private final Element accessElement; + private final Cardinality cardinality; + + private List executeWith = Collections.emptyList(); + + private NodeData childNode; + + public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, TypeMirror originalNodeType, Element accessElement, Cardinality cardinality) { + this.sourceElement = sourceElement; + this.sourceAnnotationMirror = sourceMirror; + this.name = name; + this.type = nodeType; + this.originalType = originalNodeType; + this.accessElement = accessElement; + this.cardinality = cardinality; + } + + public List getExecuteWith() { + return executeWith; + } + + public void setExecuteWith(List executeWith) { + this.executeWith = executeWith; + } + + public ExecutableTypeData findExecutableType(ProcessorContext context, TypeData targetType) { + ExecutableTypeData executableType = childNode.findExecutableType(targetType, getExecuteWith().size()); + if (executableType == null) { + executableType = findAnyGenericExecutableType(context); + } + return executableType; + } + + public List findGenericExecutableTypes(ProcessorContext context) { + return childNode.findGenericExecutableTypes(context, getExecuteWith().size()); + } + + public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context) { + return childNode.findAnyGenericExecutableType(context, getExecuteWith().size()); + } + + public TypeMirror getOriginalType() { + return originalType; + } + + @Override + public Element getMessageElement() { + return sourceElement; + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return sourceAnnotationMirror; + } + + public void setNode(NodeData nodeData) { + this.childNode = nodeData; + if (nodeData != null) { + getMessages().addAll(nodeData.collectMessages()); + } + } + + public Element getAccessElement() { + return accessElement; + } + + public TypeMirror getNodeType() { + return type; + } + + public Cardinality getCardinality() { + return cardinality; + } + + public NodeData getNodeData() { + return childNode; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return "NodeFieldData[name=" + getName() + ", kind=" + cardinality + ", node=" + getNodeData() + "]"; + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,489 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality; + +public class NodeData extends Template implements Comparable { + + private final String nodeId; + private final String shortName; + private final List enclosingNodes = new ArrayList<>(); + private NodeData declaringNode; + + private final TypeSystemData typeSystem; + private final List children; + private final List childExecutions; + private final List fields; + private final List assumptions; + + private ParameterSpec instanceParameterSpec; + + private final List specializations = new ArrayList<>(); + private final List shortCircuits = new ArrayList<>(); + private final List casts = new ArrayList<>(); + private Map> executableTypes; + + private final NodeExecutionData thisExecution; + + public NodeData(ProcessorContext context, TypeElement type, String shortName, TypeSystemData typeSystem, List children, List executions, + List fields, List assumptions) { + super(context, type, null, null); + this.nodeId = type.getSimpleName().toString(); + this.shortName = shortName; + this.typeSystem = typeSystem; + this.fields = fields; + this.children = children; + this.childExecutions = executions; + this.assumptions = assumptions; + this.thisExecution = new NodeExecutionData(new NodeChildData(null, null, "this", getNodeType(), getNodeType(), null, Cardinality.ONE), -1, false); + this.thisExecution.getChild().setNode(this); + } + + public NodeData(ProcessorContext context, TypeElement type) { + this(context, type, null, null, null, null, null, null); + } + + public NodeExecutionData getThisExecution() { + return thisExecution; + } + + public boolean isFallbackReachable() { + SpecializationData generic = getGenericSpecialization(); + if (generic != null) { + return generic.isReachable(); + } + return false; + } + + public void addEnclosedNode(NodeData node) { + this.enclosingNodes.add(node); + node.declaringNode = this; + } + + public List getChildExecutions() { + return childExecutions; + } + + public int getSignatureSize() { + if (getSpecializations() != null && !getSpecializations().isEmpty()) { + return getSpecializations().get(0).getSignatureSize(); + } + return 0; + } + + public boolean needsFrame(ProcessorContext context) { + for (SpecializationData specialization : specializations) { + if (!specialization.isReachable()) { + continue; + } + if (specialization.hasFrame(context)) { + return true; + } + } + return false; + } + + public boolean isPolymorphic(ProcessorContext context) { + return needsRewrites(context); + } + + public List getCasts() { + return casts; + } + + public String getShortName() { + return shortName; + } + + public List getFields() { + return fields; + } + + @Override + protected List findChildContainers() { + List containerChildren = new ArrayList<>(); + if (enclosingNodes != null) { + containerChildren.addAll(enclosingNodes); + } + if (typeSystem != null) { + containerChildren.add(typeSystem); + } + if (specializations != null) { + for (MessageContainer specialization : specializations) { + if (specialization.getMessageElement() != null) { + containerChildren.add(specialization); + } + } + } + if (executableTypes != null) { + containerChildren.addAll(getExecutableTypes()); + } + if (shortCircuits != null) { + containerChildren.addAll(shortCircuits); + } + if (children != null) { + containerChildren.addAll(children); + } + if (fields != null) { + containerChildren.addAll(fields); + } + if (casts != null) { + containerChildren.addAll(casts); + } + return containerChildren; + } + + public ParameterSpec getInstanceParameterSpec() { + return instanceParameterSpec; + } + + public void setInstanceParameterSpec(ParameterSpec instanceParameter) { + this.instanceParameterSpec = instanceParameter; + } + + public String getNodeId() { + return nodeId; + } + + public TypeMirror getNodeType() { + return getTemplateType().asType(); + } + + public List getAssumptions() { + return assumptions; + } + + public boolean needsFactory() { + if (specializations == null) { + return false; + } + if (getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { + return false; + } + + boolean noSpecialization = true; + for (SpecializationData specialization : specializations) { + noSpecialization = noSpecialization && !specialization.isSpecialized(); + } + return !noSpecialization; + } + + public boolean supportsFrame() { + if (executableTypes != null) { + for (ExecutableTypeData execType : getExecutableTypes(-1)) { + if (execType.findParameter("frameValue") == null) { + return false; + } + } + } + return true; + } + + public NodeExecutionData findExecutionByExpression(String childNameExpression) { + String childName = childNameExpression; + int index = -1; + + int start = childName.indexOf('['); + int end = childName.lastIndexOf(']'); + if (start != -1 && end != -1 && start < end) { + try { + index = Integer.parseInt(childName.substring(start + 1, end)); + childName = childName.substring(0, start); + childName = NodeExecutionData.createName(childName, index); + } catch (NumberFormatException e) { + // ignore + } + } + + for (NodeExecutionData execution : childExecutions) { + if (execution.getName().equals(childName) && (execution.getIndex() == -1 || execution.getIndex() == index)) { + return execution; + } + } + return null; + } + + public List getNodeDeclaringChildren() { + List nodeChildren = new ArrayList<>(); + for (NodeData child : getEnclosingNodes()) { + if (child.needsFactory()) { + nodeChildren.add(child); + } + nodeChildren.addAll(child.getNodeDeclaringChildren()); + } + return nodeChildren; + } + + public NodeData getDeclaringNode() { + return declaringNode; + } + + public List getEnclosingNodes() { + return enclosingNodes; + } + + public List getAllTemplateMethods() { + List methods = new ArrayList<>(); + + for (SpecializationData specialization : getSpecializations()) { + methods.add(specialization); + } + + methods.addAll(getExecutableTypes()); + methods.addAll(getShortCircuits()); + if (getCasts() != null) { + methods.addAll(getCasts()); + } + + return methods; + } + + public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context, int evaluatedCount) { + List types = findGenericExecutableTypes(context, evaluatedCount); + for (ExecutableTypeData type : types) { + if (type.getType().isGeneric()) { + return type; + } + } + + for (ExecutableTypeData type : types) { + if (!type.getType().isVoid()) { + return type; + } + } + + for (ExecutableTypeData type : types) { + return type; + } + return null; + } + + public List getExecutableTypes(int evaluatedCount) { + if (executableTypes == null) { + return Collections.emptyList(); + } + if (evaluatedCount == -1) { + List typeData = new ArrayList<>(); + for (int currentEvaluationCount : executableTypes.keySet()) { + typeData.addAll(executableTypes.get(currentEvaluationCount)); + } + return typeData; + } else { + List types = executableTypes.get(evaluatedCount); + if (types == null) { + return Collections.emptyList(); + } + return types; + } + } + + public List findGenericExecutableTypes(ProcessorContext context, int evaluatedCount) { + List types = new ArrayList<>(); + for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) { + if (!type.hasUnexpectedValue(context)) { + types.add(type); + } + } + return types; + } + + public ExecutableTypeData findExecutableType(TypeData prmitiveType, int evaluatedCount) { + for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) { + if (ElementUtils.typeEquals(type.getType().getPrimitiveType(), prmitiveType.getPrimitiveType())) { + return type; + } + } + return null; + } + + public boolean needsRewrites(ProcessorContext context) { + boolean needsRewrites = false; + + for (SpecializationData specialization : getSpecializations()) { + if (specialization.hasRewrite(context)) { + needsRewrites = true; + break; + } + } + return needsRewrites || getSpecializations().size() > 1; + } + + public SpecializationData getPolymorphicSpecialization() { + for (SpecializationData specialization : specializations) { + if (specialization.isPolymorphic()) { + return specialization; + } + } + return null; + } + + public SpecializationData getGenericSpecialization() { + for (SpecializationData specialization : specializations) { + if (specialization.isGeneric()) { + return specialization; + } + } + return null; + } + + public SpecializationData getUninitializedSpecialization() { + for (SpecializationData specialization : specializations) { + if (specialization.isUninitialized()) { + return specialization; + } + } + return null; + } + + @Override + public TypeSystemData getTypeSystem() { + return typeSystem; + } + + public String dump() { + return dump(0); + } + + private String dump(int level) { + String indent = ""; + for (int i = 0; i < level; i++) { + indent += " "; + } + StringBuilder builder = new StringBuilder(); + + builder.append(String.format("%s%s {", indent, toString())); + + dumpProperty(builder, indent, "templateClass", ElementUtils.getQualifiedName(getTemplateType())); + dumpProperty(builder, indent, "typeSystem", getTypeSystem()); + dumpProperty(builder, indent, "fields", getChildren()); + dumpProperty(builder, indent, "executableTypes", getExecutableTypes()); + dumpProperty(builder, indent, "specializations", getSpecializations()); + dumpProperty(builder, indent, "assumptions", getAssumptions()); + dumpProperty(builder, indent, "casts", getCasts()); + dumpProperty(builder, indent, "messages", collectMessages()); + if (getEnclosingNodes().size() > 0) { + builder.append(String.format("\n%s children = [", indent)); + for (NodeData node : getEnclosingNodes()) { + builder.append("\n"); + builder.append(node.dump(level + 1)); + } + builder.append(String.format("\n%s ]", indent)); + } + builder.append(String.format("%s}", indent)); + return builder.toString(); + } + + private static void dumpProperty(StringBuilder b, String indent, String propertyName, Object value) { + if (value instanceof List) { + List list = (List) value; + if (!list.isEmpty()) { + b.append(String.format("\n%s %s = %s", indent, propertyName, dumpList(indent, (List) value))); + } + } else { + if (value != null) { + b.append(String.format("\n%s %s = %s", indent, propertyName, value)); + } + } + } + + private static String dumpList(String indent, List array) { + if (array == null) { + return "null"; + } + + if (array.isEmpty()) { + return "[]"; + } else if (array.size() == 1) { + return "[" + array.get(0).toString() + "]"; + } + + StringBuilder b = new StringBuilder(); + b.append("["); + for (Object object : array) { + b.append("\n "); + b.append(indent); + b.append(object); + b.append(", "); + } + b.append("\n ").append(indent).append("]"); + return b.toString(); + } + + public NodeChildData findChild(String name) { + for (NodeChildData field : getChildren()) { + if (field.getName().equals(name)) { + return field; + } + } + return null; + } + + public List getChildren() { + return children; + } + + public List getSpecializations() { + return specializations; + } + + public List getExecutableTypes() { + return getExecutableTypes(-1); + } + + public List getShortCircuits() { + return shortCircuits; + } + + public void setExecutableTypes(Map> executableTypes) { + this.executableTypes = executableTypes; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + getNodeId() + "]"; + } + + public CreateCastData findCast(String name) { + if (getCasts() != null) { + for (CreateCastData cast : getCasts()) { + if (cast.getChildNames().contains(name)) { + return cast; + } + } + } + return null; + } + + public int compareTo(NodeData o) { + return getNodeId().compareTo(o.getNodeId()); + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeExecutionData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeExecutionData.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality; + +public class NodeExecutionData { + + private final NodeChildData child; + private final String name; + private final int index; + private final boolean shortCircuit; + + public NodeExecutionData(NodeChildData child, int index, boolean shortCircuit) { + this.child = child; + this.index = index; + this.shortCircuit = shortCircuit; + this.name = createName(); + } + + private String createName() { + return createName(child.getName(), index); + } + + public TypeMirror getNodeType() { + TypeMirror type; + if (child.getCardinality() == Cardinality.MANY && child.getNodeType().getKind() == TypeKind.ARRAY) { + type = ((ArrayType) child.getNodeType()).getComponentType(); + } else { + type = child.getNodeType(); + } + return type; + } + + public String getName() { + return name; + } + + public NodeChildData getChild() { + return child; + } + + public int getIndex() { + return index; + } + + public boolean isIndexed() { + return index > -1; + } + + public boolean isShortCircuit() { + return shortCircuit; + } + + public String getShortCircuitId() { + return createShortCircuitId(child, index); + } + + public static String createShortCircuitId(NodeChildData child, int varArgsIndex) { + String shortCircuitName = child.getName(); + if (child.getCardinality().isMany()) { + shortCircuitName = shortCircuitName + "[" + varArgsIndex + "]"; + } + return shortCircuitName; + } + + public static String createName(String childName, int index) { + if (index > -1) { + return childName + index; + } + return childName; + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeFieldData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeFieldData.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public class NodeFieldData extends MessageContainer { + + private final Element messageElement; + private final AnnotationMirror messageAnnotation; + private final String name; + private final TypeMirror type; + private final boolean generated; + private ExecutableElement getter; + + public NodeFieldData(Element messageElement, AnnotationMirror messageAnnotation, TypeMirror type, String name, boolean generated) { + this.messageElement = messageElement; + this.messageAnnotation = messageAnnotation; + this.name = name; + this.type = type; + this.generated = generated; + } + + public void setGetter(ExecutableElement getter) { + this.getter = getter; + } + + @Override + public Element getMessageElement() { + return messageElement; + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return messageAnnotation; + } + + public String getName() { + return name; + } + + public TypeMirror getType() { + return type; + } + + public boolean isGenerated() { + return generated; + } + + public ExecutableElement getGetter() { + return getter; + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.java.*; + +public final class Parameter { + + private final ParameterSpec specification; + private TypeData typeSystemType; + private TemplateMethod method; + private final String localName; + private final int specificationVarArgsIndex; + private final int typeVarArgsIndex; + private final TypeMirror actualType; + + public Parameter(ParameterSpec specification, TypeMirror actualType, int specificationVarArgsIndex, int typeVarArgsIndex) { + this.specification = specification; + this.actualType = actualType; + this.typeSystemType = null; + + this.specificationVarArgsIndex = specificationVarArgsIndex; + + String valueName = specification.getName() + "Value"; + if (specificationVarArgsIndex > -1) { + valueName += specificationVarArgsIndex; + } + this.typeVarArgsIndex = typeVarArgsIndex; + this.localName = valueName; + } + + public Parameter(ParameterSpec specification, TypeData actualType, int specificationIndex, int varArgsIndex) { + this(specification, actualType.getPrimitiveType(), specificationIndex, varArgsIndex); + this.typeSystemType = actualType; + } + + public Parameter(Parameter parameter, TypeData otherType) { + this(parameter.specification, otherType, parameter.specificationVarArgsIndex, parameter.typeVarArgsIndex); + } + + public Parameter(Parameter parameter) { + this.specification = parameter.specification; + this.actualType = parameter.actualType; + this.typeSystemType = parameter.typeSystemType; + this.specificationVarArgsIndex = parameter.specificationVarArgsIndex; + this.localName = parameter.localName; + this.typeVarArgsIndex = parameter.typeVarArgsIndex; + } + + public int getTypeVarArgsIndex() { + return typeVarArgsIndex; + } + + public int getSpecificationVarArgsIndex() { + return specificationVarArgsIndex; + } + + public String getLocalName() { + return localName; + } + + void setMethod(TemplateMethod method) { + this.method = method; + } + + public ParameterSpec getSpecification() { + return specification; + } + + public TemplateMethod getMethod() { + return method; + } + + public TypeMirror getType() { + return actualType; + } + + public TypeData getTypeSystemType() { + return typeSystemType; + } + + public boolean isTypeVarArgs() { + return typeVarArgsIndex >= 0; + } + + public Parameter getPreviousParameter() { + return method.getPreviousParam(this); + } + + @Override + public String toString() { + return ElementUtils.getSimpleName(actualType); + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import java.util.*; + +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.model.MethodSpec.TypeDef; + +public class ParameterSpec { + + private final String name; + private final List allowedTypes; + private final Set allowedTypesIdentifier; + + /** Type is bound to local final variable. */ + private boolean local; + private boolean signature; + + /** Optional bound execution of node. */ + private NodeExecutionData execution; + private TypeDef typeDefinition; + + public ParameterSpec(String name, List allowedTypes, Set typeIdentifiers) { + this.name = name; + this.allowedTypes = allowedTypes; + this.allowedTypesIdentifier = typeIdentifiers; + } + + public ParameterSpec(String name, TypeMirror type) { + this(name, Arrays.asList(type), new HashSet<>(Arrays.asList(ElementUtils.getUniqueIdentifier(type)))); + } + + public ParameterSpec(ParameterSpec o, List allowedTypes, Set typeIdentifiers) { + this.name = o.name; + this.local = o.local; + this.typeDefinition = o.typeDefinition; + this.execution = o.execution; + this.signature = o.signature; + this.allowedTypes = allowedTypes; + this.allowedTypesIdentifier = typeIdentifiers; + } + + public NodeExecutionData getExecution() { + return execution; + } + + public void setExecution(NodeExecutionData executionData) { + this.execution = executionData; + this.signature = execution != null; + } + + public void setSignature(boolean signature) { + this.signature = signature; + } + + void setTypeDefinition(TypeDef typeDefinition) { + this.typeDefinition = typeDefinition; + } + + TypeDef getTypeDefinition() { + return typeDefinition; + } + + public void setLocal(boolean local) { + this.local = local; + } + + public boolean isSignature() { + return signature; + } + + public boolean isLocal() { + return local; + } + + public String getName() { + return name; + } + + public List getAllowedTypes() { + return allowedTypes; + } + + public boolean matches(TypeMirror actualType) { + return allowedTypesIdentifier.contains(ElementUtils.getUniqueIdentifier(actualType)); + } + + @Override + public String toString() { + return toSignatureString(false); + } + + public String toSignatureString(boolean typeOnly) { + StringBuilder builder = new StringBuilder(); + if (typeDefinition != null) { + builder.append("<" + typeDefinition.getName() + ">"); + } else if (getAllowedTypes().size() >= 1) { + builder.append(ElementUtils.getSimpleName(getAllowedTypes().get(0))); + } else { + builder.append("void"); + } + if (!typeOnly) { + builder.append(" "); + builder.append(getName()); + } + return builder.toString(); + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ShortCircuitData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ShortCircuitData.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import com.oracle.truffle.dsl.processor.java.*; + +public class ShortCircuitData extends TemplateMethod { + + private ShortCircuitData genericShortCircuitMethod; + private final String valueName; + + public ShortCircuitData(TemplateMethod template, String valueName) { + super(template); + this.valueName = valueName; + } + + public String getValueName() { + return valueName; + } + + public void setGenericShortCircuitMethod(ShortCircuitData genericShortCircuitMethod) { + this.genericShortCircuitMethod = genericShortCircuitMethod; + } + + public boolean isGeneric() { + return genericShortCircuitMethod == null; + } + + public ShortCircuitData getGeneric() { + if (isGeneric()) { + return this; + } else { + return genericShortCircuitMethod; + } + } + + public boolean isCompatibleTo(SpecializationData specialization) { + if (isGeneric() && specialization.isGeneric()) { + return true; + } + + for (Parameter param : getParameters()) { + Parameter specializationParam = specialization.findParameter(param.getLocalName()); + if (!ElementUtils.typeEquals(param.getType(), specializationParam.getType())) { + return false; + } + } + return true; + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import java.util.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; + +public final class SpecializationData extends TemplateMethod { + + public enum SpecializationKind { + UNINITIALIZED, + SPECIALIZED, + POLYMORPHIC, + GENERIC + } + + private final NodeData node; + private final SpecializationKind kind; + private final List exceptions; + private List guards = Collections.emptyList(); + private List shortCircuits; + private List assumptions = Collections.emptyList(); + private final Set contains = new TreeSet<>(); + private final Set containsNames = new TreeSet<>(); + private final Set excludedBy = new TreeSet<>(); + private String insertBeforeName; + private SpecializationData insertBefore; + private boolean reachable; + private int index; + + public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind, List exceptions) { + super(template); + this.node = node; + this.kind = kind; + this.exceptions = exceptions; + this.index = template.getNaturalOrder(); + + for (SpecializationThrowsData exception : exceptions) { + exception.setSpecialization(this); + } + } + + public void setInsertBefore(SpecializationData insertBefore) { + this.insertBefore = insertBefore; + } + + public void setInsertBeforeName(String insertBeforeName) { + this.insertBeforeName = insertBeforeName; + } + + public SpecializationData getInsertBefore() { + return insertBefore; + } + + public String getInsertBeforeName() { + return insertBeforeName; + } + + public Set getContainsNames() { + return containsNames; + } + + public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind) { + this(node, template, kind, new ArrayList()); + } + + public Set getContains() { + return contains; + } + + public Set getExcludedBy() { + return excludedBy; + } + + public void setReachable(boolean reachable) { + this.reachable = reachable; + } + + public boolean isReachable() { + return reachable; + } + + public boolean isPolymorphic() { + return kind == SpecializationKind.POLYMORPHIC; + } + + @Override + protected List findChildContainers() { + List sinks = new ArrayList<>(); + if (exceptions != null) { + sinks.addAll(exceptions); + } + if (guards != null) { + for (GuardExpression guard : guards) { + if (guard.isResolved()) { + sinks.add(guard.getResolvedGuard()); + } + } + } + return sinks; + } + + public boolean hasRewrite(ProcessorContext context) { + if (!getExceptions().isEmpty()) { + return true; + } + if (!getGuards().isEmpty()) { + return true; + } + if (!getAssumptions().isEmpty()) { + return true; + } + for (Parameter parameter : getSignatureParameters()) { + ExecutableTypeData type = parameter.getSpecification().getExecution().getChild().findExecutableType(context, parameter.getTypeSystemType()); + if (type.hasUnexpectedValue(context)) { + return true; + } + if (type.getReturnType().getTypeSystemType().needsCastTo(parameter.getTypeSystemType())) { + return true; + } + + } + return false; + } + + @Override + public int compareTo(TemplateMethod other) { + if (this == other) { + return 0; + } else if (!(other instanceof SpecializationData)) { + return super.compareTo(other); + } + SpecializationData m2 = (SpecializationData) other; + int kindOrder = kind.compareTo(m2.kind); + if (kindOrder != 0) { + return kindOrder; + } + + int compare = 0; + int order1 = index; + int order2 = m2.index; + if (order1 != NO_NATURAL_ORDER && order2 != NO_NATURAL_ORDER) { + compare = Integer.compare(order1, order2); + if (compare != 0) { + return compare; + } + } + + return super.compareTo(other); + } + + public void setIndex(int order) { + this.index = order; + } + + public int getIndex() { + return index; + } + + public boolean isContainedBy(SpecializationData next) { + if (compareTo(next) > 0) { + // must be declared after the current specialization + return false; + } + + Iterator currentSignature = getSignatureParameters().iterator(); + Iterator nextSignature = next.getSignatureParameters().iterator(); + + while (currentSignature.hasNext() && nextSignature.hasNext()) { + TypeData currentType = currentSignature.next().getTypeSystemType(); + TypeData prevType = nextSignature.next().getTypeSystemType(); + + if (!currentType.isImplicitSubtypeOf(prevType)) { + return false; + } + } + + for (String nextAssumption : next.getAssumptions()) { + if (!getAssumptions().contains(nextAssumption)) { + return false; + } + } + + Iterator nextGuards = next.getGuards().iterator(); + while (nextGuards.hasNext()) { + GuardExpression nextGuard = nextGuards.next(); + boolean implied = false; + for (GuardExpression currentGuard : getGuards()) { + if (currentGuard.implies(nextGuard)) { + implied = true; + break; + } + } + if (!implied) { + return false; + } + } + + return true; + } + + public String createReferenceName() { + if (getMethod() == null) { + return "-"; + } + return ElementUtils.createReferenceName(getMethod()); + } + + public NodeData getNode() { + return node; + } + + public void setGuards(List guards) { + this.guards = guards; + } + + public boolean isSpecialized() { + return kind == SpecializationKind.SPECIALIZED; + } + + public boolean isGeneric() { + return kind == SpecializationKind.GENERIC; + } + + public boolean isUninitialized() { + return kind == SpecializationKind.UNINITIALIZED; + } + + public List getExceptions() { + return exceptions; + } + + public List getGuards() { + return guards; + } + + public void setShortCircuits(List shortCircuits) { + this.shortCircuits = shortCircuits; + } + + public List getShortCircuits() { + return shortCircuits; + } + + public List getAssumptions() { + return assumptions; + } + + public void setAssumptions(List assumptions) { + this.assumptions = assumptions; + } + + public SpecializationData findNextSpecialization() { + List specializations = node.getSpecializations(); + for (int i = 0; i < specializations.size() - 1; i++) { + if (specializations.get(i) == this) { + return specializations.get(i + 1); + } + } + return null; + } + + @Override + public String toString() { + return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getTypeSignature()); + } + + public boolean hasFrame(ProcessorContext context) { + for (Parameter param : getParameters()) { + if (ElementUtils.typeEquals(param.getType(), context.getTruffleTypes().getFrame())) { + return true; + } + } + return false; + } + + public boolean isReachableAfter(SpecializationData prev) { + if (!prev.isSpecialized()) { + return true; + } + + if (!prev.getExceptions().isEmpty()) { + return true; + } + + Iterator currentSignature = getSignatureParameters().iterator(); + Iterator prevSignature = prev.getSignatureParameters().iterator(); + + while (currentSignature.hasNext() && prevSignature.hasNext()) { + TypeData currentType = currentSignature.next().getTypeSystemType(); + TypeData prevType = prevSignature.next().getTypeSystemType(); + + if (!currentType.isImplicitSubtypeOf(prevType)) { + return true; + } + } + + for (String prevAssumption : prev.getAssumptions()) { + if (!getAssumptions().contains(prevAssumption)) { + return true; + } + } + + Iterator prevGuards = prev.getGuards().iterator(); + Iterator currentGuards = getGuards().iterator(); + while (prevGuards.hasNext()) { + GuardExpression prevGuard = prevGuards.next(); + GuardExpression currentGuard = currentGuards.hasNext() ? currentGuards.next() : null; + if (currentGuard == null || !currentGuard.implies(prevGuard)) { + return true; + } + } + + return false; + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationThrowsData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationThrowsData.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public class SpecializationThrowsData extends MessageContainer { + + private final AnnotationValue annotationValue; + private final AnnotationMirror annotationMirror; + private final TypeMirror javaClass; + private SpecializationData specialization; + + public SpecializationThrowsData(AnnotationMirror annotationMirror, AnnotationValue value, TypeMirror javaClass) { + this.annotationMirror = annotationMirror; + this.annotationValue = value; + this.javaClass = javaClass; + } + + void setSpecialization(SpecializationData specialization) { + this.specialization = specialization; + } + + @Override + public Element getMessageElement() { + return specialization.getMessageElement(); + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return annotationMirror; + } + + @Override + public AnnotationValue getMessageAnnotationValue() { + return annotationValue; + } + + public TypeMirror getJavaClass() { + return javaClass; + } + + public SpecializationData getSpecialization() { + return specialization; + } + + public AnnotationMirror getAnnotationMirror() { + return annotationMirror; + } + + public SpecializationData getTransitionTo() { + return specialization.findNextSpecialization(); + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Template.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Template.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import java.util.*; + +import javax.lang.model.element.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; + +public abstract class Template extends MessageContainer { + + private final ProcessorContext context; + private final TypeElement templateType; + private final String templateMethodName; + private final AnnotationMirror annotation; + + public Template(ProcessorContext context, TypeElement templateType, String templateMethodName, AnnotationMirror annotation) { + this.context = context; + this.templateType = templateType; + this.templateMethodName = templateMethodName; + this.annotation = annotation; + } + + public ProcessorContext getContext() { + return context; + } + + @Override + public MessageContainer getBaseContainer() { + return this; + } + + public abstract TypeSystemData getTypeSystem(); + + @Override + public Element getMessageElement() { + return templateType; + } + + @Override + protected List findChildContainers() { + return Collections.emptyList(); + } + + public String getTemplateMethodName() { + return templateMethodName; + } + + public TypeElement getTemplateType() { + return templateType; + } + + public AnnotationMirror getTemplateTypeAnnotation() { + return annotation; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + ElementUtils.getSimpleName(getTemplateType()) + "]"; + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.util.*; + +/** + * Note: this class has a natural ordering that is inconsistent with equals. + */ +public class TemplateMethod extends MessageContainer implements Comparable { + + public static final int NO_NATURAL_ORDER = -1; + + private String id; + private final Template template; + private final int naturalOrder; + private final MethodSpec specification; + private final ExecutableElement method; + private final AnnotationMirror markerAnnotation; + private Parameter returnType; + private final List parameters; + private final Map parameterCache = new HashMap<>(); + + public TemplateMethod(String id, int naturalOrder, Template template, MethodSpec specification, ExecutableElement method, AnnotationMirror markerAnnotation, Parameter returnType, + List parameters) { + this.template = template; + this.specification = specification; + this.naturalOrder = naturalOrder; + this.method = method; + this.markerAnnotation = markerAnnotation; + this.returnType = returnType; + this.parameters = new ArrayList<>(); + for (Parameter param : parameters) { + Parameter newParam = new Parameter(param); + this.parameters.add(newParam); + newParam.setMethod(this); + parameterCache.put(param.getLocalName(), param); + } + if (returnType != null) { + parameterCache.put(returnType.getLocalName(), returnType); + } + this.id = id; + } + + public int getNaturalOrder() { + return naturalOrder; + } + + public TemplateMethod(TemplateMethod method) { + this(method.id, method.naturalOrder, method.template, method.specification, method.method, method.markerAnnotation, method.returnType, method.parameters); + getMessages().addAll(method.getMessages()); + } + + public TemplateMethod(TemplateMethod method, ExecutableElement executable) { + this(method.id, method.naturalOrder, method.template, method.specification, executable, method.markerAnnotation, method.returnType, method.parameters); + getMessages().addAll(method.getMessages()); + } + + @Override + public Element getMessageElement() { + return method; + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return markerAnnotation; + } + + @Override + protected List findChildContainers() { + return Collections.emptyList(); + } + + public void setId(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public Template getTemplate() { + return template; + } + + public MethodSpec getSpecification() { + return specification; + } + + public Parameter getReturnType() { + return returnType; + } + + public void replaceParameter(String localName, Parameter newParameter) { + if (returnType.getLocalName().equals(localName)) { + returnType = newParameter; + returnType.setMethod(this); + } else { + Parameter local = findParameter(localName); + int index = parameters.indexOf(local); + parameters.set(index, newParameter); + } + } + + public List getRequiredParameters() { + List requiredParameters = new ArrayList<>(); + for (Parameter parameter : getParameters()) { + if (getSpecification().getRequired().contains(parameter.getSpecification())) { + requiredParameters.add(parameter); + } + } + return requiredParameters; + } + + public Iterable getSignatureParameters() { + return new FilteredIterable<>(getParameters(), new Predicate() { + public boolean evaluate(Parameter value) { + return value.getSpecification().isSignature(); + } + }); + } + + public List getParameters() { + return parameters; + } + + public List findParameters(ParameterSpec spec) { + List foundParameters = new ArrayList<>(); + for (Parameter param : getReturnTypeAndParameters()) { + if (param.getSpecification().getName().equals(spec.getName())) { + foundParameters.add(param); + } + } + return foundParameters; + } + + public List findByExecutionData(NodeExecutionData execution) { + List foundParameters = new ArrayList<>(); + for (Parameter parameter : getParameters()) { + ParameterSpec spec = parameter.getSpecification(); + if (spec != null && spec.getExecution() != null && spec.getExecution().equals(execution) && parameter.getSpecification().isSignature()) { + foundParameters.add(parameter); + } + } + return foundParameters; + } + + public Parameter findParameter(String valueName) { + return parameterCache.get(valueName); + } + + public List getReturnTypeAndParameters() { + List allParameters = new ArrayList<>(getParameters().size() + 1); + if (getReturnType() != null) { + allParameters.add(getReturnType()); + } + allParameters.addAll(getParameters()); + return Collections.unmodifiableList(allParameters); + } + + public boolean canBeAccessedByInstanceOf(TypeMirror type) { + TypeMirror methodType = ElementUtils.findNearestEnclosingType(getMethod()).asType(); + return ElementUtils.isAssignable(type, methodType) || ElementUtils.isAssignable(methodType, type); + } + + public ExecutableElement getMethod() { + return method; + } + + public String getMethodName() { + if (getMethod() != null) { + return getMethod().getSimpleName().toString(); + } else { + return "$synthetic"; + } + } + + public AnnotationMirror getMarkerAnnotation() { + return markerAnnotation; + } + + @Override + public String toString() { + return String.format("%s [id = %s, method = %s]", getClass().getSimpleName(), getId(), getMethod()); + } + + public Parameter getPreviousParam(Parameter searchParam) { + Parameter prev = null; + for (Parameter param : getParameters()) { + if (param == searchParam) { + return prev; + } + prev = param; + } + return prev; + } + + @SuppressWarnings("unused") + public int getSignatureSize() { + int signatureSize = 0; + for (Parameter parameter : getSignatureParameters()) { + signatureSize++; + } + return signatureSize; + } + + public TypeSignature getTypeSignature() { + TypeSignature signature = new TypeSignature(); + signature.types.add(getReturnType().getTypeSystemType()); + for (Parameter parameter : getSignatureParameters()) { + TypeData typeData = parameter.getTypeSystemType(); + if (typeData != null) { + signature.types.add(typeData); + } + } + return signature; + } + + public Parameter getSignatureParameter(int searchIndex) { + int index = 0; + for (Parameter parameter : getParameters()) { + if (!parameter.getSpecification().isSignature()) { + continue; + } + if (index == searchIndex) { + return parameter; + } + index++; + } + return null; + } + + public void updateSignature(TypeSignature signature) { + // TODO(CH): fails in normal usage - output ok though + // assert signature.size() >= 1; + + int signatureIndex = 0; + for (Parameter parameter : getReturnTypeAndParameters()) { + if (!parameter.getSpecification().isSignature()) { + continue; + } + if (signatureIndex >= signature.size()) { + break; + } + TypeData newType = signature.get(signatureIndex++); + if (!parameter.getTypeSystemType().equals(newType)) { + replaceParameter(parameter.getLocalName(), new Parameter(parameter, newType)); + } + } + } + + @Override + public int compareTo(TemplateMethod o) { + if (this == o) { + return 0; + } + + int compare = compareBySignature(o); + if (compare == 0) { + // if signature sorting failed sort by id + compare = getId().compareTo(o.getId()); + } + if (compare == 0) { + // if still no difference sort by enclosing type name + TypeElement enclosingType1 = ElementUtils.findNearestEnclosingType(getMethod()); + TypeElement enclosingType2 = ElementUtils.findNearestEnclosingType(o.getMethod()); + compare = enclosingType1.getQualifiedName().toString().compareTo(enclosingType2.getQualifiedName().toString()); + } + return compare; + } + + public List getParametersAfter(Parameter genericParameter) { + boolean found = false; + List foundParameters = new ArrayList<>(); + for (Parameter param : getParameters()) { + if (param.getLocalName().equals(genericParameter.getLocalName())) { + found = true; + } else if (found) { + foundParameters.add(param); + } + } + return foundParameters; + } + + public int compareBySignature(TemplateMethod compareMethod) { + final TypeSystemData typeSystem = getTemplate().getTypeSystem(); + if (typeSystem != compareMethod.getTemplate().getTypeSystem()) { + throw new IllegalStateException("Cannot compare two methods with different type systems."); + } + + List signature1 = getSignatureTypes(this); + List signature2 = getSignatureTypes(compareMethod); + + int result = 0; + for (int i = 0; i < Math.max(signature1.size(), signature2.size()); i++) { + TypeMirror t1 = i < signature1.size() ? signature1.get(i) : null; + TypeMirror t2 = i < signature2.size() ? signature2.get(i) : null; + result = compareParameter(typeSystem, t1, t2); + if (result != 0) { + break; + } + } + + return result; + } + + protected static int compareParameter(TypeSystemData data, TypeMirror signature1, TypeMirror signature2) { + if (signature1 == null) { + return 1; + } else if (signature2 == null) { + return -1; + } + + if (ElementUtils.typeEquals(signature1, signature2)) { + return 0; + } + + int index1 = data.findType(signature1); + int index2 = data.findType(signature2); + if (index1 != -1 && index2 != -1) { + return index1 - index2; + } + + // TODO this version if subclass of should be improved. + if (signature1.getKind() == TypeKind.DECLARED && signature2.getKind() == TypeKind.DECLARED) { + TypeElement element1 = ElementUtils.fromTypeMirror(signature1); + TypeElement element2 = ElementUtils.fromTypeMirror(signature2); + + if (ElementUtils.getDirectSuperTypes(element1).contains(element2)) { + return -1; + } else if (ElementUtils.getDirectSuperTypes(element2).contains(element1)) { + return 1; + } + } + return ElementUtils.getSimpleName(signature1).compareTo(ElementUtils.getSimpleName(signature2)); + } + + public static List getSignatureTypes(TemplateMethod method) { + List types = new ArrayList<>(); + for (Parameter param : method.getSignatureParameters()) { + types.add(param.getType()); + } + return types; + } + + public static class TypeSignature implements Iterable, Comparable { + + private final List types; + + public TypeSignature() { + this.types = new ArrayList<>(); + } + + public TypeSignature(List signature) { + this.types = signature; + } + + @Override + public int hashCode() { + return types.hashCode(); + } + + public int size() { + return types.size(); + } + + public TypeData get(int index) { + return types.get(index); + } + + public int compareTo(TypeSignature other) { + if (this == other) { + return 0; + } else if (types.size() != other.types.size()) { + return types.size() - other.types.size(); + } else if (types.isEmpty()) { + return 0; + } + + for (int i = 0; i < types.size(); i++) { + TypeData type1 = types.get(i); + TypeData type2 = other.types.get(i); + + int comparison = type1.compareTo(type2); + if (comparison != 0) { + return comparison; + } + } + + return 0; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof TypeSignature) { + return ((TypeSignature) obj).types.equals(types); + } + return super.equals(obj); + } + + public Iterator iterator() { + return types.iterator(); + } + + @Override + public String toString() { + return types.toString(); + } + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCastData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCastData.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +public class TypeCastData extends TemplateMethod { + + private final TypeData targetType; + private final TypeData sourceType; + + public TypeCastData(TemplateMethod method, TypeData sourceType, TypeData targetType) { + super(method); + this.sourceType = sourceType; + this.targetType = targetType; + } + + public boolean isGeneric() { + return sourceType.isGeneric(); + } + + public TypeData getSourceType() { + return sourceType; + } + + public TypeData getTargetType() { + return targetType; + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCheckData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCheckData.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +public class TypeCheckData extends TemplateMethod { + + private final TypeData checkedType; + private final TypeData valueType; + + public TypeCheckData(TemplateMethod method, TypeData checkedType, TypeData valueType) { + super(method); + this.checkedType = checkedType; + this.valueType = valueType; + } + + public boolean isGeneric() { + return valueType.isGeneric(); + } + + public TypeData getCheckedType() { + return checkedType; + } + + public TypeData getValueType() { + return valueType; + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeData.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.java.*; + +public class TypeData extends MessageContainer implements Comparable { + + private final TypeSystemData typeSystem; + private final AnnotationValue annotationValue; + private final TypeMirror primitiveType; + private final TypeMirror boxedType; + + private final int index; + private final List typeCasts = new ArrayList<>(); + private final List typeChecks = new ArrayList<>(); + + public TypeData(TypeSystemData typeSystem, int index, AnnotationValue value, TypeMirror primitiveType, TypeMirror boxedType) { + this.index = index; + this.typeSystem = typeSystem; + this.annotationValue = value; + this.primitiveType = primitiveType; + this.boxedType = boxedType; + } + + public int getIndex() { + return index; + } + + @Override + public Element getMessageElement() { + return typeSystem.getMessageElement(); + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return typeSystem.getMessageAnnotation(); + } + + @Override + public AnnotationValue getMessageAnnotationValue() { + return annotationValue; + } + + public void addTypeCast(TypeCastData typeCast) { + this.typeCasts.add(typeCast); + } + + public void addTypeCheck(TypeCheckData typeCheck) { + this.typeChecks.add(typeCheck); + } + + public List getTypeCasts() { + return typeCasts; + } + + public List getTypeChecks() { + return typeChecks; + } + + public TypeSystemData getTypeSystem() { + return typeSystem; + } + + public TypeMirror getPrimitiveType() { + return primitiveType; + } + + public TypeMirror getBoxedType() { + return boxedType; + } + + public boolean isGeneric() { + return ElementUtils.typeEquals(boxedType, getTypeSystem().getGenericType()); + } + + public boolean isVoid() { + if (getTypeSystem().getVoidType() == null) { + return false; + } + return ElementUtils.typeEquals(boxedType, getTypeSystem().getVoidType().getBoxedType()); + } + + public int compareTo(TypeData o) { + if (this.equals(o)) { + return 0; + } + return index - o.index; + } + + @Override + public int hashCode() { + return Objects.hash(index, primitiveType); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof TypeData)) { + return false; + } + TypeData otherType = (TypeData) obj; + return index == otherType.index && ElementUtils.typeEquals(primitiveType, otherType.primitiveType); + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + ElementUtils.getSimpleName(primitiveType) + "]"; + } + + public boolean equalsType(TypeData actualTypeData) { + return ElementUtils.typeEquals(boxedType, actualTypeData.boxedType); + } + + public boolean needsCastTo(TypeData targetType) { + return ElementUtils.needsCastTo(getPrimitiveType(), targetType.getPrimitiveType()); + } + + public boolean needsCastTo(TypeMirror targetType) { + return ElementUtils.needsCastTo(getPrimitiveType(), targetType); + } + + public boolean isPrimitive() { + return ElementUtils.isPrimitive(getPrimitiveType()); + } + + public boolean isImplicitSubtypeOf(TypeData other) { + List casts = other.getTypeSystem().lookupByTargetType(other); + for (ImplicitCastData cast : casts) { + if (isSubtypeOf(cast.getSourceType())) { + return true; + } + } + return isSubtypeOf(other); + } + + public boolean isSubtypeOf(TypeData other) { + return ElementUtils.isSubtype(boxedType, other.boxedType); + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; + +public class TypeSystemData extends Template { + + private List types; + private List primitiveTypeMirrors = new ArrayList<>(); + private List boxedTypeMirrors = new ArrayList<>(); + private Map cachedTypes = new HashMap<>(); + + private List implicitCasts; + private List casts; + private List checks; + + private TypeMirror genericType; + private TypeData voidType; + + public TypeSystemData(ProcessorContext context, TypeElement templateType, AnnotationMirror annotation) { + super(context, templateType, null, annotation); + } + + @Override + public TypeSystemData getTypeSystem() { + return this; + } + + public void setTypes(List types) { + this.types = types; + if (types != null) { + for (TypeData typeData : types) { + primitiveTypeMirrors.add(typeData.getPrimitiveType()); + boxedTypeMirrors.add(typeData.getBoxedType()); + cachedTypes.put(ElementUtils.getUniqueIdentifier(typeData.getPrimitiveType()), typeData); + cachedTypes.put(ElementUtils.getUniqueIdentifier(typeData.getBoxedType()), typeData); + } + } + } + + public void setImplicitCasts(List implicitCasts) { + this.implicitCasts = implicitCasts; + } + + public List getImplicitCasts() { + return implicitCasts; + } + + public void setCasts(List casts) { + this.casts = casts; + } + + public void setChecks(List checks) { + this.checks = checks; + } + + public void setGenericType(TypeMirror genericType) { + this.genericType = genericType; + } + + public void setVoidType(TypeData voidType) { + this.voidType = voidType; + } + + @Override + protected List findChildContainers() { + List sinks = new ArrayList<>(); + if (types != null) { + sinks.addAll(types); + } + if (checks != null) { + sinks.addAll(checks); + } + if (casts != null) { + sinks.addAll(casts); + } + if (implicitCasts != null) { + sinks.addAll(implicitCasts); + } + return sinks; + } + + public TypeData getVoidType() { + return voidType; + } + + public List getBoxedTypeMirrors() { + return boxedTypeMirrors; + } + + public List getPrimitiveTypeMirrors() { + return primitiveTypeMirrors; + } + + public Set getTypeIdentifiers() { + return cachedTypes.keySet(); + } + + public List getTypes() { + return types; + } + + public TypeMirror getGenericType() { + return genericType; + } + + public TypeData getGenericTypeData() { + TypeData result = types.get(types.size() - 2); + assert result.getBoxedType() == genericType; + return result; + } + + public TypeData findType(String simpleName) { + for (TypeData type : types) { + if (ElementUtils.getSimpleName(type.getBoxedType()).equals(simpleName)) { + return type; + } + } + return null; + } + + public TypeData findTypeData(TypeMirror type) { + if (ElementUtils.typeEquals(voidType.getPrimitiveType(), type)) { + return voidType; + } + + int index = findType(type); + if (index == -1) { + return null; + } + return types.get(index); + } + + public int findType(TypeMirror type) { + TypeData data = cachedTypes.get(ElementUtils.getUniqueIdentifier(type)); + if (data != null) { + return data.getIndex(); + } + return -1; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[template = " + ElementUtils.getSimpleName(getTemplateType()) + ", types = " + types + "]"; + } + + public List lookupByTargetType(TypeData targetType) { + if (getImplicitCasts() == null) { + return Collections.emptyList(); + } + List foundCasts = new ArrayList<>(); + for (ImplicitCastData cast : getImplicitCasts()) { + if (cast.getTargetType().equals(targetType)) { + foundCasts.add(cast); + } + } + return foundCasts; + } + + public ImplicitCastData lookupCast(TypeData sourceType, TypeData targetType) { + if (getImplicitCasts() == null) { + return null; + } + for (ImplicitCastData cast : getImplicitCasts()) { + if (cast.getSourceType().equals(sourceType) && cast.getTargetType().equals(targetType)) { + return cast; + } + } + return null; + } + + public List lookupSourceTypes(TypeData type) { + List sourceTypes = new ArrayList<>(); + sourceTypes.add(type); + if (getImplicitCasts() != null) { + for (ImplicitCastData cast : getImplicitCasts()) { + if (cast.getTargetType() == type) { + sourceTypes.add(cast.getSourceType()); + } + } + } + Collections.sort(sourceTypes); + return sourceTypes; + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastData.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.node; - -import java.util.*; - -import com.oracle.truffle.dsl.processor.template.*; - -public class CreateCastData extends TemplateMethod { - - private final List childNames; - - public CreateCastData(TemplateMethod method, List childNames) { - super(method); - this.childNames = childNames; - } - - public List getChildNames() { - return childNames; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.node; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.template.*; - -public class CreateCastParser extends NodeMethodParser { - - public CreateCastParser(ProcessorContext context, NodeData operation) { - super(context, operation); - } - - @Override - public Class getAnnotationType() { - return CreateCast.class; - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - List childNames = Utils.getAnnotationValueList(String.class, mirror, "value"); - NodeChildData foundChild = null; - for (String childName : childNames) { - foundChild = getNode().findChild(childName); - if (foundChild != null) { - break; - } - } - TypeMirror baseType = getContext().getTruffleTypes().getNode(); - if (foundChild != null) { - baseType = foundChild.getOriginalType(); - } - - MethodSpec spec = new MethodSpec(new InheritsParameterSpec(getContext(), "child", baseType)); - addDefaultFieldMethodSpec(spec); - ParameterSpec childSpec = new ParameterSpec("castedChild", baseType); - childSpec.setSignature(true); - spec.addRequired(childSpec); - return spec; - } - - @Override - public CreateCastData create(TemplateMethod method, boolean invalid) { - AnnotationMirror mirror = method.getMarkerAnnotation(); - List childNames = Utils.getAnnotationValueList(String.class, mirror, "value"); - CreateCastData cast = new CreateCastData(method, childNames); - AnnotationValue value = Utils.getAnnotationValue(mirror, "value"); - TypeMirror type = null; - if (childNames == null || childNames.isEmpty()) { - cast.addError(value, "No value specified but required."); - return cast; - } - - for (String childName : childNames) { - NodeChildData child = getNode().findChild(childName); - if (child == null) { - // error - cast.addError(value, "Specified child '%s' not found.", childName); - continue; - } - if (type == null) { - type = child.getNodeType(); - } else if (!Utils.typeEquals(type, child.getNodeType())) { - cast.addError(value, "All child nodes for a cast must have the same node type."); - continue; - } - } - return cast; - } - - private static class InheritsParameterSpec extends ParameterSpec { - - private final ProcessorContext context; - - public InheritsParameterSpec(ProcessorContext context, String name, TypeMirror... allowedTypes) { - super(name, Arrays.asList(allowedTypes)); - this.context = context; - } - - @Override - public boolean matches(TypeMirror actualType) { - boolean found = false; - for (TypeMirror specType : getAllowedTypes()) { - if (Utils.isAssignable(context, actualType, specType)) { - found = true; - break; - } - } - return found; - } - } -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeData.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.node; - -import javax.lang.model.element.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.template.*; -import com.oracle.truffle.dsl.processor.typesystem.*; - -public class ExecutableTypeData extends TemplateMethod { - - private final TypeSystemData typeSystem; - private final TypeData type; - - public ExecutableTypeData(TemplateMethod method, ExecutableElement executable, TypeSystemData typeSystem, TypeData type) { - super(method, executable); - this.typeSystem = typeSystem; - this.type = type; - if (executable.getParameters().size() < method.getMethod().getParameters().size()) { - throw new IllegalArgumentException(String.format("Method parameter count mismatch %s != %s.", executable.getParameters(), method.getMethod().getParameters())); - } - } - - public TypeData getType() { - return type; - } - - public TypeSystemData getTypeSystem() { - return typeSystem; - } - - public boolean hasFrame() { - return getMethod().getParameters().size() > 0; - } - - public boolean hasUnexpectedValue(ProcessorContext context) { - return Utils.canThrowType(getMethod().getThrownTypes(), context.getTruffleTypes().getUnexpectedValueException()); - } - - public boolean isFinal() { - return getMethod().getModifiers().contains(Modifier.FINAL); - } - - public boolean isAbstract() { - return getMethod().getModifiers().contains(Modifier.ABSTRACT); - } - - public int getEvaluatedCount() { - int count = 0; - for (ActualParameter parameter : getParameters()) { - if (parameter.getSpecification().isSignature()) { - count++; - } - } - return count; - } - - @Override - public int hashCode() { - return type.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof ExecutableTypeData) { - return type.equals(((ExecutableTypeData) obj).type); - } - return super.equals(obj); - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.node; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.template.*; -import com.oracle.truffle.dsl.processor.typesystem.*; - -public class ExecutableTypeMethodParser extends NodeMethodParser { - - public ExecutableTypeMethodParser(ProcessorContext context, NodeData node) { - super(context, node); - setEmitErrors(false); - setParseNullOnError(false); - setUseVarArgs(true); - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - MethodSpec spec = createDefaultMethodSpec(method, mirror, false, null); - List requiredSpecs = new ArrayList<>(spec.getRequired()); - spec.getRequired().clear(); - - List allowedTypes = getNode().getTypeSystem().getPrimitiveTypeMirrors(); - for (ParameterSpec originalSpec : requiredSpecs) { - spec.addRequired(new ParameterSpec(originalSpec, allowedTypes)); - } - spec.setIgnoreAdditionalSpecifications(true); - spec.setIgnoreAdditionalParameters(true); - spec.setVariableRequiredParameters(true); - // varargs - ParameterSpec otherParameters = new ParameterSpec("other", allowedTypes); - otherParameters.setSignature(true); - spec.addRequired(otherParameters); - return spec; - } - - @Override - public final boolean isParsable(ExecutableElement method) { - if (method.getModifiers().contains(Modifier.STATIC)) { - return false; - } else if (method.getModifiers().contains(Modifier.NATIVE)) { - return false; - } - return method.getSimpleName().toString().startsWith("execute"); - } - - @Override - protected List nodeTypeMirrors(NodeData nodeData) { - List types = new ArrayList<>(getNode().getTypeSystem().getPrimitiveTypeMirrors()); - types.add(getNode().getTypeSystem().getVoidType().getPrimitiveType()); - return types; - } - - @Override - public ExecutableTypeData create(TemplateMethod method, boolean invalid) { - TypeData resolvedType = method.getReturnType().getTypeSystemType(); - return new ExecutableTypeData(method, method.getMethod(), getNode().getTypeSystem(), resolvedType); - } - - @Override - public Class getAnnotationType() { - return null; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.node; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.node.SpecializationData.SpecializationKind; -import com.oracle.truffle.dsl.processor.template.*; - -public class GenericParser extends NodeMethodParser { - - public GenericParser(ProcessorContext context, NodeData node) { - super(context, node); - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - return createDefaultMethodSpec(method, mirror, true, null); - } - - @Override - protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) { - List execTypes = execution.getChild().findGenericExecutableTypes(getContext()); - List types = new ArrayList<>(); - for (ExecutableTypeData type : execTypes) { - types.add(type.getType().getPrimitiveType()); - } - ParameterSpec spec = new ParameterSpec(execution.getName(), types); - spec.setExecution(execution); - return spec; - } - - @Override - public SpecializationData create(TemplateMethod method, boolean invalid) { - return new SpecializationData(getNode(), method, SpecializationKind.GENERIC); - } - - @Override - public Class getAnnotationType() { - return Generic.class; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeChildData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeChildData.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,169 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.node; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.template.*; -import com.oracle.truffle.dsl.processor.typesystem.*; - -public class NodeChildData extends MessageContainer { - - public enum Cardinality { - ONE, - MANY; - - public boolean isMany() { - return this == MANY; - } - - public boolean isOne() { - return this == ONE; - } - } - - private NodeData parentNode; - private final Element sourceElement; - private final AnnotationMirror sourceAnnotationMirror; - private final String name; - private final TypeMirror type; - private final TypeMirror originalType; - private final Element accessElement; - private final Cardinality cardinality; - - private List executeWith = Collections.emptyList(); - - private NodeData childNode; - - public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, TypeMirror originalNodeType, Element accessElement, Cardinality cardinality) { - this.sourceElement = sourceElement; - this.sourceAnnotationMirror = sourceMirror; - this.name = name; - this.type = nodeType; - this.originalType = originalNodeType; - this.accessElement = accessElement; - this.cardinality = cardinality; - } - - void setParentNode(NodeData parentNode) { - this.parentNode = parentNode; - } - - public List getExecuteWith() { - return executeWith; - } - - void setExecuteWith(List executeWith) { - this.executeWith = executeWith; - } - - public boolean needsImplicitCast(ProcessorContext context) { - if (!parentNode.needsRewrites(context)) { - return false; - } - - boolean used = false; - for (NodeExecutionData execution : parentNode.getChildExecutions()) { - if (execution.getChild() == this) { - used = true; - break; - } - } - if (!used) { - return false; - } - - return getNodeData().getTypeSystem().getImplicitCasts() != null && !getNodeData().getTypeSystem().getImplicitCasts().isEmpty(); - } - - public ExecutableTypeData findExecutableType(ProcessorContext context, TypeData targetType) { - ExecutableTypeData executableType = childNode.findExecutableType(targetType, getExecuteWith().size()); - if (executableType == null) { - executableType = findAnyGenericExecutableType(context); - } - return executableType; - } - - public List findGenericExecutableTypes(ProcessorContext context) { - return childNode.findGenericExecutableTypes(context, getExecuteWith().size()); - } - - public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context) { - return childNode.findAnyGenericExecutableType(context, getExecuteWith().size()); - } - - public List findExecutableTypes() { - return childNode.getExecutableTypes(getExecuteWith().size()); - } - - public TypeMirror getOriginalType() { - return originalType; - } - - @Override - public Element getMessageElement() { - return sourceElement; - } - - @Override - public AnnotationMirror getMessageAnnotation() { - return sourceAnnotationMirror; - } - - void setNode(NodeData nodeData) { - this.childNode = nodeData; - if (nodeData != null) { - getMessages().addAll(nodeData.collectMessages()); - } - } - - public Element getAccessElement() { - return accessElement; - } - - public TypeMirror getNodeType() { - return type; - } - - public Cardinality getCardinality() { - return cardinality; - } - - public NodeData getNodeData() { - return childNode; - } - - public String getName() { - return name; - } - - @Override - public String toString() { - return "NodeFieldData[name=" + getName() + ", kind=" + cardinality + ", node=" + getNodeData() + "]"; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2968 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.node; - -import static com.oracle.truffle.dsl.processor.Utils.*; -import static javax.lang.model.element.Modifier.*; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; - -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.ast.*; -import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality; -import com.oracle.truffle.dsl.processor.node.SpecializationGroup.TypeGuard; -import com.oracle.truffle.dsl.processor.template.*; -import com.oracle.truffle.dsl.processor.typesystem.*; - -public class NodeCodeGenerator extends CompilationUnitFactory { - - private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode"; - - private static final String EXECUTE_GENERIC_NAME = "executeGeneric0"; - private static final String EXECUTE_SPECIALIZE_NAME = "executeAndSpecialize0"; - private static final String EXECUTE_POLYMORPHIC_NAME = "executePolymorphic0"; - - private static final String UPDATE_TYPES_NAME = "updateTypes"; - private static final String COPY_WITH_CONSTRUCTOR_NAME = "copyWithConstructor"; - private static final String CREATE_SPECIALIZATION_NAME = "createSpecialization"; - - public NodeCodeGenerator(ProcessorContext context) { - super(context); - } - - private TypeMirror getUnexpectedValueException() { - return getContext().getTruffleTypes().getUnexpectedValueException(); - } - - private static String factoryClassName(NodeData node) { - return node.getNodeId() + "Factory"; - } - - private static String nodeSpecializationClassName(SpecializationData specialization) { - String nodeid = resolveNodeId(specialization.getNode()); - String name = Utils.firstLetterUpperCase(nodeid); - name += Utils.firstLetterUpperCase(specialization.getId()); - name += "Node"; - return name; - } - - private static String nodePolymorphicClassName(NodeData node) { - return Utils.firstLetterUpperCase(resolveNodeId(node)) + "PolymorphicNode"; - } - - private static String resolveNodeId(NodeData node) { - String nodeid = node.getNodeId(); - if (nodeid.endsWith("Node") && !nodeid.equals("Node")) { - nodeid = nodeid.substring(0, nodeid.length() - 4); - } - return nodeid; - } - - private static String valueNameEvaluated(ActualParameter targetParameter) { - return valueName(targetParameter) + "Evaluated"; - } - - private static String implicitTypeName(ActualParameter param) { - return param.getLocalName() + "ImplicitType"; - } - - private static String polymorphicTypeName(ActualParameter param) { - return param.getLocalName() + "PolymorphicType"; - } - - private static String valueName(ActualParameter param) { - return param.getLocalName(); - } - - private static CodeTree createAccessChild(NodeExecutionData targetExecution, String thisReference) { - String reference = thisReference; - if (reference == null) { - reference = "this"; - } - CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); - Element accessElement = targetExecution.getChild().getAccessElement(); - if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) { - builder.string(reference).string(".").string(targetExecution.getChild().getName()); - } else if (accessElement.getKind() == ElementKind.FIELD) { - builder.string(reference).string(".").string(accessElement.getSimpleName().toString()); - } else { - throw new AssertionError(); - } - if (targetExecution.isIndexed()) { - builder.string("[" + targetExecution.getIndex() + "]"); - } - return builder.getRoot(); - } - - private static String castValueName(ActualParameter parameter) { - return valueName(parameter) + "Cast"; - } - - private void addInternalValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame, boolean evaluated) { - if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { - method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue")); - } - for (ActualParameter parameter : specialization.getParameters()) { - ParameterSpec spec = parameter.getSpecification(); - if (forceFrame && spec.getName().equals("frame")) { - continue; - } - if (spec.isLocal()) { - continue; - } - - String name = valueName(parameter); - if (evaluated && spec.isSignature()) { - name = valueNameEvaluated(parameter); - } - - method.addParameter(new CodeVariableElement(parameter.getType(), name)); - } - } - - private void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, - Map customNames) { - if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { - builder.string("frameValue"); - } - for (ActualParameter parameter : specialization.getParameters()) { - ParameterSpec spec = parameter.getSpecification(); - if (forceFrame && spec.getName().equals("frame")) { - continue; - } - - if (parameter.getSpecification().isLocal()) { - continue; - } - - ActualParameter sourceParameter = source.findParameter(parameter.getLocalName()); - - if (customNames != null && customNames.containsKey(parameter.getLocalName())) { - builder.string(customNames.get(parameter.getLocalName())); - } else if (unexpectedValueName != null && parameter.getLocalName().equals(unexpectedValueName)) { - builder.cast(parameter.getType(), CodeTreeBuilder.singleString("ex.getResult()")); - } else if (sourceParameter != null) { - builder.string(valueName(sourceParameter, parameter)); - } else { - builder.string(valueName(parameter)); - } - } - } - - private String valueName(ActualParameter sourceParameter, ActualParameter targetParameter) { - if (!sourceParameter.getSpecification().isSignature()) { - return valueName(targetParameter); - } else if (sourceParameter.getTypeSystemType() != null && targetParameter.getTypeSystemType() != null) { - if (sourceParameter.getTypeSystemType().needsCastTo(getContext(), targetParameter.getTypeSystemType())) { - return castValueName(targetParameter); - } - } - return valueName(targetParameter); - } - - private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName, - String... customSignatureValueNames) { - CodeTreeBuilder builder = parent.create(); - - boolean castedValues = sourceMethod != targetMethod; - - builder.startGroup(); - ExecutableElement method = targetMethod.getMethod(); - if (method == null) { - throw new UnsupportedOperationException(); - } - TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement()); - NodeData node = (NodeData) targetMethod.getTemplate(); - - if (target == null) { - boolean accessible = targetMethod.canBeAccessedByInstanceOf(getContext(), node.getNodeType()); - if (accessible) { - if (builder.findMethod().getModifiers().contains(STATIC)) { - if (method.getModifiers().contains(STATIC)) { - builder.type(targetClass.asType()); - } else { - builder.string(THIS_NODE_LOCAL_VAR_NAME); - } - } else { - if (targetMethod instanceof ExecutableTypeData) { - builder.string("this"); - } else { - builder.string("super"); - } - } - } else { - if (method.getModifiers().contains(STATIC)) { - builder.type(targetClass.asType()); - } else { - ActualParameter firstParameter = null; - for (ActualParameter searchParameter : targetMethod.getParameters()) { - if (searchParameter.getSpecification().isSignature()) { - firstParameter = searchParameter; - break; - } - } - if (firstParameter == null) { - throw new AssertionError(); - } - - ActualParameter sourceParameter = sourceMethod.findParameter(firstParameter.getLocalName()); - - if (castedValues && sourceParameter != null) { - builder.string(valueName(sourceParameter, firstParameter)); - } else { - builder.string(valueName(firstParameter)); - } - } - } - builder.string("."); - } else { - builder.tree(target); - } - builder.startCall(method.getSimpleName().toString()); - - int signatureIndex = 0; - - for (ActualParameter targetParameter : targetMethod.getParameters()) { - ActualParameter valueParameter = null; - if (sourceMethod != null) { - valueParameter = sourceMethod.findParameter(targetParameter.getLocalName()); - } - if (valueParameter == null) { - valueParameter = targetParameter; - } - TypeMirror targetType = targetParameter.getType(); - TypeMirror valueType = null; - if (valueParameter != null) { - valueType = valueParameter.getType(); - } - - if (signatureIndex < customSignatureValueNames.length && targetParameter.getSpecification().isSignature()) { - builder.string(customSignatureValueNames[signatureIndex]); - signatureIndex++; - } else if (targetParameter.getSpecification().isLocal()) { - builder.startGroup(); - if (builder.findMethod().getModifiers().contains(Modifier.STATIC)) { - builder.string(THIS_NODE_LOCAL_VAR_NAME).string("."); - } else { - builder.string("this."); - } - builder.string(targetParameter.getSpecification().getName()); - builder.end(); - } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) { - builder.cast(targetParameter.getType(), CodeTreeBuilder.singleString("ex.getResult()")); - } else if (!Utils.needsCastTo(getContext(), valueType, targetType)) { - builder.startGroup(); - builder.string(valueName(targetParameter)); - builder.end(); - } else { - builder.string(castValueName(targetParameter)); - } - } - - builder.end().end(); - - return builder.getRoot(); - } - - private static String baseClassName(NodeData node) { - String nodeid = resolveNodeId(node); - String name = Utils.firstLetterUpperCase(nodeid); - name += "BaseNode"; - return name; - } - - private static CodeTree createCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder parent, NodeData node, String methodName, CodeTree... args) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - startCallTypeSystemMethod(context, builder, node.getTypeSystem(), methodName); - for (CodeTree arg : args) { - builder.tree(arg); - } - builder.end().end(); - return builder.getRoot(); - } - - private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body, TypeSystemData typeSystem, String methodName) { - VariableElement singleton = TypeSystemCodeGenerator.findSingleton(context, typeSystem); - assert singleton != null; - - body.startGroup(); - body.staticReference(singleton.getEnclosingElement().asType(), singleton.getSimpleName().toString()); - body.string(".").startCall(methodName); - } - - /** - *

    -     * variant1 $condition != null
    -     *
    -     * $type $name = defaultValue($type);
    -     * if ($condition) {
    -     *     $name = $value;
    -     * }
    -     *
    -     * variant2 $condition != null
    -     * $type $name = $value;
    -     * 
    - * - * . - */ - private static CodeTree createLazyAssignment(CodeTreeBuilder parent, String name, TypeMirror type, CodeTree condition, CodeTree value) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - if (condition == null) { - builder.declaration(type, name, value); - } else { - builder.declaration(type, name, new CodeTreeBuilder(parent).defaultValue(type).getRoot()); - - builder.startIf().tree(condition).end(); - builder.startBlock(); - builder.startStatement(); - builder.string(name); - builder.string(" = "); - builder.tree(value); - builder.end(); // statement - builder.end(); // block - } - return builder.getRoot(); - } - - protected void emitEncounteredSynthetic(CodeTreeBuilder builder, TemplateMethod current) { - CodeTreeBuilder nodes = builder.create(); - CodeTreeBuilder arguments = builder.create(); - nodes.startCommaGroup(); - arguments.startCommaGroup(); - boolean empty = true; - for (ActualParameter parameter : current.getParameters()) { - NodeExecutionData executionData = parameter.getSpecification().getExecution(); - if (executionData != null) { - if (executionData.isShortCircuit()) { - nodes.nullLiteral(); - arguments.string(valueName(parameter.getPreviousParameter())); - } - nodes.tree(createAccessChild(executionData, null)); - arguments.string(valueName(parameter)); - empty = false; - } - } - nodes.end(); - arguments.end(); - - builder.startThrow().startNew(getContext().getType(UnsupportedSpecializationException.class)); - builder.string("this"); - builder.startNewArray(getContext().getTruffleTypes().getNodeArray(), null); - - builder.tree(nodes.getRoot()); - builder.end(); - if (!empty) { - builder.tree(arguments.getRoot()); - } - builder.end().end(); - } - - private static List findUserConstructors(TypeMirror nodeType) { - List constructors = new ArrayList<>(); - for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(nodeType).getEnclosedElements())) { - if (constructor.getModifiers().contains(PRIVATE)) { - continue; - } - if (isCopyConstructor(constructor)) { - continue; - } - constructors.add(constructor); - } - - if (constructors.isEmpty()) { - constructors.add(new CodeExecutableElement(null, Utils.getSimpleName(nodeType))); - } - - return constructors; - } - - private static ExecutableElement findCopyConstructor(TypeMirror type) { - for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(type).getEnclosedElements())) { - if (constructor.getModifiers().contains(PRIVATE)) { - continue; - } - if (isCopyConstructor(constructor)) { - return constructor; - } - } - - return null; - } - - private static boolean isCopyConstructor(ExecutableElement element) { - if (element.getParameters().size() != 1) { - return false; - } - VariableElement var = element.getParameters().get(0); - TypeElement enclosingType = Utils.findNearestEnclosingType(var); - if (Utils.typeEquals(var.asType(), enclosingType.asType())) { - return true; - } - List types = Utils.getDirectSuperTypes(enclosingType); - for (TypeElement type : types) { - if (!(type instanceof CodeTypeElement)) { - // no copy constructors which are not generated types - return false; - } - - if (Utils.typeEquals(var.asType(), type.asType())) { - return true; - } - } - return false; - } - - @Override - @SuppressWarnings("unchecked") - protected void createChildren(NodeData node) { - List casts = new ArrayList<>(getElement().getEnclosedElements()); - getElement().getEnclosedElements().clear(); - - Map> childTypes = new LinkedHashMap<>(); - for (NodeData nodeChild : node.getEnclosingNodes()) { - NodeCodeGenerator generator = new NodeCodeGenerator(getContext()); - childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements()); - } - - if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) { - NodeFactoryFactory factory = new NodeFactoryFactory(context, childTypes); - add(factory, node); - factory.getElement().getEnclosedElements().addAll(casts); - } - } - - protected CodeTree createCastType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) { - if (targetType == null) { - return value; - } else if (sourceType != null && !sourceType.needsCastTo(getContext(), targetType)) { - return value; - } - - CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); - String targetMethodName; - if (expect) { - targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType); - } else { - targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType); - } - startCallTypeSystemMethod(getContext(), builder, typeSystem, targetMethodName); - builder.tree(value); - builder.end().end(); - return builder.getRoot(); - } - - protected CodeTree createExpectType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, CodeTree expression) { - return createCastType(typeSystem, sourceType, targetType, true, expression); - } - - public CodeTree createDeoptimize(CodeTreeBuilder parent) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - builder.startStatement(); - builder.startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end(); - builder.end(); - return builder.getRoot(); - } - - private class NodeFactoryFactory extends ClassElementFactory { - - private final Map> childTypes; - private CodeTypeElement generatedNode; - - public NodeFactoryFactory(ProcessorContext context, Map> childElements) { - super(context); - this.childTypes = childElements; - } - - @Override - protected CodeTypeElement create(NodeData node) { - Modifier visibility = Utils.getVisibility(node.getTemplateType().getModifiers()); - CodeTypeElement clazz = createClass(node, modifiers(), factoryClassName(node), null, false); - if (visibility != null) { - clazz.getModifiers().add(visibility); - } - clazz.getModifiers().add(Modifier.FINAL); - clazz.add(createConstructorUsingFields(modifiers(PRIVATE), clazz)); - return clazz; - } - - @Override - protected void createChildren(NodeData node) { - CodeTypeElement clazz = getElement(); - - Modifier createVisibility = Utils.getVisibility(clazz.getModifiers()); - - CodeTypeElement polymorphicNode = null; - if (node.needsFactory()) { - NodeBaseFactory factory = new NodeBaseFactory(context); - add(factory, node.getGenericSpecialization() == null ? node.getSpecializations().get(0) : node.getGenericSpecialization()); - generatedNode = factory.getElement(); - - if (node.needsRewrites(context)) { - clazz.add(createCreateGenericMethod(node, createVisibility)); - } - - createFactoryMethods(node, clazz, createVisibility); - - for (SpecializationData specialization : node.getSpecializations()) { - if (!specialization.isReachable()) { - continue; - } - - if (specialization.isPolymorphic() && node.isPolymorphic()) { - PolymorphicNodeFactory polymorphicFactory = new PolymorphicNodeFactory(getContext(), generatedNode); - add(polymorphicFactory, specialization); - polymorphicNode = polymorphicFactory.getElement(); - continue; - } - - add(new SpecializedNodeFactory(context, generatedNode), specialization); - } - - TypeMirror nodeFactory = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(NodeFactory.class)), node.getNodeType()); - clazz.getImplements().add(nodeFactory); - clazz.add(createCreateNodeMethod(node)); - clazz.add(createGetNodeClassMethod(node)); - clazz.add(createGetNodeSignaturesMethod()); - clazz.add(createGetChildrenSignatureMethod(node)); - clazz.add(createGetInstanceMethod(node, createVisibility)); - clazz.add(createInstanceConstant(node, clazz.asType())); - } - - if (polymorphicNode != null) { - patchParameterType(clazz, UPDATE_TYPES_NAME, generatedNode.asType(), polymorphicNode.asType()); - } - - for (NodeData childNode : childTypes.keySet()) { - if (childNode.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { - continue; - } - - for (TypeElement type : childTypes.get(childNode)) { - Set typeModifiers = ((CodeTypeElement) type).getModifiers(); - Modifier visibility = Utils.getVisibility(type.getModifiers()); - typeModifiers.clear(); - if (visibility != null) { - typeModifiers.add(visibility); - } - - typeModifiers.add(Modifier.STATIC); - typeModifiers.add(Modifier.FINAL); - clazz.add(type); - } - } - - List children = node.getNodeDeclaringChildren(); - if (node.getDeclaringNode() == null && children.size() > 0) { - clazz.add(createGetFactories(node)); - } - - } - - private void patchParameterType(CodeTypeElement enclosingClass, String methodName, TypeMirror originalType, TypeMirror newType) { - for (TypeElement enclosedType : ElementFilter.typesIn(enclosingClass.getEnclosedElements())) { - CodeTypeElement type = (CodeTypeElement) enclosedType; - ExecutableElement method = type.getMethod(methodName); - for (VariableElement v : method.getParameters()) { - CodeVariableElement var = (CodeVariableElement) v; - if (Utils.typeEquals(var.getType(), originalType)) { - var.setType(newType); - } - } - } - } - - private CodeExecutableElement createGetNodeClassMethod(NodeData node) { - TypeMirror returnType = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(Class.class)), node.getNodeType()); - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeClass"); - CodeTreeBuilder builder = method.createBuilder(); - builder.startReturn().typeLiteral(node.getNodeType()).end(); - return method; - } - - private CodeExecutableElement createGetNodeSignaturesMethod() { - TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class)); - TypeMirror classType = getContext().getType(Class.class); - TypeMirror returnType = Utils.getDeclaredType(listType, Utils.getDeclaredType(listType, classType)); - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeSignatures"); - CodeTreeBuilder builder = method.createBuilder(); - builder.startReturn(); - builder.startStaticCall(getContext().getType(Arrays.class), "asList"); - List constructors = findUserConstructors(generatedNode.asType()); - for (ExecutableElement constructor : constructors) { - builder.tree(createAsList(builder, Utils.asTypeMirrors(constructor.getParameters()), classType)); - } - builder.end(); - builder.end(); - return method; - } - - private CodeExecutableElement createGetChildrenSignatureMethod(NodeData node) { - Types types = getContext().getEnvironment().getTypeUtils(); - TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class)); - TypeMirror classType = getContext().getType(Class.class); - TypeMirror nodeType = getContext().getTruffleTypes().getNode(); - TypeMirror wildcardNodeType = types.getWildcardType(nodeType, null); - classType = Utils.getDeclaredType(Utils.fromTypeMirror(classType), wildcardNodeType); - TypeMirror returnType = Utils.getDeclaredType(listType, classType); - - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getExecutionSignature"); - CodeTreeBuilder builder = method.createBuilder(); - - List signatureTypes = new ArrayList<>(); - assert !node.getSpecializations().isEmpty(); - SpecializationData data = node.getSpecializations().get(0); - - for (ActualParameter parameter : data.getSignatureParameters()) { - signatureTypes.add(parameter.getSpecification().getExecution().getNodeType()); - } - - builder.startReturn().tree(createAsList(builder, signatureTypes, classType)).end(); - return method; - } - - private CodeTree createAsList(CodeTreeBuilder parent, List types, TypeMirror elementClass) { - CodeTreeBuilder builder = parent.create(); - builder.startGroup(); - builder.type(getContext().getType(Arrays.class)); - builder.string(".<").type(elementClass).string(">"); - builder.startCall("asList"); - for (TypeMirror typeMirror : types) { - builder.typeLiteral(typeMirror); - } - builder.end().end(); - return builder.getRoot(); - } - - private CodeExecutableElement createCreateNodeMethod(NodeData node) { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNode"); - CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Object.class), "arguments"); - method.setVarArgs(true); - method.addParameter(arguments); - - CodeTreeBuilder builder = method.createBuilder(); - List signatures = findUserConstructors(generatedNode.asType()); - boolean ifStarted = false; - - for (ExecutableElement element : signatures) { - ifStarted = builder.startIf(ifStarted); - builder.string("arguments.length == " + element.getParameters().size()); - - int index = 0; - for (VariableElement param : element.getParameters()) { - if (Utils.isObject(param.asType())) { - continue; - } - builder.string(" && "); - if (!param.asType().getKind().isPrimitive()) { - builder.string("(arguments[" + index + "] == null || "); - } - builder.string("arguments[" + index + "] instanceof "); - builder.type(Utils.boxType(getContext(), param.asType())); - if (!param.asType().getKind().isPrimitive()) { - builder.string(")"); - } - index++; - } - builder.end(); - builder.startBlock(); - - builder.startReturn().startCall("create"); - index = 0; - for (VariableElement param : element.getParameters()) { - builder.startGroup(); - if (!Utils.isObject(param.asType())) { - builder.string("(").type(param.asType()).string(") "); - } - builder.string("arguments[").string(String.valueOf(index)).string("]"); - builder.end(); - index++; - } - builder.end().end(); - - builder.end(); // block - } - - builder.startElseBlock(); - builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)); - builder.doubleQuote("Invalid create signature."); - builder.end().end(); - builder.end(); // else block - return method; - } - - private ExecutableElement createGetInstanceMethod(NodeData node, Modifier visibility) { - TypeElement nodeFactoryType = Utils.fromTypeMirror(getContext().getType(NodeFactory.class)); - TypeMirror returnType = Utils.getDeclaredType(nodeFactoryType, node.getNodeType()); - - CodeExecutableElement method = new CodeExecutableElement(modifiers(), returnType, "getInstance"); - if (visibility != null) { - method.getModifiers().add(visibility); - } - method.getModifiers().add(Modifier.STATIC); - - String varName = instanceVarName(node); - - CodeTreeBuilder builder = method.createBuilder(); - builder.startIf(); - builder.string(varName).string(" == null"); - builder.end().startBlock(); - - builder.startStatement(); - builder.string(varName); - builder.string(" = "); - builder.startNew(factoryClassName(node)).end(); - builder.end(); - - builder.end(); - builder.startReturn().string(varName).end(); - return method; - } - - private String instanceVarName(NodeData node) { - if (node.getDeclaringNode() != null) { - return Utils.firstLetterLowerCase(factoryClassName(node)) + "Instance"; - } else { - return "instance"; - } - } - - private CodeVariableElement createInstanceConstant(NodeData node, TypeMirror factoryType) { - String varName = instanceVarName(node); - CodeVariableElement var = new CodeVariableElement(modifiers(), factoryType, varName); - var.getModifiers().add(Modifier.PRIVATE); - var.getModifiers().add(Modifier.STATIC); - return var; - } - - private ExecutableElement createGetFactories(NodeData node) { - List children = node.getNodeDeclaringChildren(); - if (node.needsFactory()) { - children.add(node); - } - - List nodeTypesList = new ArrayList<>(); - TypeMirror prev = null; - boolean allSame = true; - for (NodeData child : children) { - nodeTypesList.add(child.getNodeType()); - if (prev != null && !Utils.typeEquals(child.getNodeType(), prev)) { - allSame = false; - } - prev = child.getNodeType(); - } - TypeMirror commonNodeSuperType = Utils.getCommonSuperType(getContext(), nodeTypesList.toArray(new TypeMirror[nodeTypesList.size()])); - - Types types = getContext().getEnvironment().getTypeUtils(); - TypeMirror factoryType = getContext().getType(NodeFactory.class); - TypeMirror baseType; - if (allSame) { - baseType = Utils.getDeclaredType(Utils.fromTypeMirror(factoryType), commonNodeSuperType); - } else { - baseType = Utils.getDeclaredType(Utils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null)); - } - TypeMirror listType = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(List.class)), baseType); - - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), listType, "getFactories"); - - CodeTreeBuilder builder = method.createBuilder(); - builder.startReturn(); - builder.startStaticCall(getContext().getType(Arrays.class), "asList"); - - for (NodeData child : children) { - builder.startGroup(); - NodeData childNode = child; - List factories = new ArrayList<>(); - while (childNode.getDeclaringNode() != null) { - factories.add(childNode); - childNode = childNode.getDeclaringNode(); - } - Collections.reverse(factories); - for (NodeData nodeData : factories) { - builder.string(factoryClassName(nodeData)).string("."); - } - builder.string("getInstance()"); - builder.end(); - } - builder.end(); - builder.end(); - return method; - } - - private void createFactoryMethods(NodeData node, CodeTypeElement clazz, Modifier createVisibility) { - List constructors = findUserConstructors(generatedNode.asType()); - for (ExecutableElement constructor : constructors) { - clazz.add(createCreateMethod(node, createVisibility, constructor)); - } - } - - private CodeExecutableElement createCreateMethod(NodeData node, Modifier visibility, ExecutableElement constructor) { - CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), constructor); - method.setSimpleName(CodeNames.of("create")); - method.getModifiers().clear(); - if (visibility != null) { - method.getModifiers().add(visibility); - } - method.getModifiers().add(Modifier.STATIC); - method.setReturnType(node.getNodeType()); - - CodeTreeBuilder body = method.createBuilder(); - body.startReturn(); - if (node.getSpecializations().isEmpty()) { - body.nullLiteral(); - } else { - body.startCall(nodeSpecializationClassName(node.getSpecializations().get(0)), CREATE_SPECIALIZATION_NAME); - for (VariableElement var : method.getParameters()) { - body.string(var.getSimpleName().toString()); - } - body.end(); - } - body.end(); - return method; - } - - private CodeExecutableElement createCreateGenericMethod(NodeData node, Modifier visibility) { - CodeExecutableElement method = new CodeExecutableElement(modifiers(), node.getNodeType(), "createGeneric"); - if (visibility != null) { - method.getModifiers().add(visibility); - } - method.getModifiers().add(Modifier.STATIC); - method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); - - CodeTreeBuilder body = method.createBuilder(); - - SpecializationData found = null; - List specializations = node.getSpecializations(); - for (int i = 0; i < specializations.size(); i++) { - if (specializations.get(i).isReachable()) { - found = specializations.get(i); - } - } - - if (found == null) { - body.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end(); - } else { - body.startReturn().startCall(nodeSpecializationClassName(found), CREATE_SPECIALIZATION_NAME).startGroup().string(THIS_NODE_LOCAL_VAR_NAME).end().end().end(); - } - return method; - } - } - - private class NodeBaseFactory extends ClassElementFactory { - - public NodeBaseFactory(ProcessorContext context) { - super(context); - } - - @Override - protected CodeTypeElement create(SpecializationData specialization) { - NodeData node = specialization.getNode(); - CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, ABSTRACT, STATIC), baseClassName(node), node.getNodeType(), false); - - for (NodeChildData child : node.getChildren()) { - clazz.add(createChildField(child)); - - if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) { - ExecutableElement getter = (ExecutableElement) child.getAccessElement(); - CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), getter); - method.getModifiers().remove(Modifier.ABSTRACT); - CodeTreeBuilder builder = method.createBuilder(); - builder.startReturn().string("this.").string(child.getName()).end(); - clazz.add(method); - } - } - - for (NodeFieldData field : node.getFields()) { - if (!field.isGenerated()) { - continue; - } - - clazz.add(new CodeVariableElement(modifiers(PROTECTED, FINAL), field.getType(), field.getName())); - if (field.getGetter() != null && field.getGetter().getModifiers().contains(Modifier.ABSTRACT)) { - CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), field.getGetter()); - method.getModifiers().remove(Modifier.ABSTRACT); - method.createBuilder().startReturn().string("this.").string(field.getName()).end(); - clazz.add(method); - } - } - - for (String assumption : node.getAssumptions()) { - clazz.add(createAssumptionField(assumption)); - } - - createConstructors(node, clazz); - - return clazz; - } - - @Override - protected void createChildren(SpecializationData specialization) { - NodeData node = specialization.getNode(); - CodeTypeElement clazz = getElement(); - - SpecializationGroup rootGroup = createSpecializationGroups(node); - - if (node.needsRewrites(context)) { - if (node.isPolymorphic()) { - - CodeVariableElement var = new CodeVariableElement(modifiers(PROTECTED), clazz.asType(), "next0"); - var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation())); - clazz.add(var); - - CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getPolymorphicSpecialization()); - clazz.add(genericCachedExecute); - - getElement().add(createUpdateTypes(clazz.asType())); - } - - for (CodeExecutableElement method : createImplicitChildrenAccessors()) { - clazz.add(method); - } - clazz.add(createGenericExecuteAndSpecialize(node, rootGroup)); - clazz.add(createInfoMessage(node)); - } - - if (needsInvokeCopyConstructorMethod()) { - clazz.add(createCopy(clazz.asType(), null)); - } - - if (node.getGenericSpecialization() != null && node.getGenericSpecialization().isReachable()) { - clazz.add(createGenericExecute(node, rootGroup)); - } - } - - protected boolean needsInvokeCopyConstructorMethod() { - return getModel().getNode().isPolymorphic(); - } - - protected CodeExecutableElement createCopy(TypeMirror baseType, SpecializationData specialization) { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), baseType, COPY_WITH_CONSTRUCTOR_NAME); - if (specialization == null) { - method.getModifiers().add(ABSTRACT); - } else { - CodeTreeBuilder builder = method.createBuilder(); - builder.startReturn(); - builder.startNew(getElement().asType()); - builder.string("this"); - for (ActualParameter param : getImplicitTypeParameters(specialization)) { - builder.string(implicitTypeName(param)); - } - builder.end().end(); - } - return method; - } - - private List createImplicitChildrenAccessors() { - NodeData node = getModel().getNode(); - List> prototype = Collections.nCopies(node.getGenericSpecialization().getParameters().size(), null); - List> expectTypes = new ArrayList<>(prototype); - - for (ExecutableTypeData executableType : node.getExecutableTypes()) { - for (int i = 0; i < executableType.getEvaluatedCount(); i++) { - ActualParameter parameter = executableType.getSignatureParameter(i); - if (i >= expectTypes.size()) { - break; - } - Set types = expectTypes.get(i); - if (types == null) { - types = new TreeSet<>(); - expectTypes.set(i, types); - } - types.add(parameter.getTypeSystemType()); - } - } - - List methods = new ArrayList<>(); - List> visitedList = new ArrayList<>(prototype); - for (SpecializationData spec : node.getSpecializations()) { - int signatureIndex = -1; - for (ActualParameter param : spec.getParameters()) { - if (!param.getSpecification().isSignature()) { - continue; - } - signatureIndex++; - Set visitedTypeData = visitedList.get(signatureIndex); - if (visitedTypeData == null) { - visitedTypeData = new TreeSet<>(); - visitedList.set(signatureIndex, visitedTypeData); - } - - if (visitedTypeData.contains(param.getTypeSystemType())) { - continue; - } - visitedTypeData.add(param.getTypeSystemType()); - - Set expect = expectTypes.get(signatureIndex); - if (expect == null) { - expect = Collections.emptySet(); - } - - methods.addAll(createExecuteChilds(param, expect)); - } - } - return methods; - } - - private CodeTree truffleBooleanOption(CodeTreeBuilder parent, String name) { - CodeTreeBuilder builder = parent.create(); - builder.staticReference(getContext().getTruffleTypes().getTruffleOptions(), name); - return builder.getRoot(); - } - - private Element createInfoMessage(NodeData node) { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), getContext().getType(String.class), "createInfo0"); - method.addParameter(new CodeVariableElement(getContext().getType(String.class), "message")); - addInternalValueParameters(method, node.getGenericSpecialization(), false, false); - - CodeTreeBuilder builder = method.createBuilder(); - - builder.startIf().tree(truffleBooleanOption(builder, TruffleTypes.OPTION_DETAILED_REWRITE_REASONS)).end(); - builder.startBlock(); - - builder.startStatement().string("StringBuilder builder = new StringBuilder(message)").end(); - builder.startStatement().startCall("builder", "append").doubleQuote(" (").end().end(); - - String sep = null; - for (ActualParameter parameter : node.getGenericSpecialization().getSignatureParameters()) { - builder.startStatement(); - builder.string("builder"); - if (sep != null) { - builder.startCall(".append").doubleQuote(sep).end(); - } - builder.startCall(".append").doubleQuote(parameter.getLocalName()).end(); - builder.startCall(".append").doubleQuote(" = ").end(); - builder.startCall(".append").string(parameter.getLocalName()).end(); - builder.end(); - - if (!Utils.isPrimitive(parameter.getType())) { - builder.startIf().string(parameter.getLocalName() + " != null").end(); - builder.startBlock(); - } - builder.startStatement(); - if (Utils.isPrimitive(parameter.getType())) { - builder.startCall("builder.append").doubleQuote(" (" + Utils.getSimpleName(parameter.getType()) + ")").end(); - } else { - builder.startCall("builder.append").doubleQuote(" (").end(); - builder.startCall(".append").string(parameter.getLocalName() + ".getClass().getSimpleName()").end(); - builder.startCall(".append").doubleQuote(")").end(); - } - builder.end(); - if (!Utils.isPrimitive(parameter.getType())) { - builder.end(); - } - - sep = ", "; - } - - builder.startStatement().startCall("builder", "append").doubleQuote(")").end().end(); - builder.startReturn().string("builder.toString()").end(); - - builder.end(); - builder.startElseBlock(); - builder.startReturn().string("message").end(); - builder.end(); - - return method; - } - - private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph) { - CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), EXECUTE_POLYMORPHIC_NAME); - addInternalValueParameters(cachedExecute, polymorph, true, false); - - ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0); - boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext()); - if (sourceThrowsUnexpected && sourceExecutableType.getType().equals(node.getGenericSpecialization().getReturnType().getTypeSystemType())) { - sourceThrowsUnexpected = false; - } - if (sourceThrowsUnexpected) { - cachedExecute.getThrownTypes().add(getContext().getType(UnexpectedResultException.class)); - } - return cachedExecute; - - } - - private void createConstructors(NodeData node, CodeTypeElement clazz) { - List constructors = findUserConstructors(node.getNodeType()); - ExecutableElement sourceSectionConstructor = null; - if (constructors.isEmpty()) { - clazz.add(createUserConstructor(clazz, null)); - } else { - for (ExecutableElement constructor : constructors) { - clazz.add(createUserConstructor(clazz, constructor)); - if (NodeParser.isSourceSectionConstructor(context, constructor)) { - sourceSectionConstructor = constructor; - } - } - } - if (node.needsRewrites(getContext())) { - clazz.add(createCopyConstructor(clazz, findCopyConstructor(node.getNodeType()), sourceSectionConstructor)); - } - } - - private CodeExecutableElement createUserConstructor(CodeTypeElement type, ExecutableElement superConstructor) { - CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString()); - CodeTreeBuilder builder = method.createBuilder(); - - NodeData node = getModel().getNode(); - - if (superConstructor != null) { - for (VariableElement param : superConstructor.getParameters()) { - method.getParameters().add(CodeVariableElement.clone(param)); - } - } - - if (superConstructor != null) { - builder.startStatement().startSuperCall(); - for (VariableElement param : superConstructor.getParameters()) { - builder.string(param.getSimpleName().toString()); - } - builder.end().end(); - } - - for (VariableElement var : type.getFields()) { - NodeChildData child = node.findChild(var.getSimpleName().toString()); - - if (child != null) { - method.getParameters().add(new CodeVariableElement(child.getOriginalType(), child.getName())); - } else { - method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString())); - } - - builder.startStatement(); - String fieldName = var.getSimpleName().toString(); - - CodeTree init = createStaticCast(builder, child, fieldName); - - builder.string("this.").string(fieldName).string(" = ").tree(init); - builder.end(); - } - return method; - } - - private CodeTree createStaticCast(CodeTreeBuilder parent, NodeChildData child, String fieldName) { - NodeData parentNode = getModel().getNode(); - if (child != null) { - CreateCastData createCast = parentNode.findCast(child.getName()); - if (createCast != null) { - return createTemplateMethodCall(parent, null, parentNode.getGenericSpecialization(), createCast, null, fieldName); - } - } - return CodeTreeBuilder.singleString(fieldName); - } - - private CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor, ExecutableElement sourceSectionConstructor) { - CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString()); - CodeTreeBuilder builder = method.createBuilder(); - method.getParameters().add(new CodeVariableElement(type.asType(), "copy")); - - if (superConstructor != null) { - builder.startStatement().startSuperCall().string("copy").end().end(); - } else if (sourceSectionConstructor != null) { - builder.startStatement().startSuperCall().string("copy.getSourceSection()").end().end(); - } - - for (VariableElement var : type.getFields()) { - builder.startStatement(); - final String varName = var.getSimpleName().toString(); - final TypeMirror varType = var.asType(); - - String copyAccess = "copy." + varName; - if (Utils.isAssignable(getContext(), varType, getContext().getTruffleTypes().getNodeArray())) { - copyAccess += ".clone()"; - } - CodeTree init = CodeTreeBuilder.singleString(copyAccess); - builder.startStatement().string("this.").string(varName).string(" = ").tree(init).end(); - } - - return method; - } - - private CodeVariableElement createAssumptionField(String assumption) { - CodeVariableElement var = new CodeVariableElement(getContext().getTruffleTypes().getAssumption(), assumption); - var.getModifiers().add(Modifier.FINAL); - return var; - } - - private CodeVariableElement createChildField(NodeChildData child) { - TypeMirror type = child.getNodeType(); - CodeVariableElement var = new CodeVariableElement(type, child.getName()); - var.getModifiers().add(Modifier.PROTECTED); - - DeclaredType annotationType; - if (child.getCardinality() == Cardinality.MANY) { - var.getModifiers().add(Modifier.FINAL); - annotationType = getContext().getTruffleTypes().getChildrenAnnotation(); - } else { - annotationType = getContext().getTruffleTypes().getChildAnnotation(); - } - - var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType)); - return var; - } - - private CodeExecutableElement createGenericExecuteAndSpecialize(final NodeData node, SpecializationGroup rootGroup) { - TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType(); - CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), genericReturnType, EXECUTE_SPECIALIZE_NAME); - method.addParameter(new CodeVariableElement(getContext().getType(int.class), "minimumState")); - addInternalValueParameters(method, node.getGenericSpecialization(), true, false); - method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason")); - - CodeTreeBuilder builder = method.createBuilder(); - builder.startStatement(); - builder.startStaticCall(getContext().getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end(); - builder.end(); - - String currentNode = "this"; - for (SpecializationData specialization : node.getSpecializations()) { - if (!specialization.getExceptions().isEmpty()) { - currentNode = "current"; - builder.declaration(baseClassName(node), currentNode, "this"); - break; - } - } - - builder.startStatement().string("String message = ").startCall("createInfo0").string("reason"); - addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, false, null); - builder.end().end(); - - final String currentNodeVar = currentNode; - builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), rootGroup, true, new CodeBlock() { - - public CodeTree create(CodeTreeBuilder b, SpecializationData current) { - return createGenericInvokeAndSpecialize(b, node.getGenericSpecialization(), current, currentNodeVar); - } - }, null, false, true, false)); - - boolean firstUnreachable = true; - for (SpecializationData current : node.getSpecializations()) { - if (current.isReachable()) { - continue; - } - if (firstUnreachable) { - emitEncounteredSynthetic(builder, current); - firstUnreachable = false; - } - } - emitUnreachableSpecializations(builder, node); - - return method; - } - - private SpecializationGroup createSpecializationGroups(final NodeData node) { - List specializations = node.getSpecializations(); - List filteredSpecializations = new ArrayList<>(); - for (SpecializationData current : specializations) { - if (current.isUninitialized() || current.isPolymorphic() || !current.isReachable()) { - continue; - } - filteredSpecializations.add(current); - } - - return SpecializationGroup.create(filteredSpecializations); - } - - private CodeExecutableElement createGenericExecute(NodeData node, SpecializationGroup group) { - TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType(); - CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), genericReturnType, EXECUTE_GENERIC_NAME); - - if (!node.needsFrame(getContext())) { - method.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getSlowPath())); - } - addInternalValueParameters(method, node.getGenericSpecialization(), node.needsFrame(getContext()), false); - final CodeTreeBuilder builder = method.createBuilder(); - - builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), group, false, new CodeBlock() { - - public CodeTree create(CodeTreeBuilder b, SpecializationData current) { - return createGenericInvoke(builder, current.getNode().getGenericSpecialization(), current); - } - }, null, false, true, false)); - - emitUnreachableSpecializations(builder, node); - - return method; - } - - private void emitUnreachableSpecializations(final CodeTreeBuilder builder, NodeData node) { - for (SpecializationData current : node.getSpecializations()) { - if (current.isReachable()) { - continue; - } - builder.string("// unreachable ").string(current.getId()).newLine(); - } - } - - protected CodeTree createExecuteTree(CodeTreeBuilder outerParent, final SpecializationData source, final SpecializationGroup group, final boolean checkMinimumState, - final CodeBlock guardedblock, final CodeTree elseBlock, boolean forceElse, final boolean emitAssumptions, final boolean typedCasts) { - return guard(outerParent, source, group, checkMinimumState, new CodeBlock() { - - public CodeTree create(CodeTreeBuilder parent, Integer ifCount) { - CodeTreeBuilder builder = parent.create(); - - if (group.getSpecialization() != null) { - builder.tree(guardedblock.create(builder, group.getSpecialization())); - - assert group.getChildren().isEmpty() : "missed a specialization"; - - } else { - for (SpecializationGroup childGroup : group.getChildren()) { - builder.tree(createExecuteTree(builder, source, childGroup, checkMinimumState, guardedblock, null, false, emitAssumptions, typedCasts)); - } - } - - return builder.getRoot(); - } - }, elseBlock, forceElse, emitAssumptions, typedCasts); - } - - private CodeTree guard(CodeTreeBuilder parent, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, CodeBlock bodyBlock, CodeTree elseBlock, - boolean forceElse, boolean emitAssumptions, boolean typedCasts) { - CodeTreeBuilder builder = parent.create(); - - int ifCount = emitGuards(builder, source, group, checkMinimumState, emitAssumptions, typedCasts); - - if (isReachableGroup(group, ifCount, checkMinimumState)) { - builder.tree(bodyBlock.create(builder, ifCount)); - } - - builder.end(ifCount); - - if (elseBlock != null) { - if (ifCount > 0 || forceElse) { - builder.tree(elseBlock); - } - } - - return builder.getRoot(); - } - - private boolean isReachableGroup(SpecializationGroup group, int ifCount, boolean checkMinimumState) { - if (ifCount != 0) { - return true; - } - SpecializationGroup previous = group.getPreviousGroup(); - if (previous == null || previous.findElseConnectableGuards(checkMinimumState).isEmpty()) { - return true; - } - - /* - * Hacky else case. In this case the specialization is not reachable due to previous - * else branch. This is only true if the minimum state is not checked. - */ - if (previous.getGuards().size() == 1 && previous.getTypeGuards().isEmpty() && previous.getAssumptions().isEmpty() && !checkMinimumState && - (previous.getParent() == null || previous.getMaxSpecializationIndex() != previous.getParent().getMaxSpecializationIndex())) { - return false; - } - - return true; - } - - private int emitGuards(CodeTreeBuilder builder, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, boolean emitAssumptions, boolean typedCasts) { - NodeData node = source.getNode(); - - CodeTreeBuilder guardsBuilder = builder.create(); - CodeTreeBuilder castBuilder = builder.create(); - CodeTreeBuilder guardsCastBuilder = builder.create(); - - String guardsAnd = ""; - String guardsCastAnd = ""; - - boolean minimumState = checkMinimumState; - if (minimumState) { - int groupMaxIndex = group.getUncheckedSpecializationIndex(); - - if (groupMaxIndex > -1) { - guardsBuilder.string(guardsAnd); - guardsBuilder.string("minimumState < " + groupMaxIndex); - guardsAnd = " && "; - } - } - - if (emitAssumptions) { - for (String assumption : group.getAssumptions()) { - guardsBuilder.string(guardsAnd); - guardsBuilder.string("this"); - guardsBuilder.string(".").string(assumption).string(".isValid()"); - guardsAnd = " && "; - } - } - - for (TypeGuard typeGuard : group.getTypeGuards()) { - ActualParameter valueParam = source.getSignatureParameter(typeGuard.getSignatureIndex()); - - if (valueParam == null) { - /* - * If used inside a execute evaluated method then the value param may not exist. - * In that case we assume that the value is executed generic or of the current - * specialization. - */ - if (group.getSpecialization() != null) { - valueParam = group.getSpecialization().getSignatureParameter(typeGuard.getSignatureIndex()); - } else { - valueParam = node.getGenericSpecialization().getSignatureParameter(typeGuard.getSignatureIndex()); - } - } - - NodeExecutionData execution = valueParam.getSpecification().getExecution(); - CodeTree implicitGuard = createTypeGuard(guardsBuilder, execution, valueParam, typeGuard.getType(), typedCasts); - if (implicitGuard != null) { - guardsBuilder.string(guardsAnd); - guardsBuilder.tree(implicitGuard); - guardsAnd = " && "; - } - - CodeTree cast = createCast(castBuilder, execution, valueParam, typeGuard.getType(), checkMinimumState, typedCasts); - if (cast != null) { - castBuilder.tree(cast); - } - } - List elseGuards = group.findElseConnectableGuards(checkMinimumState); - - for (GuardData guard : group.getGuards()) { - if (elseGuards.contains(guard)) { - continue; - } - - if (needsTypeGuard(source, group, guard)) { - guardsCastBuilder.tree(createMethodGuard(builder, guardsCastAnd, source, guard)); - guardsCastAnd = " && "; - } else { - guardsBuilder.tree(createMethodGuard(builder, guardsAnd, source, guard)); - guardsAnd = " && "; - } - } - - int ifCount = startGuardIf(builder, guardsBuilder, 0, elseGuards); - builder.tree(castBuilder.getRoot()); - ifCount = startGuardIf(builder, guardsCastBuilder, ifCount, elseGuards); - return ifCount; - } - - private int startGuardIf(CodeTreeBuilder builder, CodeTreeBuilder conditionBuilder, int ifCount, List elseGuard) { - int newIfCount = ifCount; - - if (!conditionBuilder.isEmpty()) { - if (ifCount == 0 && !elseGuard.isEmpty()) { - builder.startElseIf(); - } else { - builder.startIf(); - } - builder.tree(conditionBuilder.getRoot()); - builder.end().startBlock(); - newIfCount++; - } else if (ifCount == 0 && !elseGuard.isEmpty()) { - builder.startElseBlock(); - newIfCount++; - } - return newIfCount; - } - - private boolean needsTypeGuard(SpecializationData source, SpecializationGroup group, GuardData guard) { - int signatureIndex = 0; - for (ActualParameter parameter : guard.getParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } - - TypeGuard typeGuard = group.findTypeGuard(signatureIndex); - if (typeGuard != null) { - TypeData requiredType = typeGuard.getType(); - - ActualParameter sourceParameter = source.findParameter(parameter.getLocalName()); - if (sourceParameter == null) { - sourceParameter = source.getNode().getGenericSpecialization().findParameter(parameter.getLocalName()); - } - - if (Utils.needsCastTo(getContext(), sourceParameter.getType(), requiredType.getPrimitiveType())) { - return true; - } - } - - signatureIndex++; - } - return false; - } - - private CodeTree createTypeGuard(CodeTreeBuilder parent, NodeExecutionData execution, ActualParameter source, TypeData targetType, boolean typedCasts) { - NodeData node = execution.getChild().getNodeData(); - - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - - TypeData sourceType = source.getTypeSystemType(); - - if (!sourceType.needsCastTo(getContext(), targetType)) { - return null; - } - - builder.startGroup(); - - if (execution.isShortCircuit()) { - ActualParameter shortCircuit = source.getPreviousParameter(); - assert shortCircuit != null; - builder.string("("); - builder.string("!").string(valueName(shortCircuit)); - builder.string(" || "); - } - - String castMethodName; - String castTypeName = null; - List types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType); - if (types.size() > 1) { - castMethodName = TypeSystemCodeGenerator.isImplicitTypeMethodName(targetType); - if (typedCasts) { - castTypeName = implicitTypeName(source); - } - } else { - castMethodName = TypeSystemCodeGenerator.isTypeMethodName(targetType); - } - - startCallTypeSystemMethod(getContext(), builder, node.getTypeSystem(), castMethodName); - builder.string(valueName(source)); - if (castTypeName != null) { - builder.string(castTypeName); - } - builder.end().end(); // call - - if (execution.isShortCircuit()) { - builder.string(")"); - } - - builder.end(); // group - - return builder.getRoot(); - } - - // TODO merge redundancies with #createTypeGuard - private CodeTree createCast(CodeTreeBuilder parent, NodeExecutionData execution, ActualParameter source, TypeData targetType, boolean checkMinimumState, boolean typedCasts) { - NodeData node = execution.getChild().getNodeData(); - TypeData sourceType = source.getTypeSystemType(); - - if (!sourceType.needsCastTo(getContext(), targetType)) { - return null; - } - - CodeTree condition = null; - if (execution.isShortCircuit()) { - ActualParameter shortCircuit = source.getPreviousParameter(); - assert shortCircuit != null; - condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); - } - - String castMethodName; - String castTypeName = null; - List types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType); - if (types.size() > 1) { - castMethodName = TypeSystemCodeGenerator.asImplicitTypeMethodName(targetType); - if (typedCasts) { - castTypeName = implicitTypeName(source); - } - } else { - castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType); - } - - List args = new ArrayList<>(); - args.add(CodeTreeBuilder.singleString(valueName(source))); - if (castTypeName != null) { - args.add(CodeTreeBuilder.singleString(castTypeName)); - } - - CodeTree value = createCallTypeSystemMethod(context, parent, node, castMethodName, args.toArray(new CodeTree[0])); - - CodeTreeBuilder builder = parent.create(); - builder.tree(createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, value)); - if (checkMinimumState && types.size() > 1) { - CodeTree castType = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.getImplicitClass(targetType), CodeTreeBuilder.singleString(valueName(source))); - builder.tree(createLazyAssignment(builder, implicitTypeName(source), getContext().getType(Class.class), condition, castType)); - } - - return builder.getRoot(); - } - - private CodeTree createMethodGuard(CodeTreeBuilder parent, String prefix, SpecializationData source, GuardData guard) { - CodeTreeBuilder builder = parent.create(); - builder.string(prefix); - if (guard.isNegated()) { - builder.string("!"); - } - builder.tree(createTemplateMethodCall(builder, null, source, guard, null)); - return builder.getRoot(); - } - - protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - - if (current.getMethod() == null) { - emitEncounteredSynthetic(builder, current); - } else { - builder.startReturn().tree(createTemplateMethodCall(builder, null, source, current, null)).end(); - } - - return encloseThrowsWithFallThrough(current, builder.getRoot()); - } - - protected CodeTree createGenericInvokeAndSpecialize(CodeTreeBuilder parent, SpecializationData source, SpecializationData current, String currentNodeVar) { - CodeTreeBuilder builder = parent.create(); - CodeTreeBuilder prefix = parent.create(); - - NodeData node = current.getNode(); - - if (current.isGeneric() && node.isPolymorphic()) { - builder.startIf().string(currentNodeVar).string(".next0 == null && minimumState > 0").end().startBlock(); - builder.tree(createRewritePolymorphic(builder, node, currentNodeVar)); - builder.end(); - builder.startElseBlock(); - builder.tree(createRewriteGeneric(builder, source, current, currentNodeVar)); - builder.end(); - } else { - if (current.getExceptions().isEmpty()) { - builder.tree(createGenericInvoke(builder, source, current, createReplaceCall(builder, current, currentNodeVar, currentNodeVar, null), null)); - } else { - builder.startStatement().string(currentNodeVar).string(" = ").tree(createReplaceCall(builder, current, currentNodeVar, currentNodeVar, null)).end(); - builder.tree(createGenericInvoke(builder, source, current, null, CodeTreeBuilder.singleString(currentNodeVar))); - } - } - CodeTreeBuilder root = parent.create(); - root.tree(prefix.getRoot()); - root.tree(encloseThrowsWithFallThrough(current, builder.getRoot())); - return root.getRoot(); - } - - private CodeTree createRewriteGeneric(CodeTreeBuilder parent, SpecializationData source, SpecializationData current, String currentNode) { - NodeData node = current.getNode(); - - CodeTreeBuilder builder = parent.create(); - builder.declaration(getContext().getTruffleTypes().getNode(), "root", currentNode); - builder.startIf().string(currentNode).string(".next0 != null").end().startBlock(); - /* - * Communicates to the caller of executeAndSpecialize that it was rewritten to generic. - * Its important that this is used instead of the currentNode since the caller is this. - * CurrentNode may not be this anymore at this place. - */ - builder.statement("this.next0 = null"); - builder.tree(createFindRoot(builder, node, false)); - builder.end(); - builder.end(); - builder.tree(createGenericInvoke(builder, source, current, createReplaceCall(builder, current, "root", "(" + baseClassName(node) + ") root", null), null)); - return builder.getRoot(); - } - - protected CodeTree createFindRoot(CodeTreeBuilder parent, NodeData node, boolean countDepth) { - CodeTreeBuilder builder = parent.create(); - builder.startDoBlock(); - builder.startAssert().string("root != null").string(" : ").doubleQuote("No polymorphic parent node.").end(); - builder.startStatement().string("root = ").string("root.getParent()").end(); - if (countDepth) { - builder.statement("depth++"); - } - builder.end(); - builder.startDoWhile(); - builder.string("!").startParantheses().instanceOf("root", nodePolymorphicClassName(node)).end(); - builder.end(); - return builder.getRoot(); - } - - private CodeTree encloseThrowsWithFallThrough(SpecializationData current, CodeTree tree) { - if (current.getExceptions().isEmpty()) { - return tree; - } - CodeTreeBuilder builder = new CodeTreeBuilder(null); - - builder.startTryBlock(); - builder.tree(tree); - for (SpecializationThrowsData exception : current.getExceptions()) { - builder.end().startCatchBlock(exception.getJavaClass(), "rewriteEx"); - builder.string("// fall through").newLine(); - } - builder.end(); - - return builder.getRoot(); - } - - protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current, CodeTree replaceCall, CodeTree replaceVar) { - assert replaceCall == null || replaceVar == null; - CodeTreeBuilder builder = parent.create(); - CodeTree replace = replaceVar; - if (replace == null) { - replace = replaceCall; - } - if (current.isGeneric()) { - builder.startReturn().tree(replace).string(".").startCall(EXECUTE_GENERIC_NAME); - addInternalValueParameterNames(builder, source, current, null, current.getNode().needsFrame(getContext()), null); - builder.end().end(); - } else if (current.getMethod() == null) { - if (replaceCall != null) { - builder.statement(replaceCall); - } - emitEncounteredSynthetic(builder, current); - } else if (!current.canBeAccessedByInstanceOf(getContext(), source.getNode().getNodeType())) { - if (replaceCall != null) { - builder.statement(replaceCall); - } - builder.startReturn().tree(createTemplateMethodCall(parent, null, source, current, null)).end(); - } else { - replace.add(new CodeTree(CodeTreeKind.STRING, null, ".")); - builder.startReturn().tree(createTemplateMethodCall(parent, replace, source, current, null)).end(); - } - return builder.getRoot(); - } - - protected CodeTree createReplaceCall(CodeTreeBuilder builder, SpecializationData current, String target, String source, String message) { - String className = nodeSpecializationClassName(current); - CodeTreeBuilder replaceCall = builder.create(); - if (target != null) { - replaceCall.startCall(target, "replace"); - } else { - replaceCall.startCall("replace"); - } - replaceCall.startGroup().cast(baseClassName(current.getNode())).startCall(className, CREATE_SPECIALIZATION_NAME).string(source); - for (ActualParameter param : current.getSignatureParameters()) { - NodeChildData child = param.getSpecification().getExecution().getChild(); - List types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); - if (types.size() > 1) { - replaceCall.string(implicitTypeName(param)); - } - } - replaceCall.end().end(); - - if (message == null) { - replaceCall.string("message"); - } else { - replaceCall.doubleQuote(message); - } - replaceCall.end(); - return replaceCall.getRoot(); - } - - private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node, String currentNode) { - String polyClassName = nodePolymorphicClassName(node); - String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization()); - CodeTreeBuilder builder = parent.create(); - - builder.declaration(getElement().asType(), "currentCopy", currentNode + "." + COPY_WITH_CONSTRUCTOR_NAME + "()"); - for (ActualParameter param : getModel().getSignatureParameters()) { - NodeExecutionData execution = param.getSpecification().getExecution(); - builder.startStatement().tree(createAccessChild(execution, "currentCopy")).string(" = ").nullLiteral().end(); - } - builder.startStatement().string("currentCopy.next0 = ").startNew(uninitializedName).string("currentCopy").end().end(); - - builder.declaration(polyClassName, "polymorphic", builder.create().startNew(polyClassName).string(currentNode).end()); - builder.startStatement().string("polymorphic.next0 = ").string("currentCopy").end(); - builder.startStatement().startCall(currentNode, "replace").string("polymorphic").string("message").end().end(); - - builder.startReturn(); - builder.startCall("currentCopy.next0", EXECUTE_POLYMORPHIC_NAME); - addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, null); - builder.end(); - builder.end(); - - return builder.getRoot(); - } - - protected CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) { - TypeData type = executable.getType(); - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - NodeData node = specialization.getNode(); - - ExecutableTypeData castedType = node.findExecutableType(type, 0); - TypeData primaryType = castExecutable.getType(); - - boolean needsTry = castExecutable.hasUnexpectedValue(getContext()); - boolean returnVoid = type.isVoid(); - - List executeParameters = new ArrayList<>(); - for (ActualParameter sourceParameter : executable.getSignatureParameters()) { - ActualParameter targetParameter = castExecutable.findParameter(sourceParameter.getLocalName()); - if (targetParameter != null) { - executeParameters.add(targetParameter); - } - } - - // execute names are enforced no cast - String[] executeParameterNames = new String[executeParameters.size()]; - for (int i = 0; i < executeParameterNames.length; i++) { - executeParameterNames[i] = valueName(executeParameters.get(i)); - } - - builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null)); - - CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null, executeParameterNames); - if (needsTry) { - if (!returnVoid) { - builder.declaration(primaryType.getPrimitiveType(), "value"); - } - builder.startTryBlock(); - - if (returnVoid) { - builder.statement(primaryExecuteCall); - } else { - builder.startStatement(); - builder.string("value = "); - builder.tree(primaryExecuteCall); - builder.end(); - } - - builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); - if (returnVoid) { - builder.string("// ignore").newLine(); - } else { - builder.startReturn(); - builder.tree(createExpectExecutableType(node, specialization.getNode().getTypeSystem().getGenericTypeData(), castedType, CodeTreeBuilder.singleString("ex.getResult()"))); - builder.end(); - } - builder.end(); - - if (!returnVoid) { - builder.startReturn(); - builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), executable, CodeTreeBuilder.singleString("value"))); - builder.end(); - } - } else { - if (returnVoid) { - builder.statement(primaryExecuteCall); - } else { - builder.startReturn(); - builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), executable, primaryExecuteCall)); - builder.end(); - } - } - - return builder.getRoot(); - } - - protected CodeTree createExpectExecutableType(NodeData node, TypeData sourceType, ExecutableTypeData castedType, CodeTree value) { - boolean hasUnexpected = castedType.hasUnexpectedValue(getContext()); - return createCastType(node.getTypeSystem(), sourceType, castedType.getType(), hasUnexpected, value); - } - - protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List targetParameters, - ActualParameter unexpectedParameter) { - CodeTreeBuilder builder = parent.create(); - for (ActualParameter targetParameter : targetParameters) { - if (!targetParameter.getSpecification().isSignature()) { - continue; - } - NodeExecutionData execution = targetParameter.getSpecification().getExecution(); - CodeTree executionExpressions = createExecuteChild(builder, execution, sourceExecutable, targetParameter, unexpectedParameter); - CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpressions, specialization, sourceExecutable, targetParameter, execution.isShortCircuit(), unexpectedParameter); - CodeTree shortCircuitTree = createShortCircuitTree(builder, unexpectedTree, specialization, targetParameter, unexpectedParameter); - - if (shortCircuitTree == executionExpressions) { - if (containsNewLine(executionExpressions)) { - builder.declaration(targetParameter.getType(), valueName(targetParameter)); - builder.tree(shortCircuitTree); - } else { - builder.startStatement().type(targetParameter.getType()).string(" ").tree(shortCircuitTree).end(); - } - } else { - builder.tree(shortCircuitTree); - } - - } - return builder.getRoot(); - } - - private ExecutableTypeData resolveExecutableType(NodeExecutionData execution, TypeData type) { - ExecutableTypeData targetExecutable = execution.getChild().findExecutableType(getContext(), type); - if (targetExecutable == null) { - targetExecutable = execution.getChild().findAnyGenericExecutableType(getContext()); - } - return targetExecutable; - } - - private CodeTree createExecuteChild(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData sourceExecutable, ActualParameter targetParameter, - ActualParameter unexpectedParameter) { - SpecializationData specialization = getModel(); - TreeSet possiblePolymorphicTypes = lookupPolymorphicTargetTypes(targetParameter); - if (specialization.isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null && possiblePolymorphicTypes.size() > 1) { - - CodeTreeBuilder builder = parent.create(); - - boolean elseIf = false; - for (TypeData possiblePolymoprhicType : possiblePolymorphicTypes) { - if (possiblePolymoprhicType.isGeneric()) { - continue; - } - elseIf = builder.startIf(elseIf); - - ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName()); - TypeData sourceType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null; - builder.string(polymorphicTypeName(targetParameter)).string(" == ").typeLiteral(possiblePolymoprhicType.getPrimitiveType()); - builder.end().startBlock(); - builder.startStatement(); - builder.tree(createExecuteChildExpression(parent, execution, sourceType, new ActualParameter(targetParameter, possiblePolymoprhicType), unexpectedParameter, null)); - builder.end(); - builder.end(); - } - - builder.startElseBlock(); - builder.startStatement().tree(createExecuteChildImplicit(parent, execution, sourceExecutable, targetParameter, unexpectedParameter)).end(); - builder.end(); - - return builder.getRoot(); - } else { - return createExecuteChildImplicit(parent, execution, sourceExecutable, targetParameter, unexpectedParameter); - } - } - - protected final List getImplicitTypeParameters(SpecializationData model) { - List parameter = new ArrayList<>(); - for (ActualParameter param : model.getSignatureParameters()) { - NodeChildData child = param.getSpecification().getExecution().getChild(); - List types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); - if (types.size() > 1) { - parameter.add(param); - } - } - return parameter; - } - - protected final TreeSet lookupPolymorphicTargetTypes(ActualParameter param) { - SpecializationData specialization = getModel(); - TreeSet possiblePolymorphicTypes = new TreeSet<>(); - for (SpecializationData otherSpecialization : specialization.getNode().getSpecializations()) { - if (!otherSpecialization.isSpecialized()) { - continue; - } - ActualParameter otherParameter = otherSpecialization.findParameter(param.getLocalName()); - if (otherParameter != null) { - possiblePolymorphicTypes.add(otherParameter.getTypeSystemType()); - } - } - return possiblePolymorphicTypes; - } - - private CodeTree createExecuteChildImplicit(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData sourceExecutable, ActualParameter param, ActualParameter unexpectedParameter) { - CodeTreeBuilder builder = parent.create(); - ActualParameter sourceParameter = sourceExecutable.findParameter(param.getLocalName()); - String childExecuteName = createExecuteChildMethodName(param, sourceParameter != null); - if (childExecuteName != null) { - builder.string(valueName(param)); - builder.string(" = "); - builder.startCall(childExecuteName); - - for (ActualParameter parameters : sourceExecutable.getParameters()) { - if (parameters.getSpecification().isSignature()) { - continue; - } - builder.string(parameters.getLocalName()); - } - - if (sourceParameter != null) { - builder.string(valueNameEvaluated(sourceParameter)); - } - - builder.string(implicitTypeName(param)); - - builder.end(); - } else { - List sourceTypes = execution.getChild().getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); - TypeData expectType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null; - if (sourceTypes.size() > 1) { - builder.tree(createExecuteChildImplicitExpressions(parent, param, expectType)); - } else { - builder.tree(createExecuteChildExpression(parent, execution, expectType, param, unexpectedParameter, null)); - } - } - return builder.getRoot(); - } - - private String createExecuteChildMethodName(ActualParameter param, boolean expect) { - NodeExecutionData execution = param.getSpecification().getExecution(); - NodeChildData child = execution.getChild(); - if (child.getExecuteWith().size() > 0) { - return null; - } - List sourceTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); - if (sourceTypes.size() <= 1) { - return null; - } - String prefix = expect ? "expect" : "execute"; - String suffix = execution.getIndex() > -1 ? String.valueOf(execution.getIndex()) : ""; - return prefix + Utils.firstLetterUpperCase(child.getName()) + Utils.firstLetterUpperCase(Utils.getSimpleName(param.getType())) + suffix; - } - - private List createExecuteChilds(ActualParameter param, Set expectTypes) { - CodeExecutableElement executeMethod = createExecuteChild(param, null); - if (executeMethod == null) { - return Collections.emptyList(); - } - List childs = new ArrayList<>(); - childs.add(executeMethod); - - for (TypeData expectType : expectTypes) { - CodeExecutableElement method = createExecuteChild(param, expectType); - if (method != null) { - childs.add(method); - } - } - return childs; - } - - private CodeExecutableElement createExecuteChild(ActualParameter param, TypeData expectType) { - String childExecuteName = createExecuteChildMethodName(param, expectType != null); - if (childExecuteName == null) { - return null; - } - - CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, expectType != null ? STATIC : FINAL), param.getType(), childExecuteName); - method.getThrownTypes().add(getContext().getTruffleTypes().getUnexpectedValueException()); - method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue")); - if (expectType != null) { - method.addParameter(new CodeVariableElement(expectType.getPrimitiveType(), valueNameEvaluated(param))); - } - method.addParameter(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param))); - - CodeTreeBuilder builder = method.createBuilder(); - builder.declaration(param.getType(), valueName(param)); - builder.tree(createExecuteChildImplicitExpressions(builder, param, expectType)); - builder.startReturn().string(valueName(param)).end(); - - return method; - } - - private CodeTree createExecuteChildImplicitExpressions(CodeTreeBuilder parent, ActualParameter targetParameter, TypeData expectType) { - CodeTreeBuilder builder = parent.create(); - NodeData node = getModel().getNode(); - NodeExecutionData execution = targetParameter.getSpecification().getExecution(); - List sourceTypes = node.getTypeSystem().lookupSourceTypes(targetParameter.getTypeSystemType()); - boolean elseIf = false; - int index = 0; - for (TypeData sourceType : sourceTypes) { - if (index < sourceTypes.size() - 1) { - elseIf = builder.startIf(elseIf); - builder.string(implicitTypeName(targetParameter)).string(" == ").typeLiteral(sourceType.getPrimitiveType()); - builder.end(); - builder.startBlock(); - } else { - builder.startElseBlock(); - } - - ExecutableTypeData implictExecutableTypeData = execution.getChild().findExecutableType(getContext(), sourceType); - if (implictExecutableTypeData == null) { - /* - * For children with executeWith.size() > 0 an executable type may not exist so - * use the generic executable type which is guaranteed to exist. An expect call - * is inserted automatically by #createExecuteExpression. - */ - implictExecutableTypeData = execution.getChild().getNodeData().findExecutableType(node.getTypeSystem().getGenericTypeData(), execution.getChild().getExecuteWith().size()); - } - - ImplicitCastData cast = execution.getChild().getNodeData().getTypeSystem().lookupCast(sourceType, targetParameter.getTypeSystemType()); - CodeTree execute = createExecuteChildExpression(builder, execution, expectType, targetParameter, null, cast); - builder.statement(execute); - builder.end(); - index++; - } - return builder.getRoot(); - } - - private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData execution, TypeData sourceParameterType, ActualParameter targetParameter, - ActualParameter unexpectedParameter, ImplicitCastData cast) { - // assignments: targetType <- castTargetType <- castSourceType <- sourceType - TypeData sourceType = sourceParameterType; - TypeData targetType = targetParameter.getTypeSystemType(); - TypeData castSourceType = targetType; - TypeData castTargetType = targetType; - - if (cast != null) { - castSourceType = cast.getSourceType(); - castTargetType = cast.getTargetType(); - } - - CodeTree expression; - if (sourceType == null) { - ExecutableTypeData targetExecutable = resolveExecutableType(execution, castSourceType); - expression = createExecuteChildExpression(parent, execution, targetExecutable, unexpectedParameter); - sourceType = targetExecutable.getType(); - } else { - expression = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter)); - } - - // target = expectTargetType(implicitCast(expectCastSourceType(source))) - TypeSystemData typeSystem = execution.getChild().getNodeData().getTypeSystem(); - expression = createExpectType(typeSystem, sourceType, castSourceType, expression); - expression = createImplicitCast(parent, typeSystem, cast, expression); - expression = createExpectType(typeSystem, castTargetType, targetType, expression); - - CodeTreeBuilder builder = parent.create(); - builder.string(valueName(targetParameter)); - builder.string(" = "); - builder.tree(expression); - return builder.getRoot(); - } - - private CodeTree createImplicitCast(CodeTreeBuilder parent, TypeSystemData typeSystem, ImplicitCastData cast, CodeTree expression) { - if (cast == null) { - return expression; - } - CodeTreeBuilder builder = parent.create(); - startCallTypeSystemMethod(getContext(), builder, typeSystem, cast.getMethodName()); - builder.tree(expression); - builder.end().end(); - return builder.getRoot(); - } - - private boolean containsNewLine(CodeTree tree) { - if (tree.getCodeKind() == CodeTreeKind.NEW_LINE) { - return true; - } - - for (CodeTree codeTree : tree.getEnclosedElements()) { - if (containsNewLine(codeTree)) { - return true; - } - } - return false; - } - - private boolean hasUnexpected(ActualParameter sourceParameter, ActualParameter targetParameter, ActualParameter unexpectedParameter) { - NodeExecutionData execution = targetParameter.getSpecification().getExecution(); - - if (getModel().isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null) { - // check for other polymorphic types - TreeSet polymorphicTargetTypes = lookupPolymorphicTargetTypes(targetParameter); - if (polymorphicTargetTypes.size() > 1) { - for (TypeData polymorphicTargetType : polymorphicTargetTypes) { - if (hasUnexpectedType(execution, sourceParameter, polymorphicTargetType)) { - return true; - } - } - } - } - - if (hasUnexpectedType(execution, sourceParameter, targetParameter.getTypeSystemType())) { - return true; - } - return false; - } - - private boolean hasUnexpectedType(NodeExecutionData execution, ActualParameter sourceParameter, TypeData targetType) { - List implicitSourceTypes = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType); - - for (TypeData implicitSourceType : implicitSourceTypes) { - TypeData sourceType; - ExecutableTypeData targetExecutable = resolveExecutableType(execution, implicitSourceType); - if (sourceParameter != null) { - sourceType = sourceParameter.getTypeSystemType(); - } else { - if (targetExecutable.hasUnexpectedValue(getContext())) { - return true; - } - sourceType = targetExecutable.getType(); - } - - ImplicitCastData cast = getModel().getNode().getTypeSystem().lookupCast(implicitSourceType, targetType); - if (cast != null) { - if (cast.getSourceType().needsCastTo(getContext(), targetType)) { - return true; - } - } - - if (sourceType.needsCastTo(getContext(), targetType)) { - return true; - } - } - return false; - } - - private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, ExecutableTypeData currentExecutable, ActualParameter param, - boolean shortCircuit, ActualParameter unexpectedParameter) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - ActualParameter sourceParameter = currentExecutable.findParameter(param.getLocalName()); - boolean unexpected = hasUnexpected(sourceParameter, param, unexpectedParameter); - if (!unexpected) { - return body; - } - - if (!shortCircuit) { - builder.declaration(param.getType(), valueName(param)); - } - builder.startTryBlock(); - - if (containsNewLine(body)) { - builder.tree(body); - } else { - builder.statement(body); - } - - builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); - SpecializationData generic = specialization.getNode().getGenericSpecialization(); - ActualParameter genericParameter = generic.findParameter(param.getLocalName()); - - List genericParameters = generic.getParametersAfter(genericParameter); - builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter)); - if (specialization.isPolymorphic()) { - builder.tree(createReturnOptimizeTypes(builder, currentExecutable, specialization, param)); - } else { - builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization, param, - "Expected " + param.getLocalName() + " instanceof " + Utils.getSimpleName(param.getType()))); - } - builder.end(); // catch block - - return builder.getRoot(); - } - - private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, ActualParameter param) { - NodeData node = specialization.getNode(); - SpecializationData polymorphic = node.getPolymorphicSpecialization(); - - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - builder.startStatement().string(polymorphicTypeName(param)).string(" = ").typeLiteral(getContext().getType(Object.class)).end(); - - builder.startReturn(); - - CodeTreeBuilder execute = new CodeTreeBuilder(builder); - execute.startCall("next0", EXECUTE_POLYMORPHIC_NAME); - addInternalValueParameterNames(execute, specialization, polymorphic, param.getLocalName(), true, null); - execute.end(); - - TypeData sourceType = polymorphic.getReturnType().getTypeSystemType(); - - builder.tree(createExpectExecutableType(node, sourceType, currentExecutable, execute.getRoot())); - - builder.end(); - return builder.getRoot(); - } - - private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData targetExecution, ExecutableTypeData targetExecutable, ActualParameter unexpectedParameter) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - if (targetExecution != null) { - builder.tree(createAccessChild(targetExecution, null)); - builder.string("."); - } - - builder.startCall(targetExecutable.getMethodName()); - - // TODO this should be merged with #createTemplateMethodCall - int index = 0; - for (ActualParameter parameter : targetExecutable.getParameters()) { - - if (!parameter.getSpecification().isSignature()) { - builder.string(parameter.getLocalName()); - } else { - - if (index < targetExecution.getChild().getExecuteWith().size()) { - NodeChildData child = targetExecution.getChild().getExecuteWith().get(index); - - ParameterSpec spec = getModel().getSpecification().findParameterSpec(child.getName()); - List specializationParams = getModel().findParameters(spec); - - if (specializationParams.isEmpty()) { - builder.defaultValue(parameter.getType()); - continue; - } - - ActualParameter specializationParam = specializationParams.get(0); - - TypeData targetType = parameter.getTypeSystemType(); - TypeData sourceType = specializationParam.getTypeSystemType(); - String localName = specializationParam.getLocalName(); - - if (unexpectedParameter != null && unexpectedParameter.getLocalName().equals(specializationParam.getLocalName())) { - localName = "ex.getResult()"; - sourceType = getModel().getNode().getTypeSystem().getGenericTypeData(); - } - - CodeTree value = CodeTreeBuilder.singleString(localName); - - if (sourceType.needsCastTo(getContext(), targetType)) { - value = createCallTypeSystemMethod(getContext(), builder, getModel().getNode(), TypeSystemCodeGenerator.asTypeMethodName(targetType), value); - } - builder.tree(value); - } else { - builder.defaultValue(parameter.getType()); - } - index++; - } - } - - builder.end(); - - return builder.getRoot(); - } - - private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, ActualParameter parameter, ActualParameter exceptionParam) { - NodeExecutionData execution = parameter.getSpecification().getExecution(); - if (execution == null || !execution.isShortCircuit()) { - return body; - } - - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter); - builder.tree(createShortCircuitValue(builder, specialization, execution, shortCircuitParam, exceptionParam)); - builder.declaration(parameter.getType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getType())); - builder.startIf().string(shortCircuitParam.getLocalName()).end(); - builder.startBlock(); - - if (containsNewLine(body)) { - builder.tree(body); - } else { - builder.statement(body); - } - builder.end(); - - return builder.getRoot(); - } - - private CodeTree createShortCircuitValue(CodeTreeBuilder parent, SpecializationData specialization, NodeExecutionData execution, ActualParameter shortCircuitParam, - ActualParameter exceptionParam) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - int shortCircuitIndex = 0; - for (NodeExecutionData otherExectuion : specialization.getNode().getChildExecutions()) { - if (otherExectuion.isShortCircuit()) { - if (otherExectuion == execution) { - break; - } - shortCircuitIndex++; - } - } - - builder.startStatement().type(shortCircuitParam.getType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); - ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex); - builder.tree(createTemplateMethodCall(builder, null, specialization, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null)); - builder.end(); // statement - - return builder.getRoot(); - } - - protected CodeTree createReturnExecuteAndSpecialize(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData current, ActualParameter exceptionParam, String reason) { - NodeData node = current.getNode(); - SpecializationData generic = node.getGenericSpecialization(); - CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); - specializeCall.startCall(EXECUTE_SPECIALIZE_NAME); - specializeCall.string(String.valueOf(node.getSpecializations().indexOf(current))); - addInternalValueParameterNames(specializeCall, generic, node.getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, null); - specializeCall.doubleQuote(reason); - specializeCall.end().end(); - - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - - builder.startReturn(); - builder.tree(createExpectExecutableType(node, generic.getReturnType().getTypeSystemType(), executable, specializeCall.getRoot())); - builder.end(); - - return builder.getRoot(); - } - - protected final CodeExecutableElement createUpdateTypes(TypeMirror polymorphicType) { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), getContext().getType(void.class), UPDATE_TYPES_NAME); - method.getParameters().add(new CodeVariableElement(polymorphicType, "polymorphic")); - CodeTreeBuilder builder = method.createBuilder(); - - if (getModel().isPolymorphic()) { - builder.startStatement(); - builder.startCall("next0", "updateTypes").string("polymorphic").end(); - builder.end(); - } else if (getModel().isSpecialized()) { - for (ActualParameter parameter : getModel().getParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } - if (lookupPolymorphicTargetTypes(parameter).size() <= 1) { - continue; - } - builder.startStatement(); - builder.startCall("polymorphic", createUpdateTypeName(parameter)); - builder.typeLiteral(parameter.getType()); - builder.end().end(); - } - - builder.startStatement().startCall("super", UPDATE_TYPES_NAME).string("polymorphic").end().end(); - } - return method; - } - - protected String createUpdateTypeName(ActualParameter parameter) { - return "update" + Utils.firstLetterUpperCase(parameter.getLocalName()) + "Type"; - } - } - - private class PolymorphicNodeFactory extends SpecializedNodeFactory { - - public PolymorphicNodeFactory(ProcessorContext context, CodeTypeElement nodeGen) { - super(context, nodeGen); - } - - @Override - public CodeTypeElement create(SpecializationData polymorph) { - NodeData node = polymorph.getNode(); - TypeMirror baseType = node.getNodeType(); - if (nodeGen != null) { - baseType = nodeGen.asType(); - } - CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodePolymorphicClassName(node), baseType, false); - - clazz.getAnnotationMirrors().add(createNodeInfo(node, NodeCost.POLYMORPHIC)); - - for (ActualParameter polymorphParameter : polymorph.getSignatureParameters()) { - if (!polymorphParameter.getTypeSystemType().isGeneric()) { - continue; - } - Set types = new HashSet<>(); - for (SpecializationData specialization : node.getSpecializations()) { - if (!specialization.isSpecialized()) { - continue; - } - ActualParameter parameter = specialization.findParameter(polymorphParameter.getLocalName()); - assert parameter != null; - types.add(parameter.getTypeSystemType()); - } - CodeVariableElement var = new CodeVariableElement(modifiers(PRIVATE), getContext().getType(Class.class), polymorphicTypeName(polymorphParameter)); - var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getCompilationFinal())); - clazz.add(var); - } - - return clazz; - } - - @Override - protected void createChildren(SpecializationData specialization) { - CodeTypeElement clazz = getElement(); - - createConstructors(clazz); - createExecuteMethods(specialization); - - getElement().add(createUpdateTypes(nodeGen.asType())); - - for (ActualParameter parameter : specialization.getParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } - if (lookupPolymorphicTargetTypes(parameter).size() <= 1) { - continue; - } - getElement().add(createUpdateType(parameter)); - } - - if (needsInvokeCopyConstructorMethod()) { - clazz.add(createCopy(nodeGen.asType(), specialization)); - } - - createCachedExecuteMethods(specialization); - } - - private ExecutableElement createUpdateType(ActualParameter parameter) { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), getContext().getType(void.class), createUpdateTypeName(parameter)); - method.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), "type")); - CodeTreeBuilder builder = method.createBuilder(); - - String fieldName = polymorphicTypeName(parameter); - builder.startIf().string(fieldName).isNull().end().startBlock(); - builder.startStatement().string(fieldName).string(" = ").string("type").end(); - builder.end(); - builder.startElseIf().string(fieldName).string(" != ").string("type").end(); - builder.startBlock(); - builder.startStatement().string(fieldName).string(" = ").typeLiteral(getContext().getType(Object.class)).end(); - builder.end(); - - return method; - } - - } - - private class SpecializedNodeFactory extends NodeBaseFactory { - - protected final CodeTypeElement nodeGen; - - public SpecializedNodeFactory(ProcessorContext context, CodeTypeElement nodeGen) { - super(context); - this.nodeGen = nodeGen; - } - - @Override - public CodeTypeElement create(SpecializationData specialization) { - NodeData node = specialization.getNode(); - TypeMirror baseType = node.getNodeType(); - if (nodeGen != null) { - baseType = nodeGen.asType(); - } - CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false); - - NodeCost cost; - if (specialization.isGeneric()) { - cost = NodeCost.MEGAMORPHIC; - } else if (specialization.isUninitialized()) { - cost = NodeCost.UNINITIALIZED; - } else if (specialization.isPolymorphic()) { - cost = NodeCost.POLYMORPHIC; - } else if (specialization.isSpecialized()) { - cost = NodeCost.MONOMORPHIC; - } else { - throw new AssertionError(); - } - clazz.getAnnotationMirrors().add(createNodeInfo(node, cost)); - - return clazz; - } - - protected CodeAnnotationMirror createNodeInfo(NodeData node, NodeCost cost) { - String shortName = node.getShortName(); - CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(getContext().getTruffleTypes().getNodeInfoAnnotation()); - if (shortName != null) { - nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("shortName"), new CodeAnnotationValue(shortName)); - } - - DeclaredType nodeinfoCost = getContext().getTruffleTypes().getNodeCost(); - VariableElement varKind = Utils.findVariableElement(nodeinfoCost, cost.name()); - - nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("cost"), new CodeAnnotationValue(varKind)); - return nodeInfoMirror; - } - - @Override - protected void createChildren(SpecializationData specialization) { - CodeTypeElement clazz = getElement(); - createConstructors(clazz); - - createExecuteMethods(specialization); - createCachedExecuteMethods(specialization); - if (specialization.getNode().isPolymorphic()) { - getElement().add(createUpdateTypes(nodeGen.asType())); - } - if (needsInvokeCopyConstructorMethod()) { - clazz.add(createCopy(nodeGen.asType(), specialization)); - } - - if (!specialization.isUninitialized() && specialization.getNode().needsRewrites(context)) { - clazz.add(createCopyConstructorFactoryMethod(nodeGen.asType(), specialization)); - } else { - for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) { - if (constructor.getParameters().size() == 1 && ((CodeVariableElement) constructor.getParameters().get(0)).getType().equals(nodeGen.asType())) { - // skip copy constructor - not used - continue; - } - clazz.add(createConstructorFactoryMethod(specialization, constructor)); - } - } - } - - protected void createConstructors(CodeTypeElement clazz) { - TypeElement superTypeElement = Utils.fromTypeMirror(clazz.getSuperclass()); - SpecializationData specialization = getModel(); - NodeData node = specialization.getNode(); - for (ExecutableElement constructor : ElementFilter.constructorsIn(superTypeElement.getEnclosedElements())) { - if (specialization.isUninitialized()) { - // ignore copy constructors for uninitialized if not polymorphic - if (isCopyConstructor(constructor) && !node.isPolymorphic()) { - continue; - } - } else if (node.getUninitializedSpecialization() != null) { - // ignore others than copy constructors for specialized nodes - if (!isCopyConstructor(constructor)) { - continue; - } - } - - CodeExecutableElement superConstructor = createSuperConstructor(clazz, constructor); - if (superConstructor == null) { - continue; - } - CodeTree body = superConstructor.getBodyTree(); - CodeTreeBuilder builder = superConstructor.createBuilder(); - builder.tree(body); - - if (node.isPolymorphic()) { - if (specialization.isSpecialized() || specialization.isPolymorphic()) { - builder.statement("this.next0 = copy.next0"); - } - } - if (superConstructor != null) { - for (ActualParameter param : getImplicitTypeParameters(getModel())) { - clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), implicitTypeName(param))); - superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param))); - - builder.startStatement(); - builder.string("this.").string(implicitTypeName(param)).string(" = ").string(implicitTypeName(param)); - builder.end(); - } - - clazz.add(superConstructor); - } - } - } - - protected void createExecuteMethods(SpecializationData specialization) { - NodeData node = specialization.getNode(); - CodeTypeElement clazz = getElement(); - - for (ExecutableTypeData execType : node.getExecutableTypes()) { - if (execType.isFinal()) { - continue; - } - CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, true); - clazz.add(executeMethod); - CodeTreeBuilder builder = executeMethod.getBuilder(); - CodeTree result = createExecuteBody(builder, specialization, execType); - if (result != null) { - builder.tree(result); - } else { - clazz.remove(executeMethod); - } - } - } - - protected void createCachedExecuteMethods(SpecializationData specialization) { - NodeData node = specialization.getNode(); - if (!node.isPolymorphic()) { - return; - } - - CodeTypeElement clazz = getElement(); - - final SpecializationData polymorphic = node.getPolymorphicSpecialization(); - ExecutableElement executeCached = nodeGen.getMethod(EXECUTE_POLYMORPHIC_NAME); - CodeExecutableElement executeMethod = CodeExecutableElement.clone(getContext().getEnvironment(), executeCached); - executeMethod.getModifiers().remove(Modifier.ABSTRACT); - CodeTreeBuilder builder = executeMethod.createBuilder(); - - if (specialization.isGeneric() || specialization.isPolymorphic()) { - builder.startThrow().startNew(getContext().getType(AssertionError.class)); - builder.doubleQuote("Should not be reached."); - builder.end().end(); - } else if (specialization.isUninitialized()) { - builder.tree(createAppendPolymorphic(builder, specialization)); - } else { - CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder); - elseBuilder.startReturn().startCall("this.next0", EXECUTE_POLYMORPHIC_NAME); - addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, null); - elseBuilder.end().end(); - - boolean forceElse = specialization.getExceptions().size() > 0; - builder.tree(createExecuteTree(builder, polymorphic, SpecializationGroup.create(specialization), false, new CodeBlock() { - - public CodeTree create(CodeTreeBuilder b, SpecializationData current) { - return createGenericInvoke(b, polymorphic, current); - } - }, elseBuilder.getRoot(), forceElse, true, true)); - } - clazz.add(executeMethod); - } - - private CodeTree createAppendPolymorphic(CodeTreeBuilder parent, SpecializationData specialization) { - NodeData node = specialization.getNode(); - - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - builder.tree(createDeoptimize(builder)); - - builder.declaration(getContext().getTruffleTypes().getNode(), "root", "this"); - builder.declaration(getContext().getType(int.class), "depth", "0"); - builder.tree(createFindRoot(builder, node, true)); - builder.newLine(); - - builder.startIf().string("depth > ").string(String.valueOf(node.getPolymorphicDepth())).end(); - builder.startBlock(); - String message = "Polymorphic limit reached (" + node.getPolymorphicDepth() + ")"; - String castRoot = "(" + baseClassName(node) + ") root"; - builder.tree(createGenericInvoke(builder, node.getPolymorphicSpecialization(), node.getGenericSpecialization(), - createReplaceCall(builder, node.getGenericSpecialization(), "root", castRoot, message), null)); - builder.end(); - - builder.startElseBlock(); - builder.startStatement().string("next0 = "); - builder.startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string("this").end(); - builder.end(); - - CodeTreeBuilder specializeCall = new CodeTreeBuilder(builder); - specializeCall.startCall(EXECUTE_SPECIALIZE_NAME); - specializeCall.string("0"); - addInternalValueParameterNames(specializeCall, specialization, node.getGenericSpecialization(), null, true, null); - specializeCall.startGroup().doubleQuote("Uninitialized polymorphic (").string(" + depth + ").doubleQuote("/" + node.getPolymorphicDepth() + ")").end(); - specializeCall.end().end(); - - builder.declaration(node.getGenericSpecialization().getReturnType().getType(), "result", specializeCall.getRoot()); - - CodeTree root = builder.create().cast(nodePolymorphicClassName(node)).string("root").getRoot(); - builder.startIf().string("this.next0 != null").end().startBlock(); - builder.startStatement().string("(").tree(root).string(").").startCall(UPDATE_TYPES_NAME).tree(root).end().end(); - builder.end(); - - if (Utils.isVoid(builder.findMethod().getReturnType())) { - builder.returnStatement(); - } else { - builder.startReturn().string("result").end(); - } - - builder.end(); - - return builder.getRoot(); - } - - private CodeTree createExecuteBody(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData execType) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - - List primaryExecutes = findFunctionalExecutableType(specialization, execType.getEvaluatedCount()); - - if (primaryExecutes.contains(execType) || primaryExecutes.isEmpty()) { - builder.tree(createFunctionalExecute(builder, specialization, execType)); - } else if (needsCastingExecuteMethod(execType)) { - assert !primaryExecutes.isEmpty(); - builder.tree(createCastingExecute(builder, specialization, execType, primaryExecutes.get(0))); - } else { - return null; - } - - return builder.getRoot(); - } - - private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType, boolean evaluated) { - CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod()); - - CodeTreeBuilder builder = method.createBuilder(); - int i = 0; - int signatureIndex = -1; - for (VariableElement param : method.getParameters()) { - CodeVariableElement var = CodeVariableElement.clone(param); - ActualParameter actualParameter = i < execType.getParameters().size() ? execType.getParameters().get(i) : null; - String name; - if (actualParameter != null) { - if (actualParameter.getSpecification().isSignature()) { - signatureIndex++; - } - - if (evaluated && actualParameter.getSpecification().isSignature()) { - name = valueNameEvaluated(actualParameter); - } else { - name = valueName(actualParameter); - } - - int varArgCount = getModel().getSignatureSize() - signatureIndex; - if (evaluated && actualParameter.isTypeVarArgs()) { - ActualParameter baseVarArgs = actualParameter; - name = valueName(baseVarArgs) + "Args"; - - builder.startAssert().string(name).string(" != null").end(); - builder.startAssert().string(name).string(".length == ").string(String.valueOf(varArgCount)).end(); - if (varArgCount > 0) { - List varArgsParameter = execType.getParameters().subList(i, execType.getParameters().size()); - for (ActualParameter varArg : varArgsParameter) { - if (varArgCount <= 0) { - break; - } - TypeMirror type = baseVarArgs.getType(); - if (type.getKind() == TypeKind.ARRAY) { - type = ((ArrayType) type).getComponentType(); - } - builder.declaration(type, valueNameEvaluated(varArg), name + "[" + varArg.getTypeVarArgsIndex() + "]"); - varArgCount--; - } - } - } - } else { - name = "arg" + i; - } - var.setName(name); - method.getParameters().set(i, var); - i++; - } - - method.getAnnotationMirrors().clear(); - method.getModifiers().remove(Modifier.ABSTRACT); - return method; - } - - private boolean needsCastingExecuteMethod(ExecutableTypeData execType) { - if (execType.isAbstract()) { - return true; - } - if (execType.getType().isGeneric()) { - return true; - } - return false; - } - - private List findFunctionalExecutableType(SpecializationData specialization, int evaluatedCount) { - TypeData primaryType = specialization.getReturnType().getTypeSystemType(); - List otherTypes = specialization.getNode().getExecutableTypes(evaluatedCount); - - List filteredTypes = new ArrayList<>(); - for (ExecutableTypeData compareType : otherTypes) { - if (!Utils.typeEquals(compareType.getType().getPrimitiveType(), primaryType.getPrimitiveType())) { - continue; - } - filteredTypes.add(compareType); - } - - // no direct matches found use generic where the type is Object - if (filteredTypes.isEmpty()) { - for (ExecutableTypeData compareType : otherTypes) { - if (compareType.getType().isGeneric() && !compareType.hasUnexpectedValue(getContext())) { - filteredTypes.add(compareType); - } - } - } - - if (filteredTypes.isEmpty()) { - for (ExecutableTypeData compareType : otherTypes) { - if (compareType.getType().isGeneric()) { - filteredTypes.add(compareType); - } - } - } - - return filteredTypes; - } - - private CodeTree createFunctionalExecute(CodeTreeBuilder parent, final SpecializationData specialization, final ExecutableTypeData executable) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - if (specialization.isUninitialized()) { - builder.tree(createDeoptimize(builder)); - } - - builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null)); - - CodeTree returnSpecialized = null; - - if (specialization.findNextSpecialization() != null) { - CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder); - returnBuilder.tree(createDeoptimize(builder)); - returnBuilder.tree(createReturnExecuteAndSpecialize(builder, executable, specialization, null, "One of guards " + specialization.getGuardDefinitions() + " failed")); - returnSpecialized = returnBuilder.getRoot(); - } - - builder.tree(createExecuteTree(builder, specialization, SpecializationGroup.create(specialization), false, new CodeBlock() { - - public CodeTree create(CodeTreeBuilder b, SpecializationData current) { - return createExecute(b, executable, specialization); - } - }, returnSpecialized, false, false, false)); - - return builder.getRoot(); - } - - private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) { - NodeData node = specialization.getNode(); - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - if (!specialization.getExceptions().isEmpty() || !specialization.getAssumptions().isEmpty()) { - builder.startTryBlock(); - } - - for (String assumption : specialization.getAssumptions()) { - builder.startStatement(); - builder.string("this.").string(assumption).string(".check()"); - builder.end(); - } - - CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent); - if (specialization.isPolymorphic()) { - returnBuilder.startCall("next0", EXECUTE_POLYMORPHIC_NAME); - addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, null); - returnBuilder.end(); - } else if (specialization.isUninitialized()) { - returnBuilder.startCall("super", EXECUTE_SPECIALIZE_NAME); - returnBuilder.string("0"); - addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, null); - returnBuilder.doubleQuote("Uninitialized monomorphic"); - returnBuilder.end(); - } else if (specialization.getMethod() == null && !node.needsRewrites(context)) { - emitEncounteredSynthetic(builder, specialization); - } else if (specialization.isGeneric()) { - returnBuilder.startCall("super", EXECUTE_GENERIC_NAME); - addInternalValueParameterNames(returnBuilder, specialization, specialization, null, node.needsFrame(getContext()), null); - returnBuilder.end(); - } else { - returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null)); - } - - if (!returnBuilder.isEmpty()) { - TypeData targetType = node.getTypeSystem().findTypeData(builder.findMethod().getReturnType()); - TypeData sourceType = specialization.getReturnType().getTypeSystemType(); - - builder.startReturn(); - if (targetType == null || sourceType == null) { - builder.tree(returnBuilder.getRoot()); - } else if (sourceType.needsCastTo(getContext(), targetType)) { - String castMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType); - if (!executable.hasUnexpectedValue(context)) { - castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType); - } - builder.tree(createCallTypeSystemMethod(context, parent, node, castMethodName, returnBuilder.getRoot())); - } else { - builder.tree(returnBuilder.getRoot()); - } - builder.end(); - } - - if (!specialization.getExceptions().isEmpty()) { - for (SpecializationThrowsData exception : specialization.getExceptions()) { - builder.end().startCatchBlock(exception.getJavaClass(), "ex"); - builder.tree(createDeoptimize(builder)); - builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization, null, "Thrown " + Utils.getSimpleName(exception.getJavaClass()))); - } - builder.end(); - } - if (!specialization.getAssumptions().isEmpty()) { - builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex"); - builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization, null, "Assumption failed")); - builder.end(); - } - - return builder.getRoot(); - } - - protected CodeExecutableElement createCopyConstructorFactoryMethod(TypeMirror baseType, SpecializationData specialization) { - List implicitTypeParams = getImplicitTypeParameters(specialization); - CodeVariableElement[] parameters = new CodeVariableElement[implicitTypeParams.size() + 1]; - int i = 0; - String baseName = "current"; - parameters[i++] = new CodeVariableElement(specialization.getNode().getNodeType(), baseName); - for (ActualParameter implicitTypeParam : implicitTypeParams) { - parameters[i++] = new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(implicitTypeParam)); - } - CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), CREATE_SPECIALIZATION_NAME, parameters); - CodeTreeBuilder builder = method.createBuilder(); - builder.startReturn(); - builder.startNew(getElement().asType()); - builder.startGroup().cast(baseType, CodeTreeBuilder.singleString(baseName)).end(); - for (ActualParameter param : implicitTypeParams) { - builder.string(implicitTypeName(param)); - } - builder.end().end(); - return method; - } - - protected CodeExecutableElement createConstructorFactoryMethod(SpecializationData specialization, ExecutableElement constructor) { - List parameters = constructor.getParameters(); - CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), CREATE_SPECIALIZATION_NAME, - parameters.toArray(new CodeVariableElement[parameters.size()])); - CodeTreeBuilder builder = method.createBuilder(); - builder.startReturn(); - builder.startNew(getElement().asType()); - for (VariableElement param : parameters) { - builder.string(((CodeVariableElement) param).getName()); - } - builder.end().end(); - return method; - } - } - - private interface CodeBlock { - - CodeTree create(CodeTreeBuilder parent, T value); - - } -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,520 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.node; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality; -import com.oracle.truffle.dsl.processor.template.*; -import com.oracle.truffle.dsl.processor.typesystem.*; - -public class NodeData extends Template implements Comparable { - - private final String nodeId; - private final String shortName; - private final List enclosingNodes = new ArrayList<>(); - private NodeData declaringNode; - - private final TypeSystemData typeSystem; - private final List children; - private final List childExecutions; - private final List fields; - private final List assumptions; - - private ParameterSpec instanceParameterSpec; - - private final List specializations = new ArrayList<>(); - private final List shortCircuits = new ArrayList<>(); - private final List casts = new ArrayList<>(); - private Map> executableTypes; - - private final NodeExecutionData thisExecution; - - private int polymorphicDepth = -1; - - public NodeData(TypeElement type, String shortName, TypeSystemData typeSystem, List children, List executions, List fields, - List assumptions, int polymorphicDepth) { - super(type, null, null); - this.nodeId = type.getSimpleName().toString(); - this.shortName = shortName; - this.typeSystem = typeSystem; - this.fields = fields; - this.children = children; - this.childExecutions = executions; - this.assumptions = assumptions; - this.polymorphicDepth = polymorphicDepth; - this.thisExecution = new NodeExecutionData(new NodeChildData(null, null, "this", getNodeType(), getNodeType(), null, Cardinality.ONE), -1, false); - this.thisExecution.getChild().setNode(this); - if (children != null) { - for (NodeChildData child : children) { - child.setParentNode(this); - } - } - } - - public NodeData(TypeElement type) { - this(type, null, null, null, null, null, null, -1); - } - - public NodeExecutionData getThisExecution() { - return thisExecution; - } - - public void addEnclosedNode(NodeData node) { - this.enclosingNodes.add(node); - node.declaringNode = this; - } - - public List getChildExecutions() { - return childExecutions; - } - - public int getSignatureSize() { - if (getSpecializations() != null && !getSpecializations().isEmpty()) { - return getSpecializations().get(0).getSignatureSize(); - } - return 0; - } - - public boolean needsFrame(ProcessorContext context) { - for (SpecializationData specialization : specializations) { - if (!specialization.isReachable()) { - continue; - } - if (specialization.hasFrame(context)) { - return true; - } - } - return false; - } - - public boolean needsImplicitCast(ProcessorContext context) { - for (NodeChildData child : getChildren()) { - if (child.needsImplicitCast(context)) { - return true; - } - } - return false; - } - - public int getPolymorphicDepth() { - return polymorphicDepth; - } - - public boolean isPolymorphic() { - return polymorphicDepth > 1; - } - - public void setPolymorphicDepth(int polymorphicDepth) { - this.polymorphicDepth = polymorphicDepth; - } - - public List getCasts() { - return casts; - } - - public String getShortName() { - return shortName; - } - - public List getFields() { - return fields; - } - - @Override - protected List findChildContainers() { - List containerChildren = new ArrayList<>(); - if (enclosingNodes != null) { - containerChildren.addAll(enclosingNodes); - } - if (typeSystem != null) { - containerChildren.add(typeSystem); - } - if (specializations != null) { - for (MessageContainer specialization : specializations) { - if (specialization.getMessageElement() != null) { - containerChildren.add(specialization); - } - } - } - if (executableTypes != null) { - containerChildren.addAll(getExecutableTypes()); - } - if (shortCircuits != null) { - containerChildren.addAll(shortCircuits); - } - if (children != null) { - containerChildren.addAll(children); - } - if (fields != null) { - containerChildren.addAll(fields); - } - if (casts != null) { - containerChildren.addAll(casts); - } - return containerChildren; - } - - public ParameterSpec getInstanceParameterSpec() { - return instanceParameterSpec; - } - - public void setInstanceParameterSpec(ParameterSpec instanceParameter) { - this.instanceParameterSpec = instanceParameter; - } - - public String getNodeId() { - return nodeId; - } - - public TypeMirror getNodeType() { - return getTemplateType().asType(); - } - - public List getAssumptions() { - return assumptions; - } - - public boolean needsFactory() { - if (specializations == null) { - return false; - } - if (getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { - return false; - } - - boolean noSpecialization = true; - for (SpecializationData specialization : specializations) { - noSpecialization = noSpecialization && !specialization.isSpecialized(); - } - return !noSpecialization; - } - - public boolean supportsFrame() { - if (executableTypes != null) { - for (ExecutableTypeData execType : getExecutableTypes(-1)) { - if (execType.findParameter("frameValue") == null) { - return false; - } - } - } - return true; - } - - public List getNodeDeclaringChildren() { - List nodeChildren = new ArrayList<>(); - for (NodeData child : getEnclosingNodes()) { - if (child.needsFactory()) { - nodeChildren.add(child); - } - nodeChildren.addAll(child.getNodeDeclaringChildren()); - } - return nodeChildren; - } - - public NodeData getDeclaringNode() { - return declaringNode; - } - - public List getEnclosingNodes() { - return enclosingNodes; - } - - public List getAllTemplateMethods() { - List methods = new ArrayList<>(); - - for (SpecializationData specialization : getSpecializations()) { - methods.add(specialization); - } - - methods.addAll(getExecutableTypes()); - methods.addAll(getShortCircuits()); - if (getCasts() != null) { - methods.addAll(getCasts()); - } - - return methods; - } - - public ExecutableTypeData findGenericExecutableType(ProcessorContext context, TypeData type, int evaluatedCount) { - List types = findGenericExecutableTypes(context, evaluatedCount); - for (ExecutableTypeData availableType : types) { - if (Utils.typeEquals(availableType.getType().getBoxedType(), type.getBoxedType())) { - return availableType; - } - } - return null; - } - - public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context, int evaluatedCount) { - List types = findGenericExecutableTypes(context, evaluatedCount); - for (ExecutableTypeData type : types) { - if (type.getType().isGeneric()) { - return type; - } - } - - for (ExecutableTypeData type : types) { - if (!type.getType().isVoid()) { - return type; - } - } - - for (ExecutableTypeData type : types) { - return type; - } - return null; - } - - public List getExecutableTypes(int evaluatedCount) { - if (executableTypes == null) { - return Collections.emptyList(); - } - if (evaluatedCount == -1) { - List typeData = new ArrayList<>(); - for (int currentEvaluationCount : executableTypes.keySet()) { - typeData.addAll(executableTypes.get(currentEvaluationCount)); - } - return typeData; - } else { - List types = executableTypes.get(evaluatedCount); - if (types == null) { - return Collections.emptyList(); - } - return types; - } - } - - public List findGenericExecutableTypes(ProcessorContext context, int evaluatedCount) { - List types = new ArrayList<>(); - for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) { - if (!type.hasUnexpectedValue(context)) { - types.add(type); - } - } - return types; - } - - public ExecutableTypeData findExecutableType(TypeData prmitiveType, int evaluatedCount) { - for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) { - if (Utils.typeEquals(type.getType().getPrimitiveType(), prmitiveType.getPrimitiveType())) { - return type; - } - } - return null; - } - - public SpecializationData findUniqueSpecialization(TypeData type) { - SpecializationData result = null; - for (SpecializationData specialization : specializations) { - if (specialization.getReturnType().getTypeSystemType() == type) { - if (result != null) { - // Result not unique; - return null; - } - result = specialization; - } - } - return result; - } - - public boolean needsRewrites(ProcessorContext context) { - boolean needsRewrites = false; - - for (SpecializationData specialization : getSpecializations()) { - if (specialization.hasRewrite(context)) { - needsRewrites = true; - break; - } - } - return needsRewrites || getSpecializations().size() > 1; - } - - public SpecializationData getPolymorphicSpecialization() { - for (SpecializationData specialization : specializations) { - if (specialization.isPolymorphic()) { - return specialization; - } - } - return null; - } - - public SpecializationData getGenericSpecialization() { - for (SpecializationData specialization : specializations) { - if (specialization.isGeneric()) { - return specialization; - } - } - return null; - } - - public SpecializationData getUninitializedSpecialization() { - for (SpecializationData specialization : specializations) { - if (specialization.isUninitialized()) { - return specialization; - } - } - return null; - } - - @Override - public TypeSystemData getTypeSystem() { - return typeSystem; - } - - public String dump() { - return dump(0); - } - - private String dump(int level) { - String indent = ""; - for (int i = 0; i < level; i++) { - indent += " "; - } - StringBuilder builder = new StringBuilder(); - - builder.append(String.format("%s%s {", indent, toString())); - - dumpProperty(builder, indent, "templateClass", Utils.getQualifiedName(getTemplateType())); - dumpProperty(builder, indent, "typeSystem", getTypeSystem()); - dumpProperty(builder, indent, "fields", getChildren()); - dumpProperty(builder, indent, "executableTypes", getExecutableTypes()); - dumpProperty(builder, indent, "specializations", getSpecializations()); - dumpProperty(builder, indent, "polymorphicDepth", getPolymorphicDepth()); - dumpProperty(builder, indent, "assumptions", getAssumptions()); - dumpProperty(builder, indent, "casts", getCasts()); - dumpProperty(builder, indent, "messages", collectMessages()); - if (getEnclosingNodes().size() > 0) { - builder.append(String.format("\n%s children = [", indent)); - for (NodeData node : getEnclosingNodes()) { - builder.append("\n"); - builder.append(node.dump(level + 1)); - } - builder.append(String.format("\n%s ]", indent)); - } - builder.append(String.format("%s}", indent)); - return builder.toString(); - } - - private static void dumpProperty(StringBuilder b, String indent, String propertyName, Object value) { - if (value instanceof List) { - List list = (List) value; - if (!list.isEmpty()) { - b.append(String.format("\n%s %s = %s", indent, propertyName, dumpList(indent, (List) value))); - } - } else { - if (value != null) { - b.append(String.format("\n%s %s = %s", indent, propertyName, value)); - } - } - } - - private static String dumpList(String indent, List array) { - if (array == null) { - return "null"; - } - - if (array.isEmpty()) { - return "[]"; - } else if (array.size() == 1) { - return "[" + array.get(0).toString() + "]"; - } - - StringBuilder b = new StringBuilder(); - b.append("["); - for (Object object : array) { - b.append("\n "); - b.append(indent); - b.append(object); - b.append(", "); - } - b.append("\n ").append(indent).append("]"); - return b.toString(); - } - - public NodeExecutionData findExecution(String name) { - if (getChildExecutions() == null) { - return null; - } - for (NodeExecutionData execution : getChildExecutions()) { - if (execution.getName().equals(name)) { - return execution; - } - } - return null; - } - - public NodeChildData findChild(String name) { - for (NodeChildData field : getChildren()) { - if (field.getName().equals(name)) { - return field; - } - } - return null; - } - - public List getChildren() { - return children; - } - - public List getSpecializations() { - return specializations; - } - - public List getExecutableTypes() { - return getExecutableTypes(-1); - } - - public List getShortCircuits() { - return shortCircuits; - } - - public void setExecutableTypes(Map> executableTypes) { - this.executableTypes = executableTypes; - } - - @Override - public String toString() { - return getClass().getSimpleName() + "[" + getNodeId() + "]"; - } - - public CreateCastData findCast(String name) { - if (getCasts() != null) { - for (CreateCastData cast : getCasts()) { - if (cast.getChildNames().contains(name)) { - return cast; - } - } - } - return null; - } - - public int compareTo(NodeData o) { - return getNodeId().compareTo(o.getNodeId()); - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeExecutionData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeExecutionData.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.node; - -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality; - -public class NodeExecutionData { - - private final NodeChildData child; - private final String name; - private final int index; - private final boolean shortCircuit; - - public NodeExecutionData(NodeChildData child, int index, boolean shortCircuit) { - this.child = child; - this.index = index; - this.shortCircuit = shortCircuit; - this.name = createName(); - } - - private String createName() { - if (isIndexed()) { - return child.getName() + index; - } - return child.getName(); - } - - public TypeMirror getNodeType() { - TypeMirror type; - if (child.getCardinality() == Cardinality.MANY && child.getNodeType().getKind() == TypeKind.ARRAY) { - type = ((ArrayType) child.getNodeType()).getComponentType(); - } else { - type = child.getNodeType(); - } - return type; - } - - public String getName() { - return name; - } - - public NodeChildData getChild() { - return child; - } - - public int getIndex() { - return index; - } - - public boolean isIndexed() { - return index > -1; - } - - public boolean isShortCircuit() { - return shortCircuit; - } - - public String getShortCircuitId() { - return createShortCircuitId(child, index); - } - - public static String createShortCircuitId(NodeChildData child, int varArgsIndex) { - String shortCircuitName = child.getName(); - if (child.getCardinality().isMany()) { - shortCircuitName = shortCircuitName + "[" + varArgsIndex + "]"; - } - return shortCircuitName; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeFieldData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeFieldData.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.node; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.template.*; - -public class NodeFieldData extends MessageContainer { - - private final Element messageElement; - private final AnnotationMirror messageAnnotation; - private final String name; - private final TypeMirror type; - private final boolean generated; - private ExecutableElement getter; - - public NodeFieldData(Element messageElement, AnnotationMirror messageAnnotation, TypeMirror type, String name, boolean generated) { - this.messageElement = messageElement; - this.messageAnnotation = messageAnnotation; - this.name = name; - this.type = type; - this.generated = generated; - } - - void setGetter(ExecutableElement getter) { - this.getter = getter; - } - - @Override - public Element getMessageElement() { - return messageElement; - } - - @Override - public AnnotationMirror getMessageAnnotation() { - return messageAnnotation; - } - - public String getName() { - return name; - } - - public TypeMirror getType() { - return type; - } - - public boolean isGenerated() { - return generated; - } - - public ExecutableElement getGetter() { - return getter; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.node; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.template.*; - -public abstract class NodeMethodParser extends TemplateMethodParser { - - public NodeMethodParser(ProcessorContext context, NodeData node) { - super(context, node); - } - - public NodeData getNode() { - return template; - } - - protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) { - ParameterSpec spec = new ParameterSpec(execution.getName(), nodeTypeMirrors(execution.getChild().getNodeData())); - spec.setExecution(execution); - return spec; - } - - protected List nodeTypeMirrors(NodeData nodeData) { - Set typeMirrors = new LinkedHashSet<>(); - - for (ExecutableTypeData typeData : nodeData.getExecutableTypes()) { - typeMirrors.add(typeData.getType().getPrimitiveType()); - } - - typeMirrors.add(nodeData.getTypeSystem().getGenericType()); - - return new ArrayList<>(typeMirrors); - } - - protected ParameterSpec createReturnParameterSpec() { - ParameterSpec returnValue = new ParameterSpec("returnValue", nodeTypeMirrors(getNode())); - returnValue.setExecution(getNode().getThisExecution()); - return returnValue; - } - - @Override - public boolean isParsable(ExecutableElement method) { - if (getAnnotationType() != null) { - return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null; - } - - return true; - } - - @SuppressWarnings("unused") - protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, boolean shortCircuitsEnabled, String shortCircuitName) { - MethodSpec methodSpec = new MethodSpec(createReturnParameterSpec()); - - addDefaultFrame(methodSpec); - addDefaultFieldMethodSpec(methodSpec); - addDefaultChildren(shortCircuitsEnabled, shortCircuitName, methodSpec); - - return methodSpec; - } - - public void addDefaultChildren(boolean shortCircuitsEnabled, String breakName, MethodSpec spec) { - if (getNode().getChildren() == null) { - // children are null when parsing executable types - return; - } - - for (NodeExecutionData execution : getNode().getChildExecutions()) { - if (breakName != null && execution.getShortCircuitId().equals(breakName)) { - break; - } - - if (execution.isShortCircuit() && shortCircuitsEnabled) { - spec.addRequired(new ParameterSpec(shortCircuitValueName(execution.getName()), getContext().getType(boolean.class))); - } - spec.addRequired(createValueParameterSpec(execution)); - } - } - - private void addDefaultFrame(MethodSpec methodSpec) { - if (getNode().supportsFrame()) { - methodSpec.addOptional(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame())); - } - } - - protected void addDefaultFieldMethodSpec(MethodSpec methodSpec) { - for (NodeFieldData field : getNode().getFields()) { - if (field.getGetter() == null) { - ParameterSpec spec = new ParameterSpec(field.getName(), field.getType()); - spec.setLocal(true); - methodSpec.addOptional(spec); - } - } - } - - private static String shortCircuitValueName(String valueName) { - return "has" + Utils.firstLetterUpperCase(valueName); - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1225 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.node; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; -import javax.tools.Diagnostic.Kind; - -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality; -import com.oracle.truffle.dsl.processor.node.SpecializationData.SpecializationKind; -import com.oracle.truffle.dsl.processor.template.*; -import com.oracle.truffle.dsl.processor.template.TemplateMethod.TypeSignature; -import com.oracle.truffle.dsl.processor.typesystem.*; - -public class NodeParser extends AbstractParser { - - public static final List> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, NodeChild.class, - NodeChildren.class); - - private Map parsedNodes; - - public NodeParser(ProcessorContext c) { - super(c); - } - - @Override - protected NodeData parse(Element element, AnnotationMirror mirror) { - NodeData node = null; - try { - parsedNodes = new HashMap<>(); - node = resolveNode((TypeElement) element); - if (Log.DEBUG) { - NodeData parsed = parsedNodes.get(Utils.getQualifiedName((TypeElement) element)); - if (node != null) { - String dump = parsed.dump(); - log.message(Kind.ERROR, null, null, null, dump); - } - } - } finally { - parsedNodes = null; - } - - return node; - } - - @Override - protected NodeData filterErrorElements(NodeData model) { - for (Iterator iterator = model.getEnclosingNodes().iterator(); iterator.hasNext();) { - NodeData node = filterErrorElements(iterator.next()); - if (node == null) { - iterator.remove(); - } - } - if (model.hasErrors()) { - return null; - } - return model; - } - - @Override - public boolean isDelegateToRootDeclaredType() { - return true; - } - - @Override - public Class getAnnotationType() { - return null; - } - - @Override - public List> getTypeDelegatedAnnotationTypes() { - return ANNOTATIONS; - } - - private NodeData resolveNode(TypeElement rootType) { - String typeName = Utils.getQualifiedName(rootType); - if (parsedNodes.containsKey(typeName)) { - return parsedNodes.get(typeName); - } - - List enclosedNodes = new ArrayList<>(); - for (TypeElement enclosedType : ElementFilter.typesIn(rootType.getEnclosedElements())) { - NodeData enclosedChild = resolveNode(enclosedType); - if (enclosedChild != null) { - enclosedNodes.add(enclosedChild); - } - } - - NodeData node = parseNode(rootType); - if (node == null && !enclosedNodes.isEmpty()) { - node = new NodeData(rootType); - } - - if (node != null) { - for (NodeData enclosedNode : enclosedNodes) { - node.addEnclosedNode(enclosedNode); - } - } - - parsedNodes.put(typeName, node); - return node; - } - - private NodeData parseNode(TypeElement originalTemplateType) { - // reloading the type elements is needed for ecj - TypeElement templateType = Utils.fromTypeMirror(context.reloadTypeElement(originalTemplateType)); - - if (Utils.findAnnotationMirror(processingEnv, originalTemplateType, GeneratedBy.class) != null) { - // generated nodes should not get called again. - return null; - } - - List lookupTypes = collectSuperClasses(new ArrayList(), templateType); - if (!Utils.isAssignable(context, templateType.asType(), context.getTruffleTypes().getNode())) { - return null; - } - - List elements = context.getEnvironment().getElementUtils().getAllMembers(templateType); - - NodeData node = parseNodeData(templateType, elements, lookupTypes); - if (node.hasErrors()) { - return node; // error sync point - } - - initializeChildren(node); - - node.getSpecializations().addAll(new SpecializationMethodParser(context, node).parse(elements)); - node.getSpecializations().addAll(new GenericParser(context, node).parse(elements)); - node.getCasts().addAll(new CreateCastParser(context, node).parse(elements)); - node.getShortCircuits().addAll(new ShortCircuitParser(context, node).parse(elements)); - - if (node.hasErrors()) { - return node; // error sync point - } - - verifySpecializationSameLength(node); - initializeSpecializations(elements, node); - initializeShortCircuits(node); // requires specializations and polymorphic specializations - - verifyVisibilities(node); - verifySpecializationOrder(node); - verifyMissingAbstractMethods(node, elements); - verifyConstructors(node); - verifyNamingConvention(node.getShortCircuits(), "needs"); - verifySpecializationThrows(node); - return node; - } - - private NodeData parseNodeData(TypeElement templateType, List elements, List typeHierarchy) { - AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); - if (typeSystemMirror == null) { - NodeData nodeData = new NodeData(templateType); - nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), Utils.getQualifiedName(templateType)); - return nodeData; - } - - TypeMirror typeSystemType = Utils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value"); - final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSystemType, true); - if (typeSystem == null) { - NodeData nodeData = new NodeData(templateType); - nodeData.addError("The used type system '%s' is invalid or not a Node.", Utils.getQualifiedName(typeSystemType)); - return nodeData; - } - - AnnotationMirror polymorphicMirror = findFirstAnnotation(typeHierarchy, PolymorphicLimit.class); - int polymorphicLimit = -1; - if (polymorphicMirror != null) { - AnnotationValue limitValue = Utils.getAnnotationValue(polymorphicMirror, "value"); - int customPolymorphicLimit = Utils.getAnnotationValue(Integer.class, polymorphicMirror, "value"); - if (customPolymorphicLimit < 1) { - NodeData nodeData = new NodeData(templateType); - nodeData.addError(limitValue, "Invalid polymorphic limit %s.", polymorphicLimit); - return nodeData; - } - polymorphicLimit = customPolymorphicLimit; - } - - List assumptionsList = new ArrayList<>(); - for (int i = typeHierarchy.size() - 1; i >= 0; i--) { - TypeElement type = typeHierarchy.get(i); - AnnotationMirror assumptions = Utils.findAnnotationMirror(context.getEnvironment(), type, NodeAssumptions.class); - if (assumptions != null) { - List assumptionStrings = Utils.getAnnotationValueList(String.class, assumptions, "value"); - for (String string : assumptionStrings) { - if (assumptionsList.contains(string)) { - assumptionsList.remove(string); - } - assumptionsList.add(string); - } - } - } - AnnotationMirror nodeInfoMirror = findFirstAnnotation(typeHierarchy, NodeInfo.class); - String shortName = null; - if (nodeInfoMirror != null) { - shortName = Utils.getAnnotationValue(String.class, nodeInfoMirror, "shortName"); - } - - List fields = parseFields(typeHierarchy, elements); - List children = parseChildren(elements, typeHierarchy); - List executions = parseExecutions(children, elements); - - NodeData nodeData = new NodeData(templateType, shortName, typeSystem, children, executions, fields, assumptionsList, polymorphicLimit); - nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements))); - - parsedNodes.put(Utils.getQualifiedName(templateType), nodeData); - - return nodeData; - } - - private List parseFields(List typeHierarchy, List elements) { - Set names = new HashSet<>(); - - List fields = new ArrayList<>(); - for (VariableElement field : ElementFilter.fieldsIn(elements)) { - if (field.getModifiers().contains(Modifier.STATIC)) { - continue; - } - if (field.getModifiers().contains(Modifier.PUBLIC) || field.getModifiers().contains(Modifier.PROTECTED)) { - String name = field.getSimpleName().toString(); - fields.add(new NodeFieldData(field, null, field.asType(), name, false)); - names.add(name); - } - } - - List reversedTypeHierarchy = new ArrayList<>(typeHierarchy); - Collections.reverse(reversedTypeHierarchy); - for (TypeElement typeElement : reversedTypeHierarchy) { - AnnotationMirror nodeChildrenMirror = Utils.findAnnotationMirror(processingEnv, typeElement, NodeFields.class); - List children = Utils.collectAnnotations(context, nodeChildrenMirror, "value", typeElement, NodeField.class); - - for (AnnotationMirror mirror : children) { - String name = Utils.firstLetterLowerCase(Utils.getAnnotationValue(String.class, mirror, "name")); - TypeMirror type = Utils.getAnnotationValue(TypeMirror.class, mirror, "type"); - - NodeFieldData field = new NodeFieldData(typeElement, mirror, type, name, true); - if (name.isEmpty()) { - field.addError(Utils.getAnnotationValue(mirror, "name"), "Field name cannot be empty."); - } else if (names.contains(name)) { - field.addError(Utils.getAnnotationValue(mirror, "name"), "Duplicate field name '%s'.", name); - } - names.add(name); - - fields.add(field); - } - } - - for (NodeFieldData nodeFieldData : fields) { - nodeFieldData.setGetter(findGetter(elements, nodeFieldData.getName(), nodeFieldData.getType())); - } - - return fields; - } - - private List parseChildren(List elements, final List typeHierarchy) { - Set shortCircuits = new HashSet<>(); - for (ExecutableElement method : ElementFilter.methodsIn(elements)) { - AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class); - if (mirror != null) { - shortCircuits.add(Utils.getAnnotationValue(String.class, mirror, "value")); - } - } - Map castNodeTypes = new HashMap<>(); - for (ExecutableElement method : ElementFilter.methodsIn(elements)) { - AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, CreateCast.class); - if (mirror != null) { - List children = (Utils.getAnnotationValueList(String.class, mirror, "value")); - if (children != null) { - for (String child : children) { - castNodeTypes.put(child, method.getReturnType()); - } - } - } - } - - List parsedChildren = new ArrayList<>(); - List typeHierarchyReversed = new ArrayList<>(typeHierarchy); - Collections.reverse(typeHierarchyReversed); - for (TypeElement type : typeHierarchyReversed) { - AnnotationMirror nodeChildrenMirror = Utils.findAnnotationMirror(processingEnv, type, NodeChildren.class); - - TypeMirror nodeClassType = type.getSuperclass(); - if (!Utils.isAssignable(context, nodeClassType, context.getTruffleTypes().getNode())) { - nodeClassType = null; - } - - List children = Utils.collectAnnotations(context, nodeChildrenMirror, "value", type, NodeChild.class); - int index = 0; - for (AnnotationMirror childMirror : children) { - String name = Utils.getAnnotationValue(String.class, childMirror, "value"); - if (name.equals("")) { - name = "child" + index; - } - - Cardinality cardinality = Cardinality.ONE; - - TypeMirror childType = inheritType(childMirror, "type", nodeClassType); - if (childType.getKind() == TypeKind.ARRAY) { - cardinality = Cardinality.MANY; - } - - TypeMirror originalChildType = childType; - TypeMirror castNodeType = castNodeTypes.get(name); - if (castNodeType != null) { - childType = castNodeType; - } - - Element getter = findGetter(elements, name, childType); - - NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality); - - parsedChildren.add(nodeChild); - - if (nodeChild.getNodeType() == null) { - nodeChild.addError("No valid node type could be resoleved."); - } - if (nodeChild.hasErrors()) { - continue; - } - - index++; - } - } - - List filteredChildren = new ArrayList<>(); - Set encounteredNames = new HashSet<>(); - for (int i = parsedChildren.size() - 1; i >= 0; i--) { - NodeChildData child = parsedChildren.get(i); - if (!encounteredNames.contains(child.getName())) { - filteredChildren.add(0, child); - encounteredNames.add(child.getName()); - } - } - - for (NodeChildData child : filteredChildren) { - List executeWithStrings = Utils.getAnnotationValueList(String.class, child.getMessageAnnotation(), "executeWith"); - AnnotationValue executeWithValue = Utils.getAnnotationValue(child.getMessageAnnotation(), "executeWith"); - List executeWith = new ArrayList<>(); - for (String executeWithString : executeWithStrings) { - - if (child.getName().equals(executeWithString)) { - child.addError(executeWithValue, "The child node '%s' cannot be executed with itself.", executeWithString); - continue; - } - - NodeChildData found = null; - boolean before = true; - for (NodeChildData resolveChild : filteredChildren) { - if (resolveChild == child) { - before = false; - continue; - } - if (resolveChild.getName().equals(executeWithString)) { - found = resolveChild; - break; - } - } - - if (found == null) { - child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The child node was not found.", child.getName(), executeWithString); - continue; - } else if (!before) { - child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The node %s is executed after the current node.", child.getName(), executeWithString, - executeWithString); - continue; - } - executeWith.add(found); - } - child.setExecuteWith(executeWith); - if (child.getNodeData() == null) { - continue; - } - } - - return filteredChildren; - } - - private List parseExecutions(List children, List elements) { - if (children == null) { - return null; - } - - // pre-parse short circuits - Set shortCircuits = new HashSet<>(); - List methods = ElementFilter.methodsIn(elements); - for (ExecutableElement method : methods) { - AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class); - if (mirror != null) { - shortCircuits.add(Utils.getAnnotationValue(String.class, mirror, "value")); - } - } - - boolean hasVarArgs = false; - int maxSignatureSize = 0; - if (!children.isEmpty()) { - int lastIndex = children.size() - 1; - hasVarArgs = children.get(lastIndex).getCardinality() == Cardinality.MANY; - if (hasVarArgs) { - maxSignatureSize = lastIndex; - } else { - maxSignatureSize = children.size(); - } - } - - // pre-parse specializations - for (ExecutableElement method : methods) { - AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, Specialization.class); - if (mirror == null) { - continue; - } - - int currentArgumentCount = 0; - boolean skipShortCircuit = false; - for (VariableElement var : method.getParameters()) { - TypeMirror type = var.asType(); - if (currentArgumentCount == 0) { - // skip optionals - if (Utils.typeEquals(type, context.getTruffleTypes().getFrame())) { - continue; - } - // TODO skip optional fields? - } - int childIndex = currentArgumentCount < children.size() ? currentArgumentCount : children.size() - 1; - if (childIndex == -1) { - continue; - } - if (!skipShortCircuit) { - NodeChildData child = children.get(childIndex); - if (shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, currentArgumentCount - childIndex))) { - skipShortCircuit = true; - continue; - } - } else { - skipShortCircuit = false; - } - - currentArgumentCount++; - } - maxSignatureSize = Math.max(maxSignatureSize, currentArgumentCount); - } - - List executions = new ArrayList<>(); - for (int i = 0; i < maxSignatureSize; i++) { - int childIndex = i; - boolean varArg = false; - if (childIndex >= children.size() - 1) { - if (hasVarArgs) { - childIndex = children.size() - 1; - varArg = hasVarArgs; - } else if (childIndex >= children.size()) { - break; - } - } - int varArgsIndex = varArg ? Math.abs(childIndex - i) : -1; - NodeChildData child = children.get(childIndex); - boolean shortCircuit = shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, varArgsIndex)); - executions.add(new NodeExecutionData(child, varArgsIndex, shortCircuit)); - } - return executions; - } - - private static Map> groupExecutableTypes(List executableTypes) { - Map> groupedTypes = new TreeMap<>(); - for (ExecutableTypeData type : executableTypes) { - int evaluatedCount = type.getEvaluatedCount(); - - List types = groupedTypes.get(evaluatedCount); - if (types == null) { - types = new ArrayList<>(); - groupedTypes.put(evaluatedCount, types); - } - types.add(type); - } - - for (List types : groupedTypes.values()) { - Collections.sort(types); - } - return groupedTypes; - } - - private void initializeChildren(NodeData node) { - for (NodeChildData nodeChild : node.getChildren()) { - NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(nodeChild.getNodeType())); - nodeChild.setNode(fieldNodeData); - if (fieldNodeData == null) { - nodeChild.addError("Node type '%s' is invalid or not a valid Node.", Utils.getQualifiedName(nodeChild.getNodeType())); - } else if (!Utils.typeEquals(fieldNodeData.getTypeSystem().getTemplateType().asType(), (node.getTypeSystem().getTemplateType().asType()))) { - nodeChild.addError("The @%s of the node and the @%s of the @%s does not match. %s != %s. ", TypeSystem.class.getSimpleName(), TypeSystem.class.getSimpleName(), - NodeChild.class.getSimpleName(), Utils.getSimpleName(node.getTypeSystem().getTemplateType()), Utils.getSimpleName(fieldNodeData.getTypeSystem().getTemplateType())); - } - if (fieldNodeData != null) { - List types = nodeChild.findGenericExecutableTypes(context); - if (types.isEmpty()) { - AnnotationValue executeWithValue = Utils.getAnnotationValue(nodeChild.getMessageAnnotation(), "executeWith"); - nodeChild.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", nodeChild.getExecuteWith().size(), - Utils.getSimpleName(nodeChild.getNodeType())); - } - } - } - } - - private void initializeSpecializations(List elements, final NodeData node) { - if (node.getSpecializations().isEmpty()) { - return; - } - - for (SpecializationData specialization : node.getSpecializations()) { - if (!specialization.isSpecialized()) { - continue; - } - initializeGuards(elements, specialization); - } - - initializeGeneric(node); - initializeUninitialized(node); - initializePolymorphism(node); // requires specializations - Collections.sort(node.getSpecializations()); - initializeReachability(node); - - // reduce polymorphicness if generic is not reachable - if (node.getGenericSpecialization() != null && !node.getGenericSpecialization().isReachable()) { - node.setPolymorphicDepth(1); - node.getSpecializations().remove(node.getPolymorphicSpecialization()); - } - - List needsId = new ArrayList<>(); - for (SpecializationData specialization : node.getSpecializations()) { - if (specialization.isGeneric()) { - specialization.setId("Generic"); - } else if (specialization.isUninitialized()) { - specialization.setId("Uninitialized"); - } else if (specialization.isPolymorphic()) { - specialization.setId("Polymorphic"); - } else if (specialization.isSpecialized()) { - needsId.add(specialization); - } else { - throw new AssertionError(); - } - } - - // verify specialization parameter length - List ids = initializeSpecializationIds(needsId); - for (int i = 0; i < ids.size(); i++) { - needsId.get(i).setId(ids.get(i)); - } - - } - - private void initializeReachability(final NodeData node) { - SpecializationData prev = null; - boolean reachable = true; - for (SpecializationData specialization : node.getSpecializations()) { - if (specialization.isUninitialized() || specialization.isPolymorphic()) { - specialization.setReachable(true); - continue; - } - if (prev != null && prev.equalsGuards(specialization) && prev.getExceptions().isEmpty()) { - specialization.addError("%s is not reachable.", specialization.isGeneric() ? "Generic" : "Specialization"); - } else if (!reachable && specialization.getMethod() != null) { - specialization.addError("%s is not reachable.", specialization.isGeneric() ? "Generic" : "Specialization"); - } - specialization.setReachable(reachable); - if (!specialization.hasRewrite(context)) { - reachable = false; - } - prev = specialization; - } - } - - private static List initializeSpecializationIds(List specializations) { - int lastSize = -1; - List> signatureChunks = new ArrayList<>(); - for (SpecializationData other : specializations) { - if (!other.isSpecialized()) { - continue; - } - List paramIds = new LinkedList<>(); - paramIds.add(Utils.getTypeId(other.getReturnType().getType())); - for (ActualParameter param : other.getParameters()) { - if (param.getSpecification().getExecution() == null) { - continue; - } - paramIds.add(Utils.getTypeId(param.getType())); - } - assert lastSize == -1 || lastSize == paramIds.size(); - if (lastSize != -1 && lastSize != paramIds.size()) { - throw new AssertionError(); - } - signatureChunks.add(paramIds); - lastSize = paramIds.size(); - } - - // reduce id vertically - for (int i = 0; i < lastSize; i++) { - String prev = null; - boolean allSame = true; - for (List signature : signatureChunks) { - String arg = signature.get(i); - if (prev == null) { - prev = arg; - continue; - } else if (!prev.equals(arg)) { - allSame = false; - break; - } - prev = arg; - } - - if (allSame) { - for (List signature : signatureChunks) { - signature.remove(i); - } - lastSize--; - } - } - - // reduce id horizontally - for (List signature : signatureChunks) { - if (signature.isEmpty()) { - continue; - } - String prev = null; - boolean allSame = true; - for (String arg : signature) { - if (prev == null) { - prev = arg; - continue; - } else if (!prev.equals(arg)) { - allSame = false; - break; - } - prev = arg; - } - - if (allSame) { - signature.clear(); - signature.add(prev); - } - } - - // create signatures - List signatures = new ArrayList<>(); - for (List signatureChunk : signatureChunks) { - StringBuilder b = new StringBuilder(); - if (signatureChunk.isEmpty()) { - b.append("Default"); - } else { - for (String s : signatureChunk) { - b.append(s); - } - } - signatures.add(b.toString()); - } - - Map counts = new HashMap<>(); - for (String s1 : signatures) { - Integer count = counts.get(s1); - if (count == null) { - count = 0; - } - count++; - counts.put(s1, count); - } - - for (String s : counts.keySet()) { - int count = counts.get(s); - if (count > 1) { - int number = 0; - for (ListIterator iterator = signatures.listIterator(); iterator.hasNext();) { - String s2 = iterator.next(); - if (s.equals(s2)) { - iterator.set(s2 + number); - number++; - } - } - } - } - - return signatures; - } - - private void initializeGuards(List elements, SpecializationData specialization) { - if (specialization.getGuardDefinitions().isEmpty()) { - specialization.setGuards(Collections. emptyList()); - return; - } - - List foundGuards = new ArrayList<>(); - List methods = ElementFilter.methodsIn(elements); - for (String guardDefinition : specialization.getGuardDefinitions()) { - GuardParser parser = new GuardParser(context, specialization, guardDefinition); - List guards = parser.parse(methods); - if (!guards.isEmpty()) { - foundGuards.add(guards.get(0)); - } else { - // error no guard found - MethodSpec spec = parser.createSpecification(specialization.getMethod(), null); - spec.applyTypeDefinitions("types"); - specialization.addError("Guard with method name '%s' not found. Expected signature: %n%s", guardDefinition, spec.toSignatureString("guard")); - } - } - - specialization.setGuards(foundGuards); - - } - - private void initializeGeneric(final NodeData node) { - if (!node.needsRewrites(context)) { - return; - } - - List generics = new ArrayList<>(); - for (SpecializationData spec : node.getSpecializations()) { - if (spec.isGeneric()) { - generics.add(spec); - } - } - - if (generics.size() == 1 && node.getSpecializations().size() == 1) { - // TODO this limitation should be lifted - for (SpecializationData generic : generics) { - generic.addError("@%s defined but no @%s.", Generic.class.getSimpleName(), Specialization.class.getSimpleName()); - } - } - - if (generics.isEmpty()) { - node.getSpecializations().add(createGenericSpecialization(node)); - } else { - if (generics.size() > 1) { - for (SpecializationData generic : generics) { - generic.addError("Only @%s is allowed per operation.", Generic.class.getSimpleName()); - } - } - } - } - - private SpecializationData createGenericSpecialization(final NodeData node) { - GenericParser parser = new GenericParser(context, node); - MethodSpec specification = parser.createDefaultMethodSpec(node.getSpecializations().iterator().next().getMethod(), null, true, null); - - List parameterTypes = new ArrayList<>(); - int signatureIndex = 1; - for (ParameterSpec spec : specification.getRequired()) { - parameterTypes.add(createGenericType(spec, node.getSpecializations(), signatureIndex)); - if (spec.isSignature()) { - signatureIndex++; - } - } - - TypeMirror returnType = createGenericType(specification.getReturnType(), node.getSpecializations(), 0); - SpecializationData generic = parser.create("Generic", null, null, returnType, parameterTypes); - if (generic == null) { - throw new RuntimeException("Unable to create generic signature for node " + node.getNodeId() + " with " + parameterTypes + ". Specification " + specification + "."); - } - - return generic; - } - - private TypeMirror createGenericType(ParameterSpec spec, List specializations, int signatureIndex) { - NodeExecutionData execution = spec.getExecution(); - if (execution == null) { - if (spec.getAllowedTypes().size() == 1) { - return spec.getAllowedTypes().get(0); - } else { - return Utils.getCommonSuperType(context, spec.getAllowedTypes().toArray(new TypeMirror[0])); - } - } else { - Set types = new HashSet<>(); - for (SpecializationData specialization : specializations) { - types.add(specialization.getTypeSignature().get(signatureIndex)); - } - - NodeChildData child = execution.getChild(); - TypeData genericType = null; - if (types.size() == 1) { - ExecutableTypeData executable = child.findExecutableType(context, types.iterator().next()); - if (executable != null && (signatureIndex == 0 || !executable.hasUnexpectedValue(context))) { - genericType = types.iterator().next(); - } - } - if (genericType == null) { - genericType = child.findAnyGenericExecutableType(context).getType(); - } - return genericType.getPrimitiveType(); - } - } - - private static void initializeUninitialized(final NodeData node) { - SpecializationData generic = node.getGenericSpecialization(); - if (generic == null) { - return; - } - for (ActualParameter parameter : generic.getReturnTypeAndParameters()) { - if (Utils.isObject(parameter.getType())) { - continue; - } - Set types = new HashSet<>(); - for (SpecializationData specialization : node.getSpecializations()) { - ActualParameter actualParameter = specialization.findParameter(parameter.getLocalName()); - if (actualParameter != null) { - types.add(Utils.getQualifiedName(actualParameter.getType())); - } - } - if (types.size() > 1) { - generic.replaceParameter(parameter.getLocalName(), new ActualParameter(parameter, node.getTypeSystem().getGenericTypeData())); - } - } - TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", node, generic.getSpecification(), null, null, generic.getReturnType(), generic.getParameters()); - // should not use messages from generic specialization - uninializedMethod.getMessages().clear(); - node.getSpecializations().add(new SpecializationData(node, uninializedMethod, SpecializationKind.UNINITIALIZED)); - } - - private void initializePolymorphism(NodeData node) { - initializePolymorphicDepth(node); - - if (!node.needsRewrites(context) || !node.isPolymorphic()) { - return; - } - - SpecializationData generic = node.getGenericSpecialization(); - - List polymorphicSignature = new ArrayList<>(); - List updatePolymorphic = Arrays.asList(); - for (ActualParameter genericParameter : updatePolymorphic) { - if (!genericParameter.getSpecification().isSignature()) { - continue; - } - - Set usedTypes = new HashSet<>(); - for (SpecializationData specialization : node.getSpecializations()) { - if (!specialization.isSpecialized()) { - continue; - } - ActualParameter parameter = specialization.findParameter(genericParameter.getLocalName()); - if (parameter == null) { - throw new AssertionError("Parameter existed in generic specialization but not in specialized. param = " + genericParameter.getLocalName()); - } - usedTypes.add(parameter.getTypeSystemType()); - } - - TypeData polymorphicType; - if (usedTypes.size() == 1) { - polymorphicType = usedTypes.iterator().next(); - } else { - polymorphicType = node.getTypeSystem().getGenericTypeData(); - } - polymorphicSignature.add(polymorphicType); - } - - SpecializationData polymorphic = new SpecializationData(node, generic, SpecializationKind.POLYMORPHIC); - polymorphic.updateSignature(new TypeSignature(polymorphicSignature)); - node.getSpecializations().add(polymorphic); - } - - private static void initializePolymorphicDepth(final NodeData node) { - int polymorphicCombinations = 0; - for (SpecializationData specialization : node.getSpecializations()) { - if (specialization.isGeneric()) { - continue; - } - - int combinations = 1; - for (ActualParameter parameter : specialization.getSignatureParameters()) { - combinations *= node.getTypeSystem().lookupSourceTypes(parameter.getTypeSystemType()).size(); - } - polymorphicCombinations += combinations; - } - - // initialize polymorphic depth - if (node.getPolymorphicDepth() < 0) { - node.setPolymorphicDepth(polymorphicCombinations - 1); - } - - } - - private void initializeShortCircuits(NodeData node) { - Map> groupedShortCircuits = groupShortCircuits(node.getShortCircuits()); - - boolean valid = true; - List shortCircuitExecutions = new ArrayList<>(); - for (NodeExecutionData execution : node.getChildExecutions()) { - if (!execution.isShortCircuit()) { - continue; - } - shortCircuitExecutions.add(execution); - String valueName = execution.getShortCircuitId(); - List availableCircuits = groupedShortCircuits.get(valueName); - - if (availableCircuits == null || availableCircuits.isEmpty()) { - node.addError("@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName); - valid = false; - continue; - } - - boolean sameMethodName = true; - String methodName = availableCircuits.get(0).getMethodName(); - for (ShortCircuitData circuit : availableCircuits) { - if (!circuit.getMethodName().equals(methodName)) { - sameMethodName = false; - } - } - - if (!sameMethodName) { - for (ShortCircuitData circuit : availableCircuits) { - circuit.addError("All short circuits for short cut value '%s' must have the same method name.", valueName); - } - valid = false; - continue; - } - - ShortCircuitData genericCircuit = null; - for (ShortCircuitData circuit : availableCircuits) { - if (isGenericShortCutMethod(circuit)) { - genericCircuit = circuit; - break; - } - } - - if (genericCircuit == null) { - node.addError("No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName); - valid = false; - continue; - } - - for (ShortCircuitData circuit : availableCircuits) { - if (circuit != genericCircuit) { - circuit.setGenericShortCircuitMethod(genericCircuit); - } - } - } - - if (!valid) { - return; - } - - List specializations = new ArrayList<>(); - specializations.addAll(node.getSpecializations()); - for (SpecializationData specialization : specializations) { - List assignedShortCuts = new ArrayList<>(shortCircuitExecutions.size()); - - for (NodeExecutionData shortCircuit : shortCircuitExecutions) { - List availableShortCuts = groupedShortCircuits.get(shortCircuit.getShortCircuitId()); - - ShortCircuitData genericShortCircuit = null; - ShortCircuitData compatibleShortCircuit = null; - for (ShortCircuitData circuit : availableShortCuts) { - if (circuit.isGeneric()) { - genericShortCircuit = circuit; - } else if (circuit.isCompatibleTo(specialization)) { - compatibleShortCircuit = circuit; - } - } - - if (compatibleShortCircuit == null) { - compatibleShortCircuit = genericShortCircuit; - } - assignedShortCuts.add(compatibleShortCircuit); - } - specialization.setShortCircuits(assignedShortCuts); - } - } - - private boolean isGenericShortCutMethod(ShortCircuitData method) { - for (ActualParameter parameter : method.getParameters()) { - NodeExecutionData execution = parameter.getSpecification().getExecution(); - if (execution == null) { - continue; - } - ExecutableTypeData found = null; - List executableElements = execution.getChild().findGenericExecutableTypes(context); - for (ExecutableTypeData executable : executableElements) { - if (executable.getType().equalsType(parameter.getTypeSystemType())) { - found = executable; - break; - } - } - if (found == null) { - return false; - } - } - return true; - } - - private static Map> groupShortCircuits(List shortCircuits) { - Map> group = new HashMap<>(); - for (ShortCircuitData shortCircuit : shortCircuits) { - List circuits = group.get(shortCircuit.getValueName()); - if (circuits == null) { - circuits = new ArrayList<>(); - group.put(shortCircuit.getValueName(), circuits); - } - circuits.add(shortCircuit); - } - return group; - } - - private static boolean verifySpecializationSameLength(NodeData nodeData) { - int lastArgs = -1; - for (SpecializationData specializationData : nodeData.getSpecializations()) { - int signatureArgs = specializationData.getSignatureSize(); - if (lastArgs == signatureArgs) { - continue; - } - if (lastArgs != -1) { - for (SpecializationData specialization : nodeData.getSpecializations()) { - specialization.addError("All specializations must have the same number of arguments."); - } - return false; - } else { - lastArgs = signatureArgs; - } - } - return true; - } - - private static void verifyVisibilities(NodeData node) { - if (node.getTemplateType().getModifiers().contains(Modifier.PRIVATE) && node.getSpecializations().size() > 0) { - node.addError("Classes containing a @%s annotation must not be private.", Specialization.class.getSimpleName()); - } - } - - private static void verifySpecializationOrder(NodeData node) { - List specializations = node.getSpecializations(); - for (int i = 0; i < specializations.size(); i++) { - SpecializationData m1 = specializations.get(i); - for (int j = i + 1; j < specializations.size(); j++) { - SpecializationData m2 = specializations.get(j); - int inferredOrder = m1.compareBySignature(m2); - - if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) { - int specOrder = m1.getOrder() - m2.getOrder(); - if (specOrder == 0) { - m1.addError("Order value %d used multiple times", m1.getOrder()); - m2.addError("Order value %d used multiple times", m1.getOrder()); - return; - } else if ((specOrder < 0 && inferredOrder > 0) || (specOrder > 0 && inferredOrder < 0)) { - m1.addError("Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder()); - m2.addError("Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder()); - return; - } - } else if (inferredOrder == 0) { - SpecializationData m = (m1.getOrder() == Specialization.DEFAULT_ORDER ? m1 : m2); - m.addError("Cannot calculate a consistent order for this specialization. Define the order attribute to resolve this."); - return; - } - } - } - } - - private static void verifyMissingAbstractMethods(NodeData nodeData, List originalElements) { - if (!nodeData.needsFactory()) { - // missing abstract methods only needs to be implemented - // if we need go generate factory for it. - return; - } - - List elements = new ArrayList<>(originalElements); - Set unusedElements = new HashSet<>(elements); - for (TemplateMethod method : nodeData.getAllTemplateMethods()) { - unusedElements.remove(method.getMethod()); - } - - for (NodeFieldData field : nodeData.getFields()) { - if (field.getGetter() != null) { - unusedElements.remove(field.getGetter()); - } - } - - for (NodeChildData child : nodeData.getChildren()) { - if (child.getAccessElement() != null) { - unusedElements.remove(child.getAccessElement()); - } - } - - for (ExecutableElement unusedMethod : ElementFilter.methodsIn(unusedElements)) { - if (unusedMethod.getModifiers().contains(Modifier.ABSTRACT)) { - nodeData.addError("The type %s must implement the inherited abstract method %s.", Utils.getSimpleName(nodeData.getTemplateType()), Utils.getReadableSignature(unusedMethod)); - } - } - } - - private static void verifyNamingConvention(List methods, String prefix) { - for (int i = 0; i < methods.size(); i++) { - TemplateMethod m1 = methods.get(i); - if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) { - m1.addError("Naming convention: method name must start with '%s'.", prefix); - } - } - } - - private static void verifySpecializationThrows(NodeData node) { - Map specializationMap = new HashMap<>(); - for (SpecializationData spec : node.getSpecializations()) { - specializationMap.put(spec.getMethodName(), spec); - } - for (SpecializationData sourceSpecialization : node.getSpecializations()) { - if (sourceSpecialization.getExceptions() != null) { - for (SpecializationThrowsData throwsData : sourceSpecialization.getExceptions()) { - for (SpecializationThrowsData otherThrowsData : sourceSpecialization.getExceptions()) { - if (otherThrowsData != throwsData && Utils.typeEquals(otherThrowsData.getJavaClass(), throwsData.getJavaClass())) { - throwsData.addError("Duplicate exception type."); - } - } - } - } - } - } - - private void verifyConstructors(NodeData nodeData) { - if (!nodeData.needsRewrites(context)) { - // no specialization constructor is needed if the node never rewrites. - return; - } - - TypeElement type = Utils.fromTypeMirror(nodeData.getNodeType()); - List constructors = ElementFilter.constructorsIn(type.getEnclosedElements()); - - boolean parametersFound = false; - for (ExecutableElement constructor : constructors) { - if (!constructor.getParameters().isEmpty() && !isSourceSectionConstructor(context, constructor)) { - parametersFound = true; - } - } - if (!parametersFound) { - return; - } - for (ExecutableElement e : constructors) { - if (e.getParameters().size() == 1) { - TypeMirror firstArg = e.getParameters().get(0).asType(); - if (Utils.typeEquals(firstArg, nodeData.getNodeType())) { - if (e.getModifiers().contains(Modifier.PRIVATE)) { - nodeData.addError("The specialization constructor must not be private."); - } else if (constructors.size() <= 1) { - nodeData.addError("The specialization constructor must not be the only constructor. The definition of an alternative constructor is required."); - } - return; - } - } - } - - // not found - nodeData.addError("Specialization constructor '%s(%s previousNode) { this(...); }' is required.", Utils.getSimpleName(type), Utils.getSimpleName(type)); - } - - static boolean isSourceSectionConstructor(ProcessorContext context, ExecutableElement constructor) { - return constructor.getParameters().size() == 1 && Utils.typeEquals(constructor.getParameters().get(0).asType(), context.getTruffleTypes().getSourceSection()); - } - - private AnnotationMirror findFirstAnnotation(List elements, Class annotation) { - for (Element element : elements) { - AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, element, annotation); - if (mirror != null) { - return mirror; - } - } - return null; - } - - private TypeMirror inheritType(AnnotationMirror annotation, String valueName, TypeMirror parentType) { - TypeMirror inhertNodeType = context.getTruffleTypes().getNode(); - TypeMirror value = Utils.getAnnotationValue(TypeMirror.class, annotation, valueName); - if (Utils.typeEquals(inhertNodeType, value)) { - return parentType; - } else { - return value; - } - } - - private ExecutableElement findGetter(List elements, String variableName, TypeMirror type) { - if (type == null) { - return null; - } - String methodName; - if (Utils.typeEquals(type, context.getType(boolean.class))) { - methodName = "is" + Utils.firstLetterUpperCase(variableName); - } else { - methodName = "get" + Utils.firstLetterUpperCase(variableName); - } - - for (ExecutableElement method : ElementFilter.methodsIn(elements)) { - if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && Utils.isAssignable(context, type, method.getReturnType())) { - return method; - } - } - return null; - } - - private static List collectSuperClasses(List collection, TypeElement element) { - if (element != null) { - collection.add(element); - if (element.getSuperclass() != null) { - collectSuperClasses(collection, Utils.fromTypeMirror(element.getSuperclass())); - } - } - return collection; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitData.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.node; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.template.*; - -public class ShortCircuitData extends TemplateMethod { - - private ShortCircuitData genericShortCircuitMethod; - private final String valueName; - - public ShortCircuitData(TemplateMethod template, String valueName) { - super(template); - this.valueName = valueName; - } - - public String getValueName() { - return valueName; - } - - public void setGenericShortCircuitMethod(ShortCircuitData genericShortCircuitMethod) { - this.genericShortCircuitMethod = genericShortCircuitMethod; - } - - public boolean isGeneric() { - return genericShortCircuitMethod == null; - } - - public ShortCircuitData getGeneric() { - if (isGeneric()) { - return this; - } else { - return genericShortCircuitMethod; - } - } - - public boolean isCompatibleTo(SpecializationData specialization) { - if (isGeneric() && specialization.isGeneric()) { - return true; - } - - for (ActualParameter param : getParameters()) { - ActualParameter specializationParam = specialization.findParameter(param.getLocalName()); - if (!Utils.typeEquals(param.getType(), specializationParam.getType())) { - return false; - } - } - return true; - } -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.node; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; - -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.template.*; - -public class ShortCircuitParser extends NodeMethodParser { - - private final Set shortCircuitValues; - - public ShortCircuitParser(ProcessorContext context, NodeData node) { - super(context, node); - - shortCircuitValues = new HashSet<>(); - for (NodeExecutionData execution : node.getChildExecutions()) { - if (execution.isShortCircuit()) { - shortCircuitValues.add(execution.getShortCircuitId()); - } - } - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - String shortCircuitValue = Utils.getAnnotationValue(String.class, mirror, "value"); - - return createDefaultMethodSpec(method, mirror, true, shortCircuitValue); - } - - @Override - protected ParameterSpec createReturnParameterSpec() { - return new ParameterSpec("has", getContext().getType(boolean.class)); - } - - @Override - public ShortCircuitData create(TemplateMethod method, boolean invalid) { - String shortCircuitValue = Utils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "value"); - - if (!shortCircuitValues.contains(shortCircuitValue)) { - method.addError("Invalid short circuit value %s.", shortCircuitValue); - } - - return new ShortCircuitData(method, shortCircuitValue); - } - - @Override - public Class getAnnotationType() { - return ShortCircuit.class; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,268 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.node; - -import java.util.*; - -import javax.lang.model.type.*; - -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.template.*; -import com.oracle.truffle.dsl.processor.typesystem.*; - -public class SpecializationData extends TemplateMethod { - - public enum SpecializationKind { - UNINITIALIZED, - SPECIALIZED, - POLYMORPHIC, - GENERIC - } - - private final NodeData node; - private final int order; - private final SpecializationKind kind; - private final List exceptions; - private List guardDefinitions = Collections.emptyList(); - private List guards = Collections.emptyList(); - private List shortCircuits; - private List assumptions = Collections.emptyList(); - private boolean reachable; - - public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind, int order, List exceptions) { - super(template); - this.node = node; - this.order = order; - this.kind = kind; - this.exceptions = exceptions; - - for (SpecializationThrowsData exception : exceptions) { - exception.setSpecialization(this); - } - } - - public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind) { - this(node, template, kind, Specialization.DEFAULT_ORDER, new ArrayList()); - } - - public void setReachable(boolean reachable) { - this.reachable = reachable; - } - - public boolean isReachable() { - return reachable; - } - - public boolean isPolymorphic() { - return kind == SpecializationKind.POLYMORPHIC; - } - - @Override - protected List findChildContainers() { - List sinks = new ArrayList<>(); - if (exceptions != null) { - sinks.addAll(exceptions); - } - if (guards != null) { - sinks.addAll(guards); - } - return sinks; - } - - public boolean isGenericSpecialization(ProcessorContext context) { - if (isGeneric()) { - return true; - } - if (hasRewrite(context)) { - return false; - } - - for (ActualParameter parameter : getSignatureParameters()) { - ActualParameter genericParameter = getNode().getGenericSpecialization().findParameter(parameter.getLocalName()); - if (!parameter.getTypeSystemType().equals(genericParameter.getTypeSystemType())) { - return false; - } - } - return true; - } - - public boolean hasRewrite(ProcessorContext context) { - if (!getExceptions().isEmpty()) { - return true; - } - if (!getGuards().isEmpty()) { - return true; - } - if (!getAssumptions().isEmpty()) { - return true; - } - for (ActualParameter parameter : getSignatureParameters()) { - ExecutableTypeData type = parameter.getSpecification().getExecution().getChild().findExecutableType(context, parameter.getTypeSystemType()); - if (type.hasUnexpectedValue(context)) { - return true; - } - if (type.getReturnType().getTypeSystemType().needsCastTo(context, parameter.getTypeSystemType())) { - return true; - } - - } - return false; - } - - @Override - public int compareBySignature(TemplateMethod other) { - if (this == other) { - return 0; - } else if (!(other instanceof SpecializationData)) { - return super.compareBySignature(other); - } - - SpecializationData m2 = (SpecializationData) other; - - int kindOrder = kind.compareTo(m2.kind); - if (kindOrder != 0) { - return kindOrder; - } - if (getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) { - return getOrder() - m2.getOrder(); - } - - if (getTemplate() != m2.getTemplate()) { - throw new UnsupportedOperationException("Cannot compare two specializations with different templates."); - } - - return super.compareBySignature(m2); - } - - public NodeData getNode() { - return node; - } - - public void setGuards(List guards) { - this.guards = guards; - } - - public void setGuardDefinitions(List guardDefinitions) { - this.guardDefinitions = guardDefinitions; - } - - public int getOrder() { - return order; - } - - public boolean isSpecialized() { - return kind == SpecializationKind.SPECIALIZED; - } - - public boolean isGeneric() { - return kind == SpecializationKind.GENERIC; - } - - public boolean isUninitialized() { - return kind == SpecializationKind.UNINITIALIZED; - } - - public List getExceptions() { - return exceptions; - } - - public List getGuardDefinitions() { - return guardDefinitions; - } - - public List getGuards() { - return guards; - } - - public void setShortCircuits(List shortCircuits) { - this.shortCircuits = shortCircuits; - } - - public List getShortCircuits() { - return shortCircuits; - } - - public List getAssumptions() { - return assumptions; - } - - void setAssumptions(List assumptions) { - this.assumptions = assumptions; - } - - public SpecializationData findPreviousSpecialization() { - List specializations = node.getSpecializations(); - for (int i = 0; i < specializations.size() - 1; i++) { - if (specializations.get(i) == this && i > 0) { - return specializations.get(i - 1); - } - } - return null; - } - - public SpecializationData findNextSpecialization() { - List specializations = node.getSpecializations(); - for (int i = 0; i < specializations.size() - 1; i++) { - if (specializations.get(i) == this) { - return specializations.get(i + 1); - } - } - return null; - } - - public boolean hasDynamicGuards() { - return !getGuards().isEmpty(); - } - - @Override - public String toString() { - return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getTypeSignature()); - } - - public void forceFrame(TypeMirror frameType) { - if (getParameters().isEmpty() || !Utils.typeEquals(getParameters().get(0).getType(), frameType)) { - ParameterSpec frameSpec = getSpecification().findParameterSpec("frame"); - if (frameSpec != null) { - getParameters().add(0, new ActualParameter(frameSpec, frameType, -1, -1)); - } - } - } - - public boolean equalsGuards(SpecializationData specialization) { - if (assumptions.equals(specialization.getAssumptions()) && guards.equals(specialization.getGuards()) && getTypeSignature().equalsParameters(specialization.getTypeSignature())) { - return true; - } - return false; - } - - public boolean hasFrame(ProcessorContext context) { - for (ActualParameter param : getParameters()) { - if (Utils.typeEquals(param.getType(), context.getTruffleTypes().getFrame())) { - return true; - } - } - return false; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,432 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.node; - -import java.util.*; - -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.template.*; -import com.oracle.truffle.dsl.processor.template.TemplateMethod.TypeSignature; -import com.oracle.truffle.dsl.processor.typesystem.*; - -/** - * Class creates groups of specializations to optimize the layout of generated executeAndSpecialize - * and generic execute methods. - */ -public final class SpecializationGroup { - - private final List assumptions; - private final List typeGuards; - private final List guards; - - private final NodeData node; - private final SpecializationData specialization; - private final List children = new ArrayList<>(); - - private SpecializationGroup parent; - - private SpecializationGroup(SpecializationData data) { - this.node = data.getNode(); - this.assumptions = new ArrayList<>(); - this.typeGuards = new ArrayList<>(); - this.guards = new ArrayList<>(); - this.specialization = data; - - this.assumptions.addAll(data.getAssumptions()); - TypeSignature sig = data.getTypeSignature(); - for (int i = 1; i < sig.size(); i++) { - typeGuards.add(new TypeGuard(sig.get(i), i - 1)); - } - this.guards.addAll(data.getGuards()); - } - - public SpecializationGroup(List children, List assumptionMatches, List typeGuardsMatches, List guardMatches) { - assert !children.isEmpty() : "children must not be empty"; - this.assumptions = assumptionMatches; - this.typeGuards = typeGuardsMatches; - this.guards = guardMatches; - this.node = children.get(0).node; - this.specialization = null; - updateChildren(children); - } - - public List getAllGuards() { - List collectedGuards = new ArrayList<>(); - collectedGuards.addAll(typeGuards); - if (parent != null) { - collectedGuards.addAll(parent.getAllGuards()); - } - return collectedGuards; - } - - public TypeGuard findTypeGuard(int signatureIndex) { - for (TypeGuard guard : typeGuards) { - if (guard.getSignatureIndex() == signatureIndex) { - return guard; - } - } - return null; - } - - public List findElseConnectableGuards(boolean minimumStateCheck) { - if (minimumStateCheck) { - /* - * TODO investigate further if we really cannot else connect guards if minimum state is - * required - */ - return Collections.emptyList(); - } - if (!getTypeGuards().isEmpty() || !getAssumptions().isEmpty()) { - return Collections.emptyList(); - } - - if (getGuards().isEmpty()) { - return Collections.emptyList(); - } - - List elseConnectableGuards = new ArrayList<>(); - int guardIndex = 0; - while (guardIndex < getGuards().size() && findNegatedGuardInPrevious(getGuards().get(guardIndex), minimumStateCheck) != null) { - elseConnectableGuards.add(getGuards().get(guardIndex)); - guardIndex++; - } - - return elseConnectableGuards; - } - - private GuardData findNegatedGuardInPrevious(GuardData guard, boolean minimumStateCheck) { - SpecializationGroup previous = this.getPreviousGroup(); - if (previous == null) { - return null; - } - List elseConnectedGuards = previous.findElseConnectableGuards(minimumStateCheck); - - if (previous == null || previous.getGuards().size() != elseConnectedGuards.size() + 1) { - return null; - } - - /* Guard is else branch can be connected in previous specialization. */ - if (elseConnectedGuards.contains(guard)) { - return guard; - } - - GuardData previousGuard = previous.getGuards().get(elseConnectedGuards.size()); - if (guard.getMethod().equals(previousGuard.getMethod()) && guard.isNegated() != previousGuard.isNegated()) { - return guard; - } - return null; - } - - private void updateChildren(List childs) { - if (!children.isEmpty()) { - children.clear(); - } - this.children.addAll(childs); - for (SpecializationGroup child : childs) { - child.parent = this; - } - } - - public SpecializationGroup getParent() { - return parent; - } - - public List getAssumptions() { - return assumptions; - } - - public List getTypeGuards() { - return typeGuards; - } - - public List getGuards() { - return guards; - } - - public List getChildren() { - return children; - } - - public SpecializationData getSpecialization() { - return specialization; - } - - private static SpecializationGroup combine(List groups) { - if (groups.isEmpty()) { - throw new IllegalArgumentException("empty combinations"); - } - if (groups.size() == 1) { - return null; - } - - List assumptionMatches = new ArrayList<>(); - List typeGuardsMatches = new ArrayList<>(); - List guardMatches = new ArrayList<>(); - - SpecializationGroup first = groups.get(0); - List others = groups.subList(1, groups.size()); - - outer: for (String assumption : first.assumptions) { - for (SpecializationGroup other : others) { - if (!other.assumptions.contains(assumption)) { - // assumptions can be combined unordered - continue outer; - } - } - assumptionMatches.add(assumption); - } - - outer: for (TypeGuard typeGuard : first.typeGuards) { - for (SpecializationGroup other : others) { - if (!other.typeGuards.contains(typeGuard)) { - // type guards can be combined unordered - continue outer; - } - } - typeGuardsMatches.add(typeGuard); - } - - outer: for (GuardData guard : first.guards) { - for (SpecializationGroup other : others) { - if (!other.guards.contains(guard)) { - // we must break here. One guard may depend on the other. - break outer; - } - } - guardMatches.add(guard); - } - - // check for guards for required type casts - for (Iterator iterator = guardMatches.iterator(); iterator.hasNext();) { - GuardData guardMatch = iterator.next(); - - int signatureIndex = 0; - for (ActualParameter parameter : guardMatch.getParameters()) { - signatureIndex++; - if (!parameter.getSpecification().isSignature()) { - continue; - } - - TypeMirror guardType = parameter.getType(); - - // object guards can be safely moved up - if (Utils.isObject(guardType)) { - continue; - } - - // generic guards can be safely moved up - SpecializationData generic = first.node.getGenericSpecialization(); - if (generic != null) { - ActualParameter genericParameter = generic.findParameter(parameter.getLocalName()); - if (genericParameter != null && Utils.typeEquals(genericParameter.getType(), guardType)) { - continue; - } - } - - // signature index required for moving up guards - if (containsIndex(typeGuardsMatches, signatureIndex) || (first.getParent() != null && first.getParent().containsTypeGuardIndex(signatureIndex))) { - continue; - } - - iterator.remove(); - break; - } - } - - if (assumptionMatches.isEmpty() && typeGuardsMatches.isEmpty() && guardMatches.isEmpty()) { - return null; - } - - for (SpecializationGroup group : groups) { - group.assumptions.removeAll(assumptionMatches); - group.typeGuards.removeAll(typeGuardsMatches); - group.guards.removeAll(guardMatches); - } - - List newChildren = new ArrayList<>(groups); - return new SpecializationGroup(newChildren, assumptionMatches, typeGuardsMatches, guardMatches); - } - - private boolean containsTypeGuardIndex(int index) { - if (containsIndex(typeGuards, index)) { - return true; - } - if (parent != null) { - return parent.containsTypeGuardIndex(index); - } - return false; - } - - private static boolean containsIndex(List typeGuards, int signatureIndex) { - for (TypeGuard guard : typeGuards) { - if (guard.signatureIndex == signatureIndex) { - return true; - } - } - return false; - } - - public static SpecializationGroup create(SpecializationData specialization) { - return new SpecializationGroup(specialization); - } - - public static SpecializationGroup create(List specializations) { - List groups = new ArrayList<>(); - for (SpecializationData specialization : specializations) { - groups.add(new SpecializationGroup(specialization)); - } - return new SpecializationGroup(createCombinationalGroups(groups), Collections. emptyList(), Collections. emptyList(), Collections. emptyList()); - } - - @Override - public String toString() { - return "SpecializationGroup [assumptions=" + assumptions + ", typeGuards=" + typeGuards + ", guards=" + guards + "]"; - } - - private static List createCombinationalGroups(List groups) { - if (groups.size() <= 1) { - return groups; - } - List newGroups = new ArrayList<>(); - - int i = 0; - for (i = 0; i < groups.size();) { - SpecializationGroup combined = null; - for (int j = groups.size(); j > i + 1; j--) { - combined = combine(groups.subList(i, j)); - if (combined != null) { - break; - } - } - SpecializationGroup newGroup; - if (combined == null) { - newGroup = groups.get(i); - i++; - } else { - newGroup = combined; - List originalGroups = new ArrayList<>(combined.children); - combined.updateChildren(createCombinationalGroups(originalGroups)); - i += originalGroups.size(); - } - - newGroups.add(newGroup); - - } - - return newGroups; - } - - public SpecializationGroup getPreviousGroup() { - if (parent == null || parent.children.isEmpty()) { - return null; - } - int index = parent.children.indexOf(this); - if (index <= 0) { - return null; - } - return parent.children.get(index - 1); - } - - public int getUncheckedSpecializationIndex() { - int groupMaxIndex = getMaxSpecializationIndex(); - - int genericIndex = node.getSpecializations().indexOf(node.getGenericSpecialization()); - if (groupMaxIndex >= genericIndex) { - // no minimum state check for an generic index - groupMaxIndex = -1; - } - - if (groupMaxIndex > -1) { - // no minimum state check if already checked by parent group - int parentMaxIndex = -1; - if (getParent() != null) { - parentMaxIndex = getParent().getMaxSpecializationIndex(); - } - if (groupMaxIndex == parentMaxIndex) { - groupMaxIndex = -1; - } - } - return groupMaxIndex; - } - - public int getMaxSpecializationIndex() { - if (specialization != null) { - return specialization.getNode().getSpecializations().indexOf(specialization); - } else { - int max = Integer.MIN_VALUE; - for (SpecializationGroup childGroup : getChildren()) { - max = Math.max(max, childGroup.getMaxSpecializationIndex()); - } - return max; - } - } - - public static final class TypeGuard { - - private final int signatureIndex; - private final TypeData type; - - public TypeGuard(TypeData type, int signatureIndex) { - this.type = type; - this.signatureIndex = signatureIndex; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + signatureIndex; - result = prime * result + type.hashCode(); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } else if (obj == null) { - return false; - } else if (getClass() != obj.getClass()) { - return false; - } - - TypeGuard other = (TypeGuard) obj; - if (signatureIndex != other.signatureIndex) { - return false; - } else if (!type.equals(other.type)) { - return false; - } - return true; - } - - public int getSignatureIndex() { - return signatureIndex; - } - - public TypeData getType() { - return type; - } - } -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGuardData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGuardData.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.node; - -import javax.lang.model.element.*; - -import com.oracle.truffle.dsl.processor.template.*; -import com.oracle.truffle.dsl.processor.typesystem.*; - -public class SpecializationGuardData extends MessageContainer { - - private final SpecializationData specialization; - private final AnnotationValue value; - private final String guardMethod; - private final boolean onSpecialization; - private final boolean onExecution; - - private GuardData guardDeclaration; - - public SpecializationGuardData(SpecializationData specialization, AnnotationValue value, String guardMethod, boolean onSpecialization, boolean onExecution) { - this.specialization = specialization; - this.guardMethod = guardMethod; - this.onSpecialization = onSpecialization; - this.onExecution = onExecution; - this.value = value; - } - - @Override - public Element getMessageElement() { - return specialization.getMessageElement(); - } - - @Override - public AnnotationMirror getMessageAnnotation() { - return specialization.getMessageAnnotation(); - } - - @Override - public AnnotationValue getMessageAnnotationValue() { - return value; - } - - public String getGuardMethod() { - return guardMethod; - } - - public boolean isOnExecution() { - return onExecution; - } - - public boolean isOnSpecialization() { - return onSpecialization; - } - - public void setGuardDeclaration(GuardData compatibleGuard) { - this.guardDeclaration = compatibleGuard; - } - - public GuardData getGuardDeclaration() { - return guardDeclaration; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.node; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.node.SpecializationData.SpecializationKind; -import com.oracle.truffle.dsl.processor.template.*; - -public class SpecializationMethodParser extends NodeMethodParser { - - public SpecializationMethodParser(ProcessorContext context, NodeData operation) { - super(context, operation); - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - return createDefaultMethodSpec(method, mirror, true, null); - } - - @Override - public SpecializationData create(TemplateMethod method, boolean invalid) { - return parseSpecialization(method); - } - - @Override - public Class getAnnotationType() { - return Specialization.class; - } - - private SpecializationData parseSpecialization(TemplateMethod method) { - int order = Utils.getAnnotationValue(Integer.class, method.getMarkerAnnotation(), "order"); - if (order < 0 && order != Specialization.DEFAULT_ORDER) { - method.addError("Invalid order attribute %d. The value must be >= 0 or the default value."); - } - - AnnotationValue rewriteValue = Utils.getAnnotationValue(method.getMarkerAnnotation(), "rewriteOn"); - List exceptionTypes = Utils.getAnnotationValueList(TypeMirror.class, method.getMarkerAnnotation(), "rewriteOn"); - List exceptionData = new ArrayList<>(); - for (TypeMirror exceptionType : exceptionTypes) { - SpecializationThrowsData throwsData = new SpecializationThrowsData(method.getMarkerAnnotation(), rewriteValue, exceptionType); - if (!Utils.canThrowType(method.getMethod().getThrownTypes(), exceptionType)) { - throwsData.addError("Method must specify a throws clause with the exception type '%s'.", Utils.getQualifiedName(exceptionType)); - } - exceptionData.add(throwsData); - } - - Collections.sort(exceptionData, new Comparator() { - - @Override - public int compare(SpecializationThrowsData o1, SpecializationThrowsData o2) { - return Utils.compareByTypeHierarchy(o1.getJavaClass(), o2.getJavaClass()); - } - }); - SpecializationData specialization = new SpecializationData(getNode(), method, SpecializationKind.SPECIALIZED, order, exceptionData); - List guardDefs = Utils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards"); - specialization.setGuardDefinitions(guardDefs); - - List assumptionDefs = Utils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "assumptions"); - specialization.setAssumptions(assumptionDefs); - - for (String assumption : assumptionDefs) { - if (!getNode().getAssumptions().contains(assumption)) { - specialization.addError("Undeclared assumption '%s' used. Use @NodeAssumptions to declare them.", assumption); - } - } - - return specialization; - } -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationThrowsData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationThrowsData.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.node; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.template.*; - -public class SpecializationThrowsData extends MessageContainer { - - private final AnnotationValue annotationValue; - private final AnnotationMirror annotationMirror; - private final TypeMirror javaClass; - private SpecializationData specialization; - - public SpecializationThrowsData(AnnotationMirror annotationMirror, AnnotationValue value, TypeMirror javaClass) { - this.annotationMirror = annotationMirror; - this.annotationValue = value; - this.javaClass = javaClass; - } - - void setSpecialization(SpecializationData specialization) { - this.specialization = specialization; - } - - @Override - public Element getMessageElement() { - return specialization.getMessageElement(); - } - - @Override - public AnnotationMirror getMessageAnnotation() { - return annotationMirror; - } - - @Override - public AnnotationValue getMessageAnnotationValue() { - return annotationValue; - } - - public TypeMirror getJavaClass() { - return javaClass; - } - - public SpecializationData getSpecialization() { - return specialization; - } - - public AnnotationMirror getAnnotationMirror() { - return annotationMirror; - } - - public SpecializationData getTransitionTo() { - return specialization.findNextSpecialization(); - } -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/AbstractParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/AbstractParser.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.parser; + +import java.lang.annotation.*; +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.tools.Diagnostic.Kind; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.model.*; +import com.oracle.truffle.dsl.processor.model.MessageContainer.Message; + +/** + * THIS IS NOT PUBLIC API. + */ +public abstract class AbstractParser { + + protected final ProcessorContext context; + protected final ProcessingEnvironment processingEnv; + + protected final Log log; + + public AbstractParser() { + this.context = ProcessorContext.getInstance(); + this.processingEnv = context.getEnvironment(); + this.log = context.getLog(); + } + + public final M parse(Element element) { + M model = null; + try { + AnnotationMirror mirror = null; + if (getAnnotationType() != null) { + mirror = ElementUtils.findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), getAnnotationType()); + } + + if (!context.getTruffleTypes().verify(context, element, mirror)) { + return null; + } + model = parse(element, mirror); + if (model == null) { + return null; + } + + redirectMessages(new HashSet(), model, model); + model.emitMessages(context, log); + return filterErrorElements(model); + } catch (CompileErrorException e) { + log.message(Kind.WARNING, element, null, null, "The truffle processor could not parse class due to error: %s", e.getMessage()); + return null; + } + } + + private void redirectMessages(Set visitedSinks, MessageContainer model, MessageContainer baseContainer) { + List messages = model.getMessages(); + for (int i = messages.size() - 1; i >= 0; i--) { + Message message = messages.get(i); + if (!ElementUtils.isEnclosedIn(baseContainer.getMessageElement(), message.getOriginalContainer().getMessageElement())) { + // redirect message + MessageContainer original = message.getOriginalContainer(); + String text = wrapText(original.getMessageElement(), original.getMessageAnnotation(), message.getText()); + Message redirectedMessage = new Message(null, null, baseContainer, text, message.getKind()); + model.getMessages().remove(i); + baseContainer.getMessages().add(redirectedMessage); + } + } + + for (MessageContainer childContainer : model) { + if (visitedSinks.contains(childContainer)) { + continue; + } + visitedSinks.add(childContainer); + + MessageContainer newBase = baseContainer; + if (childContainer.getBaseContainer() != null) { + newBase = childContainer.getBaseContainer(); + } + redirectMessages(visitedSinks, childContainer, newBase); + } + } + + private static String wrapText(Element element, AnnotationMirror mirror, String text) { + StringBuilder b = new StringBuilder(); + if (element != null) { + if (element.getKind() == ElementKind.METHOD) { + b.append("Method " + ElementUtils.createReferenceName((ExecutableElement) element)); + } else { + b.append("Element " + element.getSimpleName()); + } + } + if (mirror != null) { + b.append(" at annotation @" + ElementUtils.getSimpleName(mirror.getAnnotationType()).trim()); + } + + if (b.length() > 0) { + b.append(" is erroneous: ").append(text); + return b.toString(); + } else { + return text; + } + } + + protected M filterErrorElements(M model) { + return model.hasErrors() ? null : model; + } + + protected abstract M parse(Element element, AnnotationMirror mirror); + + public abstract Class getAnnotationType(); + + public boolean isDelegateToRootDeclaredType() { + return false; + } + + public List> getAllAnnotationTypes() { + List> list = new ArrayList<>(); + if (getAnnotationType() != null) { + list.add(getAnnotationType()); + } + list.addAll(getTypeDelegatedAnnotationTypes()); + return list; + } + + public List> getTypeDelegatedAnnotationTypes() { + return Collections.emptyList(); + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/CreateCastParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/CreateCastParser.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.parser; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.model.*; + +public class CreateCastParser extends NodeMethodParser { + + public CreateCastParser(ProcessorContext context, NodeData operation) { + super(context, operation); + } + + @Override + public Class getAnnotationType() { + return CreateCast.class; + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + List childNames = ElementUtils.getAnnotationValueList(String.class, mirror, "value"); + NodeChildData foundChild = null; + for (String childName : childNames) { + foundChild = getNode().findChild(childName); + if (foundChild != null) { + break; + } + } + TypeMirror baseType = getContext().getTruffleTypes().getNode(); + if (foundChild != null) { + baseType = foundChild.getOriginalType(); + } + + MethodSpec spec = new MethodSpec(new InheritsParameterSpec("child", baseType)); + addDefaultFieldMethodSpec(spec); + ParameterSpec childSpec = new ParameterSpec("castedChild", baseType); + childSpec.setSignature(true); + spec.addRequired(childSpec); + return spec; + } + + @Override + public CreateCastData create(TemplateMethod method, boolean invalid) { + AnnotationMirror mirror = method.getMarkerAnnotation(); + List childNames = ElementUtils.getAnnotationValueList(String.class, mirror, "value"); + CreateCastData cast = new CreateCastData(method, childNames); + AnnotationValue value = ElementUtils.getAnnotationValue(mirror, "value"); + TypeMirror type = null; + if (childNames == null || childNames.isEmpty()) { + cast.addError(value, "No value specified but required."); + return cast; + } + + for (String childName : childNames) { + NodeChildData child = getNode().findChild(childName); + if (child == null) { + // error + cast.addError(value, "Specified child '%s' not found.", childName); + continue; + } + if (type == null) { + type = child.getNodeType(); + } else if (!ElementUtils.typeEquals(type, child.getNodeType())) { + cast.addError(value, "All child nodes for a cast must have the same node type."); + continue; + } + } + return cast; + } + + private static class InheritsParameterSpec extends ParameterSpec { + + public InheritsParameterSpec(String name, TypeMirror... allowedTypes) { + super(name, Arrays.asList(allowedTypes), null); + } + + @Override + public boolean matches(TypeMirror actualType) { + boolean found = false; + for (TypeMirror specType : getAllowedTypes()) { + if (ElementUtils.isAssignable(actualType, specType)) { + found = true; + break; + } + } + return found; + } + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.parser; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.model.*; + +public class ExecutableTypeMethodParser extends NodeMethodParser { + + public ExecutableTypeMethodParser(ProcessorContext context, NodeData node) { + super(context, node); + setParseNullOnError(false); + getParser().setEmitErrors(false); + getParser().setUseVarArgs(true); + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + MethodSpec spec = createDefaultMethodSpec(method, mirror, false, null); + List requiredSpecs = new ArrayList<>(spec.getRequired()); + spec.getRequired().clear(); + + List allowedTypes = getNode().getTypeSystem().getPrimitiveTypeMirrors(); + Set allowedIdentifiers = getNode().getTypeSystem().getTypeIdentifiers(); + for (ParameterSpec originalSpec : requiredSpecs) { + spec.addRequired(new ParameterSpec(originalSpec, allowedTypes, allowedIdentifiers)); + } + spec.setIgnoreAdditionalSpecifications(true); + spec.setIgnoreAdditionalParameters(true); + spec.setVariableRequiredParameters(true); + // varargs + ParameterSpec otherParameters = new ParameterSpec("other", allowedTypes, allowedIdentifiers); + otherParameters.setSignature(true); + spec.addRequired(otherParameters); + return spec; + } + + @Override + protected List nodeTypeMirrors(NodeData nodeData) { + return getNode().getTypeSystem().getPrimitiveTypeMirrors(); + } + + @Override + protected Set nodeTypeIdentifiers(NodeData nodeData) { + return getNode().getTypeSystem().getTypeIdentifiers(); + } + + @Override + public final boolean isParsable(ExecutableElement method) { + if (method.getModifiers().contains(Modifier.STATIC)) { + return false; + } else if (method.getModifiers().contains(Modifier.NATIVE)) { + return false; + } + return method.getSimpleName().toString().startsWith("execute"); + } + + @Override + public ExecutableTypeData create(TemplateMethod method, boolean invalid) { + TypeData resolvedType = method.getReturnType().getTypeSystemType(); + return new ExecutableTypeData(method, method.getMethod(), getNode().getTypeSystem(), resolvedType); + } + + @Override + public Class getAnnotationType() { + return null; + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GenericParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GenericParser.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.parser; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.model.*; +import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind; + +public class GenericParser extends NodeMethodParser { + + public GenericParser(ProcessorContext context, NodeData node) { + super(context, node); + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + return createDefaultMethodSpec(method, mirror, true, null); + } + + @Override + protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) { + List execTypes = execution.getChild().findGenericExecutableTypes(getContext()); + List types = new ArrayList<>(); + Set typeIds = new HashSet<>(); + for (ExecutableTypeData type : execTypes) { + TypeMirror typeMirror = type.getType().getPrimitiveType(); + types.add(typeMirror); + typeIds.add(ElementUtils.getUniqueIdentifier(typeMirror)); + } + ParameterSpec spec = new ParameterSpec(execution.getName(), types, typeIds); + spec.setExecution(execution); + return spec; + } + + @Override + public SpecializationData create(TemplateMethod method, boolean invalid) { + return new SpecializationData(getNode(), method, SpecializationKind.GENERIC); + } + + @Override + public Class getAnnotationType() { + return Fallback.class; + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GuardParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GuardParser.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.parser; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.model.*; + +public class GuardParser extends NodeMethodParser { + + private final GuardExpression expression; + private final TemplateMethod guardedMethod; + + public GuardParser(ProcessorContext context, NodeData node, TemplateMethod compatibleSource, GuardExpression expression) { + super(context, node); + this.expression = expression; + this.guardedMethod = compatibleSource; + getParser().setEmitErrors(false); + setParseNullOnError(false); + } + + @Override + protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) { + return super.createValueParameterSpec(execution); + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + MethodSpec spec = createDefaultMethodSpec(method, mirror, true, null); + spec.setIgnoreAdditionalSpecifications(true); + spec.getRequired().clear(); + + if (expression.getResolvedChildren() != null) { + for (NodeExecutionData execution : expression.getResolvedChildren()) { + List foundInGuardedMethod = guardedMethod.findByExecutionData(execution); + for (Parameter guardedParameter : foundInGuardedMethod) { + spec.addRequired(createParameterSpec(guardedParameter)); + } + } + } else { + for (Parameter parameter : guardedMethod.getRequiredParameters()) { + spec.addRequired(createParameterSpec(parameter)); + } + } + + return spec; + } + + private ParameterSpec createParameterSpec(Parameter parameter) { + List typeMirrors = ElementUtils.getAssignableTypes(getContext(), parameter.getType()); + Set typeIds = new HashSet<>(); + for (TypeMirror typeMirror : typeMirrors) { + typeIds.add(ElementUtils.getUniqueIdentifier(typeMirror)); + } + if (parameter.getSpecification().isSignature()) { + typeIds.retainAll(getTypeSystem().getTypeIdentifiers()); + } + + return new ParameterSpec(parameter.getSpecification(), typeMirrors, typeIds); + } + + @Override + protected List nodeTypeMirrors(NodeData nodeData) { + Set typeMirrors = new LinkedHashSet<>(); + typeMirrors.addAll(nodeData.getTypeSystem().getPrimitiveTypeMirrors()); + typeMirrors.addAll(nodeData.getTypeSystem().getBoxedTypeMirrors()); + return new ArrayList<>(typeMirrors); + } + + @Override + protected Set nodeTypeIdentifiers(NodeData nodeData) { + return nodeData.getTypeSystem().getTypeIdentifiers(); + } + + @Override + protected ParameterSpec createReturnParameterSpec() { + return new ParameterSpec("returnType", getContext().getType(boolean.class)); + } + + @Override + public boolean isParsable(ExecutableElement method) { + return true; + } + + @Override + public GuardData create(TemplateMethod method, boolean invalid) { + Implies impliesAnnotation = method.getMethod().getAnnotation(Implies.class); + String[] impliesExpressions = new String[0]; + if (impliesAnnotation != null) { + impliesExpressions = impliesAnnotation.value(); + } + List guardExpressions = new ArrayList<>(); + for (String string : impliesExpressions) { + guardExpressions.add(new GuardExpression(string, false)); + } + return new GuardData(method, guardExpressions); + } + + @Override + public Class getAnnotationType() { + return null; + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ImplicitCastParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ImplicitCastParser.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.parser; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.model.*; + +public class ImplicitCastParser extends TypeSystemMethodParser { + + public ImplicitCastParser(ProcessorContext context, TypeSystemData typeSystem) { + super(context, typeSystem); + } + + @Override + public Class getAnnotationType() { + return ImplicitCast.class; + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + List types = getTypeSystem().getPrimitiveTypeMirrors(); + Set identifiers = getTypeSystem().getTypeIdentifiers(); + MethodSpec spec = new MethodSpec(new ParameterSpec("target", types, identifiers)); + spec.addRequired(new ParameterSpec("source", types, identifiers)); + return spec; + } + + @Override + public ImplicitCastData create(TemplateMethod method, boolean invalid) { + if (invalid) { + return new ImplicitCastData(method, null, null); + } + + Parameter target = method.findParameter("targetValue"); + Parameter source = method.findParameter("sourceValue"); + + TypeData targetType = target.getTypeSystemType(); + TypeData sourceType = source.getTypeSystemType(); + + if (targetType.equals(sourceType)) { + method.addError("Target type and source type of an @%s must not be the same type.", ImplicitCast.class.getSimpleName()); + } + + return new ImplicitCastData(method, sourceType, targetType); + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.parser; + +import static com.oracle.truffle.dsl.processor.java.ElementUtils.*; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.model.*; + +public final class MethodSpecParser { + + private boolean emitErrors = true; + private boolean useVarArgs = false; + + private final Template template; + + public MethodSpecParser(Template template) { + this.template = template; + } + + public Template getTemplate() { + return template; + } + + public TypeSystemData getTypeSystem() { + return template.getTypeSystem(); + } + + public boolean isEmitErrors() { + return emitErrors; + } + + public boolean isUseVarArgs() { + return useVarArgs; + } + + public void setEmitErrors(boolean emitErrors) { + this.emitErrors = emitErrors; + } + + public void setUseVarArgs(boolean useVarArgs) { + this.useVarArgs = useVarArgs; + } + + public TemplateMethod parse(MethodSpec methodSpecification, ExecutableElement method, AnnotationMirror annotation, int naturalOrder) { + if (methodSpecification == null) { + return null; + } + + methodSpecification.applyTypeDefinitions("types"); + + String id = method.getSimpleName().toString(); + TypeMirror returnType = method.getReturnType(); + List parameterTypes = new ArrayList<>(); + for (VariableElement var : method.getParameters()) { + parameterTypes.add(var.asType()); + } + + return parseImpl(methodSpecification, naturalOrder, id, method, annotation, returnType, parameterTypes); + } + + public TemplateMethod parseImpl(MethodSpec methodSpecification, int naturalOrder, String id, ExecutableElement method, AnnotationMirror annotation, TypeMirror returnType, + List parameterTypes) { + ParameterSpec returnTypeSpec = methodSpecification.getReturnType(); + Parameter returnTypeMirror = matchParameter(returnTypeSpec, returnType, -1, -1); + if (returnTypeMirror == null) { + if (emitErrors) { + TemplateMethod invalidMethod = new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList()); + String expectedReturnType = returnTypeSpec.toSignatureString(true); + String actualReturnType = ElementUtils.getSimpleName(returnType); + + String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType, + methodSpecification.toSignatureString(method.getSimpleName().toString())); + invalidMethod.addError(message); + return invalidMethod; + } else { + return null; + } + } + + List parameters = parseParameters(methodSpecification, parameterTypes, isUseVarArgs() && method != null ? method.isVarArgs() : false); + if (parameters == null) { + if (isEmitErrors() && method != null) { + TemplateMethod invalidMethod = new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList()); + String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(method), + methodSpecification.toSignatureString(method.getSimpleName().toString())); + invalidMethod.addError(message); + return invalidMethod; + } else { + return null; + } + } + + return new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, parameters); + } + + private static String createActualSignature(ExecutableElement method) { + StringBuilder b = new StringBuilder("("); + String sep = ""; + if (method != null) { + for (VariableElement var : method.getParameters()) { + b.append(sep); + b.append(ElementUtils.getSimpleName(var.asType())); + sep = ", "; + } + } + b.append(")"); + return b.toString(); + } + + /* + * Parameter parsing tries to parse required arguments starting from offset 0 with increasing + * offset until it finds a signature end that matches the required specification. If there is no + * end matching the required arguments, parsing fails. Parameters prior to the parsed required + * ones are cut and used to parse the optional parameters. + */ + private List parseParameters(MethodSpec spec, List parameterTypes, boolean varArgs) { + List parsedRequired = null; + int offset = 0; + for (; offset <= parameterTypes.size(); offset++) { + List parameters = new ArrayList<>(); + parameters.addAll(parameterTypes.subList(offset, parameterTypes.size())); + parsedRequired = parseParametersRequired(spec, parameters, varArgs); + if (parsedRequired != null) { + break; + } + } + + if (parsedRequired == null) { + return null; + } + + if (parsedRequired.isEmpty() && offset == 0) { + offset = parameterTypes.size(); + } + List potentialOptionals = parameterTypes.subList(0, offset); + List parsedOptionals = parseParametersOptional(spec, potentialOptionals); + if (parsedOptionals == null) { + return null; + } + + List finalParameters = new ArrayList<>(); + finalParameters.addAll(parsedOptionals); + finalParameters.addAll(parsedRequired); + return finalParameters; + } + + private List parseParametersOptional(MethodSpec spec, List types) { + List parsedParams = new ArrayList<>(); + + int typeStartIndex = 0; + List specifications = spec.getOptional(); + outer: for (int specIndex = 0; specIndex < specifications.size(); specIndex++) { + ParameterSpec specification = specifications.get(specIndex); + for (int typeIndex = typeStartIndex; typeIndex < types.size(); typeIndex++) { + TypeMirror actualType = types.get(typeIndex); + Parameter optionalParam = matchParameter(specification, actualType, -1, -1); + if (optionalParam != null) { + parsedParams.add(optionalParam); + typeStartIndex = typeIndex + 1; + continue outer; + } + } + } + + if (typeStartIndex < types.size()) { + // not enough types found + return null; + } + return parsedParams; + } + + private List parseParametersRequired(MethodSpec spec, List types, boolean typeVarArgs) { + List parsedParams = new ArrayList<>(); + List specifications = spec.getRequired(); + boolean specVarArgs = spec.isVariableRequiredParameters(); + int typeIndex = 0; + int specificationIndex = 0; + + ParameterSpec specification; + while ((specification = nextSpecification(specifications, specificationIndex, specVarArgs)) != null) { + TypeMirror actualType = nextActualType(types, typeIndex, typeVarArgs); + if (actualType == null) { + if (spec.isIgnoreAdditionalSpecifications()) { + break; + } + return null; + } + + int typeVarArgsIndex = typeVarArgs ? typeIndex - types.size() + 1 : -1; + int specVarArgsIndex = specVarArgs ? specificationIndex - specifications.size() + 1 : -1; + + if (typeVarArgsIndex >= 0 && specVarArgsIndex >= 0) { + // both specifications and types have a variable number of arguments + // we would get into an endless loop if we would continue + break; + } + + Parameter resolvedParameter = matchParameter(specification, actualType, specVarArgsIndex, typeVarArgsIndex); + if (resolvedParameter == null) { + return null; + } + parsedParams.add(resolvedParameter); + typeIndex++; + specificationIndex++; + } + + if (typeIndex < types.size()) { + // additional types available + if (spec.isIgnoreAdditionalParameters()) { + return parsedParams; + } else { + return null; + } + } + + return parsedParams; + } + + private static ParameterSpec nextSpecification(List specifications, int specIndex, boolean varArgs) { + if (varArgs && specIndex >= specifications.size() - 1 && !specifications.isEmpty()) { + return specifications.get(specifications.size() - 1); + } else if (specIndex < specifications.size()) { + return specifications.get(specIndex); + } else { + return null; + } + } + + private static TypeMirror nextActualType(List types, int typeIndex, boolean varArgs) { + if (varArgs && typeIndex >= types.size() - 1 && !types.isEmpty()) { + // unpack varargs array argument + TypeMirror actualType = types.get(types.size() - 1); + if (actualType.getKind() == TypeKind.ARRAY) { + actualType = ((ArrayType) actualType).getComponentType(); + } + return actualType; + } else if (typeIndex < types.size()) { + return types.get(typeIndex); + } else { + return null; + } + } + + private Parameter matchParameter(ParameterSpec specification, TypeMirror mirror, int specificationIndex, int varArgsIndex) { + TypeMirror resolvedType = mirror; + if (hasError(resolvedType)) { + return null; + } + + if (!specification.matches(resolvedType)) { + return null; + } + + TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType); + if (resolvedTypeData != null) { + return new Parameter(specification, resolvedTypeData, specificationIndex, varArgsIndex); + } else { + return new Parameter(specification, resolvedType, specificationIndex, varArgsIndex); + } + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.parser; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.model.*; + +public abstract class NodeMethodParser extends TemplateMethodParser { + + public NodeMethodParser(ProcessorContext context, NodeData node) { + super(context, node); + } + + public NodeData getNode() { + return template; + } + + protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) { + ParameterSpec spec = new ParameterSpec(execution.getName(), nodeTypeMirrors(execution.getChild().getNodeData()), nodeTypeIdentifiers(execution.getChild().getNodeData())); + spec.setExecution(execution); + return spec; + } + + protected List nodeTypeMirrors(NodeData nodeData) { + return nodeData.getTypeSystem().getPrimitiveTypeMirrors(); + } + + protected Set nodeTypeIdentifiers(NodeData nodeData) { + return nodeData.getTypeSystem().getTypeIdentifiers(); + } + + protected ParameterSpec createReturnParameterSpec() { + ParameterSpec returnValue = new ParameterSpec("returnValue", nodeTypeMirrors(getNode()), nodeTypeIdentifiers(getNode())); + returnValue.setExecution(getNode().getThisExecution()); + return returnValue; + } + + @Override + public boolean isParsable(ExecutableElement method) { + if (getAnnotationType() != null) { + return ElementUtils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null; + } + + return true; + } + + @SuppressWarnings("unused") + protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, boolean shortCircuitsEnabled, String shortCircuitName) { + MethodSpec methodSpec = new MethodSpec(createReturnParameterSpec()); + + addDefaultFrame(methodSpec); + addDefaultFieldMethodSpec(methodSpec); + addDefaultChildren(shortCircuitsEnabled, shortCircuitName, methodSpec); + + return methodSpec; + } + + private void addDefaultChildren(boolean shortCircuitsEnabled, String breakName, MethodSpec spec) { + if (getNode().getChildren() == null) { + // children are null when parsing executable types + return; + } + + for (NodeExecutionData execution : getNode().getChildExecutions()) { + if (breakName != null && execution.getShortCircuitId().equals(breakName)) { + break; + } + + if (execution.isShortCircuit() && shortCircuitsEnabled) { + spec.addRequired(new ParameterSpec(shortCircuitValueName(execution.getName()), getContext().getType(boolean.class))); + } + spec.addRequired(createValueParameterSpec(execution)); + } + } + + private void addDefaultFrame(MethodSpec methodSpec) { + if (getNode().supportsFrame()) { + methodSpec.addOptional(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame())); + } + } + + protected void addDefaultFieldMethodSpec(MethodSpec methodSpec) { + for (NodeFieldData field : getNode().getFields()) { + if (field.getGetter() == null) { + ParameterSpec spec = new ParameterSpec(field.getName(), field.getType()); + spec.setLocal(true); + methodSpec.addOptional(spec); + } + } + } + + private static String shortCircuitValueName(String valueName) { + return "has" + ElementUtils.firstLetterUpperCase(valueName); + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,1403 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.parser; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; +import javax.tools.Diagnostic.Kind; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.java.compiler.*; +import com.oracle.truffle.dsl.processor.model.*; +import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality; +import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind; +import com.oracle.truffle.dsl.processor.model.TemplateMethod.TypeSignature; + +public class NodeParser extends AbstractParser { + + public static final List> ANNOTATIONS = Arrays.asList(Fallback.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, NodeChild.class, + NodeChildren.class); + + private Map parsedNodes; + + @Override + protected NodeData parse(Element element, AnnotationMirror mirror) { + NodeData node = null; + try { + parsedNodes = new HashMap<>(); + node = resolveNode((TypeElement) element); + if (Log.DEBUG) { + NodeData parsed = parsedNodes.get(ElementUtils.getQualifiedName((TypeElement) element)); + if (node != null) { + String dump = parsed.dump(); + log.message(Kind.ERROR, null, null, null, dump); + } + } + } finally { + parsedNodes = null; + } + + return node; + } + + @Override + protected NodeData filterErrorElements(NodeData model) { + for (Iterator iterator = model.getEnclosingNodes().iterator(); iterator.hasNext();) { + NodeData node = filterErrorElements(iterator.next()); + if (node == null) { + iterator.remove(); + } + } + if (model.hasErrors()) { + return null; + } + return model; + } + + @Override + public boolean isDelegateToRootDeclaredType() { + return true; + } + + @Override + public Class getAnnotationType() { + return null; + } + + @Override + public List> getTypeDelegatedAnnotationTypes() { + return ANNOTATIONS; + } + + private NodeData resolveNode(TypeElement rootType) { + String typeName = ElementUtils.getQualifiedName(rootType); + if (parsedNodes.containsKey(typeName)) { + return parsedNodes.get(typeName); + } + + List enclosedNodes = new ArrayList<>(); + for (TypeElement enclosedType : ElementFilter.typesIn(rootType.getEnclosedElements())) { + NodeData enclosedChild = resolveNode(enclosedType); + if (enclosedChild != null) { + enclosedNodes.add(enclosedChild); + } + } + + NodeData node = parseNode(rootType); + if (node == null && !enclosedNodes.isEmpty()) { + node = new NodeData(context, rootType); + } + + if (node != null) { + for (NodeData enclosedNode : enclosedNodes) { + node.addEnclosedNode(enclosedNode); + } + } + + parsedNodes.put(typeName, node); + return node; + } + + private NodeData parseNode(TypeElement originalTemplateType) { + // reloading the type elements is needed for ecj + TypeElement templateType = ElementUtils.fromTypeMirror(context.reloadTypeElement(originalTemplateType)); + + if (ElementUtils.findAnnotationMirror(processingEnv, originalTemplateType, GeneratedBy.class) != null) { + // generated nodes should not get called again. + return null; + } + + List lookupTypes = collectSuperClasses(new ArrayList(), templateType); + if (!ElementUtils.isAssignable(templateType.asType(), context.getTruffleTypes().getNode())) { + return null; + } + List elements = new ArrayList<>(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType)); + + NodeData node = parseNodeData(templateType, elements, lookupTypes); + + parseImportGuards(node, lookupTypes, elements); + + if (node.hasErrors()) { + return node; // error sync point + } + + node.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, node).parse(elements))); + initializeChildren(node); + + node.getSpecializations().addAll(new SpecializationMethodParser(context, node).parse(elements)); + node.getSpecializations().addAll(new GenericParser(context, node).parse(elements)); + node.getCasts().addAll(new CreateCastParser(context, node).parse(elements)); + node.getShortCircuits().addAll(new ShortCircuitParser(context, node).parse(elements)); + + if (node.hasErrors()) { + return node; // error sync point + } + + verifySpecializationSameLength(node); + initializeSpecializations(elements, node); + initializeShortCircuits(node); // requires specializations and polymorphic specializations + + verifyVisibilities(node); + verifyMissingAbstractMethods(node, elements); + verifyConstructors(node); + verifyNamingConvention(node.getShortCircuits(), "needs"); + verifySpecializationThrows(node); + return node; + } + + private void parseImportGuards(NodeData node, List lookupTypes, List elements) { + for (TypeElement lookupType : lookupTypes) { + AnnotationMirror importAnnotation = ElementUtils.findAnnotationMirror(processingEnv, lookupType, ImportGuards.class); + if (importAnnotation == null) { + continue; + } + AnnotationValue importClassesValue = ElementUtils.getAnnotationValue(importAnnotation, "value"); + List importClasses = ElementUtils.getAnnotationValueList(TypeMirror.class, importAnnotation, "value"); + if (importClasses.isEmpty()) { + node.addError(importAnnotation, importClassesValue, "At least import guard classes must be specified."); + continue; + } + for (TypeMirror importGuardClass : importClasses) { + if (importGuardClass.getKind() != TypeKind.DECLARED) { + node.addError(importAnnotation, importClassesValue, "The specified import guard class '%s' is not a declared type.", ElementUtils.getQualifiedName(importGuardClass)); + continue; + } + TypeElement typeElement = ElementUtils.fromTypeMirror(importGuardClass); + + // hack to reload type is necessary for incremental compiling in eclipse. + // otherwise methods inside of import guard types are just not found. + typeElement = ElementUtils.fromTypeMirror(context.reloadType(typeElement.asType())); + + if (typeElement.getEnclosingElement().getKind().isClass() && !typeElement.getModifiers().contains(Modifier.PUBLIC)) { + node.addError(importAnnotation, importClassesValue, "The specified import guard class '%s' must be public.", ElementUtils.getQualifiedName(importGuardClass)); + continue; + } + + List importMethods = ElementFilter.methodsIn(processingEnv.getElementUtils().getAllMembers(typeElement)); + + for (ExecutableElement importMethod : importMethods) { + if (!importMethod.getModifiers().contains(Modifier.PUBLIC) || !importMethod.getModifiers().contains(Modifier.STATIC)) { + continue; + } + elements.add(importMethod); + } + } + } + } + + private NodeData parseNodeData(TypeElement templateType, List elements, List typeHierarchy) { + AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); + if (typeSystemMirror == null) { + NodeData nodeData = new NodeData(context, templateType); + nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), ElementUtils.getQualifiedName(templateType)); + return nodeData; + } + + TypeMirror typeSystemType = ElementUtils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value"); + final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSystemType, true); + if (typeSystem == null) { + NodeData nodeData = new NodeData(context, templateType); + nodeData.addError("The used type system '%s' is invalid or not a Node.", ElementUtils.getQualifiedName(typeSystemType)); + return nodeData; + } + + List assumptionsList = new ArrayList<>(); + for (int i = typeHierarchy.size() - 1; i >= 0; i--) { + TypeElement type = typeHierarchy.get(i); + AnnotationMirror assumptions = ElementUtils.findAnnotationMirror(context.getEnvironment(), type, NodeAssumptions.class); + if (assumptions != null) { + List assumptionStrings = ElementUtils.getAnnotationValueList(String.class, assumptions, "value"); + for (String string : assumptionStrings) { + if (assumptionsList.contains(string)) { + assumptionsList.remove(string); + } + assumptionsList.add(string); + } + } + } + AnnotationMirror nodeInfoMirror = findFirstAnnotation(typeHierarchy, NodeInfo.class); + String shortName = null; + if (nodeInfoMirror != null) { + shortName = ElementUtils.getAnnotationValue(String.class, nodeInfoMirror, "shortName"); + } + + List fields = parseFields(typeHierarchy, elements); + List children = parseChildren(typeHierarchy, elements); + List executions = parseExecutions(children, elements); + + NodeData nodeData = new NodeData(context, templateType, shortName, typeSystem, children, executions, fields, assumptionsList); + + parsedNodes.put(ElementUtils.getQualifiedName(templateType), nodeData); + + return nodeData; + } + + private List parseFields(List typeHierarchy, List elements) { + Set names = new HashSet<>(); + + List fields = new ArrayList<>(); + for (VariableElement field : ElementFilter.fieldsIn(elements)) { + if (field.getModifiers().contains(Modifier.STATIC)) { + continue; + } + if (field.getModifiers().contains(Modifier.PUBLIC) || field.getModifiers().contains(Modifier.PROTECTED)) { + String name = field.getSimpleName().toString(); + fields.add(new NodeFieldData(field, null, field.asType(), name, false)); + names.add(name); + } + } + + List reversedTypeHierarchy = new ArrayList<>(typeHierarchy); + Collections.reverse(reversedTypeHierarchy); + for (TypeElement typeElement : reversedTypeHierarchy) { + AnnotationMirror nodeChildrenMirror = ElementUtils.findAnnotationMirror(processingEnv, typeElement, NodeFields.class); + List children = ElementUtils.collectAnnotations(context, nodeChildrenMirror, "value", typeElement, NodeField.class); + + for (AnnotationMirror mirror : children) { + String name = ElementUtils.firstLetterLowerCase(ElementUtils.getAnnotationValue(String.class, mirror, "name")); + TypeMirror type = ElementUtils.getAnnotationValue(TypeMirror.class, mirror, "type"); + + NodeFieldData field = new NodeFieldData(typeElement, mirror, type, name, true); + if (name.isEmpty()) { + field.addError(ElementUtils.getAnnotationValue(mirror, "name"), "Field name cannot be empty."); + } else if (names.contains(name)) { + field.addError(ElementUtils.getAnnotationValue(mirror, "name"), "Duplicate field name '%s'.", name); + } + names.add(name); + + fields.add(field); + } + } + + for (NodeFieldData nodeFieldData : fields) { + nodeFieldData.setGetter(findGetter(elements, nodeFieldData.getName(), nodeFieldData.getType())); + } + + return fields; + } + + private List parseChildren(final List typeHierarchy, List elements) { + Set shortCircuits = new HashSet<>(); + for (ExecutableElement method : ElementFilter.methodsIn(elements)) { + AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, ShortCircuit.class); + if (mirror != null) { + shortCircuits.add(ElementUtils.getAnnotationValue(String.class, mirror, "value")); + } + } + Map castNodeTypes = new HashMap<>(); + for (ExecutableElement method : ElementFilter.methodsIn(elements)) { + AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, CreateCast.class); + if (mirror != null) { + List children = (ElementUtils.getAnnotationValueList(String.class, mirror, "value")); + if (children != null) { + for (String child : children) { + castNodeTypes.put(child, method.getReturnType()); + } + } + } + } + + List parsedChildren = new ArrayList<>(); + List typeHierarchyReversed = new ArrayList<>(typeHierarchy); + Collections.reverse(typeHierarchyReversed); + for (TypeElement type : typeHierarchyReversed) { + AnnotationMirror nodeChildrenMirror = ElementUtils.findAnnotationMirror(processingEnv, type, NodeChildren.class); + + TypeMirror nodeClassType = type.getSuperclass(); + if (!ElementUtils.isAssignable(nodeClassType, context.getTruffleTypes().getNode())) { + nodeClassType = null; + } + + List children = ElementUtils.collectAnnotations(context, nodeChildrenMirror, "value", type, NodeChild.class); + int index = 0; + for (AnnotationMirror childMirror : children) { + String name = ElementUtils.getAnnotationValue(String.class, childMirror, "value"); + if (name.equals("")) { + name = "child" + index; + } + + Cardinality cardinality = Cardinality.ONE; + + TypeMirror childType = inheritType(childMirror, "type", nodeClassType); + if (childType.getKind() == TypeKind.ARRAY) { + cardinality = Cardinality.MANY; + } + + TypeMirror originalChildType = childType; + TypeMirror castNodeType = castNodeTypes.get(name); + if (castNodeType != null) { + childType = castNodeType; + } + + Element getter = findGetter(elements, name, childType); + + NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality); + + parsedChildren.add(nodeChild); + + if (nodeChild.getNodeType() == null) { + nodeChild.addError("No valid node type could be resoleved."); + } + if (nodeChild.hasErrors()) { + continue; + } + + index++; + } + } + + List filteredChildren = new ArrayList<>(); + Set encounteredNames = new HashSet<>(); + for (int i = parsedChildren.size() - 1; i >= 0; i--) { + NodeChildData child = parsedChildren.get(i); + if (!encounteredNames.contains(child.getName())) { + filteredChildren.add(0, child); + encounteredNames.add(child.getName()); + } + } + + for (NodeChildData child : filteredChildren) { + List executeWithStrings = ElementUtils.getAnnotationValueList(String.class, child.getMessageAnnotation(), "executeWith"); + AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(child.getMessageAnnotation(), "executeWith"); + List executeWith = new ArrayList<>(); + for (String executeWithString : executeWithStrings) { + + if (child.getName().equals(executeWithString)) { + child.addError(executeWithValue, "The child node '%s' cannot be executed with itself.", executeWithString); + continue; + } + + NodeChildData found = null; + boolean before = true; + for (NodeChildData resolveChild : filteredChildren) { + if (resolveChild == child) { + before = false; + continue; + } + if (resolveChild.getName().equals(executeWithString)) { + found = resolveChild; + break; + } + } + + if (found == null) { + child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The child node was not found.", child.getName(), executeWithString); + continue; + } else if (!before) { + child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The node %s is executed after the current node.", child.getName(), executeWithString, + executeWithString); + continue; + } + executeWith.add(found); + } + child.setExecuteWith(executeWith); + if (child.getNodeData() == null) { + continue; + } + } + + return filteredChildren; + } + + private List parseExecutions(List children, List elements) { + if (children == null) { + return null; + } + + // pre-parse short circuits + Set shortCircuits = new HashSet<>(); + List methods = ElementFilter.methodsIn(elements); + for (ExecutableElement method : methods) { + AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, ShortCircuit.class); + if (mirror != null) { + shortCircuits.add(ElementUtils.getAnnotationValue(String.class, mirror, "value")); + } + } + + boolean hasVarArgs = false; + int maxSignatureSize = 0; + if (!children.isEmpty()) { + int lastIndex = children.size() - 1; + hasVarArgs = children.get(lastIndex).getCardinality() == Cardinality.MANY; + if (hasVarArgs) { + maxSignatureSize = lastIndex; + } else { + maxSignatureSize = children.size(); + } + } + + // pre-parse specializations + for (ExecutableElement method : methods) { + AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, Specialization.class); + if (mirror == null) { + continue; + } + + int currentArgumentCount = 0; + boolean skipShortCircuit = false; + for (VariableElement var : method.getParameters()) { + TypeMirror type = var.asType(); + if (currentArgumentCount == 0) { + // skip optionals + if (ElementUtils.typeEquals(type, context.getTruffleTypes().getFrame())) { + continue; + } + // TODO skip optional fields? + } + int childIndex = currentArgumentCount < children.size() ? currentArgumentCount : children.size() - 1; + if (childIndex == -1) { + continue; + } + if (!skipShortCircuit) { + NodeChildData child = children.get(childIndex); + if (shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, currentArgumentCount - childIndex))) { + skipShortCircuit = true; + continue; + } + } else { + skipShortCircuit = false; + } + + currentArgumentCount++; + } + maxSignatureSize = Math.max(maxSignatureSize, currentArgumentCount); + } + + List executions = new ArrayList<>(); + for (int i = 0; i < maxSignatureSize; i++) { + int childIndex = i; + boolean varArg = false; + if (childIndex >= children.size() - 1) { + if (hasVarArgs) { + childIndex = children.size() - 1; + varArg = hasVarArgs; + } else if (childIndex >= children.size()) { + break; + } + } + int varArgsIndex = varArg ? Math.abs(childIndex - i) : -1; + NodeChildData child = children.get(childIndex); + boolean shortCircuit = shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, varArgsIndex)); + executions.add(new NodeExecutionData(child, varArgsIndex, shortCircuit)); + } + return executions; + } + + private static Map> groupExecutableTypes(List executableTypes) { + Map> groupedTypes = new TreeMap<>(); + for (ExecutableTypeData type : executableTypes) { + int evaluatedCount = type.getEvaluatedCount(); + + List types = groupedTypes.get(evaluatedCount); + if (types == null) { + types = new ArrayList<>(); + groupedTypes.put(evaluatedCount, types); + } + types.add(type); + } + + for (List types : groupedTypes.values()) { + Collections.sort(types); + } + return groupedTypes; + } + + private void initializeChildren(NodeData node) { + for (NodeChildData nodeChild : node.getChildren()) { + NodeData fieldNodeData = resolveNode(ElementUtils.fromTypeMirror(nodeChild.getNodeType())); + nodeChild.setNode(fieldNodeData); + if (fieldNodeData == null) { + nodeChild.addError("Node type '%s' is invalid or not a valid Node.", ElementUtils.getQualifiedName(nodeChild.getNodeType())); + } else if (!ElementUtils.typeEquals(fieldNodeData.getTypeSystem().getTemplateType().asType(), (node.getTypeSystem().getTemplateType().asType()))) { + nodeChild.addError("The @%s of the node and the @%s of the @%s does not match. %s != %s. ", TypeSystem.class.getSimpleName(), TypeSystem.class.getSimpleName(), + NodeChild.class.getSimpleName(), ElementUtils.getSimpleName(node.getTypeSystem().getTemplateType()), + ElementUtils.getSimpleName(fieldNodeData.getTypeSystem().getTemplateType())); + } + if (fieldNodeData != null) { + List types = nodeChild.findGenericExecutableTypes(context); + if (types.isEmpty()) { + AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(nodeChild.getMessageAnnotation(), "executeWith"); + nodeChild.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", nodeChild.getExecuteWith().size(), + ElementUtils.getSimpleName(nodeChild.getNodeType())); + } + } + } + } + + private void initializeSpecializations(List elements, final NodeData node) { + if (node.getSpecializations().isEmpty()) { + return; + } + + initializeGuards(elements, node); + initializeGeneric(node); + initializeUninitialized(node); + initializeOrder(node); + initializePolymorphism(node); // requires specializations + initializeReachability(node); + initializeContains(node); + + if (!node.hasErrors()) { + initializeExceptions(node); + } + resolveContains(node); + + List needsId = new ArrayList<>(); + for (SpecializationData specialization : node.getSpecializations()) { + if (specialization.isGeneric()) { + specialization.setId("Generic"); + } else if (specialization.isUninitialized()) { + specialization.setId("Uninitialized"); + } else if (specialization.isPolymorphic()) { + specialization.setId("Polymorphic"); + } else if (specialization.isSpecialized()) { + needsId.add(specialization); + } else { + throw new AssertionError(); + } + } + + // verify specialization parameter length + List ids = initializeSpecializationIds(needsId); + for (int i = 0; i < ids.size(); i++) { + needsId.get(i).setId(ids.get(i)); + } + + } + + private static void initializeOrder(NodeData node) { + List specializations = node.getSpecializations(); + Collections.sort(specializations); + + for (SpecializationData specialization : specializations) { + String searchName = specialization.getInsertBeforeName(); + if (searchName == null || specialization.getMethod() == null) { + continue; + } + SpecializationData found = lookupSpecialization(node, searchName); + if (found == null || found.getMethod() == null) { + AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "insertBefore"); + specialization.addError(value, "The referenced specialization '%s' could not be found.", searchName); + continue; + } + + ExecutableElement currentMethod = specialization.getMethod(); + ExecutableElement insertBeforeMethod = found.getMethod(); + + TypeMirror currentEnclosedType = currentMethod.getEnclosingElement().asType(); + TypeMirror insertBeforeEnclosedType = insertBeforeMethod.getEnclosingElement().asType(); + + if (ElementUtils.typeEquals(currentEnclosedType, insertBeforeEnclosedType) || !ElementUtils.isSubtype(currentEnclosedType, insertBeforeEnclosedType)) { + AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "insertBefore"); + specialization.addError(value, "Specializations can only be inserted before specializations in superclasses.", searchName); + continue; + } + + specialization.setInsertBefore(found); + } + + for (int i = 0; i < specializations.size(); i++) { + SpecializationData specialization = specializations.get(i); + SpecializationData insertBefore = specialization.getInsertBefore(); + if (insertBefore != null) { + int insertIndex = specializations.indexOf(insertBefore); + if (insertIndex < i) { + specializations.remove(i); + specializations.add(insertIndex, specialization); + } + } + } + + for (int i = 0; i < specializations.size(); i++) { + specializations.get(i).setIndex(i); + } + } + + private static void initializeExceptions(NodeData node) { + List specializations = node.getSpecializations(); + for (int i = 0; i < specializations.size(); i++) { + SpecializationData cur = specializations.get(i); + if (cur.getExceptions().isEmpty()) { + continue; + } + SpecializationData next = i + 1 < specializations.size() ? specializations.get(i + 1) : null; + + if (!cur.isContainedBy(next)) { + next.addError("This specialiation is not a valid exceptional rewrite target for %s. To fix this make %s compatible to %s or remove the exceptional rewrite.", + cur.createReferenceName(), next != null ? next.createReferenceName() : "-", cur.createReferenceName()); + continue; + } + Set nextContains = next != null ? next.getContains() : Collections. emptySet(); + if (!nextContains.contains(cur)) { + nextContains.add(cur); + } + } + + for (SpecializationData cur : specializations) { + if (cur.getExceptions().isEmpty()) { + continue; + } + for (SpecializationData child : specializations) { + if (child != null && child != cur && child.getContains().contains(cur)) { + cur.getExcludedBy().add(child); + } + } + } + } + + private static void initializeContains(NodeData node) { + for (SpecializationData specialization : node.getSpecializations()) { + Set resolvedSpecializations = specialization.getContains(); + resolvedSpecializations.clear(); + Set includeNames = specialization.getContainsNames(); + for (String includeName : includeNames) { + // TODO reduce complexity of this lookup. + SpecializationData foundSpecialization = lookupSpecialization(node, includeName); + + if (foundSpecialization == null) { + AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains"); + specialization.addError(value, "The referenced specialization '%s' could not be found.", includeName); + } else { + if (!foundSpecialization.isContainedBy(specialization)) { + AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains"); + if (foundSpecialization.compareTo(specialization) > 0) { + specialization.addError(value, "The contained specialization '%s' must be declared before the containing specialization.", includeName); + } else { + specialization.addError(value, + "The contained specialization '%s' is not fully compatible. The contained specialization must be strictly more generic than the containing one.", + includeName); + } + + } + resolvedSpecializations.add(foundSpecialization); + } + } + } + } + + private void resolveContains(NodeData node) { + // flatten transitive includes + for (SpecializationData specialization : node.getSpecializations()) { + if (specialization.getContains().isEmpty()) { + continue; + } + Set foundSpecializations = new HashSet<>(); + collectIncludes(specialization, foundSpecializations, new HashSet()); + specialization.getContains().addAll(foundSpecializations); + } + } + + private static SpecializationData lookupSpecialization(NodeData node, String includeName) { + SpecializationData foundSpecialization = null; + for (SpecializationData searchSpecialization : node.getSpecializations()) { + if (searchSpecialization.getMethodName().equals(includeName)) { + foundSpecialization = searchSpecialization; + break; + } + } + return foundSpecialization; + } + + private void collectIncludes(SpecializationData specialization, Set found, Set visited) { + if (visited.contains(specialization)) { + // circle found + specialization.addError("Circular contained specialization '%s' found.", specialization.createReferenceName()); + return; + } + visited.add(specialization); + + for (SpecializationData included : specialization.getContains()) { + collectIncludes(included, found, new HashSet<>(visited)); + found.add(included); + } + } + + private static void initializeReachability(final NodeData node) { + List specializations = node.getSpecializations(); + for (int i = specializations.size() - 1; i >= 0; i--) { + SpecializationData current = specializations.get(i); + if (current.isPolymorphic()) { + current.setReachable(true); + continue; + } + + List shadowedBy = null; + for (int j = i - 1; j >= 0; j--) { + SpecializationData prev = specializations.get(j); + if (prev.isPolymorphic()) { + continue; + } + if (!current.isReachableAfter(prev)) { + if (shadowedBy == null) { + shadowedBy = new ArrayList<>(); + } + shadowedBy.add(prev); + } + } + + if (shadowedBy != null) { + StringBuilder name = new StringBuilder(); + String sep = ""; + for (SpecializationData shadowSpecialization : shadowedBy) { + name.append(sep); + name.append(shadowSpecialization.createReferenceName()); + sep = ", "; + } + current.addError("%s is not reachable. It is shadowed by %s.", current.isGeneric() ? "Generic" : "Specialization", name); + } + current.setReachable(shadowedBy == null); + } + } + + private static List initializeSpecializationIds(List specializations) { + int lastSize = -1; + List> signatureChunks = new ArrayList<>(); + for (SpecializationData other : specializations) { + if (!other.isSpecialized()) { + continue; + } + List paramIds = new LinkedList<>(); + paramIds.add(ElementUtils.getTypeId(other.getReturnType().getType())); + for (Parameter param : other.getParameters()) { + if (param.getSpecification().getExecution() == null) { + continue; + } + paramIds.add(ElementUtils.getTypeId(param.getType())); + } + assert lastSize == -1 || lastSize == paramIds.size(); + if (lastSize != -1 && lastSize != paramIds.size()) { + throw new AssertionError(); + } + signatureChunks.add(paramIds); + lastSize = paramIds.size(); + } + + // reduce id vertically + for (int i = 0; i < lastSize; i++) { + String prev = null; + boolean allSame = true; + for (List signature : signatureChunks) { + String arg = signature.get(i); + if (prev == null) { + prev = arg; + continue; + } else if (!prev.equals(arg)) { + allSame = false; + break; + } + prev = arg; + } + + if (allSame) { + for (List signature : signatureChunks) { + signature.remove(i); + } + lastSize--; + } + } + + // reduce id horizontally + for (List signature : signatureChunks) { + if (signature.isEmpty()) { + continue; + } + String prev = null; + boolean allSame = true; + for (String arg : signature) { + if (prev == null) { + prev = arg; + continue; + } else if (!prev.equals(arg)) { + allSame = false; + break; + } + prev = arg; + } + + if (allSame) { + signature.clear(); + signature.add(prev); + } + } + + // create signatures + List signatures = new ArrayList<>(); + for (List signatureChunk : signatureChunks) { + StringBuilder b = new StringBuilder(); + if (signatureChunk.isEmpty()) { + b.append("Default"); + } else { + for (String s : signatureChunk) { + b.append(s); + } + } + signatures.add(b.toString()); + } + + Map counts = new HashMap<>(); + for (String s1 : signatures) { + Integer count = counts.get(s1); + if (count == null) { + count = 0; + } + count++; + counts.put(s1, count); + } + + for (String s : counts.keySet()) { + int count = counts.get(s); + if (count > 1) { + int number = 0; + for (ListIterator iterator = signatures.listIterator(); iterator.hasNext();) { + String s2 = iterator.next(); + if (s.equals(s2)) { + iterator.set(s2 + number); + number++; + } + } + } + } + + return signatures; + } + + private void initializeGuards(List elements, NodeData node) { + Map> potentialGuards = new HashMap<>(); + for (SpecializationData specialization : node.getSpecializations()) { + for (GuardExpression exp : specialization.getGuards()) { + potentialGuards.put(exp.getGuardName(), null); + } + } + + TypeMirror booleanType = context.getType(boolean.class); + for (ExecutableElement potentialGuard : ElementFilter.methodsIn(elements)) { + if (potentialGuard.getModifiers().contains(Modifier.PRIVATE)) { + continue; + } + String methodName = potentialGuard.getSimpleName().toString(); + if (!potentialGuards.containsKey(methodName)) { + continue; + } + + if (!ElementUtils.typeEquals(potentialGuard.getReturnType(), booleanType)) { + continue; + } + + List potentialMethods = potentialGuards.get(methodName); + if (potentialMethods == null) { + potentialMethods = new ArrayList<>(); + potentialGuards.put(methodName, potentialMethods); + } + potentialMethods.add(potentialGuard); + } + + for (SpecializationData specialization : node.getSpecializations()) { + for (GuardExpression exp : specialization.getGuards()) { + resolveGuardExpression(node, specialization, potentialGuards, exp); + } + } + } + + private void resolveGuardExpression(NodeData node, TemplateMethod source, Map> guards, GuardExpression expression) { + List availableGuards = guards.get(expression.getGuardName()); + if (availableGuards == null) { + source.addError("No compatible guard with method name '%s' found.", expression.getGuardName()); + return; + } + + String[] childNames = expression.getChildNames(); + if (childNames != null) { + NodeExecutionData[] resolvedExecutions = new NodeExecutionData[childNames.length]; + for (int i = 0; i < childNames.length; i++) { + String childName = childNames[i]; + NodeExecutionData execution = node.findExecutionByExpression(childName); + if (execution == null) { + source.addError("Guard parameter '%s' for guard '%s' could not be mapped to a declared child node.", childName, expression.getGuardName()); + return; + } + resolvedExecutions[i] = execution; + } + expression.setResolvedChildren(resolvedExecutions); + } + + GuardParser parser = new GuardParser(context, node, source, expression); + List matchingGuards = parser.parse(availableGuards); + if (!matchingGuards.isEmpty() && matchingGuards.get(0) != null) { + expression.setResolvedGuard(matchingGuards.get(0)); + } else { + MethodSpec spec = parser.createSpecification(source.getMethod(), source.getMarkerAnnotation()); + spec.applyTypeDefinitions("types"); + source.addError("No guard with name '%s' matched the required signature. Expected signature: %n%s", expression.getGuardName(), spec.toSignatureString("guard")); + } + } + + private void initializeGeneric(final NodeData node) { + if (!node.needsRewrites(context)) { + return; + } + + List generics = new ArrayList<>(); + for (SpecializationData spec : node.getSpecializations()) { + if (spec.isGeneric()) { + generics.add(spec); + } + } + + if (generics.size() == 1 && node.getSpecializations().size() == 1) { + // TODO this limitation should be lifted + for (SpecializationData generic : generics) { + generic.addError("@%s defined but no @%s.", Fallback.class.getSimpleName(), Specialization.class.getSimpleName()); + } + } + + if (generics.isEmpty()) { + node.getSpecializations().add(createGenericSpecialization(node)); + } else { + if (generics.size() > 1) { + for (SpecializationData generic : generics) { + generic.addError("Only one @%s is allowed per operation.", Fallback.class.getSimpleName()); + } + } + } + } + + private SpecializationData createGenericSpecialization(final NodeData node) { + GenericParser parser = new GenericParser(context, node); + MethodSpec specification = parser.createDefaultMethodSpec(node.getSpecializations().iterator().next().getMethod(), null, true, null); + + List parameterTypes = new ArrayList<>(); + int signatureIndex = 1; + for (ParameterSpec spec : specification.getRequired()) { + parameterTypes.add(createGenericType(spec, node.getSpecializations(), signatureIndex)); + if (spec.isSignature()) { + signatureIndex++; + } + } + + TypeMirror returnType = createGenericType(specification.getReturnType(), node.getSpecializations(), 0); + SpecializationData generic = parser.create("Generic", TemplateMethod.NO_NATURAL_ORDER, null, null, returnType, parameterTypes); + if (generic == null) { + throw new RuntimeException("Unable to create generic signature for node " + node.getNodeId() + " with " + parameterTypes + ". Specification " + specification + "."); + } + + return generic; + } + + private TypeMirror createGenericType(ParameterSpec spec, List specializations, int signatureIndex) { + NodeExecutionData execution = spec.getExecution(); + if (execution == null) { + if (spec.getAllowedTypes().size() == 1) { + return spec.getAllowedTypes().get(0); + } else { + return ElementUtils.getCommonSuperType(context, spec.getAllowedTypes().toArray(new TypeMirror[0])); + } + } else { + Set types = new HashSet<>(); + for (SpecializationData specialization : specializations) { + types.add(specialization.getTypeSignature().get(signatureIndex)); + } + + NodeChildData child = execution.getChild(); + TypeData genericType = null; + if (types.size() == 1) { + ExecutableTypeData executable = child.findExecutableType(context, types.iterator().next()); + if (executable != null && (signatureIndex == 0 || !executable.hasUnexpectedValue(context))) { + genericType = types.iterator().next(); + } + } + if (genericType == null) { + genericType = child.findAnyGenericExecutableType(context).getType(); + } + return genericType.getPrimitiveType(); + } + } + + private static void initializeUninitialized(final NodeData node) { + SpecializationData generic = node.getGenericSpecialization(); + if (generic == null) { + return; + } + for (Parameter parameter : generic.getReturnTypeAndParameters()) { + if (ElementUtils.isObject(parameter.getType())) { + continue; + } + Set types = new HashSet<>(); + for (SpecializationData specialization : node.getSpecializations()) { + Parameter actualParameter = specialization.findParameter(parameter.getLocalName()); + if (actualParameter != null) { + types.add(ElementUtils.getQualifiedName(actualParameter.getType())); + } + } + if (types.size() > 1) { + generic.replaceParameter(parameter.getLocalName(), new Parameter(parameter, node.getTypeSystem().getGenericTypeData())); + } + } + TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", -1, node, generic.getSpecification(), null, null, generic.getReturnType(), generic.getParameters()); + // should not use messages from generic specialization + uninializedMethod.getMessages().clear(); + node.getSpecializations().add(new SpecializationData(node, uninializedMethod, SpecializationKind.UNINITIALIZED)); + } + + private void initializePolymorphism(NodeData node) { + if (!node.needsRewrites(context)) { + return; + } + + SpecializationData generic = node.getGenericSpecialization(); + + List polymorphicSignature = new ArrayList<>(); + List updatePolymorphic = Arrays.asList(); + for (Parameter genericParameter : updatePolymorphic) { + if (!genericParameter.getSpecification().isSignature()) { + continue; + } + + Set usedTypes = new HashSet<>(); + for (SpecializationData specialization : node.getSpecializations()) { + if (!specialization.isSpecialized()) { + continue; + } + Parameter parameter = specialization.findParameter(genericParameter.getLocalName()); + if (parameter == null) { + throw new AssertionError("Parameter existed in generic specialization but not in specialized. param = " + genericParameter.getLocalName()); + } + usedTypes.add(parameter.getTypeSystemType()); + } + + TypeData polymorphicType; + if (usedTypes.size() == 1) { + polymorphicType = usedTypes.iterator().next(); + } else { + polymorphicType = node.getTypeSystem().getGenericTypeData(); + } + polymorphicSignature.add(polymorphicType); + } + + SpecializationData polymorphic = new SpecializationData(node, generic, SpecializationKind.POLYMORPHIC); + polymorphic.updateSignature(new TypeSignature(polymorphicSignature)); + node.getSpecializations().add(polymorphic); + } + + private void initializeShortCircuits(NodeData node) { + Map> groupedShortCircuits = groupShortCircuits(node.getShortCircuits()); + + boolean valid = true; + List shortCircuitExecutions = new ArrayList<>(); + for (NodeExecutionData execution : node.getChildExecutions()) { + if (!execution.isShortCircuit()) { + continue; + } + shortCircuitExecutions.add(execution); + String valueName = execution.getShortCircuitId(); + List availableCircuits = groupedShortCircuits.get(valueName); + + if (availableCircuits == null || availableCircuits.isEmpty()) { + node.addError("@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName); + valid = false; + continue; + } + + boolean sameMethodName = true; + String methodName = availableCircuits.get(0).getMethodName(); + for (ShortCircuitData circuit : availableCircuits) { + if (!circuit.getMethodName().equals(methodName)) { + sameMethodName = false; + } + } + + if (!sameMethodName) { + for (ShortCircuitData circuit : availableCircuits) { + circuit.addError("All short circuits for short cut value '%s' must have the same method name.", valueName); + } + valid = false; + continue; + } + + ShortCircuitData genericCircuit = null; + for (ShortCircuitData circuit : availableCircuits) { + if (isGenericShortCutMethod(circuit)) { + genericCircuit = circuit; + break; + } + } + + if (genericCircuit == null) { + node.addError("No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName); + valid = false; + continue; + } + + for (ShortCircuitData circuit : availableCircuits) { + if (circuit != genericCircuit) { + circuit.setGenericShortCircuitMethod(genericCircuit); + } + } + } + + if (!valid) { + return; + } + + List specializations = new ArrayList<>(); + specializations.addAll(node.getSpecializations()); + for (SpecializationData specialization : specializations) { + List assignedShortCuts = new ArrayList<>(shortCircuitExecutions.size()); + + for (NodeExecutionData shortCircuit : shortCircuitExecutions) { + List availableShortCuts = groupedShortCircuits.get(shortCircuit.getShortCircuitId()); + + ShortCircuitData genericShortCircuit = null; + ShortCircuitData compatibleShortCircuit = null; + for (ShortCircuitData circuit : availableShortCuts) { + if (circuit.isGeneric()) { + genericShortCircuit = circuit; + } else if (circuit.isCompatibleTo(specialization)) { + compatibleShortCircuit = circuit; + } + } + + if (compatibleShortCircuit == null) { + compatibleShortCircuit = genericShortCircuit; + } + assignedShortCuts.add(compatibleShortCircuit); + } + specialization.setShortCircuits(assignedShortCuts); + } + } + + private boolean isGenericShortCutMethod(ShortCircuitData method) { + for (Parameter parameter : method.getParameters()) { + NodeExecutionData execution = parameter.getSpecification().getExecution(); + if (execution == null) { + continue; + } + ExecutableTypeData found = null; + List executableElements = execution.getChild().findGenericExecutableTypes(context); + for (ExecutableTypeData executable : executableElements) { + if (executable.getType().equalsType(parameter.getTypeSystemType())) { + found = executable; + break; + } + } + if (found == null) { + return false; + } + } + return true; + } + + private static Map> groupShortCircuits(List shortCircuits) { + Map> group = new HashMap<>(); + for (ShortCircuitData shortCircuit : shortCircuits) { + List circuits = group.get(shortCircuit.getValueName()); + if (circuits == null) { + circuits = new ArrayList<>(); + group.put(shortCircuit.getValueName(), circuits); + } + circuits.add(shortCircuit); + } + return group; + } + + private static boolean verifySpecializationSameLength(NodeData nodeData) { + int lastArgs = -1; + for (SpecializationData specializationData : nodeData.getSpecializations()) { + int signatureArgs = specializationData.getSignatureSize(); + if (lastArgs == signatureArgs) { + continue; + } + if (lastArgs != -1) { + for (SpecializationData specialization : nodeData.getSpecializations()) { + specialization.addError("All specializations must have the same number of arguments."); + } + return false; + } else { + lastArgs = signatureArgs; + } + } + return true; + } + + private static void verifyVisibilities(NodeData node) { + if (node.getTemplateType().getModifiers().contains(Modifier.PRIVATE) && node.getSpecializations().size() > 0) { + node.addError("Classes containing a @%s annotation must not be private.", Specialization.class.getSimpleName()); + } + } + + private static void verifyMissingAbstractMethods(NodeData nodeData, List originalElements) { + if (!nodeData.needsFactory()) { + // missing abstract methods only needs to be implemented + // if we need go generate factory for it. + return; + } + + List elements = new ArrayList<>(originalElements); + Set unusedElements = new HashSet<>(elements); + for (TemplateMethod method : nodeData.getAllTemplateMethods()) { + unusedElements.remove(method.getMethod()); + } + + for (NodeFieldData field : nodeData.getFields()) { + if (field.getGetter() != null) { + unusedElements.remove(field.getGetter()); + } + } + + for (NodeChildData child : nodeData.getChildren()) { + if (child.getAccessElement() != null) { + unusedElements.remove(child.getAccessElement()); + } + } + + for (ExecutableElement unusedMethod : ElementFilter.methodsIn(unusedElements)) { + if (unusedMethod.getModifiers().contains(Modifier.ABSTRACT)) { + nodeData.addError("The type %s must implement the inherited abstract method %s.", ElementUtils.getSimpleName(nodeData.getTemplateType()), + ElementUtils.getReadableSignature(unusedMethod)); + } + } + } + + private static void verifyNamingConvention(List methods, String prefix) { + for (int i = 0; i < methods.size(); i++) { + TemplateMethod m1 = methods.get(i); + if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) { + m1.addError("Naming convention: method name must start with '%s'.", prefix); + } + } + } + + private static void verifySpecializationThrows(NodeData node) { + Map specializationMap = new HashMap<>(); + for (SpecializationData spec : node.getSpecializations()) { + specializationMap.put(spec.getMethodName(), spec); + } + for (SpecializationData sourceSpecialization : node.getSpecializations()) { + if (sourceSpecialization.getExceptions() != null) { + for (SpecializationThrowsData throwsData : sourceSpecialization.getExceptions()) { + for (SpecializationThrowsData otherThrowsData : sourceSpecialization.getExceptions()) { + if (otherThrowsData != throwsData && ElementUtils.typeEquals(otherThrowsData.getJavaClass(), throwsData.getJavaClass())) { + throwsData.addError("Duplicate exception type."); + } + } + } + } + } + } + + private void verifyConstructors(NodeData nodeData) { + if (!nodeData.needsRewrites(context)) { + // no specialization constructor is needed if the node never rewrites. + return; + } + + TypeElement type = ElementUtils.fromTypeMirror(nodeData.getNodeType()); + List constructors = ElementFilter.constructorsIn(type.getEnclosedElements()); + + boolean parametersFound = false; + for (ExecutableElement constructor : constructors) { + if (!constructor.getParameters().isEmpty() && !isSourceSectionConstructor(context, constructor)) { + parametersFound = true; + } + } + if (!parametersFound) { + return; + } + for (ExecutableElement e : constructors) { + if (e.getParameters().size() == 1) { + TypeMirror firstArg = e.getParameters().get(0).asType(); + if (ElementUtils.typeEquals(firstArg, nodeData.getNodeType())) { + if (e.getModifiers().contains(Modifier.PRIVATE)) { + nodeData.addError("The specialization constructor must not be private."); + } else if (constructors.size() <= 1) { + nodeData.addError("The specialization constructor must not be the only constructor. The definition of an alternative constructor is required."); + } + return; + } + } + } + + // not found + nodeData.addError("Specialization constructor '%s(%s previousNode) { this(...); }' is required.", ElementUtils.getSimpleName(type), ElementUtils.getSimpleName(type)); + } + + public static boolean isSourceSectionConstructor(ProcessorContext context, ExecutableElement constructor) { + return constructor.getParameters().size() == 1 && ElementUtils.typeEquals(constructor.getParameters().get(0).asType(), context.getTruffleTypes().getSourceSection()); + } + + private AnnotationMirror findFirstAnnotation(List elements, Class annotation) { + for (Element element : elements) { + AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, element, annotation); + if (mirror != null) { + return mirror; + } + } + return null; + } + + private TypeMirror inheritType(AnnotationMirror annotation, String valueName, TypeMirror parentType) { + TypeMirror inhertNodeType = context.getTruffleTypes().getNode(); + TypeMirror value = ElementUtils.getAnnotationValue(TypeMirror.class, annotation, valueName); + if (ElementUtils.typeEquals(inhertNodeType, value)) { + return parentType; + } else { + return value; + } + } + + private ExecutableElement findGetter(List elements, String variableName, TypeMirror type) { + if (type == null) { + return null; + } + String methodName; + if (ElementUtils.typeEquals(type, context.getType(boolean.class))) { + methodName = "is" + ElementUtils.firstLetterUpperCase(variableName); + } else { + methodName = "get" + ElementUtils.firstLetterUpperCase(variableName); + } + + for (ExecutableElement method : ElementFilter.methodsIn(elements)) { + if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && ElementUtils.isAssignable(type, method.getReturnType())) { + return method; + } + } + return null; + } + + private static List collectSuperClasses(List collection, TypeElement element) { + if (element != null) { + collection.add(element); + if (element.getSuperclass() != null) { + collectSuperClasses(collection, ElementUtils.fromTypeMirror(element.getSuperclass())); + } + } + return collection; + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ShortCircuitParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ShortCircuitParser.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.parser; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.model.*; + +public class ShortCircuitParser extends NodeMethodParser { + + private final Set shortCircuitValues; + + public ShortCircuitParser(ProcessorContext context, NodeData node) { + super(context, node); + + shortCircuitValues = new HashSet<>(); + for (NodeExecutionData execution : node.getChildExecutions()) { + if (execution.isShortCircuit()) { + shortCircuitValues.add(execution.getShortCircuitId()); + } + } + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + String shortCircuitValue = ElementUtils.getAnnotationValue(String.class, mirror, "value"); + + return createDefaultMethodSpec(method, mirror, true, shortCircuitValue); + } + + @Override + protected ParameterSpec createReturnParameterSpec() { + return new ParameterSpec("has", getContext().getType(boolean.class)); + } + + @Override + public ShortCircuitData create(TemplateMethod method, boolean invalid) { + String shortCircuitValue = ElementUtils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "value"); + + if (!shortCircuitValues.contains(shortCircuitValue)) { + method.addError("Invalid short circuit value %s.", shortCircuitValue); + } + + return new ShortCircuitData(method, shortCircuitValue); + } + + @Override + public Class getAnnotationType() { + return ShortCircuit.class; + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.parser; + +import java.util.*; + +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.model.*; +import com.oracle.truffle.dsl.processor.model.TemplateMethod.TypeSignature; + +/** + * Class creates groups of specializations to optimize the layout of generated executeAndSpecialize + * and generic execute methods. + */ +public final class SpecializationGroup { + + private final List assumptions; + private final List typeGuards; + private final List guards; + + private final NodeData node; + private final SpecializationData specialization; + private final List children = new ArrayList<>(); + + private SpecializationGroup parent; + + private SpecializationGroup(SpecializationData data) { + this.node = data.getNode(); + this.assumptions = new ArrayList<>(); + this.typeGuards = new ArrayList<>(); + this.guards = new ArrayList<>(); + this.specialization = data; + + this.assumptions.addAll(data.getAssumptions()); + TypeSignature sig = data.getTypeSignature(); + for (int i = 1; i < sig.size(); i++) { + typeGuards.add(new TypeGuard(sig.get(i), i - 1)); + } + this.guards.addAll(data.getGuards()); + } + + public SpecializationGroup(List children, List assumptionMatches, List typeGuardsMatches, List guardMatches) { + assert !children.isEmpty() : "children must not be empty"; + this.assumptions = assumptionMatches; + this.typeGuards = typeGuardsMatches; + this.guards = guardMatches; + this.node = children.get(0).node; + this.specialization = null; + updateChildren(children); + } + + public List getAllGuards() { + List collectedGuards = new ArrayList<>(); + collectedGuards.addAll(typeGuards); + if (parent != null) { + collectedGuards.addAll(parent.getAllGuards()); + } + return collectedGuards; + } + + public TypeGuard findTypeGuard(int signatureIndex) { + for (TypeGuard guard : typeGuards) { + if (guard.getSignatureIndex() == signatureIndex) { + return guard; + } + } + return null; + } + + public List findElseConnectableGuards() { + if (!getTypeGuards().isEmpty() || !getAssumptions().isEmpty()) { + return Collections.emptyList(); + } + + if (getGuards().isEmpty()) { + return Collections.emptyList(); + } + + List elseConnectableGuards = new ArrayList<>(); + int guardIndex = 0; + while (guardIndex < getGuards().size() && findNegatedGuardInPrevious(getGuards().get(guardIndex)) != null) { + elseConnectableGuards.add(getGuards().get(guardIndex)); + guardIndex++; + } + + return elseConnectableGuards; + } + + private GuardExpression findNegatedGuardInPrevious(GuardExpression guard) { + SpecializationGroup previous = this.getPreviousGroup(); + if (previous == null) { + return null; + } + List elseConnectedGuards = previous.findElseConnectableGuards(); + + if (previous == null || previous.getGuards().size() != elseConnectedGuards.size() + 1) { + return null; + } + + /* Guard is else branch can be connected in previous specialization. */ + if (elseConnectedGuards.contains(guard)) { + return guard; + } + + GuardExpression previousGuard = previous.getGuards().get(elseConnectedGuards.size()); + if (guard.getResolvedGuard().getMethod().equals(previousGuard.getResolvedGuard().getMethod()) && guard.isNegated() != previousGuard.isNegated()) { + return guard; + } + return null; + } + + private void updateChildren(List childs) { + if (!children.isEmpty()) { + children.clear(); + } + this.children.addAll(childs); + for (SpecializationGroup child : childs) { + child.parent = this; + } + } + + public SpecializationGroup getParent() { + return parent; + } + + public List getAssumptions() { + return assumptions; + } + + public List getTypeGuards() { + return typeGuards; + } + + public List getGuards() { + return guards; + } + + public List getChildren() { + return children; + } + + public SpecializationData getSpecialization() { + return specialization; + } + + private static SpecializationGroup combine(List groups) { + if (groups.isEmpty()) { + throw new IllegalArgumentException("empty combinations"); + } + if (groups.size() == 1) { + return null; + } + + List assumptionMatches = new ArrayList<>(); + List typeGuardsMatches = new ArrayList<>(); + List guardMatches = new ArrayList<>(); + + SpecializationGroup first = groups.get(0); + List others = groups.subList(1, groups.size()); + + outer: for (String assumption : first.assumptions) { + for (SpecializationGroup other : others) { + if (!other.assumptions.contains(assumption)) { + // assumptions can be combined unordered + continue outer; + } + } + assumptionMatches.add(assumption); + } + + outer: for (TypeGuard typeGuard : first.typeGuards) { + for (SpecializationGroup other : others) { + if (!other.typeGuards.contains(typeGuard)) { + // type guards can be combined unordered + continue outer; + } + } + typeGuardsMatches.add(typeGuard); + } + + outer: for (GuardExpression guard : first.guards) { + for (SpecializationGroup other : others) { + if (!other.guards.contains(guard)) { + // we must break here. One guard may depend on the other. + break outer; + } + } + guardMatches.add(guard); + } + + // check for guards for required type casts + for (Iterator iterator = guardMatches.iterator(); iterator.hasNext();) { + GuardExpression guardMatch = iterator.next(); + + int signatureIndex = 0; + for (Parameter parameter : guardMatch.getResolvedGuard().getParameters()) { + signatureIndex++; + if (!parameter.getSpecification().isSignature()) { + continue; + } + + TypeMirror guardType = parameter.getType(); + + // object guards can be safely moved up + if (ElementUtils.isObject(guardType)) { + continue; + } + + // generic guards can be safely moved up + SpecializationData generic = first.node.getGenericSpecialization(); + if (generic != null) { + Parameter genericParameter = generic.findParameter(parameter.getLocalName()); + if (genericParameter != null && ElementUtils.typeEquals(genericParameter.getType(), guardType)) { + continue; + } + } + + // signature index required for moving up guards + if (containsIndex(typeGuardsMatches, signatureIndex) || (first.getParent() != null && first.getParent().containsTypeGuardIndex(signatureIndex))) { + continue; + } + + iterator.remove(); + break; + } + } + + if (assumptionMatches.isEmpty() && typeGuardsMatches.isEmpty() && guardMatches.isEmpty()) { + return null; + } + + for (SpecializationGroup group : groups) { + group.assumptions.removeAll(assumptionMatches); + group.typeGuards.removeAll(typeGuardsMatches); + group.guards.removeAll(guardMatches); + } + + List newChildren = new ArrayList<>(groups); + return new SpecializationGroup(newChildren, assumptionMatches, typeGuardsMatches, guardMatches); + } + + private boolean containsTypeGuardIndex(int index) { + if (containsIndex(typeGuards, index)) { + return true; + } + if (parent != null) { + return parent.containsTypeGuardIndex(index); + } + return false; + } + + private static boolean containsIndex(List typeGuards, int signatureIndex) { + for (TypeGuard guard : typeGuards) { + if (guard.signatureIndex == signatureIndex) { + return true; + } + } + return false; + } + + public static SpecializationGroup create(SpecializationData specialization) { + return new SpecializationGroup(specialization); + } + + public static SpecializationGroup create(List specializations) { + List groups = new ArrayList<>(); + for (SpecializationData specialization : specializations) { + groups.add(new SpecializationGroup(specialization)); + } + return new SpecializationGroup(createCombinationalGroups(groups), Collections. emptyList(), Collections. emptyList(), Collections. emptyList()); + } + + @Override + public String toString() { + return "SpecializationGroup [assumptions=" + assumptions + ", typeGuards=" + typeGuards + ", guards=" + guards + "]"; + } + + private static List createCombinationalGroups(List groups) { + if (groups.size() <= 1) { + return groups; + } + List newGroups = new ArrayList<>(); + + int i = 0; + for (i = 0; i < groups.size();) { + SpecializationGroup combined = null; + for (int j = groups.size(); j > i + 1; j--) { + combined = combine(groups.subList(i, j)); + if (combined != null) { + break; + } + } + SpecializationGroup newGroup; + if (combined == null) { + newGroup = groups.get(i); + i++; + } else { + newGroup = combined; + List originalGroups = new ArrayList<>(combined.children); + combined.updateChildren(createCombinationalGroups(originalGroups)); + i += originalGroups.size(); + } + + newGroups.add(newGroup); + + } + + return newGroups; + } + + public SpecializationGroup getPreviousGroup() { + if (parent == null || parent.children.isEmpty()) { + return null; + } + int index = parent.children.indexOf(this); + if (index <= 0) { + return null; + } + return parent.children.get(index - 1); + } + + public int getUncheckedSpecializationIndex() { + int groupMaxIndex = getMaxSpecializationIndex(); + + int genericIndex = node.getSpecializations().indexOf(node.getGenericSpecialization()); + if (groupMaxIndex >= genericIndex) { + // no minimum state check for an generic index + groupMaxIndex = -1; + } + + if (groupMaxIndex > -1) { + // no minimum state check if already checked by parent group + int parentMaxIndex = -1; + if (getParent() != null) { + parentMaxIndex = getParent().getMaxSpecializationIndex(); + } + if (groupMaxIndex == parentMaxIndex) { + groupMaxIndex = -1; + } + } + return groupMaxIndex; + } + + public int getMaxSpecializationIndex() { + if (specialization != null) { + return specialization.getNode().getSpecializations().indexOf(specialization); + } else { + int max = Integer.MIN_VALUE; + for (SpecializationGroup childGroup : getChildren()) { + max = Math.max(max, childGroup.getMaxSpecializationIndex()); + } + return max; + } + } + + public static final class TypeGuard { + + private final int signatureIndex; + private final TypeData type; + + public TypeGuard(TypeData type, int signatureIndex) { + this.type = type; + this.signatureIndex = signatureIndex; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + signatureIndex; + result = prime * result + type.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (obj == null) { + return false; + } else if (getClass() != obj.getClass()) { + return false; + } + + TypeGuard other = (TypeGuard) obj; + if (signatureIndex != other.signatureIndex) { + return false; + } else if (!type.equals(other.type)) { + return false; + } + return true; + } + + public int getSignatureIndex() { + return signatureIndex; + } + + public TypeData getType() { + return type; + } + } + + public boolean isTypeGuardUsedInAnyGuardBelow(ProcessorContext context, SpecializationData source, TypeGuard typeGuard) { + NodeExecutionData execution = source.getNode().getChildExecutions().get(typeGuard.getSignatureIndex()); + + for (GuardExpression guard : guards) { + List guardParameters = guard.getResolvedGuard().findByExecutionData(execution); + Parameter sourceParameter = source.getSignatureParameter(typeGuard.getSignatureIndex()); + for (Parameter guardParameter : guardParameters) { + if (sourceParameter.getTypeSystemType().needsCastTo(guardParameter.getType())) { + return true; + } + } + } + + for (SpecializationGroup group : getChildren()) { + if (group.isTypeGuardUsedInAnyGuardBelow(context, source, typeGuard)) { + return true; + } + } + + return false; + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.parser; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.model.*; +import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind; + +public class SpecializationMethodParser extends NodeMethodParser { + + public SpecializationMethodParser(ProcessorContext context, NodeData operation) { + super(context, operation); + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + return createDefaultMethodSpec(method, mirror, true, null); + } + + @Override + public SpecializationData create(TemplateMethod method, boolean invalid) { + return parseSpecialization(method); + } + + @Override + public Class getAnnotationType() { + return Specialization.class; + } + + private SpecializationData parseSpecialization(TemplateMethod method) { + AnnotationValue rewriteValue = ElementUtils.getAnnotationValue(method.getMarkerAnnotation(), "rewriteOn"); + List exceptionTypes = ElementUtils.getAnnotationValueList(TypeMirror.class, method.getMarkerAnnotation(), "rewriteOn"); + List exceptionData = new ArrayList<>(); + for (TypeMirror exceptionType : exceptionTypes) { + SpecializationThrowsData throwsData = new SpecializationThrowsData(method.getMarkerAnnotation(), rewriteValue, exceptionType); + if (!ElementUtils.canThrowType(method.getMethod().getThrownTypes(), exceptionType)) { + throwsData.addError("Method must specify a throws clause with the exception type '%s'.", ElementUtils.getQualifiedName(exceptionType)); + } + exceptionData.add(throwsData); + } + + Collections.sort(exceptionData, new Comparator() { + + @Override + public int compare(SpecializationThrowsData o1, SpecializationThrowsData o2) { + return ElementUtils.compareByTypeHierarchy(o1.getJavaClass(), o2.getJavaClass()); + } + }); + SpecializationData specialization = new SpecializationData(getNode(), method, SpecializationKind.SPECIALIZED, exceptionData); + + String insertBeforeName = ElementUtils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "insertBefore"); + if (!insertBeforeName.equals("")) { + specialization.setInsertBeforeName(insertBeforeName); + } + + List guardDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards"); + List guardExpressions = new ArrayList<>(); + for (String guardDef : guardDefs) { + guardExpressions.add(new GuardExpression(guardDef, true)); + } + specialization.setGuards(guardExpressions); + + List containsDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "contains"); + Set containsNames = specialization.getContainsNames(); + containsNames.clear(); + if (containsDefs != null) { + for (String include : containsDefs) { + if (!containsNames.contains(include)) { + specialization.getContainsNames().add(include); + } else { + AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains"); + specialization.addError(value, "Duplicate contains declaration '%s'.", include); + } + } + + } + + List assumptionDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "assumptions"); + specialization.setAssumptions(assumptionDefs); + + for (String assumption : assumptionDefs) { + if (!getNode().getAssumptions().contains(assumption)) { + specialization.addError("Undeclared assumption '%s' used. Use @NodeAssumptions to declare them.", assumption); + } + } + + return specialization; + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TemplateMethodParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TemplateMethodParser.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.parser; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.model.*; + +public abstract class TemplateMethodParser { + + protected final T template; + private final ProcessorContext context; + private final MethodSpecParser parser; + + private boolean parseNullOnError; + + public TemplateMethodParser(ProcessorContext context, T template) { + this.template = template; + this.context = context; + this.parser = new MethodSpecParser(template); + } + + public void setParseNullOnError(boolean parseNullOnError) { + this.parseNullOnError = parseNullOnError; + } + + public boolean isParseNullOnError() { + return parseNullOnError; + } + + public MethodSpecParser getParser() { + return parser; + } + + public ProcessorContext getContext() { + return context; + } + + public TypeSystemData getTypeSystem() { + return template.getTypeSystem(); + } + + public abstract MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror); + + public abstract E create(TemplateMethod method, boolean invalid); + + public abstract boolean isParsable(ExecutableElement method); + + public Class getAnnotationType() { + return null; + } + + public final List parse(List elements) { + List methods = new ArrayList<>(); + methods.addAll(ElementFilter.methodsIn(elements)); + + List parsedMethods = new ArrayList<>(); + boolean valid = true; + int naturalOrder = 0; + for (ExecutableElement method : methods) { + if (!isParsable(method)) { + continue; + } + + Class annotationType = getAnnotationType(); + AnnotationMirror mirror = null; + if (annotationType != null) { + mirror = ElementUtils.findAnnotationMirror(getContext().getEnvironment(), method, annotationType); + } + + E parsedMethod = parse(naturalOrder, method, mirror); + + if (method.getModifiers().contains(Modifier.PRIVATE) && parser.isEmitErrors()) { + parsedMethod.addError("Method annotated with @%s must not be private.", getAnnotationType().getSimpleName()); + parsedMethods.add(parsedMethod); + valid = false; + continue; + } + + if (parsedMethod != null) { + parsedMethods.add(parsedMethod); + } else { + valid = false; + } + naturalOrder++; + } + Collections.sort(parsedMethods); + + if (!valid && isParseNullOnError()) { + return null; + } + return parsedMethods; + } + + private E parse(int naturalOrder, ExecutableElement method, AnnotationMirror annotation) { + MethodSpec methodSpecification = createSpecification(method, annotation); + if (methodSpecification == null) { + return null; + } + + TemplateMethod templateMethod = parser.parse(methodSpecification, method, annotation, naturalOrder); + if (templateMethod != null) { + return create(templateMethod, templateMethod.hasErrors()); + } + return null; + } + + public final E create(String id, int naturalOrder, ExecutableElement methodMetadata, AnnotationMirror mirror, TypeMirror returnType, List parameterTypes) { + TemplateMethod method = parser.parseImpl(createSpecification(methodMetadata, mirror), naturalOrder, id, methodMetadata, mirror, returnType, parameterTypes); + if (method != null) { + return create(method, method.hasErrors()); + } + return null; + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCastParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCastParser.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.parser; + +import java.lang.annotation.*; + +import javax.lang.model.element.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.model.*; + +class TypeCastParser extends TypeSystemMethodParser { + + public TypeCastParser(ProcessorContext context, TypeSystemData typeSystem) { + super(context, typeSystem); + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "as"); + if (targetType == null) { + return null; + } + MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", targetType.getPrimitiveType())); + spec.addRequired(new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors(), getTypeSystem().getTypeIdentifiers())); + return spec; + } + + @Override + public TypeCastData create(TemplateMethod method, boolean invalid) { + if (invalid) { + return new TypeCastData(method, null, null); + } + + TypeData targetType = findTypeByMethodName(method, "as"); + Parameter parameter = method.findParameter("valueValue"); + + TypeData sourceType = null; + if (parameter != null) { + sourceType = getTypeSystem().findTypeData(parameter.getType()); + } + TypeCastData cast = new TypeCastData(method, sourceType, targetType); + + if (targetType != method.getReturnType().getTypeSystemType()) { + cast.addError("Cast type %s does not match to the returned type %s.", ElementUtils.getSimpleName(targetType.getPrimitiveType()), + method.getReturnType() != null ? ElementUtils.getSimpleName(method.getReturnType().getTypeSystemType().getPrimitiveType()) : null); + } + return cast; + } + + @Override + public Class getAnnotationType() { + return TypeCast.class; + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCheckParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCheckParser.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.parser; + +import java.lang.annotation.*; + +import javax.lang.model.element.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.model.*; + +class TypeCheckParser extends TypeSystemMethodParser { + + public TypeCheckParser(ProcessorContext context, TypeSystemData typeSystem) { + super(context, typeSystem); + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "is"); + if (targetType == null) { + return null; + } + MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", getContext().getType(boolean.class))); + spec.addRequired(new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors(), getTypeSystem().getTypeIdentifiers())); + return spec; + } + + @Override + public TypeCheckData create(TemplateMethod method, boolean invalid) { + TypeData checkedType = findTypeByMethodName(method, "is"); + assert checkedType != null; + Parameter parameter = method.findParameter("valueValue"); + assert parameter != null; + return new TypeCheckData(method, checkedType, parameter.getTypeSystemType()); + } + + @Override + public Class getAnnotationType() { + return TypeCheck.class; + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemMethodParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemMethodParser.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.parser; + +import javax.lang.model.element.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.model.*; + +abstract class TypeSystemMethodParser extends TemplateMethodParser { + + public TypeSystemMethodParser(ProcessorContext context, TypeSystemData typeSystem) { + super(context, typeSystem); + } + + @Override + public final boolean isParsable(ExecutableElement method) { + return ElementUtils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null; + } + + protected TypeData findTypeByMethodName(String methodName, String prefix) { + String typeName = methodName.substring(prefix.length(), methodName.length()); + TypeData type = getTypeSystem().findType(typeName); + return type; + } + + protected TypeData findTypeByMethodName(TemplateMethod method, String prefix) { + String methodName = method.getMethodName(); + if (!methodName.startsWith(prefix)) { + String annotationName = ElementUtils.getSimpleName(method.getMessageAnnotation().getAnnotationType()); + method.addError("Methods annotated with %s must match the pattern '%s'.", annotationName, String.format("%s${typeName}", prefix)); + return null; + } + String typeName = methodName.substring(prefix.length(), methodName.length()); + TypeData type = getTypeSystem().findType(typeName); + if (type == null) { + String annotationName = TypeSystem.class.getSimpleName(); + method.addError("Type '%s' is not declared in this @%s.", typeName, annotationName); + return null; + } + + return type; + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.parser; + +import static com.oracle.truffle.dsl.processor.java.ElementUtils.*; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.dsl.processor.generator.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.model.*; + +public class TypeSystemParser extends AbstractParser { + + public static final List> ANNOTATIONS = Arrays.asList(TypeSystem.class, ExpectError.class); + + @Override + public Class getAnnotationType() { + return TypeSystem.class; + } + + @Override + protected TypeSystemData parse(Element element, AnnotationMirror mirror) { + TypeElement templateType = (TypeElement) element; + AnnotationMirror templateTypeAnnotation = mirror; + TypeSystemData typeSystem = new TypeSystemData(context, templateType, templateTypeAnnotation); + + // annotation type on class path!? + TypeElement annotationTypeElement = processingEnv.getElementUtils().getTypeElement(getAnnotationType().getCanonicalName()); + if (annotationTypeElement == null) { + typeSystem.addError("Required class %s is not on the classpath.", getAnnotationType().getName()); + } + if (templateType.getModifiers().contains(Modifier.PRIVATE)) { + typeSystem.addError("A @%s must have at least package protected visibility.", getAnnotationType().getName()); + } + + if (templateType.getModifiers().contains(Modifier.FINAL)) { + typeSystem.addError("The @%s must not be final.", getAnnotationType().getName()); + } + if (typeSystem.hasErrors()) { + return typeSystem; + } + + List types = parseTypes(typeSystem); + + TypeMirror genericType = context.getType(Object.class); + TypeData voidType = new TypeData(typeSystem, types.size(), null, context.getType(void.class), context.getType(Void.class)); + types.add(voidType); + + typeSystem.setTypes(types); + if (typeSystem.hasErrors()) { + return typeSystem; + } + + typeSystem.setGenericType(genericType); + typeSystem.setVoidType(voidType); + + verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class); + + List elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType)); + List implicitCasts = new ImplicitCastParser(context, typeSystem).parse(elements); + List casts = new TypeCastParser(context, typeSystem).parse(elements); + List checks = new TypeCheckParser(context, typeSystem).parse(elements); + + if (casts == null || checks == null || implicitCasts == null) { + return typeSystem; + } + + typeSystem.setImplicitCasts(implicitCasts); + typeSystem.setCasts(casts); + typeSystem.setChecks(checks); + + if (typeSystem.hasErrors()) { + return typeSystem; + } + + for (TypeCheckData check : checks) { + check.getCheckedType().addTypeCheck(check); + } + + for (TypeCastData cast : casts) { + cast.getTargetType().addTypeCast(cast); + } + + verifyGenericTypeChecksAndCasts(typeSystem); + verifyMethodSignatures(typeSystem); + verifyNamesUnique(typeSystem); + + return typeSystem; + } + + private void verifyExclusiveMethodAnnotation(Template template, Class... annotationTypes) { + List methods = ElementFilter.methodsIn(template.getTemplateType().getEnclosedElements()); + for (ExecutableElement method : methods) { + List foundAnnotations = new ArrayList<>(); + for (int i = 0; i < annotationTypes.length; i++) { + Class annotationType = annotationTypes[i]; + AnnotationMirror mirror = ElementUtils.findAnnotationMirror(context.getEnvironment(), method, annotationType); + if (mirror != null) { + foundAnnotations.add(mirror); + } + } + if (foundAnnotations.size() > 1) { + List annotationNames = new ArrayList<>(); + for (AnnotationMirror mirror : foundAnnotations) { + annotationNames.add("@" + ElementUtils.getSimpleName(mirror.getAnnotationType())); + } + + template.addError("Non exclusive usage of annotations %s.", annotationNames); + } + } + } + + private static void verifyGenericTypeChecksAndCasts(TypeSystemData typeSystem) { + for (TypeData type : typeSystem.getTypes()) { + if (!type.getTypeChecks().isEmpty()) { + boolean hasGeneric = false; + for (TypeCheckData typeCheck : type.getTypeChecks()) { + if (typeCheck.isGeneric()) { + hasGeneric = true; + break; + } + } + if (!hasGeneric) { + type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.", + TypeCheck.class.getSimpleName(), TypeSystemCodeGenerator.isTypeMethodName(type), ElementUtils.getSimpleName(type.getBoxedType()), TypeCheck.class.getSimpleName(), + Object.class.getSimpleName()); + } + } + if (!type.getTypeCasts().isEmpty()) { + boolean hasGeneric = false; + for (TypeCastData typeCast : type.getTypeCasts()) { + if (typeCast.isGeneric()) { + hasGeneric = true; + break; + } + } + if (!hasGeneric) { + type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.", + TypeCast.class.getSimpleName(), TypeSystemCodeGenerator.asTypeMethodName(type), ElementUtils.getSimpleName(type.getBoxedType()), TypeCast.class.getSimpleName(), + Object.class.getSimpleName()); + } + } + } + } + + private List parseTypes(TypeSystemData typeSystem) { + List types = new ArrayList<>(); + List typeMirrors = ElementUtils.getAnnotationValueList(TypeMirror.class, typeSystem.getTemplateTypeAnnotation(), "value"); + if (typeMirrors.isEmpty()) { + typeSystem.addError("At least one type must be defined."); + return types; + } + + final AnnotationValue annotationValue = ElementUtils.getAnnotationValue(typeSystem.getTemplateTypeAnnotation(), "value"); + final TypeMirror objectType = context.getType(Object.class); + + int index = 0; + for (TypeMirror primitiveType : typeMirrors) { + TypeMirror primitive = ElementUtils.fillInGenericWildcards(primitiveType); + + TypeMirror boxedType = ElementUtils.boxType(context, primitive); + TypeData typeData = new TypeData(typeSystem, index, annotationValue, primitive, boxedType); + + if (isPrimitiveWrapper(primitive)) { + typeData.addError("Types must not contain primitive wrapper types."); + } + + if (ElementUtils.typeEquals(boxedType, objectType)) { + typeData.addError("Types must not contain the generic type java.lang.Object."); + } + + types.add(typeData); + index++; + } + + verifyTypeOrder(types); + + types.add(new TypeData(typeSystem, index, annotationValue, objectType, objectType)); + return types; + } + + private static void verifyTypeOrder(List types) { + Map> invalidTypes = new HashMap<>(); + + for (int i = types.size() - 1; i >= 0; i--) { + TypeData typeData = types.get(i); + TypeMirror type = typeData.getBoxedType(); + if (invalidTypes.containsKey(ElementUtils.getQualifiedName(type))) { + typeData.addError("Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", invalidTypes.get(ElementUtils.getQualifiedName(type)), + ElementUtils.getQualifiedName(type)); + } + List nextInvalidTypes = ElementUtils.getQualifiedSuperTypeNames(ElementUtils.fromTypeMirror(type)); + nextInvalidTypes.add(getQualifiedName(type)); + + for (String qualifiedName : nextInvalidTypes) { + List inheritedTypes = invalidTypes.get(qualifiedName); + if (inheritedTypes == null) { + inheritedTypes = new ArrayList<>(); + invalidTypes.put(qualifiedName, inheritedTypes); + } + inheritedTypes.add(ElementUtils.getQualifiedName(typeData.getBoxedType())); + } + } + } + + private boolean isPrimitiveWrapper(TypeMirror type) { + Types types = context.getEnvironment().getTypeUtils(); + for (TypeKind kind : TypeKind.values()) { + if (!kind.isPrimitive()) { + continue; + } + if (ElementUtils.typeEquals(type, types.boxedClass(types.getPrimitiveType(kind)).asType())) { + return true; + } + } + return false; + } + + private void verifyMethodSignatures(TypeSystemData typeSystem) { + Set generatedIsMethodNames = new HashSet<>(); + Set generatedAsMethodNames = new HashSet<>(); + Set generatedExpectMethodNames = new HashSet<>(); + + for (TypeData typeData : typeSystem.getTypes()) { + generatedIsMethodNames.add(TypeSystemCodeGenerator.isTypeMethodName(typeData)); + generatedAsMethodNames.add(TypeSystemCodeGenerator.asTypeMethodName(typeData)); + generatedExpectMethodNames.add(TypeSystemCodeGenerator.expectTypeMethodName(typeData)); + } + + List methods = ElementFilter.methodsIn(typeSystem.getTemplateType().getEnclosedElements()); + for (ExecutableElement method : methods) { + if (method.getModifiers().contains(Modifier.PRIVATE)) { + // will not conflict overridden methods + continue; + } else if (method.getParameters().size() != 1) { + continue; + } + String methodName = method.getSimpleName().toString(); + if (generatedIsMethodNames.contains(methodName)) { + verifyIsMethod(typeSystem, method); + } else if (generatedAsMethodNames.contains(methodName)) { + verifyAsMethod(typeSystem, method); + } else if (generatedExpectMethodNames.contains(methodName)) { + verifyExpectMethod(typeSystem); + } + } + } + + private boolean verifyIsMethod(TypeSystemData typeSystem, ExecutableElement method) { + AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, TypeCheck.class); + if (mirror == null) { + typeSystem.addError("Method starting with the pattern is${typeName} must be annotated with @%s.", TypeCheck.class.getSimpleName()); + return false; + } + return true; + } + + private boolean verifyAsMethod(TypeSystemData typeSystem, ExecutableElement method) { + AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, TypeCast.class); + if (mirror == null) { + typeSystem.addError("Method starting with the pattern as${typeName} must be annotated with @%s.", TypeCast.class.getSimpleName()); + return false; + } + return true; + } + + private static boolean verifyExpectMethod(TypeSystemData typeSystem) { + typeSystem.addError("Method starting with the pattern expect${typeName} must not be declared manually."); + return false; + } + + private static void verifyNamesUnique(TypeSystemData typeSystem) { + List types = typeSystem.getTypes(); + for (int i = 0; i < types.size(); i++) { + for (int j = i + 1; j < types.size(); j++) { + String name1 = ElementUtils.getSimpleName(types.get(i).getBoxedType()); + String name2 = ElementUtils.getSimpleName(types.get(j).getBoxedType()); + if (name1.equalsIgnoreCase(name2)) { + typeSystem.addError("Two types result in the same name: %s, %s.", name1, name2); + } + } + } + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.template; - -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.typesystem.*; - -public class ActualParameter { - - private final ParameterSpec specification; - private TypeData typeSystemType; - private TemplateMethod method; - private final String localName; - private final int specificationVarArgsIndex; - private final int typeVarArgsIndex; - private final TypeMirror actualType; - - public ActualParameter(ParameterSpec specification, TypeMirror actualType, int specificationVarArgsIndex, int typeVarArgsIndex) { - this.specification = specification; - this.actualType = actualType; - this.typeSystemType = null; - - this.specificationVarArgsIndex = specificationVarArgsIndex; - - String valueName = specification.getName() + "Value"; - if (specificationVarArgsIndex > -1) { - valueName += specificationVarArgsIndex; - } - this.typeVarArgsIndex = typeVarArgsIndex; - this.localName = valueName; - } - - public ActualParameter(ParameterSpec specification, TypeData actualType, int specificationIndex, int varArgsIndex) { - this(specification, actualType.getPrimitiveType(), specificationIndex, varArgsIndex); - this.typeSystemType = actualType; - } - - public ActualParameter(ActualParameter parameter, TypeData otherType) { - this(parameter.specification, otherType, parameter.specificationVarArgsIndex, parameter.typeVarArgsIndex); - } - - public ActualParameter(ActualParameter parameter) { - this.specification = parameter.specification; - this.actualType = parameter.actualType; - this.typeSystemType = parameter.typeSystemType; - this.specificationVarArgsIndex = parameter.specificationVarArgsIndex; - this.localName = parameter.localName; - this.typeVarArgsIndex = parameter.typeVarArgsIndex; - } - - public int getTypeVarArgsIndex() { - return typeVarArgsIndex; - } - - public int getSpecificationVarArgsIndex() { - return specificationVarArgsIndex; - } - - public String getLocalName() { - return localName; - } - - void setMethod(TemplateMethod method) { - this.method = method; - } - - public ParameterSpec getSpecification() { - return specification; - } - - public TemplateMethod getMethod() { - return method; - } - - public TypeMirror getType() { - return actualType; - } - - public TypeData getTypeSystemType() { - return typeSystemType; - } - - public boolean isTypeVarArgs() { - return typeVarArgsIndex >= 0; - } - - public ActualParameter getPreviousParameter() { - return method.getPreviousParam(this); - } - - @Override - public String toString() { - return Utils.getSimpleName(actualType); - } -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ClassElementFactory.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ClassElementFactory.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.template; - -import static com.oracle.truffle.dsl.processor.Utils.*; -import static javax.lang.model.element.Modifier.*; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; - -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.ast.*; - -public abstract class ClassElementFactory extends CodeElementFactory { - - public ClassElementFactory(ProcessorContext context) { - super(context); - } - - @Override - protected abstract CodeTypeElement create(M m); - - @Override - public CodeTypeElement getElement() { - return (CodeTypeElement) super.getElement(); - } - - protected CodeExecutableElement createConstructorUsingFields(Set modifiers, CodeTypeElement clazz) { - CodeExecutableElement method = new CodeExecutableElement(modifiers, null, clazz.getSimpleName().toString()); - CodeTreeBuilder builder = method.createBuilder(); - TypeElement superClass = fromTypeMirror(clazz.getSuperclass()); - ExecutableElement constructor = findConstructor(superClass); - if (constructor != null && constructor.getParameters().size() > 0) { - builder.startStatement(); - builder.startSuperCall(); - for (VariableElement parameter : constructor.getParameters()) { - method.addParameter(new CodeVariableElement(parameter.asType(), parameter.getSimpleName().toString())); - builder.string(parameter.getSimpleName().toString()); - } - builder.end(); // super - builder.end(); // statement - } - - for (VariableElement field : clazz.getFields()) { - if (field.getModifiers().contains(STATIC)) { - continue; - } - String fieldName = field.getSimpleName().toString(); - method.addParameter(new CodeVariableElement(field.asType(), fieldName)); - builder.startStatement(); - builder.string("this."); - builder.string(fieldName); - builder.string(" = "); - if (isAssignable(getContext(), field.asType(), getContext().getTruffleTypes().getNode())) { - builder.string("adoptChild(").string(fieldName).string(")"); - } else { - builder.string(fieldName); - } - builder.end(); // statement - } - - return method; - } - - private static ExecutableElement findConstructor(TypeElement clazz) { - List constructors = ElementFilter.constructorsIn(clazz.getEnclosedElements()); - if (constructors.isEmpty()) { - return null; - } else { - return constructors.get(0); - } - } - - protected CodeExecutableElement createSuperConstructor(TypeElement type, ExecutableElement element) { - if (element.getModifiers().contains(Modifier.PRIVATE)) { - return null; - } - CodeExecutableElement executable = CodeExecutableElement.clone(getContext().getEnvironment(), element); - executable.setReturnType(null); - executable.setSimpleName(CodeNames.of(type.getSimpleName().toString())); - CodeTreeBuilder b = executable.createBuilder(); - b.startStatement(); - b.startSuperCall(); - for (VariableElement v : element.getParameters()) { - b.string(v.getSimpleName().toString()); - } - b.end(); - b.end(); - - return executable; - } - - protected CodeTypeElement createClass(Template model, Set modifiers, String simpleName, TypeMirror superType, boolean enumType) { - TypeElement templateType = model.getTemplateType(); - - PackageElement pack = getContext().getEnvironment().getElementUtils().getPackageOf(templateType); - CodeTypeElement clazz = new CodeTypeElement(modifiers, enumType ? ElementKind.ENUM : ElementKind.CLASS, pack, simpleName); - TypeMirror resolvedSuperType = superType; - if (resolvedSuperType == null) { - resolvedSuperType = getContext().getType(Object.class); - } - clazz.setSuperClass(resolvedSuperType); - - CodeAnnotationMirror generatedByAnnotation = new CodeAnnotationMirror((DeclaredType) getContext().getType(GeneratedBy.class)); - generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("value"), new CodeAnnotationValue(templateType.asType())); - if (model.getTemplateMethodName() != null) { - generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("methodName"), new CodeAnnotationValue(model.getTemplateMethodName())); - } - - clazz.addAnnotationMirror(generatedByAnnotation); - - context.registerType(model.getTemplateType(), clazz.asType()); - - return clazz; - } -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/CodeElementFactory.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/CodeElementFactory.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.template; - -import javax.lang.model.element.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.ast.*; - -public abstract class CodeElementFactory { - - protected final ProcessorContext context; - private M model; - - private CodeElement element; - - public CodeElementFactory(ProcessorContext context) { - this.context = context; - } - - protected abstract CodeElement create(M m); - - @SuppressWarnings("unused") - protected void createChildren(M m) { - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - public CodeElement process(CodeElement parent, M m) { - model = m; - element = (CodeElement) create(model); - if (parent != null) { - parent.add(element); - } - if (element != null) { - createChildren(model); - } - return element; - } - - @SuppressWarnings("rawtypes") - public CodeElement getElement() { - return element; - } - - protected void add(CodeElementFactory factory, MO m) { - factory.process(this.element, m); - } - - public ProcessorContext getContext() { - return context; - } - - public M getModel() { - return model; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/CompilationUnitFactory.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/CompilationUnitFactory.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.template; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.ast.*; - -public abstract class CompilationUnitFactory extends CodeElementFactory { - - public CompilationUnitFactory(ProcessorContext context) { - super(context); - } - - @Override - public final CodeCompilationUnit create(M m) { - return new CodeCompilationUnit(); - } - - @SuppressWarnings("rawtypes") - @Override - public CodeCompilationUnit process(CodeElement parent, M m) { - return (CodeCompilationUnit) super.process(parent, m); - } - - @Override - protected abstract void createChildren(M m); - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,276 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.template; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.tools.Diagnostic.Kind; - -import com.oracle.truffle.dsl.processor.*; - -public abstract class MessageContainer { - - private final List messages = new ArrayList<>(); - - public final void addWarning(String text, Object... params) { - getMessages().add(new Message(null, this, String.format(text, params), Kind.WARNING)); - } - - public final void addError(String text, Object... params) { - addError(null, text, params); - } - - public final void addError(AnnotationValue value, String text, Object... params) { - getMessages().add(new Message(value, this, String.format(text, params), Kind.ERROR)); - } - - protected List findChildContainers() { - return Collections.emptyList(); - } - - public abstract Element getMessageElement(); - - public final void emitMessages(ProcessorContext context, TypeElement baseElement, Log log) { - emitMessagesImpl(context, baseElement, log, new HashSet(), null); - } - - private void emitMessagesImpl(ProcessorContext context, TypeElement baseElement, Log log, Set visitedSinks, List verifiedMessages) { - List childMessages; - if (verifiedMessages == null) { - childMessages = collectMessagesWithElementChildren(new HashSet(), getMessageElement()); - } else { - childMessages = verifiedMessages; - } - verifyExpectedMessages(context, log, childMessages); - - for (int i = getMessages().size() - 1; i >= 0; i--) { - emitDefault(context, baseElement, log, getMessages().get(i)); - } - - for (MessageContainer sink : findChildContainers()) { - if (visitedSinks.contains(sink)) { - continue; - } - - visitedSinks.add(sink); - if (sink.getMessageElement() == this.getMessageElement()) { - sink.emitMessagesImpl(context, baseElement, log, visitedSinks, childMessages); - } else { - sink.emitMessagesImpl(context, baseElement, log, visitedSinks, null); - } - } - } - - private List collectMessagesWithElementChildren(Set visitedSinks, Element e) { - if (visitedSinks.contains(this)) { - return Collections.emptyList(); - } - visitedSinks.add(this); - - List foundMessages = new ArrayList<>(); - if (Utils.typeEquals(getMessageElement().asType(), e.asType())) { - foundMessages.addAll(getMessages()); - } - for (MessageContainer sink : findChildContainers()) { - foundMessages.addAll(sink.collectMessagesWithElementChildren(visitedSinks, e)); - } - return foundMessages; - } - - private void verifyExpectedMessages(ProcessorContext context, Log log, List msgs) { - TypeElement expectError = context.getTruffleTypes().getExpectError(); - if (expectError != null) { - Element element = getMessageElement(); - AnnotationMirror mirror = Utils.findAnnotationMirror(element.getAnnotationMirrors(), expectError); - if (mirror != null) { - List values = Utils.getAnnotationValueList(String.class, mirror, "value"); - if (values == null) { - values = Collections.emptyList(); - } - if (values.size() != msgs.size()) { - log.message(Kind.ERROR, element, mirror, Utils.getAnnotationValue(mirror, "value"), String.format("Error count expected %s but was %s.", values.size(), msgs.size())); - } - } - } - } - - private void emitDefault(ProcessorContext context, TypeElement baseType, Log log, Message message) { - Kind kind = message.getKind(); - - Element messageElement = getMessageElement(); - AnnotationMirror messageAnnotation = getMessageAnnotation(); - AnnotationValue messageValue = getMessageAnnotationValue(); - if (message.getAnnotationValue() != null) { - messageValue = message.getAnnotationValue(); - } - - String text = message.getText(); - - TypeElement rootEnclosing = Utils.findRootEnclosingType(getMessageElement()); - TypeElement baseEnclosing = Utils.findRootEnclosingType(baseType); - if (rootEnclosing == null || !Utils.typeEquals(baseEnclosing.asType(), rootEnclosing.asType())) { - // redirect message - MessageContainer original = message.getOriginalContainer(); - messageElement = baseType; - messageAnnotation = null; - messageValue = null; - text = wrapText(original.getMessageElement(), original.getMessageAnnotation(), message.getText()); - } - - TypeElement expectError = context.getTruffleTypes().getExpectError(); - if (expectError != null) { - AnnotationMirror mirror = Utils.findAnnotationMirror(messageElement.getAnnotationMirrors(), expectError); - if (mirror != null) { - List expectedTexts = Utils.getAnnotationValueList(String.class, mirror, "value"); - boolean found = false; - for (String expectedText : expectedTexts) { - if (expectedText.endsWith("%") && text.startsWith(expectedText.substring(0, expectedText.length() - 1))) { - found = true; - break; - } else if (text.equals(expectedText)) { - found = true; - break; - } - } - if (!found) { - log.message(kind, messageElement, mirror, Utils.getAnnotationValue(mirror, "value"), "Message expected one of '%s' but was '%s'.", expectedTexts, text); - } else { - return; - } - - } - } - - log.message(kind, messageElement, messageAnnotation, messageValue, text); - } - - private static String wrapText(Element element, AnnotationMirror mirror, String text) { - StringBuilder b = new StringBuilder(); - if (element != null) { - b.append("Element " + element.toString()); - } - if (mirror != null) { - b.append(" at annotation @" + Utils.getSimpleName(mirror.getAnnotationType())); - } - - if (b.length() > 0) { - b.append(" is erroneous: ").append(text); - return b.toString(); - } else { - return text; - } - } - - public AnnotationMirror getMessageAnnotation() { - return null; - } - - public AnnotationValue getMessageAnnotationValue() { - return null; - } - - public final boolean hasErrors() { - return hasErrorsImpl(new HashSet()); - } - - public final List collectMessages() { - List collectedMessages = new ArrayList<>(); - collectMessagesImpl(collectedMessages, new HashSet()); - return collectedMessages; - } - - private void collectMessagesImpl(List collectedMessages, Set visitedSinks) { - collectedMessages.addAll(getMessages()); - for (MessageContainer sink : findChildContainers()) { - if (visitedSinks.contains(sink)) { - return; - } - - visitedSinks.add(sink); - sink.collectMessagesImpl(collectedMessages, visitedSinks); - } - } - - private boolean hasErrorsImpl(Set visitedSinks) { - for (Message msg : getMessages()) { - if (msg.getKind() == Kind.ERROR) { - return true; - } - } - for (MessageContainer sink : findChildContainers()) { - if (visitedSinks.contains(sink)) { - return false; - } - - visitedSinks.add(sink); - - if (sink.hasErrorsImpl(visitedSinks)) { - return true; - } - } - return false; - } - - public List getMessages() { - return messages; - } - - public static final class Message { - - private final MessageContainer originalContainer; - private final AnnotationValue annotationValue; - private final String text; - private final Kind kind; - - public Message(AnnotationValue annotationValue, MessageContainer originalContainer, String text, Kind kind) { - this.annotationValue = annotationValue; - this.originalContainer = originalContainer; - this.text = text; - this.kind = kind; - } - - public AnnotationValue getAnnotationValue() { - return annotationValue; - } - - public MessageContainer getOriginalContainer() { - return originalContainer; - } - - public String getText() { - return text; - } - - public Kind getKind() { - return kind; - } - - @Override - public String toString() { - return kind + ": " + text; - } - - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MethodSpec.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MethodSpec.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,239 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.template; - -import java.util.*; - -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.*; - -public class MethodSpec { - - private final ParameterSpec returnType; - private final List optional = new ArrayList<>(); - private final List required = new ArrayList<>(); - - private boolean ignoreAdditionalParameters; - private boolean ignoreAdditionalSpecifications; - private boolean variableRequiredParameters; - - private List typeDefinitions; - - public MethodSpec(ParameterSpec returnType) { - this.returnType = returnType; - } - - public void setVariableRequiredParameters(boolean variableRequiredParameters) { - this.variableRequiredParameters = variableRequiredParameters; - } - - public boolean isVariableRequiredParameters() { - return variableRequiredParameters; - } - - public void setIgnoreAdditionalParameters(boolean ignoreAdditionalParameter) { - this.ignoreAdditionalParameters = ignoreAdditionalParameter; - } - - public boolean isIgnoreAdditionalParameters() { - return ignoreAdditionalParameters; - } - - public void addOptional(ParameterSpec spec) { - optional.add(spec); - } - - public ParameterSpec addRequired(ParameterSpec spec) { - required.add(spec); - return spec; - } - - public ParameterSpec getReturnType() { - return returnType; - } - - public List getRequired() { - return required; - } - - public List getOptional() { - return optional; - } - - public List getAll() { - List specs = new ArrayList<>(); - specs.add(getReturnType()); - specs.addAll(getOptional()); - specs.addAll(getRequired()); - return specs; - } - - public ParameterSpec findParameterSpec(String name) { - for (ParameterSpec spec : getAll()) { - if (spec.getName().equals(name)) { - return spec; - } - } - return null; - } - - public void applyTypeDefinitions(String prefix) { - this.typeDefinitions = createTypeDefinitions(prefix); - } - - private List createTypeDefinitions(String prefix) { - List typeDefs = new ArrayList<>(); - - int defIndex = 0; - for (ParameterSpec spec : getAll()) { - List allowedTypes = spec.getAllowedTypes(); - List types = spec.getAllowedTypes(); - if (types != null && allowedTypes.size() > 1) { - TypeDef foundDef = null; - for (TypeDef def : typeDefs) { - if (allowedTypes.equals(def.getTypes())) { - foundDef = def; - break; - } - } - if (foundDef == null) { - foundDef = new TypeDef(types, prefix + defIndex); - typeDefs.add(foundDef); - defIndex++; - } - - spec.setTypeDefinition(foundDef); - } - } - - return typeDefs; - } - - public String toSignatureString(String methodName) { - StringBuilder b = new StringBuilder(); - b.append(" "); - b.append(createTypeSignature(returnType, true)); - - b.append(" "); - b.append(methodName); - b.append("("); - - String sep = ""; - - for (ParameterSpec optionalSpec : getOptional()) { - b.append(sep); - b.append("["); - b.append(createTypeSignature(optionalSpec, false)); - b.append("]"); - sep = ", "; - } - - for (int i = 0; i < getRequired().size(); i++) { - ParameterSpec requiredSpec = getRequired().get(i); - b.append(sep); - - if (isVariableRequiredParameters() && i == getRequired().size() - 1) { - b.append(("{")); - } - b.append(createTypeSignature(requiredSpec, false)); - if (isVariableRequiredParameters() && i == getRequired().size() - 1) { - b.append(("}")); - } - - sep = ", "; - } - - b.append(")"); - - if (typeDefinitions != null && !typeDefinitions.isEmpty()) { - b.append("\n\n"); - - String lineSep = ""; - for (TypeDef def : typeDefinitions) { - b.append(lineSep); - b.append(" <").append(def.getName()).append(">"); - b.append(" = {"); - String separator = ""; - for (TypeMirror type : def.getTypes()) { - b.append(separator).append(Utils.getSimpleName(type)); - separator = ", "; - } - b.append("}"); - lineSep = "\n"; - - } - } - return b.toString(); - } - - private static String createTypeSignature(ParameterSpec spec, boolean typeOnly) { - StringBuilder builder = new StringBuilder(); - TypeDef foundTypeDef = spec.getTypeDefinition(); - if (foundTypeDef != null) { - builder.append("<" + foundTypeDef.getName() + ">"); - } else if (spec.getAllowedTypes().size() >= 1) { - builder.append(Utils.getSimpleName(spec.getAllowedTypes().get(0))); - } else { - builder.append("void"); - } - if (!typeOnly) { - builder.append(" "); - builder.append(spec.getName()); - } - return builder.toString(); - } - - @Override - public String toString() { - return toSignatureString("methodName"); - } - - static class TypeDef { - - private final List types; - private final String name; - - public TypeDef(List types, String name) { - this.types = types; - this.name = name; - } - - public List getTypes() { - return types; - } - - public String getName() { - return name; - } - } - - public void setIgnoreAdditionalSpecifications(boolean ignoreAdditoinalSpecifications) { - this.ignoreAdditionalSpecifications = ignoreAdditoinalSpecifications; - } - - public boolean isIgnoreAdditionalSpecifications() { - return ignoreAdditionalSpecifications; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ParameterSpec.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ParameterSpec.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.template; - -import java.util.*; - -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.node.*; -import com.oracle.truffle.dsl.processor.template.MethodSpec.TypeDef; - -public class ParameterSpec { - - private final String name; - private final List allowedTypes; - - /** Type is bound to local final variable. */ - private boolean local; - private boolean signature; - - /** Optional bound execution of node. */ - private NodeExecutionData execution; - private TypeDef typeDefinition; - - public ParameterSpec(String name, List allowedTypes) { - this.name = name; - this.allowedTypes = allowedTypes; - } - - public ParameterSpec(String name, TypeMirror type) { - this(name, Arrays.asList(type)); - } - - public ParameterSpec(ParameterSpec o, List allowedTypes) { - this.name = o.name; - this.local = o.local; - this.typeDefinition = o.typeDefinition; - this.execution = o.execution; - this.signature = o.signature; - this.allowedTypes = allowedTypes; - } - - public NodeExecutionData getExecution() { - return execution; - } - - public void setExecution(NodeExecutionData executionData) { - this.execution = executionData; - this.signature = execution != null; - } - - public void setSignature(boolean signature) { - this.signature = signature; - } - - void setTypeDefinition(TypeDef typeDefinition) { - this.typeDefinition = typeDefinition; - } - - TypeDef getTypeDefinition() { - return typeDefinition; - } - - public void setLocal(boolean local) { - this.local = local; - } - - public boolean isSignature() { - return signature; - } - - public boolean isLocal() { - return local; - } - - public String getName() { - return name; - } - - public List getAllowedTypes() { - return allowedTypes; - } - - public boolean matches(TypeMirror actualType) { - for (TypeMirror mirror : allowedTypes) { - if (Utils.typeEquals(actualType, mirror)) { - return true; - } - } - return false; - } - - @Override - public String toString() { - return toSignatureString(false); - } - - public String toSignatureString(boolean typeOnly) { - StringBuilder builder = new StringBuilder(); - if (typeDefinition != null) { - builder.append("<" + typeDefinition.getName() + ">"); - } else if (getAllowedTypes().size() >= 1) { - builder.append(Utils.getSimpleName(getAllowedTypes().get(0))); - } else { - builder.append("void"); - } - if (!typeOnly) { - builder.append(" "); - builder.append(getName()); - } - return builder.toString(); - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/Template.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/Template.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.template; - -import java.util.*; - -import javax.lang.model.element.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.typesystem.*; - -public abstract class Template extends MessageContainer { - - private final TypeElement templateType; - private final String templateMethodName; - private final AnnotationMirror annotation; - - public Template(TypeElement templateType, String templateMethodName, AnnotationMirror annotation) { - this.templateType = templateType; - this.templateMethodName = templateMethodName; - this.annotation = annotation; - } - - public abstract TypeSystemData getTypeSystem(); - - @Override - public Element getMessageElement() { - return templateType; - } - - @Override - protected List findChildContainers() { - return Collections.emptyList(); - } - - public String getTemplateMethodName() { - return templateMethodName; - } - - public TypeElement getTemplateType() { - return templateType; - } - - public AnnotationMirror getTemplateTypeAnnotation() { - return annotation; - } - - @Override - public String toString() { - return getClass().getSimpleName() + "[" + Utils.getSimpleName(getTemplateType()) + "]"; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,489 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.template; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.typesystem.*; -import com.oracle.truffle.dsl.processor.util.*; - -/** - * Note: this class has a natural ordering that is inconsistent with equals. - */ -public class TemplateMethod extends MessageContainer implements Comparable { - - private String id; - private final Template template; - private final MethodSpec specification; - private final ExecutableElement method; - private final AnnotationMirror markerAnnotation; - private ActualParameter returnType; - private List parameters; - - public TemplateMethod(String id, Template template, MethodSpec specification, ExecutableElement method, AnnotationMirror markerAnnotation, ActualParameter returnType, - List parameters) { - this.template = template; - this.specification = specification; - this.method = method; - this.markerAnnotation = markerAnnotation; - this.returnType = returnType; - this.parameters = new ArrayList<>(); - for (ActualParameter param : parameters) { - ActualParameter newParam = new ActualParameter(param); - this.parameters.add(newParam); - newParam.setMethod(this); - } - this.id = id; - } - - public TemplateMethod(TemplateMethod method) { - this(method.id, method.template, method.specification, method.method, method.markerAnnotation, method.returnType, method.parameters); - getMessages().addAll(method.getMessages()); - } - - public TemplateMethod(TemplateMethod method, ExecutableElement executable) { - this(method.id, method.template, method.specification, executable, method.markerAnnotation, method.returnType, method.parameters); - getMessages().addAll(method.getMessages()); - } - - public void setParameters(List parameters) { - this.parameters = parameters; - } - - @Override - public Element getMessageElement() { - return method; - } - - @Override - public AnnotationMirror getMessageAnnotation() { - return markerAnnotation; - } - - @Override - protected List findChildContainers() { - return Collections.emptyList(); - } - - public void setId(String id) { - this.id = id; - } - - public String getId() { - return id; - } - - public Template getTemplate() { - return template; - } - - public MethodSpec getSpecification() { - return specification; - } - - public ActualParameter getReturnType() { - return returnType; - } - - public void replaceParameter(String localName, ActualParameter newParameter) { - if (returnType.getLocalName().equals(localName)) { - returnType = newParameter; - returnType.setMethod(this); - } - - for (ListIterator iterator = parameters.listIterator(); iterator.hasNext();) { - ActualParameter parameter = iterator.next(); - if (parameter.getLocalName().equals(localName)) { - iterator.set(newParameter); - newParameter.setMethod(this); - } - } - } - - public List getRequiredParameters() { - List requiredParameters = new ArrayList<>(); - for (ActualParameter parameter : getParameters()) { - if (getSpecification().getRequired().contains(parameter.getSpecification())) { - requiredParameters.add(parameter); - } - } - return requiredParameters; - } - - public Iterable getSignatureParameters() { - return new FilteredIterable<>(getParameters(), new Predicate() { - public boolean evaluate(ActualParameter value) { - return value.getSpecification().isSignature(); - } - }); - } - - public List getParameters() { - return parameters; - } - - public List findParameters(ParameterSpec spec) { - List foundParameters = new ArrayList<>(); - for (ActualParameter param : getReturnTypeAndParameters()) { - if (param.getSpecification().getName().equals(spec.getName())) { - foundParameters.add(param); - } - } - return foundParameters; - } - - public ActualParameter findParameter(String valueName) { - for (ActualParameter param : getReturnTypeAndParameters()) { - if (param.getLocalName().equals(valueName)) { - return param; - } - } - return null; - } - - public List getReturnTypeAndParameters() { - List allParameters = new ArrayList<>(getParameters().size() + 1); - if (getReturnType() != null) { - allParameters.add(getReturnType()); - } - allParameters.addAll(getParameters()); - return Collections.unmodifiableList(allParameters); - } - - public boolean canBeAccessedByInstanceOf(ProcessorContext context, TypeMirror type) { - TypeMirror methodType = Utils.findNearestEnclosingType(getMethod()).asType(); - return Utils.isAssignable(context, type, methodType) || Utils.isAssignable(context, methodType, type); - } - - public ExecutableElement getMethod() { - return method; - } - - public String getMethodName() { - if (getMethod() != null) { - return getMethod().getSimpleName().toString(); - } else { - return "$synthetic"; - } - } - - public AnnotationMirror getMarkerAnnotation() { - return markerAnnotation; - } - - @Override - public String toString() { - return String.format("%s [id = %s, method = %s]", getClass().getSimpleName(), getId(), getMethod()); - } - - public ActualParameter getPreviousParam(ActualParameter searchParam) { - ActualParameter prev = null; - for (ActualParameter param : getParameters()) { - if (param == searchParam) { - return prev; - } - prev = param; - } - return prev; - } - - @SuppressWarnings("unused") - public int getSignatureSize() { - int signatureSize = 0; - for (ActualParameter parameter : getSignatureParameters()) { - signatureSize++; - } - return signatureSize; - } - - public TypeSignature getTypeSignature() { - TypeSignature signature = new TypeSignature(); - signature.types.add(getReturnType().getTypeSystemType()); - for (ActualParameter parameter : getSignatureParameters()) { - TypeData typeData = parameter.getTypeSystemType(); - if (typeData != null) { - signature.types.add(typeData); - } - } - return signature; - } - - public ActualParameter getSignatureParameter(int searchIndex) { - int index = 0; - for (ActualParameter parameter : getParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } - if (index == searchIndex) { - return parameter; - } - index++; - } - return null; - } - - public void updateSignature(TypeSignature signature) { - // TODO(CH): fails in normal usage - output ok though - // assert signature.size() >= 1; - - int signatureIndex = 0; - for (ActualParameter parameter : getReturnTypeAndParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } - if (signatureIndex >= signature.size()) { - break; - } - TypeData newType = signature.get(signatureIndex++); - if (!parameter.getTypeSystemType().equals(newType)) { - replaceParameter(parameter.getLocalName(), new ActualParameter(parameter, newType)); - } - } - } - - @Override - public int compareTo(TemplateMethod o) { - if (this == o) { - return 0; - } - - int compare = compareBySignature(o); - if (compare == 0) { - // if signature sorting failed sort by id - compare = getId().compareTo(o.getId()); - } - if (compare == 0) { - // if still no difference sort by enclosing type name - TypeElement enclosingType1 = Utils.findNearestEnclosingType(getMethod()); - TypeElement enclosingType2 = Utils.findNearestEnclosingType(o.getMethod()); - compare = enclosingType1.getQualifiedName().toString().compareTo(enclosingType2.getQualifiedName().toString()); - } - return compare; - } - - public List getParametersAfter(ActualParameter genericParameter) { - boolean found = false; - List foundParameters = new ArrayList<>(); - for (ActualParameter param : getParameters()) { - if (param.getLocalName().equals(genericParameter.getLocalName())) { - found = true; - } else if (found) { - foundParameters.add(param); - } - } - return foundParameters; - } - - public int compareBySignature(TemplateMethod compareMethod) { - final TypeSystemData typeSystem = getTemplate().getTypeSystem(); - if (typeSystem != compareMethod.getTemplate().getTypeSystem()) { - throw new IllegalStateException("Cannot compare two methods with different type systems."); - } - - List signature1 = getSignatureTypes(this); - List signature2 = getSignatureTypes(compareMethod); - if (signature1.size() != signature2.size()) { - return signature2.size() - signature1.size(); - } - - int result = 0; - for (int i = 1; i < signature1.size(); i++) { - TypeMirror t1 = signature1.get(i); - TypeMirror t2 = signature2.get(i); - - int typeResult = compareParameter(typeSystem, t1, t2); - if (result == 0) { - result = typeResult; - } else if (typeResult != 0 && Math.signum(result) != Math.signum(typeResult)) { - // We cannot define an order. - return 0; - } - } - if (result == 0 && signature1.size() > 0) { - result = compareParameter(typeSystem, signature1.get(0), signature2.get(0)); - } - - return result; - } - - private static int compareParameter(TypeSystemData data, TypeMirror signature1, TypeMirror signature2) { - if (Utils.typeEquals(signature1, signature2)) { - return 0; - } - - int index1 = data.findType(signature1); - int index2 = data.findType(signature2); - if (index1 != -1 && index2 != -1) { - return index1 - index2; - } - - if (signature1.getKind() == TypeKind.DECLARED && signature2.getKind() == TypeKind.DECLARED) { - TypeElement element1 = Utils.fromTypeMirror(signature1); - TypeElement element2 = Utils.fromTypeMirror(signature2); - - if (Utils.getDirectSuperTypes(element1).contains(element2)) { - return -1; - } else if (Utils.getDirectSuperTypes(element2).contains(element1)) { - return 1; - } - } - return Utils.getSimpleName(signature1).compareTo(Utils.getSimpleName(signature2)); - } - - public static List getSignatureTypes(TemplateMethod method) { - List types = new ArrayList<>(); - types.add(method.getReturnType().getType()); - for (ActualParameter param : method.getSignatureParameters()) { - types.add(param.getType()); - } - return types; - } - - public static class TypeSignature implements Iterable, Comparable { - - final List types; - - public TypeSignature() { - this.types = new ArrayList<>(); - } - - public TypeSignature(List signature) { - this.types = signature; - } - - @Override - public int hashCode() { - return types.hashCode(); - } - - public int size() { - return types.size(); - } - - public TypeData get(int index) { - return types.get(index); - } - - public int compareTo(TypeSignature other) { - if (this == other) { - return 0; - } else if (types.size() != other.types.size()) { - return types.size() - other.types.size(); - } else if (types.isEmpty()) { - return 0; - } - - for (int i = 0; i < types.size(); i++) { - TypeData type1 = types.get(i); - TypeData type2 = other.types.get(i); - - int comparison = type1.compareTo(type2); - if (comparison != 0) { - return comparison; - } - } - - return 0; - } - - public TypeSignature combine(TypeSignature genericSignature, TypeSignature other) { - assert types.size() == other.types.size(); - assert genericSignature.types.size() == other.types.size(); - - if (this.equals(other)) { - return this; - } - - TypeSignature signature = new TypeSignature(); - for (int i = 0; i < types.size(); i++) { - TypeData type1 = types.get(i); - TypeData type2 = other.types.get(i); - if (type1.equals(type2)) { - signature.types.add(type1); - } else { - signature.types.add(genericSignature.types.get(i)); - } - } - return signature; - } - - public boolean equalsParameters(TypeSignature other) { - if (size() != other.size()) { - return false; - } - return types.subList(1, types.size()).equals(other.types.subList(1, other.types.size())); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof TypeSignature) { - return ((TypeSignature) obj).types.equals(types); - } - return super.equals(obj); - } - - public Iterator iterator() { - return types.iterator(); - } - - @Override - public String toString() { - return types.toString(); - } - - public boolean hasAnyParameterMatch(TypeSignature other) { - for (int i = 1; i < types.size(); i++) { - TypeData type1 = types.get(i); - TypeData type2 = other.types.get(i); - if (type1.equals(type2)) { - return true; - } - } - return false; - } - - public boolean isCompatibleTo(TypeSignature signature) { - if (size() != signature.size()) { - return false; - } - - for (int i = 0; i < size(); i++) { - TypeData o1 = get(i); - TypeData o2 = signature.get(i); - if (o1.equals(o2)) { - continue; - } else if (o2.isGeneric()) { - continue; - } else { - return false; - } - } - return true; - } - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,355 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.template; - -import static com.oracle.truffle.dsl.processor.Utils.*; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.typesystem.*; - -public abstract class TemplateMethodParser { - - private final ProcessorContext context; - - protected final T template; - - private boolean emitErrors = true; - private boolean parseNullOnError = false; - private boolean useVarArgs = false; - - public TemplateMethodParser(ProcessorContext context, T template) { - this.template = template; - this.context = context; - } - - protected void setUseVarArgs(boolean useVarArgs) { - this.useVarArgs = useVarArgs; - } - - public boolean isUseVarArgs() { - return useVarArgs; - } - - public boolean isEmitErrors() { - return emitErrors; - } - - public void setParseNullOnError(boolean nullOnError) { - this.parseNullOnError = nullOnError; - } - - public boolean isParseNullOnError() { - return parseNullOnError; - } - - public void setEmitErrors(boolean emitErrors) { - this.emitErrors = emitErrors; - } - - public ProcessorContext getContext() { - return context; - } - - public TypeSystemData getTypeSystem() { - return template.getTypeSystem(); - } - - public abstract MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror); - - public abstract E create(TemplateMethod method, boolean invalid); - - public abstract boolean isParsable(ExecutableElement method); - - public Class getAnnotationType() { - return null; - } - - public final List parse(List elements) { - List methods = new ArrayList<>(); - methods.addAll(ElementFilter.methodsIn(elements)); - - List parsedMethods = new ArrayList<>(); - boolean valid = true; - for (ExecutableElement method : methods) { - if (!isParsable(method)) { - continue; - } - - Class annotationType = getAnnotationType(); - AnnotationMirror mirror = null; - if (annotationType != null) { - mirror = Utils.findAnnotationMirror(getContext().getEnvironment(), method, annotationType); - } - - E parsedMethod = parse(method, mirror); - - if (method.getModifiers().contains(Modifier.PRIVATE) && emitErrors) { - parsedMethod.addError("Method annotated with @%s must not be private.", getAnnotationType().getSimpleName()); - parsedMethods.add(parsedMethod); - valid = false; - continue; - } - - if (parsedMethod != null) { - parsedMethods.add(parsedMethod); - } else { - valid = false; - } - } - Collections.sort(parsedMethods); - - if (!valid && parseNullOnError) { - return null; - } - return parsedMethods; - } - - private E parse(ExecutableElement method, AnnotationMirror annotation) { - MethodSpec methodSpecification = createSpecification(method, annotation); - if (methodSpecification == null) { - return null; - } - - methodSpecification.applyTypeDefinitions("types"); - - String id = method.getSimpleName().toString(); - TypeMirror returnType = method.getReturnType(); - List parameterTypes = new ArrayList<>(); - for (VariableElement var : method.getParameters()) { - parameterTypes.add(var.asType()); - } - - return parseImpl(methodSpecification, id, method, annotation, returnType, parameterTypes); - } - - private E parseImpl(MethodSpec methodSpecification, String id, ExecutableElement method, AnnotationMirror annotation, TypeMirror returnType, List parameterTypes) { - ParameterSpec returnTypeSpec = methodSpecification.getReturnType(); - ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, returnType, template, -1, -1); - if (returnTypeMirror == null) { - if (emitErrors) { - E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList()), true); - String expectedReturnType = returnTypeSpec.toSignatureString(true); - String actualReturnType = Utils.getSimpleName(returnType); - - String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType, - methodSpecification.toSignatureString(method.getSimpleName().toString())); - invalidMethod.addError(message); - return invalidMethod; - } else { - return null; - } - } - - List parameters = parseParameters(methodSpecification, parameterTypes, isUseVarArgs() && method != null ? method.isVarArgs() : false); - if (parameters == null) { - if (isEmitErrors() && method != null) { - E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList()), true); - String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(method), - methodSpecification.toSignatureString(method.getSimpleName().toString())); - invalidMethod.addError(message); - return invalidMethod; - } else { - return null; - } - } - - return create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, parameters), false); - } - - private static String createActualSignature(ExecutableElement method) { - StringBuilder b = new StringBuilder("("); - String sep = ""; - if (method != null) { - for (VariableElement var : method.getParameters()) { - b.append(sep); - b.append(Utils.getSimpleName(var.asType())); - sep = ", "; - } - } - b.append(")"); - return b.toString(); - } - - /* - * Parameter parsing tries to parse required arguments starting from offset 0 with increasing - * offset until it finds a signature end that matches the required specification. If there is no - * end matching the required arguments, parsing fails. Parameters prior to the parsed required - * ones are cut and used to parse the optional parameters. - */ - private List parseParameters(MethodSpec spec, List parameterTypes, boolean varArgs) { - List parsedRequired = null; - int offset = 0; - for (; offset <= parameterTypes.size(); offset++) { - List parameters = new ArrayList<>(); - parameters.addAll(parameterTypes.subList(offset, parameterTypes.size())); - parsedRequired = parseParametersRequired(spec, parameters, varArgs); - if (parsedRequired != null) { - break; - } - } - - if (parsedRequired == null) { - return null; - } - - if (parsedRequired.isEmpty() && offset == 0) { - offset = parameterTypes.size(); - } - List potentialOptionals = parameterTypes.subList(0, offset); - List parsedOptionals = parseParametersOptional(spec, potentialOptionals); - if (parsedOptionals == null) { - return null; - } - - List finalParameters = new ArrayList<>(); - finalParameters.addAll(parsedOptionals); - finalParameters.addAll(parsedRequired); - return finalParameters; - } - - private List parseParametersOptional(MethodSpec spec, List types) { - List parsedParams = new ArrayList<>(); - - int typeStartIndex = 0; - List specifications = spec.getOptional(); - outer: for (int specIndex = 0; specIndex < specifications.size(); specIndex++) { - ParameterSpec specification = specifications.get(specIndex); - for (int typeIndex = typeStartIndex; typeIndex < types.size(); typeIndex++) { - TypeMirror actualType = types.get(typeIndex); - ActualParameter optionalParam = matchParameter(specification, actualType, template, -1, -1); - if (optionalParam != null) { - parsedParams.add(optionalParam); - typeStartIndex = typeIndex + 1; - continue outer; - } - } - } - - if (typeStartIndex < types.size()) { - // not enough types found - return null; - } - return parsedParams; - } - - private List parseParametersRequired(MethodSpec spec, List types, boolean typeVarArgs) { - List parsedParams = new ArrayList<>(); - List specifications = spec.getRequired(); - boolean specVarArgs = spec.isVariableRequiredParameters(); - int typeIndex = 0; - int specificationIndex = 0; - - ParameterSpec specification; - while ((specification = nextSpecification(specifications, specificationIndex, specVarArgs)) != null) { - TypeMirror actualType = nextActualType(types, typeIndex, typeVarArgs); - if (actualType == null) { - if (spec.isIgnoreAdditionalSpecifications()) { - break; - } - return null; - } - - int typeVarArgsIndex = typeVarArgs ? typeIndex - types.size() + 1 : -1; - int specVarArgsIndex = specVarArgs ? specificationIndex - specifications.size() + 1 : -1; - - if (typeVarArgsIndex >= 0 && specVarArgsIndex >= 0) { - // both specifications and types have a variable number of arguments - // we would get into an endless loop if we would continue - break; - } - - ActualParameter resolvedParameter = matchParameter(specification, actualType, template, specVarArgsIndex, typeVarArgsIndex); - if (resolvedParameter == null) { - return null; - } - parsedParams.add(resolvedParameter); - typeIndex++; - specificationIndex++; - } - - if (typeIndex < types.size()) { - // additional types available - if (spec.isIgnoreAdditionalParameters()) { - return parsedParams; - } else { - return null; - } - } - - return parsedParams; - } - - private static ParameterSpec nextSpecification(List specifications, int specIndex, boolean varArgs) { - if (varArgs && specIndex >= specifications.size() - 1 && !specifications.isEmpty()) { - return specifications.get(specifications.size() - 1); - } else if (specIndex < specifications.size()) { - return specifications.get(specIndex); - } else { - return null; - } - } - - private static TypeMirror nextActualType(List types, int typeIndex, boolean varArgs) { - if (varArgs && typeIndex >= types.size() - 1 && !types.isEmpty()) { - // unpack varargs array argument - TypeMirror actualType = types.get(types.size() - 1); - if (actualType.getKind() == TypeKind.ARRAY) { - actualType = ((ArrayType) actualType).getComponentType(); - } - return actualType; - } else if (typeIndex < types.size()) { - return types.get(typeIndex); - } else { - return null; - } - } - - protected final ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template originalTemplate, int specificationIndex, int varArgsIndex) { - TypeMirror resolvedType = mirror; - if (hasError(resolvedType)) { - resolvedType = context.resolveNotYetCompiledType(mirror, originalTemplate); - } - - if (!specification.matches(resolvedType)) { - return null; - } - - TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType); - if (resolvedTypeData != null) { - return new ActualParameter(specification, resolvedTypeData, specificationIndex, varArgsIndex); - } else { - return new ActualParameter(specification, resolvedType, specificationIndex, varArgsIndex); - } - } - - public final E create(String id, ExecutableElement methodMetadata, AnnotationMirror mirror, TypeMirror returnType, List parameterTypes) { - return parseImpl(createSpecification(methodMetadata, mirror), id, methodMetadata, mirror, returnType, parameterTypes); - } -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardData.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.typesystem; - -import com.oracle.truffle.dsl.processor.node.*; -import com.oracle.truffle.dsl.processor.template.*; - -public class GuardData extends TemplateMethod { - - private final SpecializationData specialization; - private final boolean negated; - - public GuardData(TemplateMethod method, SpecializationData specialization, boolean negated) { - super(method); - this.negated = negated; - this.specialization = specialization; - } - - public boolean isNegated() { - return negated; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof GuardData) { - GuardData other = (GuardData) obj; - return getMethod().equals(other.getMethod()) && negated == other.negated; - } - return false; - } - - @Override - public int hashCode() { - return getMethod().hashCode(); - } - - public SpecializationData getSpecialization() { - return specialization; - } - - @Override - public String toString() { - return (negated ? "!" : "") + getMethodName() + getParameters().toString(); - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.typesystem; - -import java.lang.annotation.*; - -import javax.lang.model.element.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.node.*; -import com.oracle.truffle.dsl.processor.template.*; - -public class GuardParser extends NodeMethodParser { - - private final SpecializationData specialization; - private final String guardName; - private final boolean negated; - - public GuardParser(ProcessorContext context, SpecializationData specialization, String guardDefinition) { - super(context, specialization.getNode()); - this.specialization = specialization; - if (guardDefinition.startsWith("!")) { - this.guardName = guardDefinition.substring(1, guardDefinition.length()); - this.negated = true; - } else { - this.guardName = guardDefinition; - this.negated = false; - } - setEmitErrors(false); - setParseNullOnError(false); - } - - @Override - protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) { - return super.createValueParameterSpec(execution); - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - MethodSpec spec = createDefaultMethodSpec(method, mirror, true, null); - spec.setIgnoreAdditionalSpecifications(true); - spec.getRequired().clear(); - - for (ActualParameter parameter : specialization.getRequiredParameters()) { - spec.addRequired(new ParameterSpec(parameter.getSpecification(), Utils.getAssignableTypes(getContext(), parameter.getType()))); - } - - return spec; - } - - @Override - protected ParameterSpec createReturnParameterSpec() { - return new ParameterSpec("returnType", getContext().getType(boolean.class)); - } - - @Override - public boolean isParsable(ExecutableElement method) { - return method.getSimpleName().toString().equals(guardName); - } - - @Override - public GuardData create(TemplateMethod method, boolean invalid) { - return new GuardData(method, specialization, negated); - } - - @Override - public Class getAnnotationType() { - return null; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastData.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.typesystem; - -import com.oracle.truffle.dsl.processor.template.*; - -public class ImplicitCastData extends TemplateMethod { - - private final TypeData sourceType; - private final TypeData targetType; - - public ImplicitCastData(TemplateMethod method, TypeData sourceType, TypeData targetType) { - super(method); - this.sourceType = sourceType; - this.targetType = targetType; - } - - public TypeData getSourceType() { - return sourceType; - } - - public TypeData getTargetType() { - return targetType; - } - - @Override - public int compareTo(TemplateMethod o) { - if (o instanceof ImplicitCastData && sourceType != null) { - // implicit casts are ordered by source type since - // its also the order in which they are checked. - TypeData otherSourceType = ((ImplicitCastData) o).getSourceType(); - if (otherSourceType != null) { - return this.sourceType.compareTo(otherSourceType); - } - } - return super.compareTo(o); - } -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastParser.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.typesystem; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.template.*; - -public class ImplicitCastParser extends TypeSystemMethodParser { - - public ImplicitCastParser(ProcessorContext context, TypeSystemData typeSystem) { - super(context, typeSystem); - } - - @Override - public Class getAnnotationType() { - return ImplicitCast.class; - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - List types = new ArrayList<>(); - for (TypeData typeData : getTypeSystem().getTypes()) { - types.add(typeData.getPrimitiveType()); - } - MethodSpec spec = new MethodSpec(new ParameterSpec("target", types)); - spec.addRequired(new ParameterSpec("source", types)); - return spec; - } - - @Override - public ImplicitCastData create(TemplateMethod method, boolean invalid) { - if (invalid) { - return new ImplicitCastData(method, null, null); - } - - ActualParameter target = method.findParameter("targetValue"); - ActualParameter source = method.findParameter("sourceValue"); - - TypeData targetType = target.getTypeSystemType(); - TypeData sourceType = source.getTypeSystemType(); - - if (targetType.equals(sourceType)) { - method.addError("Target type and source type of an @%s must not be the same type.", ImplicitCast.class.getSimpleName()); - } - - return new ImplicitCastData(method, sourceType, targetType); - } -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastData.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.typesystem; - -import com.oracle.truffle.dsl.processor.template.*; - -public class TypeCastData extends TemplateMethod { - - private final TypeData targetType; - private final TypeData sourceType; - - public TypeCastData(TemplateMethod method, TypeData sourceType, TypeData targetType) { - super(method); - this.sourceType = sourceType; - this.targetType = targetType; - } - - public boolean isGeneric() { - return sourceType.isGeneric(); - } - - public TypeData getSourceType() { - return sourceType; - } - - public TypeData getTargetType() { - return targetType; - } -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastParser.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.typesystem; - -import java.lang.annotation.*; - -import javax.lang.model.element.*; - -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.template.*; - -class TypeCastParser extends TypeSystemMethodParser { - - public TypeCastParser(ProcessorContext context, TypeSystemData typeSystem) { - super(context, typeSystem); - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "as"); - if (targetType == null) { - return null; - } - MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", targetType.getPrimitiveType())); - spec.addRequired(new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors())); - return spec; - } - - @Override - public TypeCastData create(TemplateMethod method, boolean invalid) { - if (invalid) { - return new TypeCastData(method, null, null); - } - - TypeData targetType = findTypeByMethodName(method, "as"); - ActualParameter parameter = method.findParameter("valueValue"); - - TypeData sourceType = null; - if (parameter != null) { - sourceType = getTypeSystem().findTypeData(parameter.getType()); - } - TypeCastData cast = new TypeCastData(method, sourceType, targetType); - - if (targetType != method.getReturnType().getTypeSystemType()) { - cast.addError("Cast type %s does not match to the returned type %s.", Utils.getSimpleName(targetType.getPrimitiveType()), - method.getReturnType() != null ? Utils.getSimpleName(method.getReturnType().getTypeSystemType().getPrimitiveType()) : null); - } - return cast; - } - - @Override - public Class getAnnotationType() { - return TypeCast.class; - } -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckData.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.typesystem; - -import com.oracle.truffle.dsl.processor.template.*; - -public class TypeCheckData extends TemplateMethod { - - private final TypeData checkedType; - private final TypeData valueType; - - public TypeCheckData(TemplateMethod method, TypeData checkedType, TypeData valueType) { - super(method); - this.checkedType = checkedType; - this.valueType = valueType; - } - - public boolean isGeneric() { - return valueType.isGeneric(); - } - - public TypeData getCheckedType() { - return checkedType; - } - - public TypeData getValueType() { - return valueType; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckParser.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.typesystem; - -import java.lang.annotation.*; - -import javax.lang.model.element.*; - -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.template.*; - -class TypeCheckParser extends TypeSystemMethodParser { - - public TypeCheckParser(ProcessorContext context, TypeSystemData typeSystem) { - super(context, typeSystem); - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "is"); - if (targetType == null) { - return null; - } - MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", getContext().getType(boolean.class))); - spec.addRequired(new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors())); - return spec; - } - - @Override - public TypeCheckData create(TemplateMethod method, boolean invalid) { - TypeData checkedType = findTypeByMethodName(method, "is"); - assert checkedType != null; - ActualParameter parameter = method.findParameter("valueValue"); - assert parameter != null; - return new TypeCheckData(method, checkedType, parameter.getTypeSystemType()); - } - - @Override - public Class getAnnotationType() { - return TypeCheck.class; - } -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeData.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.typesystem; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.template.*; - -public class TypeData extends MessageContainer implements Comparable { - - private final TypeSystemData typeSystem; - private final AnnotationValue annotationValue; - private final TypeMirror primitiveType; - private final TypeMirror boxedType; - - private final int index; - private final List typeCasts = new ArrayList<>(); - private final List typeChecks = new ArrayList<>(); - - public TypeData(TypeSystemData typeSystem, int index, AnnotationValue value, TypeMirror primitiveType, TypeMirror boxedType) { - this.index = index; - this.typeSystem = typeSystem; - this.annotationValue = value; - this.primitiveType = primitiveType; - this.boxedType = boxedType; - } - - @Override - public Element getMessageElement() { - return typeSystem.getMessageElement(); - } - - @Override - public AnnotationMirror getMessageAnnotation() { - return typeSystem.getMessageAnnotation(); - } - - @Override - public AnnotationValue getMessageAnnotationValue() { - return annotationValue; - } - - void addTypeCast(TypeCastData typeCast) { - this.typeCasts.add(typeCast); - } - - void addTypeCheck(TypeCheckData typeCheck) { - this.typeChecks.add(typeCheck); - } - - public List getTypeCasts() { - return typeCasts; - } - - public List getTypeChecks() { - return typeChecks; - } - - public TypeSystemData getTypeSystem() { - return typeSystem; - } - - public TypeMirror getPrimitiveType() { - return primitiveType; - } - - public TypeMirror getBoxedType() { - return boxedType; - } - - public boolean isGeneric() { - return Utils.typeEquals(boxedType, getTypeSystem().getGenericType()); - } - - public boolean isVoid() { - if (getTypeSystem().getVoidType() == null) { - return false; - } - return Utils.typeEquals(boxedType, getTypeSystem().getVoidType().getBoxedType()); - } - - public int compareTo(TypeData o) { - if (this.equals(o)) { - return 0; - } - return index - o.index; - } - - @Override - public String toString() { - return getClass().getSimpleName() + "[" + Utils.getSimpleName(primitiveType) + "]"; - } - - public boolean equalsType(TypeData actualTypeData) { - return Utils.typeEquals(boxedType, actualTypeData.boxedType); - } - - public boolean needsCastTo(ProcessorContext context, TypeData targetType) { - return Utils.needsCastTo(context, getPrimitiveType(), targetType.getPrimitiveType()); - } - - public boolean isPrimitive() { - return Utils.isPrimitive(getPrimitiveType()); - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemCodeGenerator.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemCodeGenerator.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,308 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.typesystem; - -import static com.oracle.truffle.dsl.processor.Utils.*; -import static javax.lang.model.element.Modifier.*; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.ast.*; -import com.oracle.truffle.dsl.processor.template.*; - -public class TypeSystemCodeGenerator extends CompilationUnitFactory { - - public TypeSystemCodeGenerator(ProcessorContext context) { - super(context); - } - - public static String isTypeMethodName(TypeData type) { - return "is" + Utils.getTypeId(type.getBoxedType()); - } - - public static String isImplicitTypeMethodName(TypeData type) { - return "isImplicit" + Utils.getTypeId(type.getBoxedType()); - } - - public static String asTypeMethodName(TypeData type) { - return "as" + Utils.getTypeId(type.getBoxedType()); - } - - public static String asImplicitTypeMethodName(TypeData type) { - return "asImplicit" + Utils.getTypeId(type.getBoxedType()); - } - - public static String getImplicitClass(TypeData type) { - return "getImplicit" + Utils.getTypeId(type.getBoxedType()) + "Class"; - } - - public static String expectTypeMethodName(TypeData type) { - return "expect" + Utils.getTypeId(type.getBoxedType()); - } - - /** - * Finds the generated singleton field for a TypeSytemData instance. TypeSystemCodeGenerator - * must be applied to the TypeSystemData model before use. - */ - public static VariableElement findSingleton(ProcessorContext context, TypeSystemData typeSystem) { - TypeMirror type = context.findGeneratedClassBySimpleName(TypeClassFactory.typeName(typeSystem), typeSystem); - return Utils.findDeclaredField(type, TypeClassFactory.singletonName(typeSystem.getTemplateType().asType())); - } - - @Override - protected void createChildren(TypeSystemData m) { - add(new TypeClassFactory(context), m); - } - - protected static class TypeClassFactory extends ClassElementFactory { - - private static final String LOCAL_VALUE = "value"; - - public TypeClassFactory(ProcessorContext context) { - super(context); - } - - @Override - public CodeTypeElement create(TypeSystemData typeSystem) { - String name = typeName(typeSystem); - CodeTypeElement clazz = createClass(typeSystem, modifiers(PUBLIC, FINAL), name, typeSystem.getTemplateType().asType(), false); - - clazz.add(createConstructorUsingFields(modifiers(PROTECTED), clazz)); - CodeVariableElement singleton = createSingleton(clazz); - clazz.add(singleton); - - for (TypeData type : typeSystem.getTypes()) { - if (!type.isGeneric()) { - clazz.addOptional(createIsTypeMethod(type)); - clazz.addOptional(createAsTypeMethod(type)); - - for (TypeData sourceType : collectExpectSourceTypes(type)) { - clazz.addOptional(createExpectTypeMethod(type, sourceType)); - } - - clazz.addOptional(createAsImplicitTypeMethod(type, true)); - clazz.addOptional(createAsImplicitTypeMethod(type, false)); - clazz.addOptional(createIsImplicitTypeMethod(type, true)); - clazz.addOptional(createIsImplicitTypeMethod(type, false)); - clazz.addOptional(createGetTypeIndex(type)); - } - } - - return clazz; - } - - private static List collectExpectSourceTypes(TypeData type) { - Set sourceTypes = new HashSet<>(); - sourceTypes.add(type.getTypeSystem().getGenericTypeData()); - for (TypeCastData cast : type.getTypeCasts()) { - sourceTypes.add(cast.getSourceType()); - } - for (TypeCheckData cast : type.getTypeChecks()) { - sourceTypes.add(cast.getCheckedType()); - } - return new ArrayList<>(sourceTypes); - } - - private static String typeName(TypeSystemData typeSystem) { - String name = getSimpleName(typeSystem.getTemplateType()); - return name + "Gen"; - } - - private static String singletonName(TypeMirror type) { - return createConstantName(getSimpleName(type)); - } - - private CodeVariableElement createSingleton(CodeTypeElement clazz) { - CodeVariableElement field = new CodeVariableElement(modifiers(PUBLIC, STATIC, FINAL), clazz.asType(), singletonName(getModel().getTemplateType().asType())); - field.createInitBuilder().startNew(clazz.asType()).end(); - return field; - } - - private CodeExecutableElement createIsImplicitTypeMethod(TypeData type, boolean typed) { - TypeSystemData typeSystem = getModel(); - List casts = typeSystem.lookupByTargetType(type); - if (casts.isEmpty()) { - return null; - } - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(boolean.class), TypeSystemCodeGenerator.isImplicitTypeMethodName(type)); - method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); - if (typed) { - method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "typeHint")); - } - CodeTreeBuilder builder = method.createBuilder(); - - List sourceTypes = typeSystem.lookupSourceTypes(type); - - builder.startReturn(); - String sep = ""; - for (TypeData sourceType : sourceTypes) { - builder.string(sep); - if (typed) { - builder.string("(typeHint == ").typeLiteral(sourceType.getPrimitiveType()).string(" && "); - } - builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end(); - if (typed) { - builder.string(")"); - } - if (sourceTypes.lastIndexOf(sourceType) != sourceTypes.size() - 1) { - builder.newLine(); - } - if (sep.equals("")) { - builder.startIndention(); - } - sep = " || "; - } - builder.end(); - builder.end(); - return method; - } - - private CodeExecutableElement createAsImplicitTypeMethod(TypeData type, boolean typed) { - TypeSystemData typeSystem = getModel(); - List casts = typeSystem.lookupByTargetType(type); - if (casts.isEmpty()) { - return null; - } - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asImplicitTypeMethodName(type)); - method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); - if (typed) { - method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "typeHint")); - } - - List sourceTypes = typeSystem.lookupSourceTypes(type); - - CodeTreeBuilder builder = method.createBuilder(); - boolean elseIf = false; - for (TypeData sourceType : sourceTypes) { - elseIf = builder.startIf(elseIf); - if (typed) { - builder.string("typeHint == ").typeLiteral(sourceType.getPrimitiveType()); - } else { - builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end(); - } - - builder.end().startBlock(); - - builder.startReturn(); - ImplicitCastData cast = typeSystem.lookupCast(sourceType, type); - if (cast != null) { - builder.startCall(cast.getMethodName()); - } - builder.startCall(asTypeMethodName(sourceType)).string(LOCAL_VALUE).end(); - if (cast != null) { - builder.end(); - } - builder.end(); - builder.end(); - } - - builder.startElseBlock(); - builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end(); - builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end(); - builder.end(); - return method; - } - - private CodeExecutableElement createGetTypeIndex(TypeData type) { - TypeSystemData typeSystem = getModel(); - List casts = typeSystem.lookupByTargetType(type); - if (casts.isEmpty()) { - return null; - } - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(Class.class), TypeSystemCodeGenerator.getImplicitClass(type)); - method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); - - List sourceTypes = typeSystem.lookupSourceTypes(type); - CodeTreeBuilder builder = method.createBuilder(); - boolean elseIf = false; - for (TypeData sourceType : sourceTypes) { - elseIf = builder.startIf(elseIf); - builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end(); - builder.end().startBlock(); - builder.startReturn().typeLiteral(sourceType.getPrimitiveType()).end(); - builder.end(); - } - - builder.startElseBlock(); - builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end(); - builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end(); - builder.end(); - - return method; - } - - private CodeExecutableElement createIsTypeMethod(TypeData type) { - if (!type.getTypeChecks().isEmpty()) { - return null; - } - - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(boolean.class), TypeSystemCodeGenerator.isTypeMethodName(type)); - method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); - - DeclaredType suppressWarnings = (DeclaredType) getContext().getType(SuppressWarnings.class); - CodeAnnotationMirror annotationMirror = new CodeAnnotationMirror(suppressWarnings); - annotationMirror.setElementValue(annotationMirror.findExecutableElement("value"), new CodeAnnotationValue("static-method")); - method.getAnnotationMirrors().add(annotationMirror); - - CodeTreeBuilder body = method.createBuilder(); - body.startReturn().instanceOf(LOCAL_VALUE, type.getBoxedType()).end(); - - return method; - } - - private CodeExecutableElement createAsTypeMethod(TypeData type) { - if (!type.getTypeCasts().isEmpty()) { - return null; - } - - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asTypeMethodName(type)); - method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); - - CodeTreeBuilder body = method.createBuilder(); - String assertMessage = typeName(getModel()) + "." + asTypeMethodName(type) + ": " + Utils.getSimpleName(type.getBoxedType()) + " expected"; - body.startAssert().startCall(isTypeMethodName(type)).string(LOCAL_VALUE).end().string(" : ").doubleQuote(assertMessage).end(); - body.startReturn().cast(type.getPrimitiveType(), body.create().string(LOCAL_VALUE).getTree()).end(); - - return method; - } - - private CodeExecutableElement createExpectTypeMethod(TypeData expectedType, TypeData sourceType) { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), expectedType.getPrimitiveType(), TypeSystemCodeGenerator.expectTypeMethodName(expectedType)); - method.addParameter(new CodeVariableElement(sourceType.getPrimitiveType(), LOCAL_VALUE)); - method.addThrownType(getContext().getTruffleTypes().getUnexpectedValueException()); - - CodeTreeBuilder body = method.createBuilder(); - body.startIf().startCall(TypeSystemCodeGenerator.isTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end().startBlock(); - body.startReturn().startCall(TypeSystemCodeGenerator.asTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end(); - body.end(); // if-block - body.startThrow().startNew(getContext().getTruffleTypes().getUnexpectedValueException()).string(LOCAL_VALUE).end().end(); - - return method; - } - - } -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemData.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,227 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.typesystem; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.template.*; - -public class TypeSystemData extends Template { - - private List types; - private List primitiveTypeMirrors = new ArrayList<>(); - private List boxedTypeMirrors = new ArrayList<>(); - - private List implicitCasts; - private List casts; - private List checks; - - private TypeMirror genericType; - private TypeData voidType; - - public TypeSystemData(TypeElement templateType, AnnotationMirror annotation) { - super(templateType, null, annotation); - } - - @Override - public TypeSystemData getTypeSystem() { - return this; - } - - void setTypes(List types) { - this.types = types; - if (types != null) { - for (TypeData typeData : types) { - primitiveTypeMirrors.add(typeData.getPrimitiveType()); - boxedTypeMirrors.add(typeData.getBoxedType()); - } - } - } - - public void setImplicitCasts(List implicitCasts) { - this.implicitCasts = implicitCasts; - } - - public List getImplicitCasts() { - return implicitCasts; - } - - public void setCasts(List casts) { - this.casts = casts; - } - - public void setChecks(List checks) { - this.checks = checks; - } - - void setGenericType(TypeMirror genericType) { - this.genericType = genericType; - } - - void setVoidType(TypeData voidType) { - this.voidType = voidType; - } - - @Override - protected List findChildContainers() { - List sinks = new ArrayList<>(); - if (types != null) { - sinks.addAll(types); - } - if (checks != null) { - sinks.addAll(checks); - } - if (casts != null) { - sinks.addAll(casts); - } - if (implicitCasts != null) { - sinks.addAll(implicitCasts); - } - return sinks; - } - - public boolean isGeneric(TypeMirror type) { - return Utils.typeEquals(getGenericType(), type); - } - - public TypeData getVoidType() { - return voidType; - } - - public List getBoxedTypeMirrors() { - return boxedTypeMirrors; - } - - public List getPrimitiveTypeMirrors() { - return primitiveTypeMirrors; - } - - public List getTypes() { - return types; - } - - public TypeMirror getGenericType() { - return genericType; - } - - public TypeData getGenericTypeData() { - TypeData result = types.get(types.size() - 1); - assert result.getBoxedType() == genericType; - return result; - } - - public TypeData findType(String simpleName) { - for (TypeData type : types) { - if (Utils.getSimpleName(type.getBoxedType()).equals(simpleName)) { - return type; - } - } - return null; - } - - public TypeData findTypeData(TypeMirror type) { - if (Utils.typeEquals(voidType.getPrimitiveType(), type)) { - return voidType; - } - - int index = findType(type); - if (index == -1) { - return null; - } - return types.get(index); - } - - public int findType(TypeData typeData) { - return findType(typeData.getPrimitiveType()); - } - - public int findType(TypeMirror type) { - for (int i = 0; i < types.size(); i++) { - if (Utils.typeEquals(types.get(i).getPrimitiveType(), type)) { - return i; - } - } - return -1; - } - - @Override - public String toString() { - return getClass().getSimpleName() + "[template = " + Utils.getSimpleName(getTemplateType()) + ", types = " + types + "]"; - } - - public Set lookupCastSourceTypes() { - if (getImplicitCasts() == null) { - return null; - } - - Set sourceTypes = new TreeSet<>(); - for (ImplicitCastData cast : getImplicitCasts()) { - sourceTypes.add(cast.getSourceType()); - } - return sourceTypes; - } - - public List lookupByTargetType(TypeData targetType) { - if (getImplicitCasts() == null) { - return Collections.emptyList(); - } - List foundCasts = new ArrayList<>(); - for (ImplicitCastData cast : getImplicitCasts()) { - if (cast.getTargetType().equals(targetType)) { - foundCasts.add(cast); - } - } - return foundCasts; - } - - public ImplicitCastData lookupCast(TypeData sourceType, TypeData targetType) { - if (getImplicitCasts() == null) { - return null; - } - for (ImplicitCastData cast : getImplicitCasts()) { - if (cast.getSourceType().equals(sourceType) && cast.getTargetType().equals(targetType)) { - return cast; - } - } - return null; - } - - public List lookupSourceTypes(TypeData type) { - List sourceTypes = new ArrayList<>(); - sourceTypes.add(type); - if (getImplicitCasts() != null) { - for (ImplicitCastData cast : getImplicitCasts()) { - if (cast.getTargetType() == type) { - sourceTypes.add(cast.getSourceType()); - } - } - } - Collections.sort(sourceTypes); - return sourceTypes; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemMethodParser.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.typesystem; - -import javax.lang.model.element.*; - -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.template.*; - -abstract class TypeSystemMethodParser extends TemplateMethodParser { - - public TypeSystemMethodParser(ProcessorContext context, TypeSystemData typeSystem) { - super(context, typeSystem); - } - - @Override - public final boolean isParsable(ExecutableElement method) { - return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null; - } - - protected TypeData findTypeByMethodName(String methodName, String prefix) { - String typeName = methodName.substring(prefix.length(), methodName.length()); - TypeData type = getTypeSystem().findType(typeName); - return type; - } - - protected TypeData findTypeByMethodName(TemplateMethod method, String prefix) { - String methodName = method.getMethodName(); - if (!methodName.startsWith(prefix)) { - String annotationName = Utils.getSimpleName(method.getMessageAnnotation().getAnnotationType()); - method.addError("Methods annotated with %s must match the pattern '%s'.", annotationName, String.format("%s${typeName}", prefix)); - return null; - } - String typeName = methodName.substring(prefix.length(), methodName.length()); - TypeData type = getTypeSystem().findType(typeName); - if (type == null) { - String annotationName = TypeSystem.class.getSimpleName(); - method.addError("Type '%s' is not declared in this @%s.", typeName, annotationName); - return null; - } - - return type; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,309 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.typesystem; - -import static com.oracle.truffle.dsl.processor.Utils.*; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; - -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.template.*; - -public class TypeSystemParser extends AbstractParser { - - public static final List> ANNOTATIONS = Arrays.asList(TypeSystem.class, ExpectError.class); - - public TypeSystemParser(ProcessorContext c) { - super(c); - } - - @Override - public Class getAnnotationType() { - return TypeSystem.class; - } - - @Override - protected TypeSystemData parse(Element element, AnnotationMirror mirror) { - TypeElement templateType = (TypeElement) element; - AnnotationMirror templateTypeAnnotation = mirror; - TypeSystemData typeSystem = new TypeSystemData(templateType, templateTypeAnnotation); - - // annotation type on class path!? - TypeElement annotationTypeElement = processingEnv.getElementUtils().getTypeElement(getAnnotationType().getCanonicalName()); - if (annotationTypeElement == null) { - typeSystem.addError("Required class %s is not on the classpath.", getAnnotationType().getName()); - } - if (templateType.getModifiers().contains(Modifier.PRIVATE)) { - typeSystem.addError("A @%s must have at least package protected visibility.", getAnnotationType().getName()); - } - - if (templateType.getModifiers().contains(Modifier.FINAL)) { - typeSystem.addError("The @%s must not be final.", getAnnotationType().getName()); - } - if (typeSystem.hasErrors()) { - return typeSystem; - } - - typeSystem.setTypes(parseTypes(typeSystem)); - if (typeSystem.hasErrors()) { - return typeSystem; - } - - TypeMirror genericType = context.getType(Object.class); - TypeData voidType = new TypeData(typeSystem, typeSystem.getTypes().size(), null, context.getType(void.class), context.getType(Void.class)); - - typeSystem.setGenericType(genericType); - typeSystem.setVoidType(voidType); - - verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class); - - List elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType)); - List implicitCasts = new ImplicitCastParser(context, typeSystem).parse(elements); - List casts = new TypeCastParser(context, typeSystem).parse(elements); - List checks = new TypeCheckParser(context, typeSystem).parse(elements); - - if (casts == null || checks == null || implicitCasts == null) { - return typeSystem; - } - - typeSystem.setImplicitCasts(implicitCasts); - typeSystem.setCasts(casts); - typeSystem.setChecks(checks); - - if (typeSystem.hasErrors()) { - return typeSystem; - } - - for (TypeCheckData check : checks) { - check.getCheckedType().addTypeCheck(check); - } - - for (TypeCastData cast : casts) { - cast.getTargetType().addTypeCast(cast); - } - - verifyGenericTypeChecksAndCasts(typeSystem); - verifyMethodSignatures(typeSystem); - verifyNamesUnique(typeSystem); - - return typeSystem; - } - - protected void verifyExclusiveMethodAnnotation(Template template, Class... annotationTypes) { - List methods = ElementFilter.methodsIn(template.getTemplateType().getEnclosedElements()); - for (ExecutableElement method : methods) { - List foundAnnotations = new ArrayList<>(); - for (int i = 0; i < annotationTypes.length; i++) { - Class annotationType = annotationTypes[i]; - AnnotationMirror mirror = Utils.findAnnotationMirror(context.getEnvironment(), method, annotationType); - if (mirror != null) { - foundAnnotations.add(mirror); - } - } - if (foundAnnotations.size() > 1) { - List annotationNames = new ArrayList<>(); - for (AnnotationMirror mirror : foundAnnotations) { - annotationNames.add("@" + Utils.getSimpleName(mirror.getAnnotationType())); - } - - template.addError("Non exclusive usage of annotations %s.", annotationNames); - } - } - } - - private static void verifyGenericTypeChecksAndCasts(TypeSystemData typeSystem) { - for (TypeData type : typeSystem.getTypes()) { - if (!type.getTypeChecks().isEmpty()) { - boolean hasGeneric = false; - for (TypeCheckData typeCheck : type.getTypeChecks()) { - if (typeCheck.isGeneric()) { - hasGeneric = true; - break; - } - } - if (!hasGeneric) { - type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.", - TypeCheck.class.getSimpleName(), TypeSystemCodeGenerator.isTypeMethodName(type), Utils.getSimpleName(type.getBoxedType()), TypeCheck.class.getSimpleName(), - Object.class.getSimpleName()); - } - } - if (!type.getTypeCasts().isEmpty()) { - boolean hasGeneric = false; - for (TypeCastData typeCast : type.getTypeCasts()) { - if (typeCast.isGeneric()) { - hasGeneric = true; - break; - } - } - if (!hasGeneric) { - type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.", - TypeCast.class.getSimpleName(), TypeSystemCodeGenerator.asTypeMethodName(type), Utils.getSimpleName(type.getBoxedType()), TypeCast.class.getSimpleName(), - Object.class.getSimpleName()); - } - } - } - } - - private List parseTypes(TypeSystemData typeSystem) { - List types = new ArrayList<>(); - List typeMirrors = Utils.getAnnotationValueList(TypeMirror.class, typeSystem.getTemplateTypeAnnotation(), "value"); - if (typeMirrors.isEmpty()) { - typeSystem.addError("At least one type must be defined."); - return types; - } - - final AnnotationValue annotationValue = Utils.getAnnotationValue(typeSystem.getTemplateTypeAnnotation(), "value"); - final TypeMirror objectType = context.getType(Object.class); - - int index = 0; - for (TypeMirror primitiveType : typeMirrors) { - TypeMirror boxedType = Utils.boxType(context, primitiveType); - TypeData typeData = new TypeData(typeSystem, index, annotationValue, primitiveType, boxedType); - - if (isPrimitiveWrapper(primitiveType)) { - typeData.addError("Types must not contain primitive wrapper types."); - } - - if (Utils.typeEquals(boxedType, objectType)) { - typeData.addError("Types must not contain the generic type java.lang.Object."); - } - - types.add(typeData); - index++; - } - - verifyTypeOrder(types); - - types.add(new TypeData(typeSystem, index, annotationValue, objectType, objectType)); - - return types; - } - - private static void verifyTypeOrder(List types) { - Map> invalidTypes = new HashMap<>(); - - for (int i = types.size() - 1; i >= 0; i--) { - TypeData typeData = types.get(i); - TypeMirror type = typeData.getBoxedType(); - if (invalidTypes.containsKey(Utils.getQualifiedName(type))) { - typeData.addError("Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", invalidTypes.get(Utils.getQualifiedName(type)), Utils.getQualifiedName(type)); - } - List nextInvalidTypes = Utils.getQualifiedSuperTypeNames(Utils.fromTypeMirror(type)); - nextInvalidTypes.add(getQualifiedName(type)); - - for (String qualifiedName : nextInvalidTypes) { - List inheritedTypes = invalidTypes.get(qualifiedName); - if (inheritedTypes == null) { - inheritedTypes = new ArrayList<>(); - invalidTypes.put(qualifiedName, inheritedTypes); - } - inheritedTypes.add(Utils.getQualifiedName(typeData.getBoxedType())); - } - } - } - - private boolean isPrimitiveWrapper(TypeMirror type) { - Types types = context.getEnvironment().getTypeUtils(); - for (TypeKind kind : TypeKind.values()) { - if (!kind.isPrimitive()) { - continue; - } - if (Utils.typeEquals(type, types.boxedClass(types.getPrimitiveType(kind)).asType())) { - return true; - } - } - return false; - } - - private void verifyMethodSignatures(TypeSystemData typeSystem) { - Set generatedIsMethodNames = new HashSet<>(); - Set generatedAsMethodNames = new HashSet<>(); - Set generatedExpectMethodNames = new HashSet<>(); - - for (TypeData typeData : typeSystem.getTypes()) { - generatedIsMethodNames.add(TypeSystemCodeGenerator.isTypeMethodName(typeData)); - generatedAsMethodNames.add(TypeSystemCodeGenerator.asTypeMethodName(typeData)); - generatedExpectMethodNames.add(TypeSystemCodeGenerator.expectTypeMethodName(typeData)); - } - - List methods = ElementFilter.methodsIn(typeSystem.getTemplateType().getEnclosedElements()); - for (ExecutableElement method : methods) { - if (method.getModifiers().contains(Modifier.PRIVATE)) { - // will not conflict overridden methods - continue; - } else if (method.getParameters().size() != 1) { - continue; - } - String methodName = method.getSimpleName().toString(); - if (generatedIsMethodNames.contains(methodName)) { - verifyIsMethod(typeSystem, method); - } else if (generatedAsMethodNames.contains(methodName)) { - verifyAsMethod(typeSystem, method); - } else if (generatedExpectMethodNames.contains(methodName)) { - verifyExpectMethod(typeSystem); - } - } - } - - private boolean verifyIsMethod(TypeSystemData typeSystem, ExecutableElement method) { - AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCheck.class); - if (mirror == null) { - typeSystem.addError("Method starting with the pattern is${typeName} must be annotated with @%s.", TypeCheck.class.getSimpleName()); - return false; - } - return true; - } - - private boolean verifyAsMethod(TypeSystemData typeSystem, ExecutableElement method) { - AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCast.class); - if (mirror == null) { - typeSystem.addError("Method starting with the pattern as${typeName} must be annotated with @%s.", TypeCast.class.getSimpleName()); - return false; - } - return true; - } - - private static boolean verifyExpectMethod(TypeSystemData typeSystem) { - typeSystem.addError("Method starting with the pattern expect${typeName} must not be declared manually."); - return false; - } - - private static void verifyNamesUnique(TypeSystemData typeSystem) { - List types = typeSystem.getTypes(); - for (int i = 0; i < types.size(); i++) { - for (int j = i + 1; j < types.size(); j++) { - String name1 = Utils.getSimpleName(types.get(i).getBoxedType()); - String name2 = Utils.getSimpleName(types.get(j).getBoxedType()); - if (name1.equalsIgnoreCase(name2)) { - typeSystem.addError("Two types result in the same name: %s, %s.", name1, name2); - } - } - } - } -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java diff -r ae0f235469db -r f8e60d11c0ec 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 25 21:15:59 2014 -0700 @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.sl.test.instrument; + +import java.io.*; +import java.nio.charset.*; +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.util.*; + +import org.junit.*; +import org.junit.internal.*; +import org.junit.runner.*; +import org.junit.runner.manipulation.*; +import org.junit.runner.notification.*; +import org.junit.runners.*; +import org.junit.runners.model.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.source.*; +import com.oracle.truffle.sl.nodes.instrument.*; +import com.oracle.truffle.sl.parser.*; +import com.oracle.truffle.sl.runtime.*; +import com.oracle.truffle.sl.test.instrument.SLInstrumentTestRunner.InstrumentTestCase; + +/** + * This class builds and executes the tests for instrumenting SL. Although much of this class is + * written with future automation in mind, at the moment the tests that are created are hard-coded + * according to the file name of the test. To be automated, an automatic way of generating both the + * node visitor and the node prober is necessary. + * + * Testing is done via JUnit via comparing execution outputs with expected outputs. + */ +public final class SLInstrumentTestRunner extends ParentRunner { + + private static final String SOURCE_SUFFIX = ".sl"; + private static final String INPUT_SUFFIX = ".input"; + private static final String OUTPUT_SUFFIX = ".output"; + private static final String ASSIGNMENT_VALUE_SUFFIX = "_assnCount"; + + private static final String LF = System.getProperty("line.separator"); + private static SLContext slContext; + + static class InstrumentTestCase { + protected final Description name; + protected final Path path; + protected final String baseName; + protected final String sourceName; + protected final String testInput; + protected final String expectedOutput; + protected String actualOutput; + + protected InstrumentTestCase(Class testClass, String baseName, String sourceName, Path path, String testInput, String expectedOutput) { + this.name = Description.createTestDescription(testClass, baseName); + this.baseName = baseName; + this.sourceName = sourceName; + this.path = path; + this.testInput = testInput; + this.expectedOutput = expectedOutput; + } + } + + private final List 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'.", SLInstrumentTestSuite.class.getSimpleName(), c.getName(), + SLInstrumentTestRunner.class.getSimpleName())); + } + + String[] paths = suite.value(); + + Path root = null; + for (String path : paths) { + root = FileSystems.getDefault().getPath(path); + if (Files.exists(root)) { + break; + } + } + if (root == null && paths.length > 0) { + throw new FileNotFoundException(paths[0]); + } + + final Path rootPath = root; + + final List 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(ASSIGNMENT_VALUE_SUFFIX)) { + // Set up the execution context for Simple and register our two listeners + slContext = new SLContext(new BufferedReader(new StringReader(testCase.testInput)), printer); + + final Source source = Source.fromText(readAllLines(testCase.path), testCase.sourceName); + Parser.parseSL(slContext, source); + List functionList = slContext.getFunctionRegistry().getFunctions(); + + // Since only functions can be global in SL, this guarantees that we instrument + // everything of interest. Parsing must occur before accepting the visitors since + // the visitor which creates our instrumentation points expects a complete AST. + + for (SLFunction function : functionList) { + RootCallTarget rootCallTarget = function.getCallTarget(); + rootCallTarget.getRootNode().accept(new SLInstrumenter(slContext)); + } + + // We iterate over all tags the SLInsturmenter tagged as assignments and attach our + // test instrument to those. + for (Probe probe : slContext.findProbesTaggedAs(StandardSyntaxTag.ASSIGNMENT)) { + if (probe.isTaggedAs(StandardSyntaxTag.ASSIGNMENT)) { + probe.addInstrument(new SLPrintAssigmentValueInstrument(printer)); + } + } + + SLFunction main = slContext.getFunctionRegistry().lookup("main"); + main.getCallTarget().call(); + } else { + notifier.fireTestFailure(new Failure(testCase.name, new UnsupportedOperationException("No instrumentation found."))); + } + + String actualOutput = new String(out.toByteArray()); + Assert.assertEquals(testCase.expectedOutput, actualOutput); + } catch (Throwable ex) { + notifier.fireTestFailure(new Failure(testCase.name, ex)); + } finally { + notifier.fireTestFinished(testCase.name); + } + + } + + public static void runInMain(Class testClass, String[] args) throws InitializationError, NoTestsRemainException { + JUnitCore core = new JUnitCore(); + core.addListener(new TextListener(System.out)); + SLInstrumentTestRunner suite = new SLInstrumentTestRunner(testClass); + if (args.length > 0) { + suite.filter(new NameFilter(args[0])); + } + Result r = core.run(suite); + if (!r.wasSuccessful()) { + System.exit(1); + } + } + + private static final class NameFilter extends Filter { + private final String pattern; + + private NameFilter(String pattern) { + this.pattern = pattern.toLowerCase(); + } + + @Override + public boolean shouldRun(Description description) { + return description.getMethodName().toLowerCase().contains(pattern); + } + + @Override + public String describe() { + return "Filter contains " + pattern; + } + } +} diff -r ae0f235469db -r f8e60d11c0ec 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 25 21:15:59 2014 -0700 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.sl.test.instrument; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface SLInstrumentTestSuite { + + /** + * Defines the base path of the test suite. Multiple base paths can be specified. However only + * the first base that exists is used to lookup the test cases. + */ + String[] value(); + +} diff -r ae0f235469db -r f8e60d11c0ec 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 25 21:15:59 2014 -0700 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.sl.test.instrument; + +import java.io.*; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.sl.nodes.local.*; + +/** + * This sample instrument provides prints the value of an assignment (after the assignment is + * complete) to the {@link PrintStream} specified in the constructor. This instrument can only be + * attached to a wrapped {@link SLWriteLocalVariableNode}, but provides no guards to protect it from + * being attached elsewhere. + */ +public final class SLPrintAssigmentValueInstrument extends Instrument { + + private PrintStream output; + + public SLPrintAssigmentValueInstrument(PrintStream output) { + this.output = output; + } + + @Override + public void leave(Node astNode, VirtualFrame frame, Object result) { + output.println(result); + } +} diff -r ae0f235469db -r f8e60d11c0ec 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 25 21:15:59 2014 -0700 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.sl.test.instrument; + +import org.junit.*; +import org.junit.runner.*; + +@RunWith(SLInstrumentTestRunner.class) +@SLInstrumentTestSuite({"graal/com.oracle.truffle.sl.test/tests_instrumentation", "tests_instrumentation"}) +public class SLSimpleInstrumentTestSuite { + + public static void main(String[] args) throws Exception { + SLInstrumentTestRunner.runInMain(SLSimpleInstrumentTestSuite.class, args); + } + + /* + * Our "mx unittest" command looks for methods that are annotated with @Test. By just defining + * an empty method, this class gets included and the test suite is properly executed. + */ + @Test + public void unittest() { + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.sl.test/tests/error/TypeError02.output --- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError02.output Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.sl.test/tests/error/TypeError02.output Mon Aug 25 21:15:59 2014 -0700 @@ -1,1 +1,1 @@ -Type error at TypeError02.sl line 2 col 6: operation "if" not defined for String "4" +Type error at TypeError02.sl line 2 col 3: operation "if" not defined for String "4" diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.sl.test/tests/error/TypeError04.output --- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError04.output Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.sl.test/tests/error/TypeError04.output Mon Aug 25 21:15:59 2014 -0700 @@ -1,1 +1,1 @@ -Type error at TypeError04.sl line 2 col 4: operation "||" not defined for Boolean false, Number 4 +Type error at TypeError04.sl line 2 col 3: operation "||" not defined for Boolean false, Number 4 diff -r ae0f235469db -r f8e60d11c0ec 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 25 21:15:59 2014 -0700 @@ -0,0 +1,103 @@ +100 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +100 diff -r ae0f235469db -r f8e60d11c0ec 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 25 21:15:59 2014 -0700 @@ -0,0 +1,11 @@ +function loop(count) { + i = 0; + while (i < count) { + i = i + 1; + } + return i; +} + +function main() { + count = loop(100); +} diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java Mon Aug 25 21:15:59 2014 -0700 @@ -152,7 +152,7 @@ if (sourceCallback != null) { sourceCallback.startLoading(source); } - Parser.parseSL(context, source, null); + Parser.parseSL(context, source); if (sourceCallback != null) { sourceCallback.endLoading(source); } @@ -192,6 +192,7 @@ } finally { printScript("after execution", context, logOutput, printASTToLog, printSourceAttributionToLog, dumpASTToIGV); } + return; } /** diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java Mon Aug 25 21:15:59 2014 -0700 @@ -50,6 +50,6 @@ private static void doDefineFunction(SLContext context, String code) { Source source = Source.fromText(code, "[defineFunction]"); /* The same parsing code as for parsing the initial source. */ - Parser.parseSL(context, source, null); + Parser.parseSL(context, source); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java Mon Aug 25 21:15:59 2014 -0700 @@ -29,8 +29,6 @@ public final class SLContextFactory { - private static SLASTProber astProber; - private SLContextFactory() { } @@ -39,12 +37,6 @@ final SLContext slContext = new SLContext(new BufferedReader(new InputStreamReader(System.in)), System.out); slContext.initialize(); slContext.setVisualizer(new SLDefaultVisualizer()); - astProber = new SLASTProber(); - slContext.setASTNodeProber(astProber); return slContext; } - - public static void addNodeProber(SLNodeProber nodeProber) { - astProber.addNodeProber(nodeProber); - } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLExpressionNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLExpressionNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLExpressionNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,10 +24,13 @@ import java.math.*; +import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.source.*; +import com.oracle.truffle.sl.nodes.instrument.*; import com.oracle.truffle.sl.runtime.*; /** @@ -87,4 +90,20 @@ public SLNull executeNull(VirtualFrame frame) throws UnexpectedResultException { return SLTypesGen.SLTYPES.expectSLNull(executeGeneric(frame)); } + + @Override + public Probe probe(ExecutionContext context) { + Node parent = getParent(); + + if (parent == null) + throw new IllegalStateException("Cannot probe a node without a parent"); + + if (parent instanceof SLExpressionWrapper) + return ((SLExpressionWrapper) parent).getProbe(); + + SLExpressionWrapper wrapper = new SLExpressionWrapper((SLContext) context, this); + this.replace(wrapper); + wrapper.insertChild(); + return wrapper.getProbe(); + } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -22,9 +22,15 @@ */ package com.oracle.truffle.sl.nodes; +import java.io.*; + +import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.source.*; +import com.oracle.truffle.sl.nodes.instrument.*; +import com.oracle.truffle.sl.runtime.*; /** * The base class of all Truffle nodes for SL. All nodes (even expressions) can be used as @@ -32,7 +38,7 @@ * local variables. */ @NodeInfo(language = "Simple Language", description = "The abstract base node for all statements") -public abstract class SLStatementNode extends Node { +public abstract class SLStatementNode extends Node implements Instrumentable { public SLStatementNode(SourceSection src) { super(src); @@ -46,4 +52,53 @@ public SLStatementNode getNonWrapperNode() { return this; } + + @Override + public String toString() { + return formatSourceSection(this); + } + + /** + * Formats a source section of a node in human readable form. If no source section could be + * found it looks up the parent hierarchy until it finds a source section. Nodes where this was + * required append a '~' at the end. + * + * @param node the node to format. + * @return a formatted source section string + */ + private static String formatSourceSection(Node node) { + if (node == null) { + return ""; + } + SourceSection section = node.getSourceSection(); + boolean estimated = false; + if (section == null) { + section = node.getEncapsulatingSourceSection(); + estimated = true; + } + + if (section == null || section.getSource() == null) { + return ""; + } else { + String sourceName = new File(section.getSource().getName()).getName(); + int startLine = section.getStartLine(); + return String.format("%s:%d%s", sourceName, startLine, estimated ? "~" : ""); + } + } + + @Override + public Probe probe(ExecutionContext context) { + Node parent = getParent(); + + if (parent == null) + throw new IllegalStateException("Cannot probe a node without a parent"); + + if (parent instanceof SLStatementWrapper) + return ((SLStatementWrapper) parent).getProbe(); + + SLStatementWrapper wrapper = new SLStatementWrapper((SLContext) context, this); + this.replace(wrapper); + wrapper.insertChild(); + return wrapper.getProbe(); + } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -41,7 +41,7 @@ */ @Children private final SLStatementNode[] bodyNodes; - public SLBlockNode(SourceSection src, SLStatementNode[] bodyNodes) { + public SLBlockNode(SourceSection src, SLStatementNode... bodyNodes) { super(src); this.bodyNodes = bodyNodes; } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -24,6 +24,7 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; import com.oracle.truffle.api.utilities.*; import com.oracle.truffle.sl.nodes.*; import com.oracle.truffle.sl.runtime.*; @@ -49,8 +50,8 @@ private final BranchProfile exceptionTaken = new BranchProfile(); private final BranchProfile nullTaken = new BranchProfile(); - public SLFunctionBodyNode(SLStatementNode bodyNode) { - super(null); + public SLFunctionBodyNode(SourceSection src, SLStatementNode bodyNode) { + super(src); this.bodyNode = bodyNode; } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -46,12 +46,13 @@ @Child private SLStatementNode elsePartNode; /** - * Profiling information, collected by the interpreter, capturing whether the then-branch was - * used (analogously for the {@link #elseTaken else-branch}). This allows the compiler to - * generate better code for conditions that are always true or always false. + * Profiling information, collected by the interpreter, capturing the profiling information of + * the condition. This allows the compiler to generate better code for conditions that are + * always true or always false. Additionally the {@link CountingConditionProfile} implementation + * (as opposed to {@link BinaryConditionProfile} implementation) transmits the probability of + * the condition to be true to the compiler. */ - private final BranchProfile thenTaken = new BranchProfile(); - private final BranchProfile elseTaken = new BranchProfile(); + private final ConditionProfile condition = ConditionProfile.createCountingProfile(); public SLIfNode(SourceSection src, SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) { super(src); @@ -62,14 +63,14 @@ @Override public void executeVoid(VirtualFrame frame) { - if (evaluateCondition(frame)) { - /* In the interpreter, record profiling information that the then-branch was used. */ - thenTaken.enter(); + /* + * In the interpreter, record profiling information that the condition was executed and with + * which outcome. + */ + if (condition.profile(evaluateCondition(frame))) { /* Execute the then-branch. */ thenPartNode.executeVoid(frame); } else { - /* In the interpreter, record profiling information that the else-branch was used. */ - elseTaken.enter(); /* Execute the else-branch (which is optional according to the SL syntax). */ if (elsePartNode != null) { elsePartNode.executeVoid(frame); diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLRepeatingNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLRepeatingNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.sl.nodes.controlflow; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; +import com.oracle.truffle.api.utilities.*; +import com.oracle.truffle.sl.nodes.*; + +public final class SLRepeatingNode extends Node implements RepeatingNode { + + /** + * The condition of the loop. This in a {@link SLExpressionNode} because we require a result + * value. We do not have a node type that can only return a {@code boolean} value, so + * {@link #evaluateCondition executing the condition} can lead to a type error. + */ + @Child private SLExpressionNode conditionNode; + + /** Statement (or {@link SLBlockNode block}) executed as long as the condition is true. */ + @Child private SLStatementNode bodyNode; + + /** + * Profiling information, collected by the interpreter, capturing whether a {@code continue} + * statement was used in this loop. This allows the compiler to generate better code for loops + * without a {@code continue}. + */ + private final BranchProfile continueTaken = new BranchProfile(); + private final BranchProfile breakTaken = new BranchProfile(); + + public SLRepeatingNode(SourceSection src, SLExpressionNode conditionNode, SLStatementNode bodyNode) { + super(src); + this.conditionNode = conditionNode; + this.bodyNode = bodyNode; + } + + public boolean executeRepeating(VirtualFrame frame) { + if (evaluateCondition(frame)) { + try { + /* Execute the loop body. */ + bodyNode.executeVoid(frame); + } catch (SLContinueException ex) { + /* In the interpreter, record profiling information that the loop uses continue. */ + continueTaken.enter(); + /* Fall through to next loop iteration. */ + } catch (SLBreakException ex) { + /* In the interpreter, record profiling information that the loop uses break. */ + breakTaken.enter(); + /* Done executing this loop, exit method to execute statement following the loop. */ + return false; + } + return true; + } else { + return false; + } + } + + private boolean evaluateCondition(VirtualFrame frame) { + try { + /* + * The condition must evaluate to a boolean value, so we call the boolean-specialized + * execute method. + */ + return (conditionNode.executeBoolean(frame)); + } catch (UnexpectedResultException ex) { + /* + * The condition evaluated to a non-boolean result. This is a type error in the SL + * program. We report it with the same exception that Truffle DSL generated nodes use to + * report type errors. + */ + throw new UnsupportedSpecializationException(this, new Node[]{conditionNode}, ex.getResult()); + } + } + +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -23,89 +23,24 @@ package com.oracle.truffle.sl.nodes.controlflow; import com.oracle.truffle.api.*; -import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.source.*; -import com.oracle.truffle.api.utilities.*; import com.oracle.truffle.sl.nodes.*; @NodeInfo(shortName = "while", description = "The node implementing a while loop") public final class SLWhileNode extends SLStatementNode { - /** - * The condition of the loop. This in a {@link SLExpressionNode} because we require a result - * value. We do not have a node type that can only return a {@code boolean} value, so - * {@link #evaluateCondition executing the condition} can lead to a type error. - */ - @Child private SLExpressionNode conditionNode; - - /** Statement (or {@link SLBlockNode block}) executed as long as the condition is true. */ - @Child private SLStatementNode bodyNode; - - /** - * Profiling information, collected by the interpreter, capturing whether a {@code continue} - * statement was used in this loop. This allows the compiler to generate better code for loops - * without a {@code continue}. - */ - private final BranchProfile continueTaken = new BranchProfile(); - private final BranchProfile breakTaken = new BranchProfile(); + @Child private LoopNode loopNode; public SLWhileNode(SourceSection src, SLExpressionNode conditionNode, SLStatementNode bodyNode) { super(src); - this.conditionNode = conditionNode; - this.bodyNode = bodyNode; + this.loopNode = Truffle.getRuntime().createLoopNode(new SLRepeatingNode(src, conditionNode, bodyNode)); } @Override public void executeVoid(VirtualFrame frame) { - int count = 0; - try { - while (evaluateCondition(frame)) { - try { - /* Execute the loop body. */ - bodyNode.executeVoid(frame); - - if (CompilerDirectives.inInterpreter()) { - /* In the interpreter, profile the the number of loop iteration. */ - count++; - } - } catch (SLContinueException ex) { - /* In the interpreter, record profiling information that the loop uses continue. */ - continueTaken.enter(); - /* Fall through to next loop iteration. */ - } - } - } catch (SLBreakException ex) { - /* In the interpreter, record profiling information that the loop uses break. */ - breakTaken.enter(); - /* Done executing this loop, exit method to execute statement following the loop. */ - - } finally { - if (CompilerDirectives.inInterpreter()) { - /* - * In the interpreter, report the loop count to the Truffle system. It is used for - * compilation and inlining decisions. - */ - getRootNode().reportLoopCount(count); - } - } + loopNode.executeLoop(frame); } - private boolean evaluateCondition(VirtualFrame frame) { - try { - /* - * The condition must evaluate to a boolean value, so we call the boolean-specialized - * execute method. - */ - return conditionNode.executeBoolean(frame); - } catch (UnexpectedResultException ex) { - /* - * The condition evaluated to a non-boolean result. This is a type error in the SL - * program. We report it with the same exception that Truffle DSL generated nodes use to - * report type errors. - */ - throw new UnsupportedSpecializationException(this, new Node[]{conditionNode}, ex.getResult()); - } - } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLEqualNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLEqualNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLEqualNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -83,11 +83,11 @@ } /** - * The {@link Generic} annotation informs the Truffle DSL that this method should be executed + * The {@link Fallback} annotation informs the Truffle DSL that this method should be executed * when no {@link Specialization specialized method} matches. The operand types must be * {@link Object}. */ - @Generic + @Fallback protected boolean equal(Object left, Object right) { /* * We covered all the cases that can return true in specializations. If we compare two diff -r ae0f235469db -r f8e60d11c0ec 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 25 21:15:59 2014 -0700 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.sl.nodes.expression; + +import java.math.*; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; +import com.oracle.truffle.sl.nodes.*; +import com.oracle.truffle.sl.runtime.*; + +/** + * A {@link SLExpressionNode} that represents a parenthesized expression; it simply returns the + * value of the enclosed (child) expression. It is represented separately in the AST for the purpose + * of correct source attribution; this preserves the lexical relationship between the two + * parentheses and allows a tool to describe the expression as distinct from its contents. + */ +@NodeInfo(description = "A parenthesized expression") +public class SLParenExpressionNode extends SLExpressionNode { + + private final SLExpressionNode expression; + + public SLParenExpressionNode(SourceSection src, SLExpressionNode expression) { + super(src); + this.expression = insert(expression); + } + + @Override + public Object executeGeneric(VirtualFrame frame) { + return expression.executeGeneric(frame); + } + + @Override + public long executeLong(VirtualFrame frame) throws UnexpectedResultException { + return expression.executeLong(frame); + } + + @Override + public BigInteger executeBigInteger(VirtualFrame frame) throws UnexpectedResultException { + return expression.executeBigInteger(frame); + } + + @Override + public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException { + return expression.executeBoolean(frame); + } + + @Override + public String executeString(VirtualFrame frame) throws UnexpectedResultException { + return expression.executeString(frame); + } + + @Override + public SLFunction executeFunction(VirtualFrame frame) throws UnexpectedResultException { + return expression.executeFunction(frame); + } + + @Override + public SLNull executeNull(VirtualFrame frame) throws UnexpectedResultException { + return expression.executeNull(frame); + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTProber.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTProber.java Mon Aug 25 14:42:42 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.sl.nodes.instrument; - -import java.util.*; - -import com.oracle.truffle.api.instrument.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.sl.nodes.*; - -/** - * SLASTProber contains the collection of {@link SLNodeProber}s and methods to attach the probers to - * nodes. - */ -public final class SLASTProber implements ASTProber, SLNodeProber { - - private ArrayList nodeProbers = new ArrayList<>(); - - public SLASTProber() { - } - - /** - * Adds a {@link SLNodeProber} to this SLASTProber. Probes must be of type {@link SLNodeProber} - * and must not already have been added. - * - * @param nodeProber the {@link SLNodeProber} to add. - */ - public void addNodeProber(ASTNodeProber nodeProber) { - if (nodeProber instanceof SLNodeProber) { - assert !nodeProbers.contains(nodeProber); - nodeProbers.add((SLNodeProber) nodeProber); - } else { - throw new IllegalArgumentException("invalid prober for SL implementation"); - } - } - - /** - * Unimplemented, does nothing. - */ - public Node probeAs(Node astNode, SyntaxTag tag, Object... args) { - return astNode; - } - - /** - * Attaches the current probers to the given {@link SLStatementNode} as a statement. - * - * @param node The {@link SLStatementNode} to attach the stored set of probers to. - */ - @Override - public SLStatementNode probeAsStatement(SLStatementNode node) { - SLStatementNode result = node; - for (SLNodeProber nodeProber : nodeProbers) { - result = nodeProber.probeAsStatement(result); - } - return result; - } - - /** - * Attaches the current probers to the given {@link SLExpressionNode} as a call. This will wrap - * the passed in node in an {@link SLExpressionWrapper}, tag it as a call and attach an - * instrument to it. - * - * @param node The {@link SLExpressionNode} to attach the stored set of probers to. - * @param callName The name of the call ??? - * - */ - @Override - public SLExpressionNode probeAsCall(SLExpressionNode node, String callName) { - SLExpressionNode result = node; - for (SLNodeProber nodeProber : nodeProbers) { - result = nodeProber.probeAsCall(node, callName); - } - return result; - } - - /** - * Attaches the current probers to the given {@link SLExpressionNode} as an assignment. This - * will wrap the passed in node in an {@link SLExpressionWrapper}, tag it as an assignment and - * attach an instrument to it. - * - * @param node The {@link SLExpressionNode} to attached the stored set of probers to. - * @param localName The name of the assignment ??? - * - */ - @Override - public SLExpressionNode probeAsLocalAssignment(SLExpressionNode node, String localName) { - SLExpressionNode result = node; - for (SLNodeProber nodeProber : nodeProbers) { - result = nodeProber.probeAsLocalAssignment(result, localName); - } - return result; - } - - public ASTNodeProber getCombinedNodeProber() { - return nodeProbers.isEmpty() ? null : this; - } - -} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapper.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapper.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapper.java Mon Aug 25 21:15:59 2014 -0700 @@ -46,11 +46,19 @@ private final Probe probe; + /** + * Constructor. + * + * @param context The current Simple execution context + * @param child The {@link SLExpressionNode} that this wrapper is wrapping + */ public SLExpressionWrapper(SLContext context, SLExpressionNode child) { super(child.getSourceSection()); assert !(child instanceof SLExpressionWrapper); - this.child = insert(child); - this.probe = context.getProbe(child.getSourceSection()); + this.probe = context.createProbe(child.getSourceSection()); + this.child = child; + // The child should only be inserted after a replace, so we defer inserting the child to the + // creator of the wrapper. } @Override @@ -145,4 +153,11 @@ public SLNull executeNull(VirtualFrame frame) throws UnexpectedResultException { return SLTypesGen.SLTYPES.expectSLNull(executeGeneric(frame)); } + + /** + * Sets the parent pointer of this wrapper's child. + */ + public void insertChild() { + insert(this.child); + } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLInstrumenter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLInstrumenter.java Mon Aug 25 21:15:59 2014 -0700 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.sl.nodes.instrument; + +import static com.oracle.truffle.api.instrument.StandardSyntaxTag.*; + +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.sl.nodes.*; +import com.oracle.truffle.sl.nodes.controlflow.*; +import com.oracle.truffle.sl.nodes.local.*; +import com.oracle.truffle.sl.runtime.*; + +/** + * This is a general purpose visitor which traverses a completely parsed Simple AST and instruments + * all the nodes within it. This visitor is designed to visit the tree immediately after it has been + * parsed. + * + */ +public class SLInstrumenter implements NodeVisitor { + + private final SLContext context; + + public SLInstrumenter(SLContext context) { + this.context = context; + } + + /** + * Instruments and tags all relevant {@link SLStatementNode}s and {@link SLExpressionNode}s. + * Currently, only SLStatementNodes that are not SLExpressionNodes are tagged as statements. + */ + public boolean visit(Node node) { + // We have to distinguish between SLExpressionNode and SLStatementNode since some of the + // generated factories have methods that require SLExpressionNodes as parameters. Since + // SLExpressionNodes are a subclass of SLStatementNode, we check if something is an + // SLExpressionNode first. + if (node instanceof SLExpressionNode && node.getParent() != null) { + SLExpressionNode expressionNode = (SLExpressionNode) node; + if (expressionNode.getSourceSection() != null) { + Probe probe = expressionNode.probe(context); + // probe.tagAs(STATEMENT); + + if (node instanceof SLWriteLocalVariableNode) + probe.tagAs(ASSIGNMENT); + } + } else if (node instanceof SLStatementNode && node.getParent() != null) { + + SLStatementNode statementNode = (SLStatementNode) node; + if (statementNode.getSourceSection() != null) { + Probe probe = statementNode.probe(context); + probe.tagAs(STATEMENT); + + if (node instanceof SLWhileNode) + probe.tagAs(START_LOOP); + } + } + + return true; + } +} diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapper.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapper.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapper.java Mon Aug 25 21:15:59 2014 -0700 @@ -48,8 +48,10 @@ public SLStatementWrapper(SLContext context, SLStatementNode child) { super(child.getSourceSection()); assert !(child instanceof SLStatementWrapper); - this.child = insert(child); - this.probe = context.getProbe(child.getSourceSection()); + this.probe = context.createProbe(child.getSourceSection()); + this.child = child; + // The child should only be inserted after a replace, so we defer inserting the child to the + // creator of the wrapper. } @Override @@ -94,6 +96,12 @@ probe.leaveExceptional(child, frame, e); throw (e); } + } + /** + * Sets the parent pointer of this wrapper's child. + */ + public void insertChild() { + insert(this.child); } } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadLocalVariableNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadLocalVariableNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadLocalVariableNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -57,7 +57,7 @@ return frame.getBoolean(getSlot()); } - @Specialization(order = 1, rewriteOn = FrameSlotTypeException.class) + @Specialization(rewriteOn = FrameSlotTypeException.class) protected Object readObject(VirtualFrame frame) throws FrameSlotTypeException { return frame.getObject(getSlot()); } @@ -66,7 +66,7 @@ * This is the generic case that always succeeds. Since we already have another specialization * with the same signature above, we need to order them explicitly with the order attribute. */ - @Specialization(order = 2) + @Specialization(contains = {"readLong", "readBoolean", "readObject"}) protected Object read(VirtualFrame frame) { return frame.getValue(getSlot()); } diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java Mon Aug 25 21:15:59 2014 -0700 @@ -52,13 +52,13 @@ * {@link #isLongKind() custom guard} is specified. */ @Specialization(guards = "isLongKind") - protected long write(VirtualFrame frame, long value) { + protected long writeLong(VirtualFrame frame, long value) { frame.setLong(getSlot(), value); return value; } @Specialization(guards = "isBooleanKind") - protected boolean write(VirtualFrame frame, boolean value) { + protected boolean writeBoolean(VirtualFrame frame, boolean value) { frame.setBoolean(getSlot(), value); return value; } @@ -66,14 +66,14 @@ /** * Generic write method that works for all possible types. *

    - * Why is this method annotated with {@link Specialization} and not {@link Generic}? For a - * {@link Generic} method, the Truffle DSL generated code would try all other specializations + * Why is this method annotated with {@link Specialization} and not {@link Fallback}? For a + * {@link Fallback} method, the Truffle DSL generated code would try all other specializations * first before calling this method. We know that all these specializations would fail their * guards, so there is no point in calling them. Since this method takes a value of type * {@link Object}, it is guaranteed to never fail, i.e., once we are in this specialization the * node will never be re-specialized. */ - @Specialization + @Specialization(contains = {"writeLong", "writeBoolean"}) protected Object write(VirtualFrame frame, Object value) { if (getSlot().getKind() != FrameSlotKind.Object) { /* diff -r ae0f235469db -r f8e60d11c0ec graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame Mon Aug 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame Mon Aug 25 21:15:59 2014 -0700 @@ -33,7 +33,6 @@ import com.oracle.truffle.api.source.*; import com.oracle.truffle.sl.*; import com.oracle.truffle.sl.nodes.*; -import com.oracle.truffle.sl.nodes.instrument.*; import com.oracle.truffle.sl.runtime.*; // Checkstyle: stop @@ -52,9 +51,9 @@ public final Errors errors; private final SLNodeFactory factory; -->declarations - public Parser(SLContext context, Source source, SLNodeProber astProber) { + public Parser(SLContext context, Source source) { this.scanner = new Scanner(source.getInputStream()); - this.factory = new SLNodeFactory(context, source, astProber); + this.factory = new SLNodeFactory(context, source); errors = new Errors(); } @@ -135,8 +134,8 @@ -->initialization }; - public static void parseSL(SLContext context, Source source, SLNodeProber astProber) { - Parser parser = new Parser(context, source, astProber); + public static void parseSL(SLContext context, Source source) { + Parser parser = new Parser(context, source); parser.Parse(); if (parser.errors.errors.size() > 0) { StringBuilder msg = new StringBuilder("Error(s) parsing script:\n"); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java Mon Aug 25 21:15:59 2014 -0700 @@ -30,7 +30,6 @@ import com.oracle.truffle.api.source.*; import com.oracle.truffle.sl.*; import com.oracle.truffle.sl.nodes.*; -import com.oracle.truffle.sl.nodes.instrument.*; import com.oracle.truffle.sl.runtime.*; // Checkstyle: stop @@ -54,9 +53,9 @@ public final Errors errors; private final SLNodeFactory factory; - public Parser(SLContext context, Source source, SLNodeProber astProber) { + public Parser(SLContext context, Source source) { this.scanner = new Scanner(source.getInputStream()); - this.factory = new SLNodeFactory(context, source, astProber); + this.factory = new SLNodeFactory(context, source); errors = new Errors(); } @@ -134,8 +133,10 @@ void Function() { Expect(4); Expect(1); - factory.startFunction(t); + Token identifierToken = t; Expect(5); + int bodyStartPos = t.charPos; + factory.startFunction(identifierToken, bodyStartPos); if (la.kind == 1) { Get(); factory.addFormalParameter(t); @@ -155,14 +156,14 @@ factory.startBlock(); List body = new ArrayList<>(); Expect(8); - int lBracePos = t.charPos; + int start = t.charPos; while (StartOf(1)) { SLStatementNode s = Statement(inLoop); body.add(s); } Expect(9); - int length = (t.charPos + t.val.length()) - lBracePos; - result = factory.finishBlock(body, lBracePos, length); + int length = (t.charPos + t.val.length()) - start; + result = factory.finishBlock(body, start, length); return result; } @@ -207,8 +208,8 @@ SLStatementNode WhileStatement() { SLStatementNode result; Expect(13); + Token whileToken = t; Expect(5); - Token whileToken = t; SLExpressionNode condition = Expression(); Expect(7); SLStatementNode body = Block(true); @@ -219,8 +220,8 @@ SLStatementNode IfStatement(boolean inLoop) { SLStatementNode result; Expect(14); + Token ifToken = t; Expect(5); - Token ifToken = t; SLExpressionNode condition = Expression(); Expect(7); SLStatementNode thenPart = Block(inLoop); @@ -376,8 +377,12 @@ result = factory.createNumericLiteral(t); } else if (la.kind == 5) { Get(); + int start = t.charPos; result = Expression(); + SLExpressionNode expr = result; Expect(7); + int length = (t.charPos + t.val.length()) - start; + result = factory.createParenExpression(expr, start, length); } else SynErr(33); return result; } @@ -402,8 +407,8 @@ }; - public static void parseSL(SLContext context, Source source, SLNodeProber astProber) { - Parser parser = new Parser(context, source, astProber); + public static void parseSL(SLContext context, Source source) { + Parser parser = new Parser(context, source); parser.Parse(); if (parser.errors.errors.size() > 0) { StringBuilder msg = new StringBuilder("Error(s) parsing script:\n"); diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java Mon Aug 25 21:15:59 2014 -0700 @@ -32,7 +32,6 @@ import com.oracle.truffle.sl.nodes.call.*; import com.oracle.truffle.sl.nodes.controlflow.*; import com.oracle.truffle.sl.nodes.expression.*; -import com.oracle.truffle.sl.nodes.instrument.*; import com.oracle.truffle.sl.nodes.local.*; import com.oracle.truffle.sl.runtime.*; @@ -65,7 +64,9 @@ private final Source source; /* State while parsing a function. */ + private int functionStartPos; private String functionName; + private int functionBodyStartPos; // includes parameter list private int parameterCount; private FrameDescriptor frameDescriptor; private List methodNodes; @@ -73,21 +74,22 @@ /* State while parsing a block. */ private LexicalScope lexicalScope; - private final SLNodeProber prober; - - public SLNodeFactory(SLContext context, Source source, SLNodeProber prober) { + public SLNodeFactory(SLContext context, Source source) { this.context = context; this.source = source; - this.prober = prober; } - public void startFunction(Token nameToken) { + public void startFunction(Token nameToken, int bodyStartPos) { + assert functionStartPos == 0; assert functionName == null; + assert functionBodyStartPos == 0; assert parameterCount == 0; assert frameDescriptor == null; assert lexicalScope == null; + functionStartPos = nameToken.charPos; functionName = nameToken.val; + functionBodyStartPos = bodyStartPos; frameDescriptor = new FrameDescriptor(); methodNodes = new ArrayList<>(); startBlock(); @@ -99,24 +101,27 @@ * ensures that accesses to parameters are specialized the same way as local variables are * specialized. */ - final SourceSection src = source.createSection(nameToken.val, nameToken.charPos, nameToken.val.length()); - SLReadArgumentNode readArg = new SLReadArgumentNode(src, parameterCount); + final SourceSection src = srcFromToken(nameToken); + final SLReadArgumentNode readArg = new SLReadArgumentNode(src, parameterCount); methodNodes.add(createAssignment(nameToken, readArg)); parameterCount++; } public void finishFunction(SLStatementNode bodyNode) { methodNodes.add(bodyNode); - // TODO (mlvdv) testing - SLStatementNode methodBlock = finishBlock(methodNodes, -1, -1); + final int bodyEndPos = bodyNode.getSourceSection().getCharEndIndex(); + final SourceSection functionSrc = source.createSection(functionName, functionStartPos, bodyEndPos - functionStartPos); + final SLStatementNode methodBlock = finishBlock(methodNodes, functionBodyStartPos, bodyEndPos - functionBodyStartPos); assert lexicalScope == null : "Wrong scoping of blocks in parser"; - SLFunctionBodyNode functionBodyNode = new SLFunctionBodyNode(methodBlock); - SLRootNode rootNode = new SLRootNode(frameDescriptor, functionBodyNode, functionName); + final SLFunctionBodyNode functionBodyNode = new SLFunctionBodyNode(functionSrc, methodBlock); + final SLRootNode rootNode = new SLRootNode(frameDescriptor, functionBodyNode, functionName); context.getFunctionRegistry().register(functionName, rootNode); + functionStartPos = 0; functionName = null; + functionBodyStartPos = 0; parameterCount = 0; frameDescriptor = null; lexicalScope = null; @@ -126,34 +131,14 @@ lexicalScope = new LexicalScope(lexicalScope); } - public SLStatementNode finishBlock(List 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 +151,82 @@ } } - public SLStatementNode createBreak(Token t) { - return new SLBreakNode(source.createSection(t.val, t.charPos, t.val.length())); + /** + * Returns an {@link SLBreakNode} for the given token. + * + * @param breakToken The token containing the break node's info. + * @return A SLBreakNode for the given token. + */ + public SLStatementNode createBreak(Token breakToken) { + final SLBreakNode breakNode = new SLBreakNode(srcFromToken(breakToken)); + return breakNode; } - public SLStatementNode createContinue(Token t) { - return new SLContinueNode(source.createSection(t.val, t.charPos, t.val.length())); - } - - public SLStatementNode createWhile(Token t, SLExpressionNode conditionNode, SLStatementNode bodyNode) { - final int start = t.charPos; - final int end = bodyNode.getSourceSection().getCharEndIndex(); - return new SLWhileNode(source.createSection(t.val, start, end - start), conditionNode, bodyNode); + /** + * Returns an {@link SLContinueNode} for the given token. + * + * @param continueToken The token containing the continue node's info. + * @return A SLContinueNode built using the given token. + */ + public SLStatementNode createContinue(Token continueToken) { + final SLContinueNode continueNode = new SLContinueNode(srcFromToken(continueToken)); + return continueNode; } - public SLStatementNode createIf(Token t, SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) { - final int start = t.charPos; - final int end = elsePartNode == null ? thenPartNode.getSourceSection().getCharEndIndex() : elsePartNode.getSourceSection().getCharEndIndex(); - - // if (prober != null) { - // SLStatementNode wrappedThenNode = prober.probeAsStatement(thenPartNode); - // // SLStatementNode wrappedElseNode = prober.probeAsStatement(elsePartNode); - // return new SLIfNode(source.createSection(t.val, start, end - start), conditionNode, - // wrappedThenNode, elsePartNode); - // } - - return new SLIfNode(source.createSection(t.val, start, end - start), conditionNode, thenPartNode, elsePartNode); + /** + * Returns an {@link SLWhileNode} for the given parameters. + * + * @param whileToken The token containing the while node's info + * @param conditionNode The conditional node for this while loop + * @param bodyNode The body of the while loop + * @return A SLWhileNode built using the given parameters. + */ + public SLStatementNode createWhile(Token whileToken, SLExpressionNode conditionNode, SLStatementNode bodyNode) { + final int start = whileToken.charPos; + final int end = bodyNode.getSourceSection().getCharEndIndex(); + final SLWhileNode whileNode = new SLWhileNode(source.createSection(whileToken.val, start, end - start), conditionNode, bodyNode); + return whileNode; } + /** + * Returns an {@link SLIfNode} for the given parameters. + * + * @param ifToken The token containing the if node's info + * @param conditionNode The condition node of this if statement + * @param thenPartNode The then part of the if + * @param elsePartNode The else part of the if + * @return An SLIfNode for the given parameters. + */ + public SLStatementNode createIf(Token ifToken, SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) { + final int start = ifToken.charPos; + final int end = elsePartNode == null ? thenPartNode.getSourceSection().getCharEndIndex() : elsePartNode.getSourceSection().getCharEndIndex(); + final SLIfNode ifNode = new SLIfNode(source.createSection(ifToken.val, start, end - start), conditionNode, thenPartNode, elsePartNode); + return ifNode; + } + + /** + * Returns an {@link SLReturnNode} for the given parameters. + * + * @param t The token containing the return node's info + * @param valueNode The value of the return + * @return An SLReturnNode for the given parameters. + */ public SLStatementNode createReturn(Token t, SLExpressionNode valueNode) { final int start = t.charPos; final int length = valueNode == null ? t.val.length() : valueNode.getSourceSection().getCharEndIndex() - start; - return new SLReturnNode(source.createSection(t.val, start, length), valueNode); + final SLReturnNode returnNode = new SLReturnNode(source.createSection(t.val, start, length), valueNode); + return returnNode; } + /** + * Returns the corresponding subclass of {@link SLExpressionNode} for binary expressions. + *
    These nodes are currently not instrumented. + * + * @param opToken The operator of the binary expression + * @param leftNode The left node of the expression + * @param rightNode The right node of the expression + * @return A subclass of SLExpressionNode using the given parameters based on the given opToken. + */ public SLExpressionNode createBinary(Token opToken, SLExpressionNode leftNode, SLExpressionNode rightNode) { int start = leftNode.getSourceSection().getCharIndex(); int length = rightNode.getSourceSection().getCharEndIndex() - start; @@ -234,33 +261,52 @@ } } + /** + * Returns an {@link SLInvokeNode} for the given parameters. + * + * @param nameToken The name of the function being called + * @param parameterNodes The parameters of the function call + * @param finalToken A token used to determine the end of the sourceSelection for this call + * @return An SLInvokeNode for the given parameters. + */ public SLExpressionNode createCall(Token nameToken, List parameterNodes, Token finalToken) { final int startPos = nameToken.charPos; final int endPos = finalToken.charPos + finalToken.val.length(); final SourceSection src = source.createSection(nameToken.val, startPos, endPos - startPos); SLExpressionNode functionNode = createRead(nameToken); - if (prober != null) { - SLExpressionNode wrappedNode = prober.probeAsCall(functionNode, nameToken.val); - return SLInvokeNode.create(src, wrappedNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()])); - } return SLInvokeNode.create(src, functionNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()])); } + /** + * Returns an {@link SLWriteLocalVariableNode} for the given parameters. + * + * @param nameToken The name of the variable being assigned + * @param valueNode The value to be assigned + * @return An SLExpressionNode for the given parameters. + */ public SLExpressionNode createAssignment(Token nameToken, SLExpressionNode valueNode) { FrameSlot frameSlot = frameDescriptor.findOrAddFrameSlot(nameToken.val); lexicalScope.locals.put(nameToken.val, frameSlot); final int start = nameToken.charPos; final int length = valueNode.getSourceSection().getCharEndIndex() - start; - if (prober != null) { - final SLExpressionNode wrappedNode = prober.probeAsLocalAssignment(valueNode, nameToken.val); - return SLWriteLocalVariableNodeFactory.create(source.createSection("=", start, length), wrappedNode, frameSlot); - } return SLWriteLocalVariableNodeFactory.create(source.createSection("=", start, length), valueNode, frameSlot); } + /** + * Returns a {@link SLReadLocalVariableNode} if this read is a local variable or a + * {@link SLFunctionLiteralNode} if this read is global. In Simple, the only global names are + * functions.
    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 +320,14 @@ /* Remove the trailing and ending " */ String literal = literalToken.val; assert literal.length() >= 2 && literal.startsWith("\"") && literal.endsWith("\""); - final SourceSection src = source.createSection(literalToken.val, literalToken.charPos, literalToken.val.length()); + final SourceSection src = srcFromToken(literalToken); literal = literal.substring(1, literal.length() - 1); return new SLStringLiteralNode(src, literal); } public SLExpressionNode createNumericLiteral(Token literalToken) { - final SourceSection src = source.createSection(literalToken.val, literalToken.charPos, literalToken.val.length()); + final SourceSection src = srcFromToken(literalToken); try { /* Try if the literal is small enough to fit into a long value. */ return new SLLongLiteralNode(src, Long.parseLong(literalToken.val)); @@ -291,4 +337,16 @@ } } + public SLExpressionNode createParenExpression(SLExpressionNode expressionNode, int start, int length) { + final SourceSection src = source.createSection("()", start, length); + return new SLParenExpressionNode(src, expressionNode); + } + + /** + * Creates source description of a single token. + */ + private SourceSection srcFromToken(Token token) { + return source.createSection(token.val, token.charPos, token.val.length()); + } + } diff -r ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg Mon Aug 25 21:15:59 2014 -0700 @@ -65,9 +65,10 @@ Function = -"function" -identifier (. factory.startFunction(t); .) -"(" +"function" +identifier (. Token identifierToken = t; .) +"(" (. int bodyStartPos = t.charPos; .) + (. factory.startFunction(identifierToken, bodyStartPos); .) [ identifier (. factory.addFormalParameter(t); .) { @@ -84,12 +85,12 @@ Block = (. 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 ae0f235469db -r f8e60d11c0ec 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 25 14:42:42 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java Mon Aug 25 21:15:59 2014 -0700 @@ -33,7 +33,6 @@ import com.oracle.truffle.sl.*; import com.oracle.truffle.sl.builtins.*; import com.oracle.truffle.sl.nodes.*; -import com.oracle.truffle.sl.nodes.instrument.*; import com.oracle.truffle.sl.nodes.local.*; import com.oracle.truffle.sl.parser.*; @@ -52,7 +51,6 @@ private final PrintStream output; private final SLFunctionRegistry functionRegistry; private SourceCallback sourceCallback = null; - private SLASTProber astProber; public SLContext(BufferedReader input, PrintStream output) { this.input = input; @@ -138,13 +136,23 @@ getFunctionRegistry().register(name, rootNode); } + /** + * This function will parse the given source code, parse the code using the {@link Parser}, and + * then execute the function named main. To use this method with instrumentation, + * setASTNodeProber must have been already called. There is currently no guard to check if this + * is the case.
    + * Due to the experimental nature of the instrumentation framework, the parse that happens in + * this method will remove any previously added instrumentation. + * + * @param source The {@link Source} to execute. + */ public void executeMain(Source source) { if (sourceCallback != null) { sourceCallback.startLoading(source); } - Parser.parseSL(this, source, astProber); + Parser.parseSL(this, source); if (sourceCallback != null) { sourceCallback.endLoading(source); @@ -156,9 +164,4 @@ } main.getCallTarget().call(); } - - public void setASTNodeProber(SLASTProber astProber) { - // TODO Auto-generated method stub - this.astProber = astProber; - } } diff -r ae0f235469db -r f8e60d11c0ec make/Makefile --- a/make/Makefile Mon Aug 25 14:42:42 2014 -0700 +++ b/make/Makefile Mon Aug 25 21:15:59 2014 -0700 @@ -567,6 +567,9 @@ $(EXPORT_JRE_LIB_DIR)/%.jar: $(SHARED_DIR)/%.jar $(install-file) +$(EXPORT_JRE_LIB_EXT_DIR)/%.jar: $(SHARED_DIR)/%.jar + $(install-file) + $(EXPORT_INCLUDE_DIR)/%: $(HS_SRC_DIR)/share/vm/code/% $(install-file) diff -r ae0f235469db -r f8e60d11c0ec make/defs.make --- a/make/defs.make Mon Aug 25 14:42:42 2014 -0700 +++ b/make/defs.make Mon Aug 25 21:15:59 2014 -0700 @@ -331,6 +331,7 @@ EXPORT_JRE_DIR = $(EXPORT_PATH)/jre EXPORT_JRE_BIN_DIR = $(EXPORT_JRE_DIR)/bin EXPORT_JRE_LIB_DIR = $(EXPORT_JRE_DIR)/lib +EXPORT_JRE_LIB_EXT_DIR = $(EXPORT_JRE_LIB_DIR)/ext EXPORT_JRE_LIB_ARCH_DIR = $(EXPORT_JRE_LIB_DIR)/$(LIBARCH) # non-universal macosx builds need to appear universal @@ -347,6 +348,9 @@ EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/$(JDK_INCLUDE_SUBDIR)/jni_md.h EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jmm.h EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/graal.jar +EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/graal-truffle.jar +EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/graal-loader.jar +EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/truffle.jar .PHONY: $(HS_ALT_MAKE)/defs.make diff -r ae0f235469db -r f8e60d11c0ec mx/mx_graal.py --- a/mx/mx_graal.py Mon Aug 25 14:42:42 2014 -0700 +++ b/mx/mx_graal.py Mon Aug 25 21:15:59 2014 -0700 @@ -83,8 +83,21 @@ _minVersion = mx.VersionSpec('1.8') +class JDKDeployedDist: + def __init__(self, name, isExtension): + self.name = name + self.isExtension = isExtension + +_jdkDeployedDists = [ + JDKDeployedDist('TRUFFLE', isExtension=False), + JDKDeployedDist('GRAAL_LOADER', isExtension=False), + JDKDeployedDist('GRAAL', isExtension=False), + JDKDeployedDist('GRAAL_TRUFFLE', isExtension=False) +] + JDK_UNIX_PERMISSIONS_DIR = 0755 JDK_UNIX_PERMISSIONS_FILE = 0644 +JDK_UNIX_PERMISSIONS_EXEC = 0755 def isVMSupported(vm): if 'client' in vm and len(platform.mac_ver()[0]) != 0: @@ -458,10 +471,10 @@ _handle_missing_VM(build, vmToCheck if vmToCheck else 'graal') if installJars: - _installDistInJdks(mx.distribution('GRAAL')) - _installDistInJdks(mx.distribution('GRAAL_LOADER')) - _installDistInJdks(mx.distribution('TRUFFLE')) - _installDistInJdks(mx.distribution('GRAAL_TRUFFLE')) + for jdkDist in _jdkDeployedDists: + dist = mx.distribution(jdkDist.name) + if exists(dist.path): + _installDistInJdks(dist, jdkDist.isExtension) if vmToCheck is not None: jvmCfg = _vmCfgInJdk(jdk) @@ -545,7 +558,29 @@ os.unlink(javaSource) os.unlink(javaClass) -def _installDistInJdks(dist): +def _copyToJdk(src, dst, permissions=JDK_UNIX_PERMISSIONS_FILE): + name = os.path.basename(src) + dstLib = join(dst, name) + if mx.get_env('SYMLINK_GRAAL_JAR', None) == 'true': + # Using symlinks is much faster than copying but may + # cause issues if the lib is being updated while + # the VM is running. + if not os.path.islink(dstLib) or not os.path.realpath(dstLib) == src: + if exists(dstLib): + os.remove(dstLib) + os.symlink(src, dstLib) + else: + # do a copy and then a move to get atomic updating (on Unix) + fd, tmp = tempfile.mkstemp(suffix='', prefix=name, dir=dst) + shutil.copyfile(src, tmp) + os.close(fd) + shutil.move(tmp, dstLib) + os.chmod(dstLib, permissions) + +def _installDistInJdksExt(dist): + _installDistInJdks(dist, True) + +def _installDistInJdks(dist, ext=False): """ Installs the jar(s) for a given Distribution into all existing Graal JDKs """ @@ -557,29 +592,12 @@ if exists(jdks): for e in os.listdir(jdks): jreLibDir = join(jdks, e, 'jre', 'lib') + if ext: + jreLibDir = join(jreLibDir, 'ext') if exists(jreLibDir): - def install(srcJar, dstDir): - name = os.path.basename(srcJar) - dstJar = join(dstDir, name) - if mx.get_env('SYMLINK_GRAAL_JAR', None) == 'true': - # Using symlinks is much faster than copying but may - # cause issues if the jar is being updated while - # the VM is running. - if not os.path.islink(dstJar) or not os.path.realpath(dstJar) == srcJar: - if exists(dstJar): - os.remove(dstJar) - os.symlink(srcJar, dstJar) - else: - # do a copy and then a move to get atomic updating (on Unix) - fd, tmp = tempfile.mkstemp(suffix='', prefix=name, dir=dstDir) - shutil.copyfile(srcJar, tmp) - os.close(fd) - shutil.move(tmp, dstJar) - os.chmod(dstJar, JDK_UNIX_PERMISSIONS_FILE) - - install(dist.path, jreLibDir) + _copyToJdk(dist.path, jreLibDir) if dist.sourcesPath: - install(dist.sourcesPath, join(jdks, e)) + _copyToJdk(dist.sourcesPath, join(jdks, e)) # run a command in the windows SDK Debug Shell def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo=None): @@ -679,17 +697,19 @@ # extract latest release tag for graal try: tags = [x.split() for x in subprocess.check_output(['hg', '-R', _graal_home, 'tags']).split('\n') if x.startswith("graal-")] - current_revision = subprocess.check_output(['hg', '-R', _graal_home, 'id', '-i']).strip() + current_id = subprocess.check_output(['hg', '-R', _graal_home, 'log', '--template', '{rev}\n', '--rev', 'tip']).strip() except: # not a mercurial repository or hg commands are not available. tags = None - if tags and current_revision: + if tags and current_id: sorted_tags = sorted(tags, key=lambda e: [int(x) for x in e[0][len("graal-"):].split('.')], reverse=True) most_recent_tag_name, most_recent_tag_revision = sorted_tags[0] + most_recent_tag_id = most_recent_tag_revision[:most_recent_tag_revision.index(":")] most_recent_tag_version = most_recent_tag_name[len("graal-"):] - if current_revision == most_recent_tag_revision: + # tagged commit is one-off with commit that tags it + if int(current_id) - int(most_recent_tag_id) <= 1: cached_graal_version = most_recent_tag_version else: major, minor = map(int, most_recent_tag_version.split('.')) @@ -731,8 +751,19 @@ else: assert os.path.isdir(opts2.export_dir), '{} is not a directory'.format(opts2.export_dir) - shutil.copy(mx.distribution('GRAAL').path, opts2.export_dir) - shutil.copy(mx.distribution('GRAAL_LOADER').path, opts2.export_dir) + defsPath = join(_graal_home, 'make', 'defs.make') + with open(defsPath) as fp: + defs = fp.read() + for jdkDist in _jdkDeployedDists: + dist = mx.distribution(jdkDist.name) + defLine = 'EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/' + basename(dist.path) + if jdkDist.isExtension: + defLine = 'EXPORT_LIST += $(EXPORT_JRE_LIB_EXT_DIR)/' + basename(dist.path) + else: + defLine = 'EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/' + basename(dist.path) + if defLine not in defs: + mx.abort('Missing following line in ' + defsPath + '\n' + defLine) + shutil.copy(dist.path, opts2.export_dir) graalOptions = join(_graal_home, 'graal.options') if exists(graalOptions): shutil.copy(graalOptions, opts2.export_dir) @@ -765,7 +796,7 @@ if build is None or len(build) == 0: continue - jdk = _jdk(build, create=True) + jdk = _jdk(build, create=True, installJars=vm != 'original' and not opts2.java) if vm == 'original': if build != 'product': @@ -981,6 +1012,10 @@ if len(ignoredArgs) > 0: mx.log("Warning: The following options will be ignored by the vm because they come after the '-version' argument: " + ' '.join(ignoredArgs)) + if vm == 'original': + truffle_jar = mx.archive(['@TRUFFLE'])[0] + args = ['-Xbootclasspath/p:' + truffle_jar] + args + args = mx.java().processArgs(args) return (pfx, exe, vm, args, cwd) @@ -1119,9 +1154,11 @@ # access core Graal classes. cp = prefixCp + coreCp + os.pathsep + projectsCp if isGraalEnabled(_get_vm()): - graalDist = mx.distribution('GRAAL') - graalJarCp = set([d.output_dir() for d in graalDist.sorted_deps()]) - cp = os.pathsep.join([e for e in cp.split(os.pathsep) if e not in graalJarCp]) + excluded = set() + for jdkDist in _jdkDeployedDists: + dist = mx.distribution(jdkDist.name) + excluded.update([d.output_dir() for d in dist.sorted_deps()]) + cp = os.pathsep.join([e for e in cp.split(os.pathsep) if e not in excluded]) vmArgs = ['-XX:-UseGraalClassLoader'] + vmArgs if len(testclasses) == 1: @@ -1541,11 +1578,12 @@ mx.logv('[This execution may take a while as the NetBeans platform needs to be downloaded]') mx.run(['ant', '-f', join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml'), '-l', fp.name, 'run'], env=env) -def install(args): +def maven_install_truffle(args): """install Truffle into your local Maven repository""" - mx.archive(["@TRUFFLE"]) - mx.run(['mvn', 'install:install-file', '-DgroupId=com.oracle', '-DartifactId=truffle', '-Dversion=' + graal_version('SNAPSHOT'), '-Dpackaging=jar', '-Dfile=truffle.jar']) - mx.run(['mvn', 'install:install-file', '-DgroupId=com.oracle', '-DartifactId=truffle-dsl-processor', '-Dversion=' + graal_version('SNAPSHOT'), '-Dpackaging=jar', '-Dfile=truffle-dsl-processor.jar']) + for name in ['TRUFFLE', 'TRUFFLE-DSL-PROCESSOR']: + mx.archive(["@" + name]) + path = mx._dists[name].path + mx.run(['mvn', 'install:install-file', '-DgroupId=com.oracle', '-DartifactId=' + name.lower(), '-Dversion=' + graal_version('SNAPSHOT'), '-Dpackaging=jar', '-Dfile=' + path]) def c1visualizer(args): """run the Cl Compiler Visualizer""" @@ -1878,7 +1916,7 @@ _run_benchmark(args, sorted(availableBenchmarks), launcher) def specjbb2013(args): - """runs the composite SPECjbb2013 benchmark""" + """run the composite SPECjbb2013 benchmark""" def launcher(bm, harnessArgs, extraVmOpts): assert bm is None @@ -1887,7 +1925,7 @@ _run_benchmark(args, None, launcher) def specjbb2005(args): - """runs the composite SPECjbb2005 benchmark""" + """run the composite SPECjbb2005 benchmark""" def launcher(bm, harnessArgs, extraVmOpts): assert bm is None @@ -2156,7 +2194,7 @@ cmd = ['-jar', findbugsJar, '-textui', '-low', '-maxRank', '15'] if sys.stdout.isatty(): cmd.append('-progress') - cmd = cmd + ['-auxclasspath', mx.classpath(['GRAAL'] + [p.name for p in nonTestProjects]), '-output', findbugsResults, '-exitcode'] + args + outputDirs + cmd = cmd + ['-auxclasspath', mx.classpath([d.name for d in _jdkDeployedDists] + [p.name for p in nonTestProjects]), '-output', findbugsResults, '-exitcode'] + args + outputDirs exitcode = mx.run_java(cmd, nonZeroIsFatal=False) if exitcode != 0: with open(findbugsResults) as fp: @@ -2206,7 +2244,7 @@ 'hsdis': [hsdis, '[att]'], 'hcfdis': [hcfdis, ''], 'igv' : [igv, ''], - 'install' : [install, ''], + 'maven-install-truffle' : [maven_install_truffle, ''], 'jdkhome': [print_jdkhome, ''], 'jmh': [jmh, '[VM options] [filters|JMH-args-as-json...]'], 'dacapo': [dacapo, '[VM options] benchmarks...|"all" [DaCapo options]'], @@ -2272,7 +2310,8 @@ global _vm_prefix _vm_prefix = opts.vm_prefix - mx.distribution('GRAAL').add_update_listener(_installDistInJdks) - mx.distribution('GRAAL_LOADER').add_update_listener(_installDistInJdks) - mx.distribution('TRUFFLE').add_update_listener(_installDistInJdks) - mx.distribution('GRAAL_TRUFFLE').add_update_listener(_installDistInJdks) + for jdkDist in _jdkDeployedDists: + if jdkDist.isExtension: + mx.distribution(jdkDist.name).add_update_listener(_installDistInJdksExt) + else: + mx.distribution(jdkDist.name).add_update_listener(_installDistInJdks) diff -r ae0f235469db -r f8e60d11c0ec mx/projects --- a/mx/projects Mon Aug 25 14:42:42 2014 -0700 +++ b/mx/projects Mon Aug 25 21:15:59 2014 -0700 @@ -77,14 +77,15 @@ library@JAVA_ALLOCATION_INSTRUMENTER@sourcePath=lib/java-allocation-instrumenter.jar library@JAVA_ALLOCATION_INSTRUMENTER@urls=http://lafo.ssw.uni-linz.ac.at/java-allocation-instrumenter/java-allocation-instrumenter-8f0db117e64e.jar library@JAVA_ALLOCATION_INSTRUMENTER@sha1=476d9a44cd19d6b55f81571077dfa972a4f8a083 +library@JAVA_ALLOCATION_INSTRUMENTER@bootClassPathAgent=true library@VECMATH@path=lib/vecmath-1.3.1.jar library@VECMATH@urls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/vecmath-1.3.1.jar,http://mirrors.ibiblio.org/pub/mirrors/maven/java3d/jars/vecmath-1.3.1.jar library@VECMATH@sha1=a0ae4f51da409fa0c20fa0ca59e6bbc9413ae71d -distribution@GRAAL@path=graal.jar +distribution@GRAAL@path=build/graal.jar distribution@GRAAL@subDir=graal -distribution@GRAAL@sourcesPath=graal.src.zip +distribution@GRAAL@sourcesPath=build/graal.src.zip distribution@GRAAL@dependencies=\ com.oracle.graal.hotspot.amd64,\ com.oracle.graal.hotspot.ptx,\ @@ -94,33 +95,48 @@ com.oracle.graal.hotspot.hsail distribution@GRAAL@exclude=FINDBUGS -distribution@GRAAL_LOADER@path=graal-loader.jar +distribution@GRAAL_LOADER@path=build/graal-loader.jar distribution@GRAAL_LOADER@subDir=graal -distribution@GRAAL_LOADER@sourcesPath=graal-loader.src.zip +distribution@GRAAL_LOADER@sourcesPath=build/graal-loader.src.zip distribution@GRAAL_LOADER@dependencies=com.oracle.graal.hotspot.loader -distribution@TRUFFLE@path=truffle.jar +distribution@TRUFFLE@path=build/truffle.jar distribution@TRUFFLE@subDir=graal -distribution@TRUFFLE@sourcesPath=truffle-sources.jar +distribution@TRUFFLE@sourcesPath=build/truffle.src.zip distribution@TRUFFLE@dependencies=\ -com.oracle.truffle.api.dsl +com.oracle.truffle.api.dsl,\ +com.oracle.nfi -distribution@GRAAL_TRUFFLE@path=graal-truffle.jar +distribution@GRAAL_TRUFFLE@path=build/graal-truffle.jar distribution@GRAAL_TRUFFLE@subDir=graal -distribution@GRAAL_TRUFFLE@sourcesPath=graal-truffle-sources.jar +distribution@GRAAL_TRUFFLE@sourcesPath=build/graal-truffle.src.zip distribution@GRAAL_TRUFFLE@dependencies=\ com.oracle.graal.truffle,\ com.oracle.graal.truffle.hotspot.amd64 distribution@GRAAL_TRUFFLE@exclude=FINDBUGS distribution@GRAAL_TRUFFLE@distDependencies=GRAAL,TRUFFLE -distribution@TRUFFLE-DSL-PROCESSOR@path=truffle-dsl-processor.jar +distribution@TRUFFLE-DSL-PROCESSOR@path=build/truffle-dsl-processor.jar distribution@TRUFFLE-DSL-PROCESSOR@subDir=graal -distribution@TRUFFLE-DSL-PROCESSOR@sourcesPath=truffle-dsl-processor-sources.jar +distribution@TRUFFLE-DSL-PROCESSOR@sourcesPath=build/truffle-dsl-processor.src.zip distribution@TRUFFLE-DSL-PROCESSOR@dependencies=\ com.oracle.truffle.dsl.processor distribution@TRUFFLE-DSL-PROCESSOR@distDependencies=TRUFFLE +# nfi +project@com.oracle.nfi@subDir=graal +project@com.oracle.nfi@sourceDirs=src +project@com.oracle.nfi@dependencies= +project@com.oracle.nfi@checkstyle=com.oracle.graal.graph +project@com.oracle.nfi@javaCompliance=1.7 + +# nfi.test +project@com.oracle.nfi.test@subDir=graal +project@com.oracle.nfi.test@sourceDirs=test +project@com.oracle.nfi.test@dependencies=com.oracle.nfi,com.oracle.graal.compiler.common,JUNIT +project@com.oracle.nfi.test@checkstyle=com.oracle.graal.graph +project@com.oracle.nfi.test@javaCompliance=1.7 + # graal.api.collections project@com.oracle.graal.api.collections@subDir=graal project@com.oracle.graal.api.collections@sourceDirs=src @@ -212,14 +228,13 @@ project@com.oracle.graal.hotspotvmconfig@dependencies=com.oracle.graal.compiler.common project@com.oracle.graal.hotspotvmconfig@checkstyle=com.oracle.graal.graph project@com.oracle.graal.hotspotvmconfig@annotationProcessors=com.oracle.graal.service.processor -project@com.oracle.graal.hotspotvmconfig@annotationProcessorForDependents=true project@com.oracle.graal.hotspotvmconfig@javaCompliance=1.8 project@com.oracle.graal.hotspotvmconfig@workingSets=Graal,HotSpot # graal.hotspot project@com.oracle.graal.hotspot@subDir=graal project@com.oracle.graal.hotspot@sourceDirs=src -project@com.oracle.graal.hotspot@dependencies=com.oracle.graal.replacements,com.oracle.graal.runtime,com.oracle.graal.printer,com.oracle.graal.baseline,com.oracle.graal.hotspotvmconfig +project@com.oracle.graal.hotspot@dependencies=com.oracle.graal.replacements,com.oracle.graal.runtime,com.oracle.graal.printer,com.oracle.graal.baseline,com.oracle.graal.hotspotvmconfig,com.oracle.nfi project@com.oracle.graal.hotspot@checkstyle=com.oracle.graal.graph project@com.oracle.graal.hotspot@annotationProcessors=com.oracle.graal.replacements.verifier,com.oracle.graal.service.processor project@com.oracle.graal.hotspot@javaCompliance=1.8 @@ -303,18 +318,10 @@ project@com.oracle.graal.hotspot.test@javaCompliance=1.8 project@com.oracle.graal.hotspot.test@workingSets=Graal,HotSpot,Test -# graal.hotspot.jdk8.test -project@com.oracle.graal.hotspot.jdk8.test@subDir=graal -project@com.oracle.graal.hotspot.jdk8.test@sourceDirs=src -project@com.oracle.graal.hotspot.jdk8.test@dependencies=com.oracle.graal.compiler.test -project@com.oracle.graal.hotspot.jdk8.test@checkstyle=com.oracle.graal.graph -project@com.oracle.graal.hotspot.jdk8.test@javaCompliance=1.8 -project@com.oracle.graal.hotspot.jdk8.test@workingSets=Graal,HotSpot,Test - # graal.hotspot.amd64.test project@com.oracle.graal.hotspot.amd64.test@subDir=graal project@com.oracle.graal.hotspot.amd64.test@sourceDirs=src -project@com.oracle.graal.hotspot.amd64.test@dependencies=com.oracle.graal.asm.amd64,com.oracle.graal.compiler.test +project@com.oracle.graal.hotspot.amd64.test@dependencies=com.oracle.graal.asm.amd64,com.oracle.graal.compiler.test,com.oracle.graal.hotspot project@com.oracle.graal.hotspot.amd64.test@checkstyle=com.oracle.graal.graph project@com.oracle.graal.hotspot.amd64.test@javaCompliance=1.8 project@com.oracle.graal.hotspot.amd64.test@workingSets=Graal,HotSpot,AMD64,Test @@ -324,7 +331,6 @@ project@com.oracle.graal.options@sourceDirs=src project@com.oracle.graal.options@checkstyle=com.oracle.graal.graph project@com.oracle.graal.options@javaCompliance=1.8 -project@com.oracle.graal.options@annotationProcessorForDependents=true project@com.oracle.graal.options@workingSets=Graal,Codegen # graal.options.test @@ -335,11 +341,27 @@ project@com.oracle.graal.options.test@javaCompliance=1.8 project@com.oracle.graal.options.test@workingSets=Graal +# graal.nodeinfo +project@com.oracle.graal.nodeinfo@subDir=graal +project@com.oracle.graal.nodeinfo@sourceDirs=src +project@com.oracle.graal.nodeinfo@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.nodeinfo@javaCompliance=1.8 +project@com.oracle.graal.nodeinfo@workingSets=Graal,Graph + +# graal.nodeinfo.processor +project@com.oracle.graal.nodeinfo.processor@subDir=graal +project@com.oracle.graal.nodeinfo.processor@sourceDirs=src +project@com.oracle.graal.nodeinfo.processor@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.nodeinfo.processor@dependencies=com.oracle.graal.nodeinfo,com.oracle.truffle.dsl.processor +project@com.oracle.graal.nodeinfo.processor@javaCompliance=1.8 +project@com.oracle.graal.nodeinfo.processor@workingSets=Graal,Graph + # graal.graph project@com.oracle.graal.graph@subDir=graal project@com.oracle.graal.graph@sourceDirs=src -project@com.oracle.graal.graph@dependencies=com.oracle.graal.debug,com.oracle.graal.compiler.common,com.oracle.graal.api.collections,com.oracle.graal.api.runtime,FINDBUGS +project@com.oracle.graal.graph@dependencies=com.oracle.graal.nodeinfo,com.oracle.graal.debug,com.oracle.graal.compiler.common,com.oracle.graal.api.collections,com.oracle.graal.api.runtime,FINDBUGS project@com.oracle.graal.graph@javaCompliance=1.8 +project@com.oracle.graal.graph@annotationProcessors=com.oracle.graal.nodeinfo.processor project@com.oracle.graal.graph@workingSets=Graal,Graph # graal.graph.test @@ -519,7 +541,6 @@ project@com.oracle.graal.compiler@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler@javaCompliance=1.8 project@com.oracle.graal.compiler@annotationProcessors=com.oracle.graal.service.processor -project@com.oracle.graal.compiler@annotationProcessorForDependents=true project@com.oracle.graal.compiler@workingSets=Graal # graal.compiler.amd64 diff -r ae0f235469db -r f8e60d11c0ec mxtool/mx.py --- a/mxtool/mx.py Mon Aug 25 14:42:42 2014 -0700 +++ b/mxtool/mx.py Mon Aug 25 21:15:59 2014 -0700 @@ -76,12 +76,18 @@ self.excludedDependencies = excludedDependencies self.distDependencies = distDependencies - def sorted_deps(self, includeLibs=False): + def sorted_deps(self, includeLibs=False, transitive=False): + deps = [] + if transitive: + for depDist in [distribution(name) for name in self.distDependencies]: + for d in depDist.sorted_deps(includeLibs=includeLibs, transitive=True): + if d not in deps: + deps.append(d) try: excl = [dependency(d) for d in self.excludedDependencies] except SystemExit as e: abort('invalid excluded dependency for {} distribution: {}'.format(self.name, e)) - return [d for d in sorted_deps(self.deps, includeLibs=includeLibs) if d not in excl] + return deps + [d for d in sorted_deps(self.deps, includeLibs=includeLibs) if d not in excl] def __str__(self): return self.name @@ -89,6 +95,21 @@ def add_update_listener(self, listener): self.update_listeners.add(listener) + """ + Gets the directory in which the IDE project configuration + for this distribution is generated. If this is a distribution + derived from a project defining an annotation processor, then + None is return to indicate no IDE configuration should be + created for this distribution. + """ + def get_ide_project_dir(self): + if hasattr(self, 'definingProject') and self.definingProject.definedAnnotationProcessorsDist == self: + return None + if hasattr(self, 'subDir'): + return join(self.suite.dir, self.subDir, self.name + '.dist') + else: + return join(self.suite.dir, self.name + '.dist') + def make_archive(self): # are sources combined into main archive? unified = self.path == self.sourcesPath @@ -234,6 +255,11 @@ self.workingSets = workingSets self.dir = d + # The annotation processors defined by this project + self.definedAnnotationProcessors = None + self.definedAnnotationProcessorsDist = None + + # Verify that a JDK exists for this project if its compliance level is # less than the compliance level of the default JDK jdk = java(self.javaCompliance) @@ -435,20 +461,47 @@ self._init_packages_and_imports() return self._imported_java_packages + """ + Gets the list of projects defining the annotation processors that will be applied + when compiling this project. This includes the projects declared by the annotationProcessors property + of this project and any of its project dependencies. It also includes + any project dependencies that define an annotation processors. + """ def annotation_processors(self): if not hasattr(self, '_annotationProcessors'): - ap = set() + aps = set() if hasattr(self, '_declaredAnnotationProcessors'): - ap = set(self._declaredAnnotationProcessors) - - # find dependencies that auto-inject themselves as annotation processors to all dependents + aps = set(self._declaredAnnotationProcessors) + for ap in aps: + if project(ap).definedAnnotationProcessorsDist is None: + config = join(project(ap).source_dirs()[0], 'META-INF', 'services', 'javax.annotation.processing.Processor') + if not exists(config): + TimeStampFile(config).touch() + abort('Project ' + ap + ' declared in annotationProcessors property of ' + self.name + ' does not define any annotation processors.\n' + + 'Please specify the annotation processors in ' + config) + allDeps = self.all_deps([], includeLibs=False, includeSelf=False, includeAnnotationProcessors=False) for p in allDeps: - if hasattr(p, 'annotationProcessorForDependents') and p.annotationProcessorForDependents.lower() == 'true': - ap.add(p.name) - self._annotationProcessors = list(ap) + # Add an annotation processor dependency + if p.definedAnnotationProcessorsDist is not None: + aps.add(p.name) + + # Inherit annotation processors from dependencies + aps.update(p.annotation_processors()) + + self._annotationProcessors = list(aps) return self._annotationProcessors + """ + Gets the class path composed of the distribution jars containing the + annotation processors that will be applied when compiling this project. + """ + def annotation_processors_path(self): + aps = [project(ap) for ap in self.annotation_processors()] + if len(aps): + return os.pathsep.join([ap.definedAnnotationProcessorsDist.path for ap in aps if ap.definedAnnotationProcessorsDist]) + return None + def update_current_annotation_processors_file(self): aps = self.annotation_processors() outOfDate = False @@ -497,7 +550,7 @@ d.update(buf) return d.hexdigest() -def download_file_with_sha1(name, path, urls, sha1, sha1path, resolve, mustExist, sources=False): +def download_file_with_sha1(name, path, urls, sha1, sha1path, resolve, mustExist, sources=False, canSymlink=True): def _download_lib(): cacheDir = get_env('MX_CACHE_DIR', join(_opts.user_home, '.mx', 'cache')) if not exists(cacheDir): @@ -514,7 +567,8 @@ d = dirname(path) if d != '' and not exists(d): os.makedirs(d) - if 'symlink' in dir(os): + + if canSymlink and 'symlink' in dir(os): if exists(path): os.unlink(path) os.symlink(cachePath, path) @@ -557,16 +611,16 @@ return not result """ -A library that will be provided by the JDK but may be absent. +A library that will be provided by the JRE but may be absent. Any project or normal library that depends on a missing library will be removed from the global project and library dictionaries (i.e., _projects and _libs). This mechanism exists primarily to be able to support code -that may use functionality in one JDK (e.g., Oracle JDK) -that is not present in another JDK (e.g., OpenJDK). A +that may use functionality in one JRE (e.g., Oracle JRE) +that is not present in another JRE (e.g., OpenJDK). A motivating example is the Java Flight Recorder library -found in the Oracle JDK. +found in the Oracle JRE. """ class JreLibrary(BaseLibrary): def __init__(self, suite, name, jar, optional): @@ -648,7 +702,9 @@ if includedInJDK and java().javaCompliance >= JavaCompliance(includedInJDK): return None - return download_file_with_sha1(self.name, path, self.urls, self.sha1, sha1path, resolve, not self.optional) + bootClassPathAgent = getattr(self, 'bootClassPathAgent').lower() == 'true' if hasattr(self, 'bootClassPathAgent') else False + + return download_file_with_sha1(self.name, path, self.urls, self.sha1, sha1path, resolve, not self.optional, canSymlink=not bootClassPathAgent) def get_source_path(self, resolve): if self.sourcePath is None: @@ -824,7 +880,6 @@ srcDirs = pop_list(attrs, 'sourceDirs') deps = pop_list(attrs, 'dependencies') ap = pop_list(attrs, 'annotationProcessors') - # deps += ap javaCompliance = attrs.pop('javaCompliance', None) subDir = attrs.pop('subDir', None) if subDir is None: @@ -874,6 +929,52 @@ d.__dict__.update(attrs) self.dists.append(d) + # Create a distribution for each project that defines annotation processors + for p in self.projects: + annotationProcessors = None + for srcDir in p.source_dirs(): + configFile = join(srcDir, 'META-INF', 'services', 'javax.annotation.processing.Processor') + if exists(configFile): + with open(configFile) as fp: + annotationProcessors = [ap.strip() for ap in fp] + if len(annotationProcessors) != 0: + for ap in annotationProcessors: + if not ap.startswith(p.name): + abort(ap + ' in ' + configFile + ' does not start with ' + p.name) + if annotationProcessors: + dname = p.name.replace('.', '_').upper() + apDir = join(p.dir, 'ap') + path = join(apDir, p.name + '.jar') + sourcesPath = None + deps = [p.name] + mainClass = None + exclDeps = [] + distDeps = [] + d = Distribution(self, dname, path, sourcesPath, deps, mainClass, exclDeps, distDeps) + d.subDir = os.path.relpath(os.path.dirname(p.dir), self.dir) + self.dists.append(d) + p.definedAnnotationProcessors = annotationProcessors + p.definedAnnotationProcessorsDist = d + d.definingProject = p + + # Restrict exported annotation processors to those explicitly defined by the project + def _refineAnnotationProcessorServiceConfig(dist): + aps = dist.definingProject.definedAnnotationProcessors + apsJar = dist.path + config = 'META-INF/services/javax.annotation.processing.Processor' + with zipfile.ZipFile(apsJar, 'r') as zf: + currentAps = zf.read(config).split() + if currentAps != aps: + logv('[updating ' + config + ' in ' + apsJar + ']') + with Archiver(apsJar) as arc, zipfile.ZipFile(apsJar, 'r') as lp: + for arcname in lp.namelist(): + if arcname == config: + arc.zf.writestr(arcname, '\n'.join(aps)) + else: + arc.zf.writestr(arcname, lp.read(arcname)) + d.add_update_listener(_refineAnnotationProcessorServiceConfig) + self.dists.append(d) + if self.name is None: abort('Missing "suite=" in ' + projectsFile) @@ -2044,9 +2145,8 @@ processorArgs = [] - aps = self.proj.annotation_processors() - if len(aps) > 0: - processorPath = classpath(aps, resolve=True) + processorPath = self.proj.annotation_processors_path() + if processorPath: genDir = self.proj.source_gen_dir() if exists(genDir): shutil.rmtree(genDir) @@ -2125,6 +2225,11 @@ jdtArgs.append('@' + argfile.name) run_java(jdtVmArgs + jdtArgs) + + # Create annotation processor jar for a project that defines annotation processors + if self.proj.definedAnnotationProcessorsDist: + self.proj.definedAnnotationProcessorsDist.make_archive() + finally: for n in toBeDeleted: os.remove(n) @@ -2208,6 +2313,7 @@ return outputDir tasks = {} + updatedAnnotationProcessorDists = set() for p in sortedProjects: if p.native: if args.native: @@ -2234,13 +2340,12 @@ sourceDirs = p.source_dirs() buildReason = 'forced build' if args.force else None taskDeps = [] - if not buildReason: - for dep in p.all_deps([], includeLibs=False, includeAnnotationProcessors=True): - taskDep = tasks.get(dep.name) - if taskDep: - if not buildReason: - buildReason = dep.name + ' rebuilt' - taskDeps.append(taskDep) + for dep in p.all_deps([], includeLibs=False, includeAnnotationProcessors=True): + taskDep = tasks.get(dep.name) + if taskDep: + if not buildReason: + buildReason = dep.name + ' rebuilt' + taskDeps.append(taskDep) jasminAvailable = None javafilelist = [] @@ -2309,6 +2414,8 @@ continue task = JavaCompileTask(args, p, buildReason, javafilelist, jdk, outputDir, jdtJar, taskDeps) + if p.definedAnnotationProcessorsDist: + updatedAnnotationProcessorDists.add(p.definedAnnotationProcessorsDist) if args.parallelize: # Best to initialize class paths on main process @@ -2409,8 +2516,10 @@ log('Compiling {} failed'.format(t.proj.name)) abort('{} Java compilation tasks failed'.format(len(failed))) - for dist in sorted_dists(): - archive(['@' + dist.name]) + if args.java: + for dist in sorted_dists(): + if dist not in updatedAnnotationProcessorDists: + archive(['@' + dist.name]) if suppliedParser: return args @@ -2591,18 +2700,13 @@ _processorjars_suite(s) def _processorjars_suite(s): - projs = set() - candidates = sorted_project_deps(s.projects) - for p in candidates: - if _isAnnotationProcessorDependency(p): - projs.add(p) - + projs = [p for p in s.projects if p.definedAnnotationProcessors is not None] if len(projs) <= 0: return [] pnames = [p.name for p in projs] build(['--jdt-warning-as-error', '--projects', ",".join(pnames)]) - return archive(pnames) + return [p.definedAnnotationProcessorsDist.path for p in s.projects if p.definedAnnotationProcessorsDist is not None] def pylint(args): """run pylint (if available) over Python source files (found by 'hg locate' or by tree walk with -walk)""" @@ -2681,6 +2785,8 @@ def __enter__(self): if self.path: + if not isdir(dirname(self.path)): + os.makedirs(dirname(self.path)) fd, tmp = tempfile.mkstemp(suffix='', prefix=basename(self.path) + '.', dir=dirname(self.path)) self.tmpFd = fd self.tmpPath = tmp @@ -2947,7 +3053,7 @@ shutil.rmtree(path) def _rmIfExists(name): - if os.path.isfile(name): + if name and os.path.isfile(name): os.unlink(name) for p in projects_opt_limit_to_suites(): @@ -3372,14 +3478,23 @@ out.element('arguments', data='') out.close('buildCommand') - # The path should always be p.name/dir. independent of where the workspace actually is. - # So we use the parent folder of the project, whatever that is, to generate such a relative path. - logicalWorkspaceRoot = os.path.dirname(p.dir) - binFolder = os.path.relpath(p.output_dir(), logicalWorkspaceRoot) - - if _isAnnotationProcessorDependency(p): - refreshFile = os.path.relpath(join(p.dir, p.name + '.jar'), logicalWorkspaceRoot) - _genEclipseBuilder(out, p, 'Jar', 'archive ' + p.name, refresh=True, refreshFile=refreshFile, relevantResources=[binFolder], async=True, xmlIndent='', xmlStandalone='no') + if p.definedAnnotationProcessorsDist: + # Create a launcher that will (re)build the annotation processor + # jar any time one of its sources is modified. + dist = p.definedAnnotationProcessorsDist + + distProjects = [d for d in dist.sorted_deps(transitive=True) if d.isProject()] + relevantResources = [] + for p in distProjects: + for srcDir in p.source_dirs(): + relevantResources.append(join(p.name, os.path.relpath(srcDir, p.dir))) + relevantResources.append(join(p.name, os.path.relpath(p.output_dir(), p.dir))) + + # The path should always be p.name/dir independent of where the workspace actually is. + # So we use the parent folder of the project, whatever that is, to generate such a relative path. + logicalWorkspaceRoot = os.path.dirname(p.dir) + refreshFile = os.path.relpath(p.definedAnnotationProcessorsDist.path, logicalWorkspaceRoot) + _genEclipseBuilder(out, p, 'CreateAnnotationProcessorJar', 'archive @' + dist.name, refresh=True, refreshFile=refreshFile, relevantResources=relevantResources, async=True, xmlIndent='', xmlStandalone='no') out.close('buildSpec') out.open('natures') @@ -3436,22 +3551,13 @@ if files: files.append(join(settingsDir, name)) - if len(p.annotation_processors()) > 0: + processorPath = p.annotation_processors_path() + if processorPath: out = XMLDoc() out.open('factorypath') out.element('factorypathentry', {'kind' : 'PLUGIN', 'id' : 'org.eclipse.jst.ws.annotations.core', 'enabled' : 'true', 'runInBatchMode' : 'false'}) - for ap in p.annotation_processors(): - for dep in dependency(ap).all_deps([], True): - if dep.isLibrary(): - # Relative paths for "lib" class path entries have various semantics depending on the Eclipse - # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's - # safest to simply use absolute paths. - path = _make_absolute(dep.get_path(resolve=True), p.suite.dir) - out.element('factorypathentry', {'kind' : 'EXTJAR', 'id' : path, 'enabled' : 'true', 'runInBatchMode' : 'false'}) - if files: - files.append(path) - elif dep.isProject(): - out.element('factorypathentry', {'kind' : 'WKSPJAR', 'id' : '/' + dep.name + '/' + dep.name + '.jar', 'enabled' : 'true', 'runInBatchMode' : 'false'}) + for e in processorPath.split(os.pathsep): + out.element('factorypathentry', {'kind' : 'EXTJAR', 'id' : e, 'enabled' : 'true', 'runInBatchMode' : 'false'}) out.close('factorypath') update_file(join(p.dir, '.factorypath'), out.xml(indent='\t', newl='\n')) if files: @@ -3467,8 +3573,6 @@ logv('[Eclipse configurations are up to date - skipping]') return - - files = [] libFiles = [] if buildProcessorJars: @@ -3477,24 +3581,21 @@ for p in suite.projects: if p.native: continue - _eclipseinit_project(p) + _eclipseinit_project(p, files, libFiles) _, launchFile = make_eclipse_attach(suite, 'localhost', '8000', deps=sorted_deps(projectNames=None, includeLibs=True)) files.append(launchFile) - _zip_files(files, suite.dir, configZip.path) - _zip_files(libFiles, suite.dir, configLibsZip) - # Create an Eclipse project for each distribution that will create/update the archive - # for the distribution whenever any project of the distribution is updated. + # for the distribution whenever any (transitively) dependent project of the + # distribution is updated. for dist in suite.dists: - if hasattr(dist, 'subDir'): - projectDir = join(suite.dir, dist.subDir, dist.name + '.dist') - else: - projectDir = join(suite.dir, dist.name + '.dist') + projectDir = dist.get_ide_project_dir() + if not projectDir: + continue if not exists(projectDir): os.makedirs(projectDir) - distProjects = [d for d in dist.sorted_deps() if d.isProject()] + distProjects = [d for d in dist.sorted_deps(transitive=True) if d.isProject()] relevantResources = [] for p in distProjects: for srcDir in p.source_dirs(): @@ -3512,7 +3613,7 @@ out.close('projects') out.open('buildSpec') dist.dir = projectDir - dist.javaCompliance = max([p.javaCompliance for p in distProjects] + [JavaCompliance('1.8')]) + dist.javaCompliance = max([p.javaCompliance for p in distProjects]) _genEclipseBuilder(out, dist, 'Create' + dist.name + 'Dist', 'archive @' + dist.name, relevantResources=relevantResources, logToFile=True, refresh=False, async=True) out.close('buildSpec') out.open('natures') @@ -3523,6 +3624,9 @@ update_file(projectFile, out.xml(indent='\t', newl='\n')) files.append(projectFile) + _zip_files(files, suite.dir, configZip.path) + _zip_files(libFiles, suite.dir, configLibsZip) + def _zip_files(files, baseDir, zipPath): fd, tmp = tempfile.mkstemp(suffix='', prefix=basename(zipPath), dir=baseDir) try: @@ -3541,12 +3645,6 @@ if exists(tmp): os.remove(tmp) -def _isAnnotationProcessorDependency(p): - """ - Determines if a given project is part of an annotation processor. - """ - return p in sorted_deps(annotation_processors()) - def _genEclipseBuilder(dotProjectDoc, p, name, mxCommand, refresh=True, refreshFile=None, relevantResources=None, async=False, logToConsole=False, logToFile=False, appendToLogFile=True, xmlIndent='\t', xmlStandalone=None): externalToolDir = join(p.dir, '.externalToolBuilders') launchOut = XMLDoc() @@ -3922,8 +4020,8 @@ # Space-separated list of extra javac options javac.compilerargs= javac.deprecation=false -javac.source=1.7 -javac.target=1.7 +javac.source=""" + str(p.javaCompliance) + """ +javac.target=""" + str(p.javaCompliance) + """ javac.test.classpath=\\ ${javac.classpath}:\\ ${build.classes.dir} @@ -4242,6 +4340,9 @@ except: log("Error removing {0}".format(p.name + '.jar')) + for d in _dists.itervalues(): + if d.get_ide_project_dir(): + shutil.rmtree(d.get_ide_project_dir(), ignore_errors=True) def ideinit(args, refreshOnly=False, buildProcessorJars=True): """(re)generate Eclipse, NetBeans and Intellij project configurations""" diff -r ae0f235469db -r f8e60d11c0ec src/cpu/x86/vm/assembler_x86.cpp --- a/src/cpu/x86/vm/assembler_x86.cpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/cpu/x86/vm/assembler_x86.cpp Mon Aug 25 21:15:59 2014 -0700 @@ -666,21 +666,35 @@ // Check second byte NOT_LP64(assert((0xC0 & *ip) == 0xC0, "shouldn't have LDS and LES instructions")); + int vex_opcode; // First byte if ((0xFF & *inst) == VEX_3bytes) { + vex_opcode = VEX_OPCODE_MASK & *ip; ip++; // third byte is_64bit = ((VEX_W & *ip) == VEX_W); + } else { + vex_opcode = VEX_OPCODE_0F; } ip++; // opcode // To find the end of instruction (which == end_pc_operand). - switch (0xFF & *ip) { - case 0x61: // pcmpestri r, r/a, #8 - case 0x70: // pshufd r, r/a, #8 - case 0x73: // psrldq r, #8 - tail_size = 1; // the imm8 - break; - default: - break; + switch (vex_opcode) { + case VEX_OPCODE_0F: + switch (0xFF & *ip) { + case 0x70: // pshufd r, r/a, #8 + case 0x71: // ps[rl|ra|ll]w r, #8 + case 0x72: // ps[rl|ra|ll]d r, #8 + case 0x73: // ps[rl|ra|ll]q r, #8 + case 0xC2: // cmp[ps|pd|ss|sd] r, r, r/a, #8 + case 0xC4: // pinsrw r, r, r/a, #8 + case 0xC5: // pextrw r/a, r, #8 + case 0xC6: // shufp[s|d] r, r, r/a, #8 + tail_size = 1; // the imm8 + break; + } + break; + case VEX_OPCODE_0F_3A: + tail_size = 1; + break; } ip++; // skip opcode debug_only(has_disp32 = true); // has both kinds of operands! diff -r ae0f235469db -r f8e60d11c0ec src/cpu/x86/vm/assembler_x86.hpp --- a/src/cpu/x86/vm/assembler_x86.hpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/cpu/x86/vm/assembler_x86.hpp Mon Aug 25 21:15:59 2014 -0700 @@ -521,7 +521,8 @@ VEX_OPCODE_NONE = 0x0, VEX_OPCODE_0F = 0x1, VEX_OPCODE_0F_38 = 0x2, - VEX_OPCODE_0F_3A = 0x3 + VEX_OPCODE_0F_3A = 0x3, + VEX_OPCODE_MASK = 0x1F }; enum WhichOperand { diff -r ae0f235469db -r f8e60d11c0ec src/gpu/hsail/vm/gpu_hsail.cpp --- a/src/gpu/hsail/vm/gpu_hsail.cpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/gpu/hsail/vm/gpu_hsail.cpp Mon Aug 25 21:15:59 2014 -0700 @@ -66,7 +66,7 @@ JNINativeMethod Hsail::HSAIL_methods[] = { {CC"initialize", CC"()Z", FN_PTR(Hsail::initialize)}, {CC"generateKernel", CC"([B" STRING ")J", FN_PTR(Hsail::generate_kernel)}, - {CC"executeKernel0", CC"("HS_INSTALLED_CODE"I["OBJECT"["JLTHREAD"I[I)Z", FN_PTR(Hsail::execute_kernel_void_1d)}, + {CC"executeKernel0", CC"("HS_INSTALLED_CODE"I["OBJECT"II[I)Z", FN_PTR(Hsail::execute_kernel_void_1d)}, }; void* Hsail::_device_context = NULL; @@ -100,7 +100,7 @@ } GPU_VMENTRY(jboolean, Hsail::execute_kernel_void_1d, (JNIEnv* env, jclass, jobject kernel_handle, jint dimX, jobject args, - jobject donor_threads, jint allocBytesPerWorkitem, jobject oop_map_array)) + jint num_tlabs, jint allocBytesPerWorkitem, jobject oop_map_array)) ResourceMark rm; jlong nmethodValue = InstalledCode::address(kernel_handle); @@ -116,7 +116,7 @@ SharedRuntime::throw_and_post_jvmti_exception(JavaThread::current(), vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL); } -return execute_kernel_void_1d_internal((address) kernel, dimX, args, mh, nm, donor_threads, allocBytesPerWorkitem, oop_map_array, CHECK_0); +return execute_kernel_void_1d_internal((address) kernel, dimX, args, mh, nm, num_tlabs, allocBytesPerWorkitem, oop_map_array, CHECK_0); GPU_END static void showRanges(jboolean* a, int len) { @@ -137,14 +137,16 @@ } jboolean Hsail::execute_kernel_void_1d_internal(address kernel, int dimX, jobject args, methodHandle& mh, nmethod* nm, - jobject donor_threads, int allocBytesPerWorkitem, jobject oop_map_array, TRAPS) { + jint num_tlabs, int allocBytesPerWorkitem, jobject oop_map_array, TRAPS) { ResourceMark rm(THREAD); objArrayOop argsArray = (objArrayOop) JNIHandles::resolve(args); + // Note this length does not include the iteration variable since it is replaced by the HSA workitemid + int argsArrayLength = argsArray->length(); assert(THREAD->is_Java_thread(), "must be a JavaThread"); // We avoid HSAILAllocationInfo logic if kernel does not allocate - // in which case the donor_thread array passed in will be null - HSAILAllocationInfo* allocInfo = (donor_threads == NULL ? NULL : new HSAILAllocationInfo(donor_threads, dimX, allocBytesPerWorkitem)); + // in which case the num_tlabs passed in will be 0 + HSAILAllocationInfo* allocInfo = (num_tlabs == 0 ? NULL : new HSAILAllocationInfo(num_tlabs, dimX, allocBytesPerWorkitem)); // Reset the kernel arguments _okra_clear_args(kernel); @@ -296,7 +298,8 @@ KlassHandle methKlass = mh->method_holder(); Thread* THREAD = Thread::current(); JavaValue result(T_VOID); - JavaCallArguments javaArgs; + // Add the iteration variable to the HSA args length + JavaCallArguments javaArgs(argsArrayLength + 1); // re-resolve the args_handle here objArrayOop resolvedArgsArray = (objArrayOop) JNIHandles::resolve(args); @@ -344,8 +347,11 @@ // The kernel entrypoint is always run for the time being const char* entryPointName = "&run"; jlong okra_kernel; - jint okra_status = _okra_create_kernel(_device_context, code, entryPointName, (void**)&okra_kernel); - guarantee(okra_status==0, "_okra_create_kernel failed"); + { + TraceTime t("generate kernel ", TraceGPUInteraction); + jint okra_status = _okra_create_kernel(_device_context, code, entryPointName, (void**)&okra_kernel); + guarantee(okra_status==0, "_okra_create_kernel failed"); + } return (jlong) okra_kernel; GPU_END diff -r ae0f235469db -r f8e60d11c0ec src/gpu/hsail/vm/gpu_hsail.hpp --- a/src/gpu/hsail/vm/gpu_hsail.hpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/gpu/hsail/vm/gpu_hsail.hpp Mon Aug 25 21:15:59 2014 -0700 @@ -185,10 +185,10 @@ // static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args); JNIEXPORT static jboolean execute_kernel_void_1d(JNIEnv* env, jclass, jobject hotspotInstalledCode, jint dimX, jobject args, - jobject donorThreads, int allocBytesPerWorkitem, jobject oop_map_array); + jint num_tlabs, int allocBytesPerWorkitem, jobject oop_map_array); static jboolean execute_kernel_void_1d_internal(address kernel, int dimX, jobject args, methodHandle& mh, nmethod* nm, - jobject donorThreads, int allocBytesPerWorkitem, jobject oop_map_array, TRAPS); + jint num_tlabs, int allocBytesPerWorkitem, jobject oop_map_array, TRAPS); static GraalEnv::CodeInstallResult install_code(Handle& compiled_code, CodeBlob*& cb, Handle installed_code, Handle triggered_deoptimizations); diff -r ae0f235469db -r f8e60d11c0ec src/gpu/hsail/vm/gpu_hsail_Tlab.hpp --- a/src/gpu/hsail/vm/gpu_hsail_Tlab.hpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/gpu/hsail/vm/gpu_hsail_Tlab.hpp Mon Aug 25 21:15:59 2014 -0700 @@ -41,7 +41,7 @@ HeapWord* _end; HeapWord* _last_good_top; HeapWord* _original_top; - JavaThread* _donor_thread; // donor thread associated with this tlabInfo + ThreadLocalAllocBuffer* _tlab; // tlab associated with this tlabInfo HSAILAllocationInfo* _alloc_info; // same as what is in HSAILDeoptimizationInfo // Accessors @@ -50,11 +50,12 @@ HeapWord* end() { return _end; } HeapWord* last_good_top() { return _last_good_top; } HeapWord* original_top() { return _original_top; } - void initialize(HeapWord* start, HeapWord* top, HeapWord* end, JavaThread* donorThread, HSAILAllocationInfo* allocInfo) { + ThreadLocalAllocBuffer* tlab() { return _tlab; } + void initialize(HeapWord* start, HeapWord* top, HeapWord* end, ThreadLocalAllocBuffer* tlab, HSAILAllocationInfo* allocInfo) { _start = start; _top = _original_top = top; _end = end; - _donor_thread = donorThread; + _tlab = tlab; _alloc_info = allocInfo; } }; @@ -63,54 +64,56 @@ class HSAILAllocationInfo : public CHeapObj { friend class VMStructs; private: - JavaThread** donorThreads; - jint _num_donor_threads; - size_t _tlab_align_reserve_bytes; // filled in from ThreadLocalAllocBuffer::alignment_reserve_in_bytes() - HSAILTlabInfo** _cur_tlab_infos; // array of current tlab info pointers, one per donor_thread + jint _num_tlabs; + size_t _tlab_align_reserve_bytes; // filled in from ThreadLocalAllocBuffer::alignment_reserve_in_bytes() + HSAILTlabInfo** _cur_tlab_infos; // array of current tlab info pointers, one per num_tlabs HSAILTlabInfo* _tlab_infos_pool_start; // pool for new tlab_infos HSAILTlabInfo* _tlab_infos_pool_next; // where next will be allocated from HSAILTlabInfo* _tlab_infos_pool_end; // where next will be allocated from public: - HSAILAllocationInfo(jobject donor_threads_jobj, int dimX, int allocBytesPerWorkitem) { - // fill in the donorThreads array - objArrayOop donorThreadObjects = (objArrayOop) JNIHandles::resolve(donor_threads_jobj); - _num_donor_threads = donorThreadObjects->length(); - guarantee(_num_donor_threads > 0, "need at least one donor thread"); - donorThreads = NEW_C_HEAP_ARRAY(JavaThread*, _num_donor_threads, mtInternal); - for (int i = 0; i < _num_donor_threads; i++) { - donorThreads[i] = java_lang_Thread::thread(donorThreadObjects->obj_at(i)); + HSAILAllocationInfo(jint num_tlabs, int dimX, int allocBytesPerWorkitem) { + _num_tlabs = num_tlabs; + // if this thread doesn't have gpu_hsail_tlabs allocated yet, do so now + JavaThread* thread = JavaThread::current(); + if (thread->get_gpu_hsail_tlabs_count() == 0) { + thread->initialize_gpu_hsail_tlabs(num_tlabs); + if (TraceGPUInteraction) { + for (int i = 0; i < num_tlabs; i++) { + ThreadLocalAllocBuffer* tlab = thread->get_gpu_hsail_tlab_at(i); + tty->print("initialized gpu_hsail_tlab %d at %p -> ", i, tlab); + printTlabInfoFromThread(tlab); + } + } } - + // Compute max_tlab_infos based on amount of free heap space size_t max_tlab_infos; { - JavaThread* donorThread = donorThreads[0]; - ThreadLocalAllocBuffer* tlab = &donorThread->tlab(); + ThreadLocalAllocBuffer* tlab = &thread->tlab(); size_t new_tlab_size = tlab->compute_size(0); - size_t heap_bytes_free = Universe::heap()->unsafe_max_tlab_alloc(donorThread); + size_t heap_bytes_free = Universe::heap()->unsafe_max_tlab_alloc(thread); if (new_tlab_size != 0) { - max_tlab_infos = MIN2(heap_bytes_free / new_tlab_size, (size_t)(64 * _num_donor_threads)); + max_tlab_infos = MIN2(heap_bytes_free / new_tlab_size, (size_t)(64 * _num_tlabs)); } else { - max_tlab_infos = 8 * _num_donor_threads; // an arbitrary multiple + max_tlab_infos = 8 * _num_tlabs; // an arbitrary multiple } if (TraceGPUInteraction) { tty->print_cr("heapFree = %ld, newTlabSize=%ld, tlabInfos allocated = %ld", heap_bytes_free, new_tlab_size, max_tlab_infos); } } - _cur_tlab_infos = NEW_C_HEAP_ARRAY(HSAILTlabInfo*, _num_donor_threads, mtInternal); + _cur_tlab_infos = NEW_C_HEAP_ARRAY(HSAILTlabInfo*, _num_tlabs, mtInternal); _tlab_infos_pool_start = NEW_C_HEAP_ARRAY(HSAILTlabInfo, max_tlab_infos, mtInternal); - _tlab_infos_pool_next = &_tlab_infos_pool_start[_num_donor_threads]; + _tlab_infos_pool_next = &_tlab_infos_pool_start[_num_tlabs]; _tlab_infos_pool_end = &_tlab_infos_pool_start[max_tlab_infos]; _tlab_align_reserve_bytes = ThreadLocalAllocBuffer::alignment_reserve_in_bytes(); - // we will fill the first N tlabInfos from the donor threads - for (int i = 0; i < _num_donor_threads; i++) { - JavaThread* donorThread = donorThreads[i]; - ThreadLocalAllocBuffer* tlab = &donorThread->tlab(); + // we will fill the first N tlabInfos from the gpu_hsail_tlabs + for (int i = 0; i < _num_tlabs; i++) { + ThreadLocalAllocBuffer* tlab = thread->get_gpu_hsail_tlab_at(i); if (TraceGPUInteraction) { - tty->print("donorThread %d, is %p, tlab at %p -> ", i, donorThread, tlab); + tty->print("gpu_hsail_tlab %d at %p -> ", i, tlab); printTlabInfoFromThread(tlab); } @@ -122,13 +125,13 @@ // here, it might make sense to do a gc now rather than to start // the kernel and have it deoptimize. How to do that? if (tlab->end() == NULL) { - bool success = getNewTlabForDonorThread(tlab, i); + bool success = getNewGpuHsailTlab(tlab); if (TraceGPUInteraction) { if (success) { - tty->print("donorThread %d, refilled tlab, -> ", i); + tty->print("gpu_hsail_tlab %d, refilled tlab, -> ", i); printTlabInfoFromThread(tlab); } else { - tty->print("donorThread %d, could not refill tlab, left as ", i); + tty->print("gpu_hsail_tlab %d, could not refill tlab, left as ", i); printTlabInfoFromThread(tlab); } } @@ -137,20 +140,19 @@ // extract the necessary tlab fields into a TlabInfo record HSAILTlabInfo* pTlabInfo = &_tlab_infos_pool_start[i]; _cur_tlab_infos[i] = pTlabInfo; - pTlabInfo->initialize(tlab->start(), tlab->top(), tlab->end(), donorThread, this); + pTlabInfo->initialize(tlab->start(), tlab->top(), tlab->end(), tlab, this); } } ~HSAILAllocationInfo() { FREE_C_HEAP_ARRAY(HSAILTlabInfo*, _cur_tlab_infos, mtInternal); FREE_C_HEAP_ARRAY(HSAILTlabInfo, _tlab_infos_pool_start, mtInternal); - FREE_C_HEAP_ARRAY(JavaThread*, donorThreads, mtInternal); } void postKernelCleanup() { // go thru all the tlabInfos, fix up any tlab tops that overflowed // complete the tlabs if they overflowed - // update the donor threads tlabs when appropriate + // update the gpu_hsail_tlabs when appropriate bool anyOverflows = false; size_t bytesAllocated = 0; // if there was an overflow in allocating tlabInfos, correct it here @@ -166,8 +168,7 @@ tty->print_cr("postprocess tlabInfo %p, start=%p, top=%p, end=%p, last_good_top=%p", tlabInfo, tlabInfo->start(), tlabInfo->top(), tlabInfo->end(), tlabInfo->last_good_top()); } - JavaThread* donorThread = tlabInfo->_donor_thread; - ThreadLocalAllocBuffer* tlab = &donorThread->tlab(); + ThreadLocalAllocBuffer* tlab = tlabInfo->tlab(); bool overflowed = false; // if a tlabInfo has NULL fields, i.e. we could not prime it on entry, // or we could not get a tlab from the gpu, so ignore tlabInfo here @@ -177,14 +178,14 @@ overflowed = true; if (TraceGPUInteraction) { long overflowAmount = (long) tlabInfo->top() - (long) tlabInfo->last_good_top(); - tty->print_cr("tlabInfo %p (donorThread = %p) overflowed by %ld bytes, setting last good top to %p", tlabInfo, donorThread, overflowAmount, tlabInfo->last_good_top()); + tty->print_cr("tlabInfo %p (tlab = %p) overflowed by %ld bytes, setting last good top to %p", tlabInfo, tlab, overflowAmount, tlabInfo->last_good_top()); } tlabInfo->_top = tlabInfo->last_good_top(); } - // fill the donor thread tlab with the tlabInfo information + // fill the gpu_hsail_tlab with the tlabInfo information // we do this even if it will get overwritten by a later tlabinfo - // because it helps with tlab statistics for that donor thread + // because it helps with tlab statistics for that tlab tlab->fill(tlabInfo->start(), tlabInfo->top(), (tlabInfo->end() - tlabInfo->start()) + tlab->alignment_reserve()); // if there was an overflow, make it parsable with retire = true @@ -215,7 +216,7 @@ private: // fill and retire old tlab and get a new one // if we can't get one, no problem someone will eventually do a gc - bool getNewTlabForDonorThread(ThreadLocalAllocBuffer* tlab, int idx) { + bool getNewGpuHsailTlab(ThreadLocalAllocBuffer* tlab) { tlab->clear_before_allocation(); // fill and retire old tlab (will also check for null) diff -r ae0f235469db -r f8e60d11c0ec src/gpu/hsail/vm/vmStructs_hsail.hpp --- a/src/gpu/hsail/vm/vmStructs_hsail.hpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/gpu/hsail/vm/vmStructs_hsail.hpp Mon Aug 25 21:15:59 2014 -0700 @@ -58,8 +58,8 @@ nonstatic_field(HSAILTlabInfo, _end, HeapWord*) \ nonstatic_field(HSAILTlabInfo, _last_good_top, HeapWord*) \ nonstatic_field(HSAILTlabInfo, _original_top, HeapWord*) \ - nonstatic_field(HSAILTlabInfo, _donor_thread, JavaThread*) \ nonstatic_field(HSAILTlabInfo, _alloc_info, HSAILAllocationInfo*) \ + nonstatic_field(HSAILTlabInfo, _tlab, ThreadLocalAllocBuffer*) \ #define VM_TYPES_GPU_HSAIL(declare_type, declare_toplevel_type) \ declare_toplevel_type(HSAILFrame) \ diff -r ae0f235469db -r f8e60d11c0ec src/os/bsd/vm/os_bsd.cpp --- a/src/os/bsd/vm/os_bsd.cpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/os/bsd/vm/os_bsd.cpp Mon Aug 25 21:15:59 2014 -0700 @@ -3805,6 +3805,11 @@ return fetcher.result(); } +address os::get_pc(void* context) { + ucontext_t *uc = (ucontext_t*)context; + return os::Bsd::ucontext_get_pc(uc); +} + int os::Bsd::safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime) { return pthread_cond_timedwait(_cond, _mutex, _abstime); diff -r ae0f235469db -r f8e60d11c0ec src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/os/linux/vm/os_linux.cpp Mon Aug 25 21:15:59 2014 -0700 @@ -5035,6 +5035,11 @@ return fetcher.result(); } +address os::get_pc(void* context) { + ucontext_t *uc = (ucontext_t*)context; + return os::Linux::ucontext_get_pc(uc); +} + int os::Linux::safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime) { if (is_NPTL()) { diff -r ae0f235469db -r f8e60d11c0ec src/os/solaris/vm/os_solaris.cpp --- a/src/os/solaris/vm/os_solaris.cpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/os/solaris/vm/os_solaris.cpp Mon Aug 25 21:15:59 2014 -0700 @@ -4379,6 +4379,10 @@ return fetcher.result(); } +address os::get_pc(void* context) { + ucontext_t *uc = (ucontext_t*)context; + return os::Solaris::ucontext_get_pc(uc); +} // This does not do anything on Solaris. This is basically a hook for being // able to use structured exception handling (thread-local exception filters) on, e.g., Win32. diff -r ae0f235469db -r f8e60d11c0ec src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/os/windows/vm/os_windows.cpp Mon Aug 25 21:15:59 2014 -0700 @@ -3672,6 +3672,16 @@ #endif } +address os::get_pc(void* context) { + CONTEXT* uc = (CONTEXT*)context; +#ifdef _M_AMD64 + return (address) uc->Rip; +#else + return (address) uc->Eip; +#endif +} + + // GetCurrentThreadId() returns DWORD intx os::current_thread_id() { return GetCurrentThreadId(); } diff -r ae0f235469db -r f8e60d11c0ec src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSlider.java --- a/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSlider.java Mon Aug 25 14:42:42 2014 -0700 +++ b/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSlider.java Mon Aug 25 21:15:59 2014 -0700 @@ -26,24 +26,26 @@ import com.sun.hotspot.igv.data.ChangedListener; import java.awt.*; +import java.awt.geom.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.util.List; -import javax.swing.JComponent; +import javax.swing.*; /** * * @author Thomas Wuerthinger */ -public class RangeSlider extends JComponent implements ChangedListener, MouseListener, MouseMotionListener { +public class RangeSlider extends JComponent implements ChangedListener, MouseListener, MouseMotionListener, Scrollable { public static final int HEIGHT = 40; - public static final int BAR_HEIGHT = 22; - public static final int BAR_SELECTION_ENDING_HEIGHT = 16; - public static final int BAR_SELECTION_HEIGHT = 10; - public static final int BAR_THICKNESS = 2; - public static final int BAR_CIRCLE_SIZE = 9; + public static final float BAR_HEIGHT = 22; + public static final float BAR_SELECTION_ENDING_HEIGHT = 16; + public static final float BAR_SELECTION_HEIGHT = 10; + public static final float BAR_THICKNESS = 2; + public static final float BAR_CIRCLE_SIZE = 9; + public static final float BAR_CIRCLE_CONNECTOR_SIZE = 6; public static final int MOUSE_ENDING_OFFSET = 3; public static final Color BACKGROUND_COLOR = Color.white; public static final Color BAR_COLOR = Color.black; @@ -90,15 +92,61 @@ return model; } + /** + * Returns the preferred size of the viewport for a view component. + * For example, the preferred size of a JList component + * is the size required to accommodate all of the cells in its list. + * However, the value of preferredScrollableViewportSize + * is the size required for JList.getVisibleRowCount rows. + * A component without any properties that would affect the viewport + * size should just return getPreferredSize here. + * + * @return the preferredSize of a JViewport whose view + * is this Scrollable + * @see JViewport#getPreferredSize + */ + public Dimension getPreferredScrollableViewportSize() { + return getPreferredSize(); + } + + public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { + if (orientation == SwingConstants.VERTICAL) { + return 1; + } + + return (int)(BAR_CIRCLE_SIZE + BAR_CIRCLE_CONNECTOR_SIZE); + } + + public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { + return orientation == SwingConstants.VERTICAL ? visibleRect.height / 2 : visibleRect.width / 2; + } + + public boolean getScrollableTracksViewportWidth() { + return false; + } + + public boolean getScrollableTracksViewportHeight() { + return true; + } + @Override public Dimension getPreferredSize() { Dimension d = super.getPreferredSize(); d.height = HEIGHT; + d.width = Math.max(d.width, (int)(2 * BAR_CIRCLE_CONNECTOR_SIZE + getPaintingModel().getPositions().size() * (BAR_CIRCLE_SIZE + BAR_CIRCLE_CONNECTOR_SIZE))); return d; } @Override public void changed(RangeSliderModel source) { + revalidate(); + + float barStartY = getBarStartY(); + int circleCenterY = (int)(barStartY + BAR_HEIGHT / 2); + int startX = (int)getStartXPosition(model.getFirstPosition()); + int endX = (int)getEndXPosition(model.getSecondPosition()); + Rectangle r = new Rectangle(startX, circleCenterY, endX - startX, 1); + scrollRectToVisible(r); update(); } @@ -106,22 +154,22 @@ this.repaint(); } - private int getXPosition(int index) { + private float getXPosition(int index) { assert index >= 0 && index < getPaintingModel().getPositions().size(); return getXOffset() * (index + 1); } - private int getXOffset() { + private float getXOffset() { int size = getPaintingModel().getPositions().size(); - int width = getWidth(); + float width = (float)getWidth(); return (width / (size + 1)); } - private int getEndXPosition(int index) { + private float getEndXPosition(int index) { return getXPosition(index) + getXOffset() / 2; } - private int getStartXPosition(int index) { + private float getStartXPosition(int index) { return getXPosition(index) - getXOffset() / 2; } @@ -135,7 +183,7 @@ int height = getHeight(); g2.setColor(BACKGROUND_COLOR); - g2.fillRect(0, 0, width, height); + g2.fill(new Rectangle2D.Float(0, 0, width, height)); // Nothing to paint? if (getPaintingModel() == null || getPaintingModel().getPositions().size() == 0) { @@ -150,30 +198,30 @@ } - private int getBarStartY() { - return getHeight() - BAR_HEIGHT; + private float getBarStartY() { + return getHeight() / 2 - BAR_HEIGHT / 2; } private void paintBar(Graphics2D g) { List list = getPaintingModel().getPositions(); - int barStartY = getBarStartY(); + float barStartY = getBarStartY(); g.setColor(BAR_COLOR); - g.fillRect(getXPosition(0), barStartY + BAR_HEIGHT / 2 - BAR_THICKNESS / 2, getXPosition(list.size() - 1) - getXPosition(0), BAR_THICKNESS); + g.fill(new Rectangle2D.Float(getXPosition(0), barStartY + BAR_HEIGHT / 2 - BAR_THICKNESS / 2, getXPosition(list.size() - 1) - getXPosition(0), BAR_THICKNESS)); - int circleCenterY = barStartY + BAR_HEIGHT / 2; + float circleCenterY = barStartY + BAR_HEIGHT / 2; for (int i = 0; i < list.size(); i++) { - int curX = getXPosition(i); + float curX = getXPosition(i); g.setColor(getPaintingModel().getColors().get(i)); - g.fillOval(curX - BAR_CIRCLE_SIZE / 2, circleCenterY - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE); + g.fill(new Ellipse2D.Float(curX - BAR_CIRCLE_SIZE / 2, circleCenterY - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE)); g.setColor(Color.black); - g.drawOval(curX - BAR_CIRCLE_SIZE / 2, circleCenterY - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE); + g.draw(new Ellipse2D.Float(curX - BAR_CIRCLE_SIZE / 2, circleCenterY - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE)); String curS = list.get(i); if (curS != null && curS.length() > 0) { - int startX = getStartXPosition(i); - int endX = getEndXPosition(i); + float startX = getStartXPosition(i); + float endX = getEndXPosition(i); FontMetrics metrics = g.getFontMetrics(); Rectangle bounds = metrics.getStringBounds(curS, g).getBounds(); if (bounds.width < endX - startX && bounds.height < barStartY) { @@ -187,10 +235,10 @@ private void paintSelected(Graphics2D g, int start, int end) { - int startX = getStartXPosition(start); - int endX = getEndXPosition(end); - int barStartY = getBarStartY(); - int barSelectionEndingStartY = barStartY + BAR_HEIGHT / 2 - BAR_SELECTION_ENDING_HEIGHT / 2; + float startX = getStartXPosition(start); + float endX = getEndXPosition(end); + float barStartY = getBarStartY(); + float barSelectionEndingStartY = barStartY + BAR_HEIGHT / 2 - BAR_SELECTION_ENDING_HEIGHT / 2; paintSelectedEnding(g, startX, barSelectionEndingStartY); paintSelectedEnding(g, endX, barSelectionEndingStartY); @@ -200,18 +248,18 @@ } else if (isOverBar) { g.setColor(BAR_SELECTION_COLOR_ROLLOVER); } - g.fillRect(startX, barStartY + BAR_HEIGHT / 2 - BAR_SELECTION_HEIGHT / 2, endX - startX, BAR_SELECTION_HEIGHT); + g.fill(new Rectangle2D.Float(startX, barStartY + BAR_HEIGHT / 2 - BAR_SELECTION_HEIGHT / 2, endX - startX, BAR_SELECTION_HEIGHT)); } - private void paintSelectedEnding(Graphics g, int x, int y) { + private void paintSelectedEnding(Graphics2D g, float x, float y) { g.setColor(BAR_COLOR); - g.fillRect(x - BAR_THICKNESS / 2, y, BAR_THICKNESS, BAR_SELECTION_ENDING_HEIGHT); + g.fill(new Rectangle2D.Float(x - BAR_THICKNESS / 2, y, BAR_THICKNESS, BAR_SELECTION_ENDING_HEIGHT)); } private boolean isOverSecondPosition(Point p) { if (p.y >= getBarStartY()) { - int destX = getEndXPosition(getPaintingModel().getSecondPosition()); - int off = Math.abs(destX - p.x); + float destX = getEndXPosition(getPaintingModel().getSecondPosition()); + float off = Math.abs(destX - p.x); return off <= MOUSE_ENDING_OFFSET; } return false; @@ -219,8 +267,8 @@ private boolean isOverFirstPosition(Point p) { if (p.y >= getBarStartY()) { - int destX = getStartXPosition(getPaintingModel().getFirstPosition()); - int off = Math.abs(destX - p.x); + float destX = getStartXPosition(getPaintingModel().getFirstPosition()); + float off = Math.abs(destX - p.x); return off <= MOUSE_ENDING_OFFSET; } return false; @@ -235,9 +283,12 @@ @Override public void mouseDragged(MouseEvent e) { + Rectangle r = new Rectangle(e.getX(), e.getY(), 1, 1); + scrollRectToVisible(r); + if (state == State.DragBar) { - int firstX = this.getStartXPosition(model.getFirstPosition()); - int newFirstX = firstX + e.getPoint().x - startPoint.x; + float firstX = this.getStartXPosition(model.getFirstPosition()); + float newFirstX = firstX + e.getPoint().x - startPoint.x; int newIndex = getIndexFromPosition(newFirstX) + 1; if (newIndex + model.getSecondPosition() - model.getFirstPosition() >= model.getPositions().size()) { newIndex = model.getPositions().size() - (model.getSecondPosition() - model.getFirstPosition()) - 1; @@ -264,13 +315,13 @@ } } - private int getIndexFromPosition(int x) { + private int getIndexFromPosition(float x) { if (x < getXPosition(0)) { return -1; } for (int i = 0; i < getPaintingModel().getPositions().size() - 1; i++) { - int startX = getXPosition(i); - int endX = getXPosition(i + 1); + float startX = getXPosition(i); + float endX = getXPosition(i + 1); if (x >= startX && x <= endX) { return i; } diff -r ae0f235469db -r f8e60d11c0ec src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java --- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java Mon Aug 25 14:42:42 2014 -0700 +++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java Mon Aug 25 21:15:59 2014 -0700 @@ -197,7 +197,8 @@ rangeSliderModel = new DiagramViewModel(diagram.getGraph().getGroup(), filterChain, sequence); rangeSlider = new RangeSlider(); rangeSlider.setModel(rangeSliderModel); - container.add(BorderLayout.CENTER, rangeSlider); + JScrollPane pane = new JScrollPane(rangeSlider, ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); + container.add(BorderLayout.CENTER, pane); scene = new DiagramScene(actions, rangeSliderModel); content = new InstanceContent(); diff -r ae0f235469db -r f8e60d11c0ec src/share/tools/IdealGraphVisualizer/nbproject/project.properties --- a/src/share/tools/IdealGraphVisualizer/nbproject/project.properties Mon Aug 25 14:42:42 2014 -0700 +++ b/src/share/tools/IdealGraphVisualizer/nbproject/project.properties Mon Aug 25 21:15:59 2014 -0700 @@ -40,5 +40,5 @@ # Disable assertions for RequestProcessor to prevent annoying messages in case # of multiple SceneAnimator update tasks in the default RequestProcessor. -run.args.extra = -J-server -J-da:org.openide.util.RequestProcessor -J-Xms2g -J-Xmx8g +run.args.extra = -J-server -J-da:org.openide.util.RequestProcessor -J-Xms2g -J-Xmx8g -J-Djava.lang.Integer.IntegerCache.high=20000 debug.args.extra = -J-server -J-da:org.openide.util.RequestProcessor diff -r ae0f235469db -r f8e60d11c0ec src/share/vm/classfile/javaClasses.cpp --- a/src/share/vm/classfile/javaClasses.cpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/share/vm/classfile/javaClasses.cpp Mon Aug 25 21:15:59 2014 -0700 @@ -594,6 +594,12 @@ set_init_lock(mirror(), r); // Set protection domain also +#ifdef GRAAL + if (k->class_loader() == SystemDictionary::graal_loader()) { + // Same protection domain as for classes loaded by the boot loader + protection_domain = Handle(); + } +#endif set_protection_domain(mirror(), protection_domain()); // Initialize static fields diff -r ae0f235469db -r f8e60d11c0ec src/share/vm/compiler/disassembler.cpp --- a/src/share/vm/compiler/disassembler.cpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/share/vm/compiler/disassembler.cpp Mon Aug 25 21:15:59 2014 -0700 @@ -493,6 +493,10 @@ void Disassembler::decode(CodeBlob* cb, outputStream* st) { if (!load_library()) return; + if (cb->is_nmethod()) { + decode((nmethod*)cb, st); + return; + } decode_env env(cb, st); env.output()->print_cr("----------------------------------------------------------------------"); env.output()->print_cr("%s at [" PTR_FORMAT ", " PTR_FORMAT "] %d bytes", cb->name(), cb->code_begin(), cb->code_end(), ((jlong)(cb->code_end() - cb->code_begin())) * sizeof(unsigned char*)); diff -r ae0f235469db -r f8e60d11c0ec src/share/vm/gc_interface/collectedHeap.cpp --- a/src/share/vm/gc_interface/collectedHeap.cpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/share/vm/gc_interface/collectedHeap.cpp Mon Aug 25 21:15:59 2014 -0700 @@ -503,7 +503,12 @@ "Attempt to fill tlabs before main thread has been added" " to threads list is doomed to failure!"); for (JavaThread *thread = Threads::first(); thread; thread = thread->next()) { - if (use_tlab) thread->tlab().make_parsable(retire_tlabs); + if (use_tlab) { + thread->tlab().make_parsable(retire_tlabs); +#ifdef GRAAL + thread->gpu_hsail_tlabs_make_parsable(retire_tlabs); +#endif + } #if defined(COMPILER2) || defined(GRAAL) // The deferred store barriers must all have been flushed to the // card-table (or other remembered set structure) before GC starts diff -r ae0f235469db -r f8e60d11c0ec src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/share/vm/graal/graalRuntime.cpp Mon Aug 25 21:15:59 2014 -0700 @@ -39,6 +39,7 @@ address GraalRuntime::_external_deopt_i2c_entry = NULL; jobject GraalRuntime::_HotSpotGraalRuntime_instance = NULL; +bool GraalRuntime::_HotSpotGraalRuntime_initialized = false; void GraalRuntime::initialize_natives(JNIEnv *env, jclass c2vmClass) { uintptr_t heap_end = (uintptr_t) Universe::heap()->reserved_region().end(); @@ -486,7 +487,7 @@ } JRT_END -JRT_ENTRY(void, GraalRuntime::log_object(JavaThread* thread, oopDesc* obj, jint flags)) +JRT_LEAF(void, GraalRuntime::log_object(JavaThread* thread, oopDesc* obj, jint flags)) bool string = mask_bits_are_true(flags, LOG_OBJECT_STRING); bool addr = mask_bits_are_true(flags, LOG_OBJECT_ADDRESS); bool newline = mask_bits_are_true(flags, LOG_OBJECT_NEWLINE); @@ -599,7 +600,7 @@ } JRT_END -JRT_ENTRY(void, GraalRuntime::log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline)) +JRT_LEAF(void, GraalRuntime::log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline)) union { jlong l; jdouble d; @@ -663,6 +664,28 @@ return JNIHandles::make_local((oop) result.get_jobject()); JVM_END +// private static NativeFunctionInterfaceRuntime.createInterface() +JVM_ENTRY(jobject, JVM_CreateNativeFunctionInterface(JNIEnv *env, jclass c)) + const char* backendName = NULL; + #ifdef TARGET_ARCH_x86 + #ifdef _LP64 + backendName = "com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend"; + #endif + #endif + + if (backendName == NULL) { + return NULL; + } + TempNewSymbol name = SymbolTable::new_symbol(backendName, CHECK_NULL); + KlassHandle klass = GraalRuntime::resolve_or_fail(name, CHECK_NULL); + + TempNewSymbol makeInstance = SymbolTable::new_symbol("createNativeFunctionInterface", CHECK_NULL); + TempNewSymbol sig = SymbolTable::new_symbol("()Lcom/oracle/nfi/api/NativeFunctionInterface;", CHECK_NULL); + JavaValue result(T_OBJECT); + JavaCalls::call_static(&result, klass, makeInstance, sig, CHECK_NULL); + return JNIHandles::make_local((oop) result.get_jobject()); +JVM_END + void GraalRuntime::check_generated_sources_sha1(TRAPS) { TempNewSymbol name = SymbolTable::new_symbol("GeneratedSourcesSha1", CHECK_ABORT); KlassHandle klass = load_required_class(name); @@ -681,6 +704,7 @@ Handle GraalRuntime::get_HotSpotGraalRuntime() { if (JNIHandles::resolve(_HotSpotGraalRuntime_instance) == NULL) { + guarantee(!_HotSpotGraalRuntime_initialized, "cannot reinitialize HotSpotGraalRuntime"); Thread* THREAD = Thread::current(); check_generated_sources_sha1(CHECK_ABORT_(Handle())); TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotGraalRuntime", CHECK_ABORT_(Handle())); @@ -690,6 +714,7 @@ JavaValue result(T_OBJECT); JavaCalls::call_static(&result, klass, runtime, sig, CHECK_ABORT_(Handle())); _HotSpotGraalRuntime_instance = JNIHandles::make_global((oop) result.get_jobject()); + _HotSpotGraalRuntime_initialized = true; } return Handle(JNIHandles::resolve_non_null(_HotSpotGraalRuntime_instance)); } @@ -703,7 +728,8 @@ JVM_ENTRY(jboolean, JVM_ParseGraalOptions(JNIEnv *env, jclass c)) HandleMark hm; KlassHandle hotSpotOptionsClass(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c))); - return GraalRuntime::parse_arguments(hotSpotOptionsClass, CHECK_false); + bool result = GraalRuntime::parse_arguments(hotSpotOptionsClass, CHECK_false); + return result; JVM_END jint GraalRuntime::check_arguments(TRAPS) { @@ -749,7 +775,7 @@ return CITime || CITimeEach; } -void GraalRuntime::check_required_value(const char* name, int name_len, const char* value, TRAPS) { +void GraalRuntime::check_required_value(const char* name, size_t name_len, const char* value, TRAPS) { if (value == NULL) { char buf[200]; jio_snprintf(buf, sizeof(buf), "Must use '-G:%.*s=' format for %.*s option", name_len, name, name_len, name); @@ -765,7 +791,7 @@ if (first == '+' || first == '-') { name = arg + 1; name_len = strlen(name); - recognized = set_option(hotSpotOptionsClass, name, (int)name_len, arg, CHECK); + recognized = set_option_bool(hotSpotOptionsClass, name, name_len, first, CHECK); } else { char* sep = strchr(arg, '='); name = arg; @@ -776,13 +802,13 @@ } else { name_len = strlen(name); } - recognized = set_option(hotSpotOptionsClass, name, (int)name_len, value, CHECK); + recognized = set_option(hotSpotOptionsClass, name, name_len, value, CHECK); } if (!recognized) { bool throw_err = hotSpotOptionsClass.is_null(); if (!hotSpotOptionsClass.is_null()) { - set_option_helper(hotSpotOptionsClass, name, (int)name_len, Handle(), ' ', Handle(), 0L); + set_option_helper(hotSpotOptionsClass, name, name_len, Handle(), ' ', Handle(), 0L); if (!HAS_PENDING_EXCEPTION) { throw_err = true; } @@ -798,7 +824,7 @@ void GraalRuntime::parse_graal_options_file(KlassHandle hotSpotOptionsClass, TRAPS) { const char* home = Arguments::get_java_home(); - int path_len = (int)strlen(home) + (int)strlen("/lib/graal.options") + 1; + size_t path_len = strlen(home) + strlen("/lib/graal.options") + 1; char* path = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, path_len); char sep = os::file_separator()[0]; sprintf(path, "%s%clib%cgraal.options", home, sep, sep); @@ -843,7 +869,7 @@ } } -jlong GraalRuntime::parse_primitive_option_value(char spec, const char* name, int name_len, const char* value, TRAPS) { +jlong GraalRuntime::parse_primitive_option_value(char spec, const char* name, size_t name_len, const char* value, TRAPS) { check_required_value(name, name_len, value, CHECK_(0L)); union { jint i; @@ -880,11 +906,11 @@ THROW_MSG_(vmSymbols::java_lang_InternalError(), buf, 0L); } -void GraalRuntime::set_option_helper(KlassHandle hotSpotOptionsClass, char* name, int name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue) { +void GraalRuntime::set_option_helper(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue) { Thread* THREAD = Thread::current(); Handle name_handle; if (name != NULL) { - if ((int) strlen(name) > name_len) { + if (strlen(name) > name_len) { // Temporarily replace '=' with NULL to create the Java string for the option name char save = name[name_len]; name[name_len] = '\0'; @@ -894,7 +920,7 @@ return; } } else { - assert((int) strlen(name) == name_len, "must be"); + assert(strlen(name) == name_len, "must be"); name_handle = java_lang_String::create_from_str(name, CHECK); } } @@ -990,6 +1016,12 @@ CLEAR_PENDING_EXCEPTION; tty->print_cr(message); call_printStackTrace(exception, THREAD); + + // Give other aborting threads to also print their stack traces. + // This can be very useful when debugging class initialization + // failures. + os::sleep(THREAD, 200, false); + vm_abort(dump_core); } diff -r ae0f235469db -r f8e60d11c0ec src/share/vm/graal/graalRuntime.hpp --- a/src/share/vm/graal/graalRuntime.hpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/share/vm/graal/graalRuntime.hpp Mon Aug 25 21:15:59 2014 -0700 @@ -32,6 +32,7 @@ private: static jobject _HotSpotGraalRuntime_instance; + static bool _HotSpotGraalRuntime_initialized; static address _external_deopt_i2c_entry; static const char* _generated_sources_sha1; @@ -51,7 +52,7 @@ * @param value string value to parse * @throws InternalError if value could not be parsed according to spec */ - static jlong parse_primitive_option_value(char spec, const char* name, int name_len, const char* value, TRAPS); + static jlong parse_primitive_option_value(char spec, const char* name, size_t name_len, const char* value, TRAPS); /** * Loads default option value overrides from a /lib/graal.options if it exists. Each @@ -69,6 +70,21 @@ static void parse_argument(KlassHandle hotSpotOptionsClass, char* arg, TRAPS); /** + * Searches for a Boolean Graal option denoted by a given name and sets it value. + * + * The definition of this method is in graalRuntime.inline.hpp + * which is generated by com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp. + * + * @param hotSpotOptionsClass the HotSpotOptions klass or NULL if only checking for valid option + * @param name option name + * @param name_len length of option name + * @param value '+' to set the option, '-' to reset the option + * @returns true if the option was found + * @throws InternalError if there was a problem setting the option's value + */ + static bool set_option_bool(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, char value, TRAPS); + + /** * Searches for a Graal option denoted by a given name and sets it value. * * The definition of this method is in graalRuntime.inline.hpp @@ -80,12 +96,12 @@ * @returns true if the option was found * @throws InternalError if there was a problem setting the option's value */ - static bool set_option(KlassHandle hotSpotOptionsClass, char* name, int name_len, const char* value, TRAPS); + static bool set_option(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, const char* value, TRAPS); /** * Raises an InternalError for an option that expects a value but was specified without a "=" prefix. */ - static void check_required_value(const char* name, int name_len, const char* value, TRAPS); + static void check_required_value(const char* name, size_t name_len, const char* value, TRAPS); /** * Java call to HotSpotOptions.setOption(String name, OptionValue option, char spec, String stringValue, long primitiveValue) @@ -93,7 +109,7 @@ * @param name option name * @param name_len length of option name */ - static void set_option_helper(KlassHandle hotSpotOptionsClass, char* name, int name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue); + static void set_option_helper(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue); /** * Instantiates a service object, calls its default constructor and returns it. @@ -111,7 +127,7 @@ static void initialize_natives(JNIEnv *env, jclass c2vmClass); - static bool is_HotSpotGraalRuntime_initialized() { return _HotSpotGraalRuntime_instance != NULL; } + static bool is_HotSpotGraalRuntime_initialized() { return _HotSpotGraalRuntime_initialized; } /** * Gets the singleton HotSpotGraalRuntime instance, initializing it if necessary diff -r ae0f235469db -r f8e60d11c0ec src/share/vm/memory/threadLocalAllocBuffer.cpp --- a/src/share/vm/memory/threadLocalAllocBuffer.cpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/share/vm/memory/threadLocalAllocBuffer.cpp Mon Aug 25 21:15:59 2014 -0700 @@ -48,6 +48,13 @@ for(JavaThread *thread = Threads::first(); thread; thread = thread->next()) { thread->tlab().accumulate_statistics(); thread->tlab().initialize_statistics(); +#ifdef GRAAL + for (jint i = 0; i < thread->get_gpu_hsail_tlabs_count(); i++) { + thread->get_gpu_hsail_tlab_at(i)->accumulate_statistics(); + thread->get_gpu_hsail_tlab_at(i)->initialize_statistics(); + } +#endif + } // Publish new stats if some allocation occurred. @@ -129,6 +136,11 @@ void ThreadLocalAllocBuffer::resize_all_tlabs() { for(JavaThread *thread = Threads::first(); thread; thread = thread->next()) { thread->tlab().resize(); +#ifdef GRAAL + for (jint i = 0; i < thread->get_gpu_hsail_tlabs_count(); i++) { + thread->get_gpu_hsail_tlab_at(i)->resize(); + } +#endif } } @@ -188,11 +200,12 @@ invariants(); } -void ThreadLocalAllocBuffer::initialize() { +void ThreadLocalAllocBuffer::initialize(Thread* owning_thread) { initialize(NULL, // start NULL, // top NULL); // end + _owning_thread = owning_thread; set_desired_size(initial_desired_size()); // Following check is needed because at startup the main (primordial) @@ -221,7 +234,7 @@ // During jvm startup, the main (primordial) thread is initialized // before the heap is initialized. So reinitialize it now. guarantee(Thread::current()->is_Java_thread(), "tlab initialization thread not Java thread"); - Thread::current()->tlab().initialize(); + Thread::current()->tlab().initialize(Thread::current()); if (PrintTLAB && Verbose) { gclog_or_tty->print("TLAB min: " SIZE_FORMAT " initial: " SIZE_FORMAT " max: " SIZE_FORMAT "\n", @@ -303,9 +316,7 @@ } Thread* ThreadLocalAllocBuffer::myThread() { - return (Thread*)(((char *)this) + - in_bytes(start_offset()) - - in_bytes(Thread::tlab_start_offset())); + return _owning_thread; } diff -r ae0f235469db -r f8e60d11c0ec src/share/vm/memory/threadLocalAllocBuffer.hpp --- a/src/share/vm/memory/threadLocalAllocBuffer.hpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/share/vm/memory/threadLocalAllocBuffer.hpp Mon Aug 25 21:15:59 2014 -0700 @@ -38,6 +38,9 @@ // used to make it available for such multiplexing. class ThreadLocalAllocBuffer: public CHeapObj { friend class VMStructs; +#ifdef GRAAL + friend class HSAILAllocationInfo; +#endif private: HeapWord* _start; // address of TLAB HeapWord* _top; // address after last allocation @@ -53,6 +56,7 @@ unsigned _slow_refill_waste; unsigned _gc_waste; unsigned _slow_allocations; + Thread* _owning_thread; AdaptiveWeightedAverage _allocation_fraction; // fraction of eden allocated in tlabs @@ -153,7 +157,7 @@ static void resize_all_tlabs(); void fill(HeapWord* start, HeapWord* top, size_t new_size); - void initialize(); + void initialize(Thread* owning_thread); static size_t refill_waste_limit_increment() { return TLABWasteIncrement; } diff -r ae0f235469db -r f8e60d11c0ec src/share/vm/prims/nativeLookup.cpp --- a/src/share/vm/prims/nativeLookup.cpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/share/vm/prims/nativeLookup.cpp Mon Aug 25 21:15:59 2014 -0700 @@ -128,6 +128,7 @@ jobject JNICALL JVM_GetGraalRuntime(JNIEnv *env, jclass c); jobject JNICALL JVM_GetGraalServiceImpls(JNIEnv *env, jclass c); jobject JNICALL JVM_CreateTruffleRuntime(JNIEnv *env, jclass c); + jobject JNICALL JVM_CreateNativeFunctionInterface(JNIEnv *env, jclass c); jboolean JNICALL JVM_ParseGraalOptions(JNIEnv *env, jclass hotspotOptionsClass); #ifdef COMPILERGRAAL void JNICALL JVM_PrintAndResetGraalCompRate(JNIEnv *env, jclass c); @@ -144,11 +145,12 @@ { CC"Java_sun_misc_Perf_registerNatives", NULL, FN_PTR(JVM_RegisterPerfMethods) }, { CC"Java_sun_hotspot_WhiteBox_registerNatives", NULL, FN_PTR(JVM_RegisterWhiteBoxMethods) }, #ifdef GRAAL - { CC"Java_com_oracle_graal_api_runtime_Graal_initializeRuntime", NULL, FN_PTR(JVM_GetGraalRuntime) }, - { CC"Java_com_oracle_graal_api_runtime_Services_getServiceImpls", NULL, FN_PTR(JVM_GetGraalServiceImpls) }, - { CC"Java_com_oracle_truffle_api_Truffle_createRuntime", NULL, FN_PTR(JVM_CreateTruffleRuntime) }, - { CC"Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_init", NULL, FN_PTR(JVM_InitializeGraalNatives) }, - { CC"Java_com_oracle_graal_hotspot_HotSpotOptions_parseVMOptions", NULL, FN_PTR(JVM_ParseGraalOptions) }, + { CC"Java_com_oracle_graal_api_runtime_Graal_initializeRuntime", NULL, FN_PTR(JVM_GetGraalRuntime) }, + { CC"Java_com_oracle_graal_api_runtime_Services_getServiceImpls", NULL, FN_PTR(JVM_GetGraalServiceImpls) }, + { CC"Java_com_oracle_truffle_api_Truffle_createRuntime", NULL, FN_PTR(JVM_CreateTruffleRuntime) }, + { CC"Java_com_oracle_nfi_NativeFunctionInterfaceRuntime_createInterface", NULL, FN_PTR(JVM_CreateNativeFunctionInterface) }, + { CC"Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_init", NULL, FN_PTR(JVM_InitializeGraalNatives) }, + { CC"Java_com_oracle_graal_hotspot_HotSpotOptions_parseVMOptions", NULL, FN_PTR(JVM_ParseGraalOptions) }, #endif }; diff -r ae0f235469db -r f8e60d11c0ec src/share/vm/runtime/os.cpp --- a/src/share/vm/runtime/os.cpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/share/vm/runtime/os.cpp Mon Aug 25 21:15:59 2014 -0700 @@ -1269,6 +1269,8 @@ #endif #ifdef GRAAL "%/lib/graal-loader.jar:" +#endif +#ifndef NO_TRUFFLE_JAR "%/lib/truffle.jar:" #endif "%/classes"; diff -r ae0f235469db -r f8e60d11c0ec src/share/vm/runtime/os.hpp --- a/src/share/vm/runtime/os.hpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/share/vm/runtime/os.hpp Mon Aug 25 21:15:59 2014 -0700 @@ -563,6 +563,9 @@ static void *find_agent_function(AgentLibrary *agent_lib, bool check_lib, const char *syms[], size_t syms_len); + + static address get_pc(void* context); + // Print out system information; they are called by fatal error handler. // Output format may be different on different platforms. static void print_os_info(outputStream* st); diff -r ae0f235469db -r f8e60d11c0ec src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/share/vm/runtime/sharedRuntime.cpp Mon Aug 25 21:15:59 2014 -0700 @@ -853,8 +853,8 @@ if (!cb->is_nmethod()) { bool is_in_blob = cb->is_adapter_blob() || cb->is_method_handles_adapter_blob(); if (!is_in_blob) { - cb->print(); - fatal(err_msg("exception happened outside interpreter, nmethods and vtable stubs at pc " INTPTR_FORMAT, pc)); + // Allow normal crash reporting to handle this + return NULL; } Events::log_exception(thread, "NullPointerException in code blob at " INTPTR_FORMAT, pc); // There is no handler here, so we will simply unwind. diff -r ae0f235469db -r f8e60d11c0ec src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/share/vm/runtime/thread.cpp Mon Aug 25 21:15:59 2014 -0700 @@ -1474,7 +1474,9 @@ #ifdef GRAAL set_gpu_exception_bci(0); set_gpu_exception_method(NULL); - set_gpu_hsail_deopt_info(NULL); + set_gpu_hsail_deopt_info(NULL); + _gpu_hsail_tlabs_count = 0; + _gpu_hsail_tlabs = NULL; #endif set_thread_state(_thread_new); #if INCLUDE_NMT @@ -1694,6 +1696,8 @@ } FREE_C_HEAP_ARRAY(jlong, _graal_counters, mtInternal); } + + delete_gpu_hsail_tlabs(); #endif // GRAAL } @@ -1968,7 +1972,7 @@ remove_stack_guard_pages(); if (UseTLAB) { - tlab().make_parsable(true); // retire TLAB + tlabs_make_parsable(true); // retire TLABs, if any } if (JvmtiEnv::environments_might_exist()) { @@ -2047,7 +2051,7 @@ remove_stack_guard_pages(); if (UseTLAB) { - tlab().make_parsable(true); // retire TLAB, if any + tlabs_make_parsable(true); // retire TLABs, if any } #if INCLUDE_ALL_GCS @@ -4792,3 +4796,54 @@ VMThread* thread = VMThread::vm_thread(); if (thread != NULL) thread->verify(); } + +void JavaThread::tlabs_make_parsable(bool retire) { + // do the primary tlab for this thread + tlab().make_parsable(retire); +#ifdef GRAAL + // do the gpu_hsail tlabs if any + gpu_hsail_tlabs_make_parsable(retire); +#endif +} + + +#ifdef GRAAL +void JavaThread::initialize_gpu_hsail_tlabs(jint count) { + if (!UseTLAB) return; + // create tlabs + _gpu_hsail_tlabs = NEW_C_HEAP_ARRAY(ThreadLocalAllocBuffer*, count, mtInternal); + // initialize + for (jint i = 0; i < count; i++) { + _gpu_hsail_tlabs[i] = new ThreadLocalAllocBuffer(); + _gpu_hsail_tlabs[i]->initialize(Thread::current()); + } + _gpu_hsail_tlabs_count = count; +} + +ThreadLocalAllocBuffer* JavaThread::get_gpu_hsail_tlab_at(jint idx) { + assert(idx >= 0 && idx < get_gpu_hsail_tlabs_count(), "illegal gpu tlab index"); + return _gpu_hsail_tlabs[idx]; +} + +void JavaThread::gpu_hsail_tlabs_make_parsable(bool retire) { + for (jint i = 0; i < get_gpu_hsail_tlabs_count(); i++) { + get_gpu_hsail_tlab_at(i)->make_parsable(retire); + } +} + +void JavaThread::delete_gpu_hsail_tlabs() { + if (!UseTLAB) return; + if (_gpu_hsail_tlabs_count == 0) return; + + gpu_hsail_tlabs_make_parsable(true); + for (jint i = 0; i < get_gpu_hsail_tlabs_count(); i++) { + delete get_gpu_hsail_tlab_at(i); + } + FREE_C_HEAP_ARRAY(ThreadLocalAllocBuffer*, _gpu_hsail_tlabs, mtInternal); + _gpu_hsail_tlabs = NULL; + _gpu_hsail_tlabs_count = 0; +} + + +#endif + diff -r ae0f235469db -r f8e60d11c0ec src/share/vm/runtime/thread.hpp --- a/src/share/vm/runtime/thread.hpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/share/vm/runtime/thread.hpp Mon Aug 25 21:15:59 2014 -0700 @@ -436,7 +436,7 @@ ThreadLocalAllocBuffer& tlab() { return _tlab; } void initialize_tlab() { if (UseTLAB) { - tlab().initialize(); + tlab().initialize(this); } } @@ -950,6 +950,8 @@ Method* _gpu_exception_method; // Record the hsailDeoptimization info so gc oops_do processing can find it void* _gpu_hsail_deopt_info; + jint _gpu_hsail_tlabs_count; + ThreadLocalAllocBuffer** _gpu_hsail_tlabs; #endif public: @@ -960,9 +962,17 @@ Method* get_gpu_exception_method() { return _gpu_exception_method; } void set_gpu_hsail_deopt_info(void * deoptInfo) { _gpu_hsail_deopt_info = deoptInfo; } void* get_gpu_hsail_deopt_info() { return _gpu_hsail_deopt_info; } + jint get_gpu_hsail_tlabs_count() { return _gpu_hsail_tlabs_count; } + + void initialize_gpu_hsail_tlabs(jint count); + ThreadLocalAllocBuffer* get_gpu_hsail_tlab_at(jint idx); + void gpu_hsail_tlabs_make_parsable(bool retire); + void delete_gpu_hsail_tlabs(); #endif - + private: + void tlabs_make_parsable(bool retire); + // support for JNI critical regions jint _jni_active_critical; // count of entries into JNI critical region diff -r ae0f235469db -r f8e60d11c0ec src/share/vm/utilities/vmError.cpp --- a/src/share/vm/utilities/vmError.cpp Mon Aug 25 14:42:42 2014 -0700 +++ b/src/share/vm/utilities/vmError.cpp Mon Aug 25 21:15:59 2014 -0700 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "compiler/compileBroker.hpp" +#include "compiler/disassembler.hpp" #include "gc_interface/collectedHeap.hpp" #include "prims/whitebox.hpp" #include "runtime/arguments.hpp" @@ -532,6 +533,32 @@ st->cr(); } + STEP(102, "(printing code blob if possible)") + + if (_verbose && _context) { + address pc = os::get_pc(_context); + CodeBlob* cb = CodeCache::find_blob(pc); + if (cb != NULL) { + if (Interpreter::contains(pc)) { + // The interpreter CodeBlob is very large so try to print the codelet instead. + InterpreterCodelet* codelet = Interpreter::codelet_containing(pc); + if (codelet != NULL) { + codelet->print_on(st); + Disassembler::decode(codelet->code_begin(), codelet->code_end(), st); + } + } else { + StubCodeDesc* desc = StubCodeDesc::desc_for(pc); + if (desc != NULL) { + desc->print_on(st); + Disassembler::decode(desc->begin(), desc->end(), st); + } else { + Disassembler::decode(cb, st); + st->cr(); + } + } + } + } + STEP(105, "(printing register info)") // decode register contents if possible