# HG changeset patch # User Christian Humer # Date 1389117152 -3600 # Node ID 5a0c694ef735053dc64ecbbe6bf04f6766b3ac87 # Parent 25ecb47a6d0ea683cd69a1cfa9b989eb4ced255e Truffle-DSL: Removed API classes NodeId, NodeContainer and SpecializationListener. diff -r 25ecb47a6d0e -r 5a0c694ef735 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BoxedString.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/BoxedString.java Tue Jan 07 18:52:32 2014 +0100 @@ -0,0 +1,41 @@ +/* + * 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.api.dsl.test; + +public class BoxedString { + + private final String delegate; + + public BoxedString(String delegate) { + this.delegate = delegate; + } + + public String getDelegate() { + return delegate; + } + + @Override + public String toString() { + return getDelegate(); + } +} diff -r 25ecb47a6d0e -r 5a0c694ef735 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 Tue Jan 07 12:22:47 2014 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/GuardsTest.java Tue Jan 07 18:52:32 2014 +0100 @@ -38,8 +38,6 @@ 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.NodeContainerTest.Str; -import com.oracle.truffle.api.dsl.test.NodeContainerTest.StrBase; 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; @@ -124,18 +122,18 @@ public void testGuardWithBaseClass() { TestRootNode root = createRoot(GuardWithBaseClassFactory.getInstance()); - assertEquals(42, executeWith(root, new Str("42"))); + assertEquals(42, executeWith(root, new BExtendsAbstract())); } @NodeChild("expression") public abstract static class GuardWithBaseClass extends ValueNode { - boolean baseGuard(StrBase base) { + boolean baseGuard(Abstract base) { return true; } @Specialization(guards = "baseGuard") - int doSpecialized(Str value0) { + int doSpecialized(BExtendsAbstract value0) { return 42; } } @@ -227,7 +225,7 @@ @Test public void testGuardResolve2() { TestRootNode root = createRoot(TestGuardResolve2Factory.getInstance()); - assertEquals(42, executeWith(root, new Str(""))); + assertEquals(42, executeWith(root, new BExtendsAbstract())); } @NodeChild("expression") @@ -237,12 +235,12 @@ return false; } - boolean guard(StrBase primitive) { + boolean guard(Abstract primitive) { return true; } @Specialization(guards = "guard") - int doSpecialized(Str value0) { + int doSpecialized(BExtendsAbstract value0) { return 42; } } @@ -251,7 +249,7 @@ public void testGuardResolve3() { TestRootNode root = createRoot(TestGuardResolve3Factory.getInstance()); - assertEquals(42, executeWith(root, new Str(""))); + assertEquals(42, executeWith(root, new BExtendsAbstract())); } @NodeChild("expression") @@ -261,16 +259,16 @@ return false; } - boolean guard(StrBase primitive) { + boolean guard(Abstract primitive) { return false; } - boolean guard(Str primitive) { + boolean guard(BExtendsAbstract primitive) { return true; } @Specialization(guards = "guard") - int doSpecialized(Str value0) { + int doSpecialized(BExtendsAbstract value0) { return 42; } } @@ -278,12 +276,12 @@ @NodeChild("expression") public abstract static class TestGuardResolve4 extends ValueNode { - boolean guard(StrBase primitive) { + boolean guard(Abstract primitive) { return false; } @Specialization(guards = "guard") - int doSpecialized(Str value0) { + int doSpecialized(BExtendsAbstract value0) { return 42; } } diff -r 25ecb47a6d0e -r 5a0c694ef735 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 Tue Jan 07 12:22:47 2014 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java Tue Jan 07 18:52:32 2014 +0100 @@ -28,14 +28,13 @@ import com.oracle.truffle.api.dsl.test.ImplicitCastTestFactory.ImplicitCast0NodeFactory; import com.oracle.truffle.api.dsl.test.ImplicitCastTestFactory.ImplicitCast1NodeFactory; import com.oracle.truffle.api.dsl.test.ImplicitCastTestFactory.ImplicitCast2NodeFactory; -import com.oracle.truffle.api.dsl.test.NodeContainerTest.Str; import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; import com.oracle.truffle.api.frame.*; public class ImplicitCastTest { - @TypeSystem({int.class, boolean.class, String.class, Str.class}) + @TypeSystem({int.class, boolean.class, String.class}) static class ImplicitCast0Types { @ImplicitCast diff -r 25ecb47a6d0e -r 5a0c694ef735 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeContainerTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeContainerTest.java Tue Jan 07 12:22:47 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,179 +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.NodeContainerTestFactory.StrFactory.StrAccessContextFactory; -import com.oracle.truffle.api.dsl.test.NodeContainerTestFactory.StrFactory.StrConcatFactory; -import com.oracle.truffle.api.dsl.test.NodeContainerTestFactory.StrFactory.StrLengthFactory; -import com.oracle.truffle.api.dsl.test.NodeContainerTestFactory.StrFactory.StrSubstrFactory; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; - -public class NodeContainerTest { - - @Test - public void testConcat() { - TestRootNode node = createRoot(StrConcatFactory.getInstance(), new Context()); - Str str1 = new Str("42"); - Str str2 = new Str(" is the number."); - assertEquals(str1.concat(str2), executeWith(node, str1, str2)); - } - - @Test(expected = UnsupportedOperationException.class) - public void testConcatUnsupported() { - TestRootNode node = createRoot(StrConcatFactory.getInstance(), new Context()); - executeWith(node, 42, new Str(" is the number.")); - } - - @Test - public void testSubstrSpecialized() { - TestRootNode node = createRoot(StrSubstrFactory.getInstance(), new Context()); - Str str = new Str("test 42"); - - assertEquals(str.substr(5, 7), executeWith(node, str, 5, 7)); - } - - @Test - public void testSubstrGeneric() { - TestRootNode node = createRoot(StrSubstrFactory.getInstance(), new Context()); - Str str = new Str("test 42"); - - assertEquals(Str.substr(str, "5", "7"), executeWith(node, str, "5", "7")); - } - - @Test(expected = UnsupportedOperationException.class) - public void testSubstrUnsupported() { - TestRootNode node = createRoot(StrSubstrFactory.getInstance(), new Context()); - executeWith(node, new Object(), "5", "7"); - } - - @Test - public void testLength() { - TestRootNode node = createRoot(StrLengthFactory.getInstance(), new Context()); - Str testStr = new Str("test 42"); - assertEquals(testStr.length(), executeWith(node, testStr)); - } - - @Test(expected = UnsupportedOperationException.class) - public void testLengthUnsupported() { - TestRootNode node = createRoot(StrLengthFactory.getInstance(), new Context()); - executeWith(node, new Object()); - } - - @Test - public void testAccessContext() { - Context context = new Context(); - TestRootNode node = createRoot(StrAccessContextFactory.getInstance(), context); - // accessible by node - assertSame(context, node.getNode().getContext()); - // accessible by execution - assertSame(context, executeWith(node)); - } - - static class StrBase { - - } - - @NodeContainer(BuiltinNode.class) - static class Str extends StrBase { - - private final String internal; - - public Str(String internal) { - this.internal = internal; - } - - @Specialization - Str concat(Str s1) { - return new Str(internal + s1.internal); - } - - @Specialization - Str substr(int beginIndex, int endIndex) { - return new Str(internal.substring(beginIndex, endIndex)); - } - - @Generic - static Str substr(Object thisValue, Object beginIndex, Object endIndex) { - if (!(thisValue instanceof Str)) { - throw new UnsupportedOperationException(); - } - return ((Str) thisValue).substr(convertInt(beginIndex), convertInt(endIndex)); - } - - @Specialization - int length() { - return internal.length(); - } - - @Specialization - static Object accessContext(Context context) { - return context; - } - - static int convertInt(Object value) { - if (value instanceof Number) { - return ((Number) value).intValue(); - } else if (value instanceof String) { - return Integer.parseInt((String) value); - } - throw new RuntimeException("Invalid datatype"); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Str) { - return internal.equals(((Str) obj).internal); - } - return super.equals(obj); - } - - @Override - public String toString() { - return internal; - } - - @Override - public int hashCode() { - return internal.hashCode(); - } - } - - @NodeChild(value = "children", type = ValueNode[].class) - @NodeField(name = "context", type = Context.class) - abstract static class BuiltinNode extends ValueNode { - - public abstract Context getContext(); - } - - static class Context { - - } - -} diff -r 25ecb47a6d0e -r 5a0c694ef735 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 Tue Jan 07 12:22:47 2014 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java Tue Jan 07 18:52:32 2014 +0100 @@ -28,8 +28,13 @@ import org.junit.*; import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.*; -import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.TestContainerFactory.TestContainerContainerFieldFactory; +import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.IntFieldNoGetterTestNodeFactory; +import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.IntFieldTestNodeFactory; +import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.MultipleFieldsTestNodeFactory; +import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.ObjectContainerNodeFactory; +import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.RewriteTestNodeFactory; +import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.StringFieldTestNodeFactory; +import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.TestContainerFactory; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; public class NodeFieldTest { @@ -125,7 +130,7 @@ @Test public void testStringContainer() { - assertEquals(42, createCallTarget(TestContainerContainerFieldFactory.create(42, "42")).call()); + assertEquals(42, createCallTarget(TestContainerFactory.create("42")).call()); } @NodeField(name = "field", type = int.class) @@ -135,13 +140,12 @@ } - @NodeContainer(IntContainerNode.class) @NodeField(name = "anotherField", type = String.class) - abstract static class TestContainer { + abstract static class TestContainer extends ValueNode { @Specialization - static int containerField(int field, String anotherField) { - return anotherField.equals("42") ? field : -1; + int containerField(String field) { + return field.equals("42") ? 42 : -1; } } diff -r 25ecb47a6d0e -r 5a0c694ef735 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 Tue Jan 07 12:22:47 2014 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java Tue Jan 07 18:52:32 2014 +0100 @@ -28,7 +28,6 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.dsl.test.NodeContainerTest.BuiltinNode; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ArgumentNode; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ChildrenNode; import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestArguments; @@ -52,7 +51,7 @@ ArgumentNode[] argumentNodes = arguments(factory.getExecutionSignature().size()); List argumentList = new ArrayList<>(); - if (ChildrenNode.class.isAssignableFrom(factory.getNodeClass()) || BuiltinNode.class.isAssignableFrom(factory.getNodeClass())) { + if (ChildrenNode.class.isAssignableFrom(factory.getNodeClass())) { argumentList.add(argumentNodes); } else { argumentList.addAll(Arrays.asList(argumentNodes)); diff -r 25ecb47a6d0e -r 5a0c694ef735 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 Tue Jan 07 12:22:47 2014 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java Tue Jan 07 18:52:32 2014 +0100 @@ -24,13 +24,12 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.dsl.test.NodeContainerTest.Str; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; public class TypeSystemTest { - @TypeSystem({int.class, boolean.class, String.class, Str.class, CallTarget.class, BExtendsAbstract.class, CExtendsAbstract.class, Abstract.class, Object[].class}) + @TypeSystem({int.class, boolean.class, String.class, CallTarget.class, BExtendsAbstract.class, CExtendsAbstract.class, Abstract.class, Object[].class}) static class SimpleTypes { static int intCheck; @@ -48,11 +47,6 @@ return (int) value; } - @ImplicitCast - Str castStr(String strvalue) { - return new Str(strvalue); - } - } @TypeSystemReference(SimpleTypes.class) @@ -66,10 +60,6 @@ return SimpleTypesGen.SIMPLETYPES.expectInteger(execute(frame)); } - public Str executeStr(VirtualFrame frame) throws UnexpectedResultException { - return SimpleTypesGen.SIMPLETYPES.expectStr(execute(frame)); - } - public String executeString(VirtualFrame frame) throws UnexpectedResultException { return SimpleTypesGen.SIMPLETYPES.expectString(execute(frame)); } diff -r 25ecb47a6d0e -r 5a0c694ef735 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/package-info.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/package-info.java Tue Jan 07 12:22:47 2014 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/package-info.java Tue Jan 07 18:52:32 2014 +0100 @@ -41,7 +41,6 @@ * *
    *
  • What do I need to get started? {@link com.oracle.truffle.api.dsl.test.TypeSystemTest}
  • - *
  • How would you generate function nodes for runtime objects? {@link com.oracle.truffle.api.dsl.test.NodeContainerTest}
  • *
*

* diff -r 25ecb47a6d0e -r 5a0c694ef735 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeContainer.java --- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeContainer.java Tue Jan 07 12:22:47 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +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.*; - -import com.oracle.truffle.api.nodes.*; - -/** - * A node container can be used to enable Truffle-DSL in classes which do not extend {@link Node}. - * Compared to normal {@link Node} implementation the nodes are not identified by a class but by - * their method name. There are cases were method signatures are matching exactly but should be in - * the same {@link Node}. In this case use {@link NodeId} to disambiguate such cases. - */ -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.TYPE}) -public @interface NodeContainer { - - /** The node class to use as base class for {@link Node} definitions grouped by method names. */ - Class value(); - -} diff -r 25ecb47a6d0e -r 5a0c694ef735 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeId.java --- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeId.java Tue Jan 07 12:22:47 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +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, ElementType.TYPE}) -public @interface NodeId { - - String value(); - -} diff -r 25ecb47a6d0e -r 5a0c694ef735 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/SpecializationListener.java --- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/SpecializationListener.java Tue Jan 07 12:22:47 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +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 SpecializationListener { -} diff -r 25ecb47a6d0e -r 5a0c694ef735 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 Tue Jan 07 12:22:47 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java Tue Jan 07 18:52:32 2014 +0100 @@ -30,6 +30,7 @@ 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 { @@ -57,8 +58,7 @@ @Override public SpecializationData create(TemplateMethod method, boolean invalid) { - SpecializationData data = new SpecializationData(method, true, false, false); - return data; + return new SpecializationData(getNode(), method, SpecializationKind.GENERIC); } @Override diff -r 25ecb47a6d0e -r 5a0c694ef735 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 Tue Jan 07 12:22:47 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeChildData.java Tue Jan 07 18:52:32 2014 +0100 @@ -45,24 +45,20 @@ } } - private final NodeData parent; + 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 nodeData; + private NodeData childNode; - public NodeChildData(NodeData parent, Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, TypeMirror originalNodeType, Element accessElement, - Cardinality cardinality) { - this.parent = parent; + 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; @@ -72,6 +68,10 @@ this.cardinality = cardinality; } + void setParentNode(NodeData parentNode) { + this.parentNode = parentNode; + } + public List getExecuteWith() { return executeWith; } @@ -81,12 +81,12 @@ } public boolean needsImplicitCast(ProcessorContext context) { - if (!parent.needsRewrites(context)) { + if (!parentNode.needsRewrites(context)) { return false; } boolean used = false; - for (NodeExecutionData execution : parent.getChildExecutions()) { + for (NodeExecutionData execution : parentNode.getChildExecutions()) { if (execution.getChild() == this) { used = true; break; @@ -100,7 +100,7 @@ } public ExecutableTypeData findExecutableType(ProcessorContext context, TypeData targetType) { - ExecutableTypeData executableType = nodeData.findExecutableType(targetType, getExecuteWith().size()); + ExecutableTypeData executableType = childNode.findExecutableType(targetType, getExecuteWith().size()); if (executableType == null) { executableType = findAnyGenericExecutableType(context); } @@ -108,15 +108,15 @@ } public List findGenericExecutableTypes(ProcessorContext context) { - return nodeData.findGenericExecutableTypes(context, getExecuteWith().size()); + return childNode.findGenericExecutableTypes(context, getExecuteWith().size()); } public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context) { - return nodeData.findAnyGenericExecutableType(context, getExecuteWith().size()); + return childNode.findAnyGenericExecutableType(context, getExecuteWith().size()); } public List findExecutableTypes() { - return nodeData.getExecutableTypes(getExecuteWith().size()); + return childNode.getExecutableTypes(getExecuteWith().size()); } public TypeMirror getOriginalType() { @@ -134,7 +134,7 @@ } void setNode(NodeData nodeData) { - this.nodeData = nodeData; + this.childNode = nodeData; if (nodeData != null) { getMessages().addAll(nodeData.collectMessages()); } @@ -153,7 +153,7 @@ } public NodeData getNodeData() { - return nodeData; + return childNode; } public String getName() { diff -r 25ecb47a6d0e -r 5a0c694ef735 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 Tue Jan 07 12:22:47 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Tue Jan 07 18:52:32 2014 +0100 @@ -47,6 +47,7 @@ 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"; @@ -70,16 +71,8 @@ return name; } - private static String nodePolymorphicClassName(NodeData node, SpecializationData specialization) { - String nodeid = resolveNodeId(node); - - String name = Utils.firstLetterUpperCase(nodeid); - if (specialization == node.getGenericPolymorphicSpecialization()) { - name += "PolymorphicNode"; - } else { - name += "Polymorphic" + polymorphicIndex(node, specialization) + "Node"; - } - return name; + private static String nodePolymorphicClassName(NodeData node) { + return Utils.firstLetterUpperCase(resolveNodeId(node)) + "PolymorphicNode"; } private static String resolveNodeId(NodeData node) { @@ -110,30 +103,6 @@ return valueName(parameter) + "Cast"; } - private static String executeCachedName(SpecializationData polymorphic) { - NodeData node = polymorphic.getNode(); - boolean generic = polymorphic == node.getGenericPolymorphicSpecialization(); - - if (generic) { - return "executeCachedGeneric0"; - } else { - return "executeCached" + polymorphicIndex(node, polymorphic); - } - } - - private static int polymorphicIndex(NodeData node, SpecializationData polymorphic) { - int index = 0; - for (SpecializationData specialization : node.getPolymorphicSpecializations()) { - if (specialization == polymorphic) { - break; - } - if (specialization != node.getGenericPolymorphicSpecialization()) { - index++; - } - } - return index; - } - 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")); @@ -439,11 +408,9 @@ getElement().getEnclosedElements().clear(); Map> childTypes = new LinkedHashMap<>(); - if (node.getDeclaredNodes() != null && !node.getDeclaredNodes().isEmpty()) { - for (NodeData nodeChild : node.getDeclaredNodes()) { - NodeCodeGenerator generator = new NodeCodeGenerator(getContext()); - childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements()); - } + 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) { @@ -525,15 +492,18 @@ createFactoryMethods(node, clazz, createVisibility); - if (node.isPolymorphic()) { - PolymorphicNodeFactory generic = new PolymorphicNodeFactory(getContext(), generatedNode); - add(generic, node.getGenericPolymorphicSpecialization()); - polymorphicNode = generic.getElement(); - } 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); } @@ -572,7 +542,7 @@ } List children = node.getNodeDeclaringChildren(); - if (node.getParent() == null && children.size() > 0) { + if (node.getDeclaringNode() == null && children.size() > 0) { clazz.add(createGetFactories(node)); } @@ -755,7 +725,7 @@ } private String instanceVarName(NodeData node) { - if (node.getParent() != null) { + if (node.getDeclaringNode() != null) { return Utils.firstLetterLowerCase(factoryClassName(node)) + "Instance"; } else { return "instance"; @@ -808,9 +778,9 @@ builder.startGroup(); NodeData childNode = child; List factories = new ArrayList<>(); - while (childNode.getParent() != null) { + while (childNode.getDeclaringNode() != null) { factories.add(childNode); - childNode = childNode.getParent(); + childNode = childNode.getDeclaringNode(); } Collections.reverse(factories); for (NodeData nodeData : factories) { @@ -950,7 +920,7 @@ builder.statement("this.next0 = adoptChild(next0)"); clazz.add(setter); - CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getGenericPolymorphicSpecialization()); + CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getPolymorphicSpecialization()); clazz.add(genericCachedExecute); getElement().add(createUpdateTypes(clazz.asType())); @@ -1144,8 +1114,7 @@ } private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph) { - String name = executeCachedName(polymorph); - CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), name); + CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), EXECUTE_POLYMORPHIC_NAME); addInternalValueParameters(cachedExecute, polymorph, true, true); ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0); @@ -1305,8 +1274,6 @@ builder.startStaticCall(getContext().getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end(); builder.end(); - emitSpecializationListeners(builder, node); - String currentNode = "this"; for (SpecializationData specialization : node.getSpecializations()) { if (!specialization.getExceptions().isEmpty()) { @@ -1330,7 +1297,7 @@ boolean firstUnreachable = true; for (SpecializationData current : node.getSpecializations()) { - if (current.isUninitialized() || current.isReachable()) { + if (current.isReachable()) { continue; } if (firstUnreachable) { @@ -1347,7 +1314,7 @@ List specializations = node.getSpecializations(); List filteredSpecializations = new ArrayList<>(); for (SpecializationData current : specializations) { - if (current.isUninitialized() || !current.isReachable()) { + if (current.isUninitialized() || current.isPolymorphic() || !current.isReachable()) { continue; } filteredSpecializations.add(current); @@ -1380,7 +1347,7 @@ private void emitUnreachableSpecializations(final CodeTreeBuilder builder, NodeData node) { for (SpecializationData current : node.getSpecializations()) { - if (current.isUninitialized() || current.isReachable()) { + if (current.isReachable()) { continue; } builder.string("// unreachable ").string(current.getId()).newLine(); @@ -1751,7 +1718,7 @@ } builder.end(); builder.startDoWhile(); - builder.string("!").startParantheses().instanceOf("root", nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization())).end(); + builder.string("!").startParantheses().instanceOf("root", nodePolymorphicClassName(node)).end(); builder.end(); return builder.getRoot(); } @@ -1829,7 +1796,7 @@ } private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node, String currentNode) { - String polyClassName = nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization()); + String polyClassName = nodePolymorphicClassName(node); String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization()); CodeTreeBuilder builder = parent.create(); @@ -1840,7 +1807,7 @@ builder.startStatement().startCall("currentCopy", "setNext0").startNew(uninitializedName).string(currentNode).end().end().end(); builder.startReturn(); - builder.startCall("currentCopy.next0", executeCachedName(node.getGenericPolymorphicSpecialization())); + builder.startCall("currentCopy.next0", EXECUTE_POLYMORPHIC_NAME); addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, true, null); builder.end(); builder.end(); @@ -1848,14 +1815,6 @@ return builder.getRoot(); } - private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) { - for (TemplateMethod listener : node.getSpecializationListeners()) { - builder.startStatement(); - builder.tree(createTemplateMethodCall(builder, null, listener, listener, null)); - builder.end(); // statement - } - } - protected CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) { TypeData type = executable.getType(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); @@ -2302,8 +2261,7 @@ private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, ActualParameter param) { NodeData node = specialization.getNode(); - assert !node.getPolymorphicSpecializations().isEmpty(); - SpecializationData generic = node.getGenericPolymorphicSpecialization(); + SpecializationData polymorphic = node.getPolymorphicSpecialization(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); builder.startStatement().string(polymorphicTypeName(param)).string(" = ").typeLiteral(getContext().getType(Object.class)).end(); @@ -2311,11 +2269,11 @@ builder.startReturn(); CodeTreeBuilder execute = new CodeTreeBuilder(builder); - execute.startCall("next0", executeCachedName(generic)); - addInternalValueParameterNames(execute, specialization, generic, param.getLocalName(), true, true, null); + execute.startCall("next0", EXECUTE_POLYMORPHIC_NAME); + addInternalValueParameterNames(execute, specialization, polymorphic, param.getLocalName(), true, true, null); execute.end(); - TypeData sourceType = generic.getReturnType().getTypeSystemType(); + TypeData sourceType = polymorphic.getReturnType().getTypeSystemType(); builder.tree(createExpectExecutableType(node, sourceType, currentExecutable, execute.getRoot())); @@ -2505,7 +2463,7 @@ if (nodeGen != null) { baseType = nodeGen.asType(); } - CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodePolymorphicClassName(node, polymorph), baseType, false); + CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodePolymorphicClassName(node), baseType, false); clazz.getAnnotationMirrors().add(createNodeInfo(node, Kind.POLYMORPHIC)); @@ -2602,8 +2560,12 @@ kind = Kind.GENERIC; } else if (specialization.isUninitialized()) { kind = Kind.UNINITIALIZED; + } else if (specialization.isPolymorphic()) { + kind = Kind.POLYMORPHIC; + } else if (specialization.isSpecialized()) { + kind = Kind.SPECIALIZED; } else { - kind = Kind.SPECIALIZED; + throw new AssertionError(); } clazz.getAnnotationMirrors().add(createNodeInfo(node, kind)); @@ -2709,9 +2671,9 @@ CodeTypeElement clazz = getElement(); - final SpecializationData polymorphic = node.getGenericPolymorphicSpecialization(); - - ExecutableElement executeCached = nodeGen.getMethod(executeCachedName(polymorphic)); + final SpecializationData polymorphic = node.getPolymorphicSpecialization(); + + ExecutableElement executeCached = nodeGen.getMethod(EXECUTE_POLYMORPHIC_NAME); // ExecutableTypeData execType = new ExecutableTypeData(polymorphic, executeCached, // node.getTypeSystem(), polymorphic.getReturnType().getTypeSystemType()); @@ -2729,7 +2691,7 @@ builder.tree(createAppendPolymorphic(builder, specialization)); } else { CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder); - elseBuilder.startReturn().startCall("this.next0", executeCachedName(polymorphic)); + elseBuilder.startReturn().startCall("this.next0", EXECUTE_POLYMORPHIC_NAME); addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, true, null); elseBuilder.end().end(); @@ -2759,7 +2721,7 @@ builder.startBlock(); String message = "Polymorphic limit reached (" + node.getPolymorphicDepth() + ")"; String castRoot = "(" + baseClassName(node) + ") root"; - builder.tree(createGenericInvoke(builder, node.getGenericPolymorphicSpecialization(), node.getGenericSpecialization(), + builder.tree(createGenericInvoke(builder, node.getPolymorphicSpecialization(), node.getGenericSpecialization(), createReplaceCall(builder, node.getGenericSpecialization(), "root", castRoot, message), null)); builder.end(); @@ -2777,7 +2739,7 @@ builder.declaration(node.getGenericSpecialization().getReturnType().getType(), "result", specializeCall.getRoot()); - CodeTree root = builder.create().cast(nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization())).string("root").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(); @@ -2950,7 +2912,7 @@ CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent); if (specialization.isPolymorphic()) { - returnBuilder.startCall("next0", executeCachedName(specialization)); + returnBuilder.startCall("next0", EXECUTE_POLYMORPHIC_NAME); addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true, null); returnBuilder.end(); } else if (specialization.isUninitialized()) { diff -r 25ecb47a6d0e -r 5a0c694ef735 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 Tue Jan 07 12:22:47 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java Tue Jan 07 18:52:32 2014 +0100 @@ -34,58 +34,57 @@ 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 List declaredNodes = new ArrayList<>(); - private boolean nodeContainer; - private TypeSystemData typeSystem; - private List children; - private List childExecutions; - private List fields; - private TypeMirror nodeType; + private final TypeSystemData typeSystem; + private final List children; + private final List childExecutions; + private final List fields; + private final List assumptions; + private ParameterSpec instanceParameterSpec; - private List specializations; - private List polymorphicSpecializations; - private SpecializationData genericPolymorphicSpecialization; - private List specializationListeners; + private final List specializations = new ArrayList<>(); + private final List shortCircuits = new ArrayList<>(); + private final List casts = new ArrayList<>(); private Map> executableTypes; - private List shortCircuits; - private List assumptions; - private List casts; private int polymorphicDepth = -1; - private String shortName; - public NodeData(TypeElement type, String id) { + public NodeData(TypeElement type, String shortName, TypeSystemData typeSystem, List children, List executions, List fields, + List assumptions, int polymorphicDepth) { super(type, null, null); - this.nodeId = id; + 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; + + if (children != null) { + for (NodeChildData child : children) { + child.setParentNode(this); + } + } } - public NodeData(NodeData splitSource, String templateMethodName, String nodeId) { - super(splitSource.getTemplateType(), templateMethodName, null); - this.nodeId = nodeId; - this.declaringNode = splitSource.declaringNode; - this.declaredNodes = splitSource.declaredNodes; - this.typeSystem = splitSource.typeSystem; - this.nodeType = splitSource.nodeType; - this.specializations = splitSource.specializations; - this.specializationListeners = splitSource.specializationListeners; - this.executableTypes = splitSource.executableTypes; - this.shortCircuits = splitSource.shortCircuits; - this.fields = splitSource.fields; - this.children = splitSource.children; - this.assumptions = splitSource.assumptions; + public NodeData(TypeElement type) { + this(type, null, null, null, null, null, null, -1); + } + + public void addEnclosedNode(NodeData node) { + this.enclosingNodes.add(node); + node.declaringNode = this; } public List getChildExecutions() { return childExecutions; } - void setChildExecutions(List signature) { - this.childExecutions = signature; - } - public int getSignatureSize() { if (getSpecializations() != null && !getSpecializations().isEmpty()) { return getSpecializations().get(0).getSignatureSize(); @@ -122,7 +121,7 @@ return polymorphicDepth > 1; } - void setPolymorphicDepth(int polymorphicDepth) { + public void setPolymorphicDepth(int polymorphicDepth) { this.polymorphicDepth = polymorphicDepth; } @@ -130,43 +129,19 @@ return casts; } - void setCasts(List casts) { - this.casts = casts; - } - - void setShortName(String shortName) { - this.shortName = shortName; - } - public String getShortName() { return shortName; } - public boolean isNodeContainer() { - return nodeContainer; - } - - void setTypeSystem(TypeSystemData typeSystem) { - this.typeSystem = typeSystem; - } - - void setFields(List fields) { - this.fields = fields; - } - public List getFields() { return fields; } - void setNodeContainer(boolean splitByMethodName) { - this.nodeContainer = splitByMethodName; - } - @Override protected List findChildContainers() { List containerChildren = new ArrayList<>(); - if (declaredNodes != null) { - containerChildren.addAll(declaredNodes); + if (enclosingNodes != null) { + containerChildren.addAll(enclosingNodes); } if (typeSystem != null) { containerChildren.add(typeSystem); @@ -178,9 +153,6 @@ } } } - if (specializationListeners != null) { - containerChildren.addAll(specializationListeners); - } if (executableTypes != null) { containerChildren.addAll(getExecutableTypes()); } @@ -212,16 +184,9 @@ } public TypeMirror getNodeType() { - if (nodeType != null) { - return nodeType; - } return getTemplateType().asType(); } - void setAssumptions(List assumptions) { - this.assumptions = assumptions; - } - public List getAssumptions() { return assumptions; } @@ -236,7 +201,7 @@ boolean noSpecialization = true; for (SpecializationData specialization : specializations) { - noSpecialization = noSpecialization && specialization.isGeneric() || specialization.isUninitialized(); + noSpecialization = noSpecialization && !specialization.isSpecialized(); } return !noSpecialization; } @@ -254,7 +219,7 @@ public List getNodeDeclaringChildren() { List nodeChildren = new ArrayList<>(); - for (NodeData child : getDeclaredNodes()) { + for (NodeData child : getEnclosingNodes()) { if (child.needsFactory()) { nodeChildren.add(child); } @@ -263,24 +228,12 @@ return nodeChildren; } - void setDeclaredNodes(List declaredChildren) { - this.declaredNodes = declaredChildren; - - for (NodeData child : declaredChildren) { - child.declaringNode = this; - } - } - - public NodeData getParent() { + public NodeData getDeclaringNode() { return declaringNode; } - public List getDeclaredNodes() { - return declaredNodes; - } - - public void setNodeType(TypeMirror nodeType) { - this.nodeType = nodeType; + public List getEnclosingNodes() { + return enclosingNodes; } public List getAllTemplateMethods() { @@ -290,7 +243,6 @@ methods.add(specialization); } - methods.addAll(getSpecializationListeners()); methods.addAll(getExecutableTypes()); methods.addAll(getShortCircuits()); if (getCasts() != null) { @@ -394,6 +346,15 @@ 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()) { @@ -436,13 +397,12 @@ dumpProperty(builder, indent, "executableTypes", getExecutableTypes()); dumpProperty(builder, indent, "specializations", getSpecializations()); dumpProperty(builder, indent, "polymorphicDepth", getPolymorphicDepth()); - dumpProperty(builder, indent, "polymorphic", getPolymorphicSpecializations()); dumpProperty(builder, indent, "assumptions", getAssumptions()); dumpProperty(builder, indent, "casts", getCasts()); dumpProperty(builder, indent, "messages", collectMessages()); - if (getDeclaredNodes().size() > 0) { + if (getEnclosingNodes().size() > 0) { builder.append(String.format("\n%s children = [", indent)); - for (NodeData node : getDeclaredNodes()) { + for (NodeData node : getEnclosingNodes()) { builder.append("\n"); builder.append(node.dump(level + 1)); } @@ -513,30 +473,8 @@ return children; } - void setChildren(List fields) { - this.children = fields; - } - public List getSpecializations() { - return getSpecializations(false); - } - - public List getSpecializations(boolean userDefinedOnly) { - if (userDefinedOnly) { - List specs = new ArrayList<>(); - for (SpecializationData spec : specializations) { - if (spec.getMethod() != null) { - specs.add(spec); - } - } - return specs; - } else { - return specializations; - } - } - - public List getSpecializationListeners() { - return specializationListeners; + return specializations; } public List getExecutableTypes() { @@ -547,43 +485,10 @@ return shortCircuits; } - void setSpecializations(List specializations) { - this.specializations = specializations; - if (this.specializations != null) { - for (SpecializationData specialization : specializations) { - specialization.setNode(this); - } - } - } - - void setPolymorphicSpecializations(List polymorphicSpecializations) { - this.polymorphicSpecializations = polymorphicSpecializations; - } - - public List getPolymorphicSpecializations() { - return polymorphicSpecializations; - } - - void setGenericPolymorphicSpecialization(SpecializationData genericPolymoprhicSpecialization) { - this.genericPolymorphicSpecialization = genericPolymoprhicSpecialization; - } - - public SpecializationData getGenericPolymorphicSpecialization() { - return genericPolymorphicSpecialization; - } - - void setSpecializationListeners(List specializationListeners) { - this.specializationListeners = specializationListeners; - } - - void setExecutableTypes(Map> executableTypes) { + public void setExecutableTypes(Map> executableTypes) { this.executableTypes = executableTypes; } - void setShortCircuits(List shortCircuits) { - this.shortCircuits = shortCircuits; - } - @Override public String toString() { return getClass().getSimpleName() + "[" + getNodeId() + "]"; diff -r 25ecb47a6d0e -r 5a0c694ef735 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 Tue Jan 07 12:22:47 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java Tue Jan 07 18:52:32 2014 +0100 @@ -109,7 +109,7 @@ protected void addDefaultFieldMethodSpec(MethodSpec methodSpec) { for (NodeFieldData field : getNode().getFields()) { - if (getNode().isNodeContainer() || field.getGetter() == null) { + if (field.getGetter() == null) { ParameterSpec spec = new ParameterSpec(field.getName(), field.getType()); spec.setLocal(true); methodSpec.addOptional(spec); diff -r 25ecb47a6d0e -r 5a0c694ef735 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 Tue Jan 07 12:22:47 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java Tue Jan 07 18:52:32 2014 +0100 @@ -34,14 +34,15 @@ 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.*; 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 TemplateParser { +public class NodeParser extends AbstractParser { - public static final List> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, SpecializationListener.class, - NodeContainer.class, NodeChild.class, NodeChildren.class, NodeId.class); + public static final List> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, NodeChild.class, + NodeChildren.class); private Map parsedNodes; @@ -51,7 +52,6 @@ @Override protected NodeData parse(Element element, AnnotationMirror mirror) { - assert element instanceof TypeElement; NodeData node = null; try { parsedNodes = new HashMap<>(); @@ -72,7 +72,7 @@ @Override protected NodeData filterErrorElements(NodeData model) { - for (Iterator iterator = model.getDeclaredNodes().iterator(); iterator.hasNext();) { + for (Iterator iterator = model.getEnclosingNodes().iterator(); iterator.hasNext();) { NodeData node = filterErrorElements(iterator.next()); if (node == null) { iterator.remove(); @@ -105,29 +105,27 @@ return parsedNodes.get(typeName); } - List types = ElementFilter.typesIn(rootType.getEnclosedElements()); - - List children = new ArrayList<>(); - for (TypeElement childElement : types) { - NodeData childNode = resolveNode(childElement); - if (childNode != null) { - children.add(childNode); + List enclosedNodes = new ArrayList<>(); + for (TypeElement enclosedType : ElementFilter.typesIn(rootType.getEnclosedElements())) { + NodeData enclosedChild = resolveNode(enclosedType); + if (enclosedChild != null) { + enclosedNodes.add(enclosedChild); } } - NodeData rootNode = parseNode(rootType); - if (rootNode == null && children.size() > 0) { - rootNode = new NodeData(rootType, rootType.getSimpleName().toString()); + NodeData node = parseNode(rootType); + if (node == null && !enclosedNodes.isEmpty()) { + node = new NodeData(rootType); } - parsedNodes.put(typeName, rootNode); - - if (rootNode != null) { - children.addAll(rootNode.getDeclaredNodes()); - rootNode.setDeclaredNodes(children); + if (node != null) { + for (NodeData enclosedNode : enclosedNodes) { + node.addEnclosedNode(enclosedNode); + } } - return rootNode; + parsedNodes.put(typeName, node); + return node; } private NodeData parseNode(TypeElement originalTemplateType) { @@ -139,153 +137,69 @@ return null; } - List lookupTypes = findSuperClasses(new ArrayList(), templateType); - Collections.reverse(lookupTypes); - - AnnotationMirror nodeClass = findFirstAnnotation(lookupTypes, NodeContainer.class); - TypeMirror nodeType = null; - if (Utils.isAssignable(context, templateType.asType(), context.getTruffleTypes().getNode())) { - nodeType = templateType.asType(); - } - if (nodeClass != null) { - nodeType = inheritType(nodeClass, "value", nodeType); - } - - if (nodeType == null) { + List lookupTypes = collectSuperClasses(new ArrayList(), templateType); + if (!Utils.isAssignable(context, templateType.asType(), context.getTruffleTypes().getNode())) { return null; } - Elements elementUtil = context.getEnvironment().getElementUtils(); - Set elementSet = new HashSet<>(elementUtil.getAllMembers(templateType)); - if (!Utils.typeEquals(templateType.asType(), nodeType)) { - elementSet.addAll(elementUtil.getAllMembers(Utils.fromTypeMirror(nodeType))); - - List nodeLookupTypes = findSuperClasses(new ArrayList(), Utils.fromTypeMirror(nodeType)); - Collections.reverse(nodeLookupTypes); - lookupTypes.addAll(nodeLookupTypes); + List elements = context.getEnvironment().getElementUtils().getAllMembers(templateType); - Set types = new HashSet<>(); - for (ListIterator iterator = lookupTypes.listIterator(); iterator.hasNext();) { - TypeElement typeElement = iterator.next(); - if (types.contains(typeElement)) { - iterator.remove(); - } else { - types.add(typeElement); - } - } - } - List elements = new ArrayList<>(elementSet); - - NodeData node = parseNodeData(templateType, nodeType, elements, lookupTypes); - + NodeData node = parseNodeData(templateType, elements, lookupTypes); if (node.hasErrors()) { return node; // error sync point } - parseMethods(node, 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; - } - - List nodes; - - if (node.isNodeContainer()) { - nodes = splitNodeData(node); - } else { - nodes = new ArrayList<>(); - nodes.add(node); + return node; // error sync point } - for (NodeData splittedNode : nodes) { - if (templateType.getModifiers().contains(Modifier.PRIVATE) && splittedNode.getSpecializations().size() > 0) { - splittedNode.addError("Classes containing a @%s annotation must not be private.", Specialization.class.getSimpleName()); - } + verifySpecializationSameLength(node); + initializeSpecializations(elements, node); + initializeShortCircuits(node); // requires specializations and polymorphic specializations - finalizeSpecializations(elements, splittedNode); - verifyNode(splittedNode, elements); - createPolymorphicSpecializations(splittedNode); - assignShortCircuitsToSpecializations(splittedNode); - } - - if (node.isNodeContainer()) { - node.setDeclaredNodes(nodes); - node.setSpecializationListeners(new ArrayList()); - node.setSpecializations(new ArrayList()); - } + verifyVisibilities(node); + verifySpecializationOrder(node); + verifyMissingAbstractMethods(node, elements); + verifyConstructors(node); + verifyNamingConvention(node.getShortCircuits(), "needs"); + verifySpecializationThrows(node); return node; } - private void createPolymorphicSpecializations(NodeData node) { - if (!node.needsRewrites(context) || !node.isPolymorphic()) { - node.setPolymorphicSpecializations(Collections. emptyList()); - return; - } - - SpecializationData generic = node.getGenericSpecialization(); - - List polymorphicSignature = new ArrayList<>(); - // TODO we should support more optimized for boxing - // List updatePolymorphic = generic.getReturnTypeAndParameters(); - 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 specialization = new SpecializationData(generic, false, false, true); - specialization.updateSignature(new TypeSignature(polymorphicSignature)); - specialization.setNode(node); - node.setGenericPolymorphicSpecialization(specialization); - // TODO remove polymoprhic specializations - node.setPolymorphicSpecializations(Collections. emptyList()); - } - - private NodeData parseNodeData(TypeElement templateType, TypeMirror nodeType, List elements, List typeHierarchy) { - NodeData nodeData = new NodeData(templateType, templateType.getSimpleName().toString()); - + private NodeData parseNodeData(TypeElement templateType, List elements, List typeHierarchy) { AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); if (typeSystemMirror == null) { - nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), Utils.getQualifiedName(nodeType)); + 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 typeSytemType = Utils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value"); - final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSytemType, true); + TypeMirror typeSystemType = Utils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value"); + final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSystemType, true); if (typeSystem == null) { - nodeData.addError("The used type system '%s' is invalid or not a Node.", Utils.getQualifiedName(typeSytemType)); + 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 polymorphicLimit = Utils.getAnnotationValue(Integer.class, polymorphicMirror, "value"); - if (polymorphicLimit < 1) { + 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; } - nodeData.setPolymorphicDepth(polymorphicLimit); + polymorphicLimit = customPolymorphicLimit; } List assumptionsList = new ArrayList<>(); @@ -303,109 +217,21 @@ } } AnnotationMirror nodeInfoMirror = findFirstAnnotation(typeHierarchy, NodeInfo.class); + String shortName = null; if (nodeInfoMirror != null) { - nodeData.setShortName(Utils.getAnnotationValue(String.class, nodeInfoMirror, "shortName")); - } - - nodeData.setAssumptions(new ArrayList<>(assumptionsList)); - nodeData.setNodeType(nodeType); - AnnotationMirror nodeContainer = findFirstAnnotation(typeHierarchy, NodeContainer.class); - nodeData.setNodeContainer(nodeContainer != null); - nodeData.setTypeSystem(typeSystem); - nodeData.setFields(parseFields(typeHierarchy, elements)); - nodeData.setChildren(parseChildren(nodeData, elements, typeHierarchy)); - nodeData.setChildExecutions(parseDefaultSignature(nodeData, elements)); - nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements))); - - // resolveChildren invokes cyclic parsing. - parsedNodes.put(Utils.getQualifiedName(templateType), nodeData); - resolveChildren(nodeData); - - return nodeData; - } - - private List parseDefaultSignature(NodeData node, List elements) { - if (node.getChildren() == 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 (!node.getChildren().isEmpty()) { - int lastIndex = node.getChildren().size() - 1; - hasVarArgs = node.getChildren().get(lastIndex).getCardinality() == Cardinality.MANY; - if (hasVarArgs) { - maxSignatureSize = lastIndex; - } else { - maxSignatureSize = node.getChildren().size(); - } + shortName = Utils.getAnnotationValue(String.class, nodeInfoMirror, "shortName"); } - // pre-parse specializations - for (ExecutableElement method : methods) { - AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, Specialization.class); - if (mirror == null) { - continue; - } + List fields = parseFields(typeHierarchy, elements); + List children = parseChildren(elements, typeHierarchy); + List executions = parseExecutions(children, elements); - 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 < node.getChildren().size() ? currentArgumentCount : node.getChildren().size() - 1; - if (childIndex == -1) { - continue; - } - if (!skipShortCircuit) { - NodeChildData child = node.getChildren().get(childIndex); - if (shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, currentArgumentCount - childIndex))) { - skipShortCircuit = true; - continue; - } - } else { - skipShortCircuit = false; - } + NodeData nodeData = new NodeData(templateType, shortName, typeSystem, children, executions, fields, assumptionsList, polymorphicLimit); + nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements))); - currentArgumentCount++; - } - maxSignatureSize = Math.max(maxSignatureSize, currentArgumentCount); - } + parsedNodes.put(Utils.getQualifiedName(templateType), nodeData); - List executions = new ArrayList<>(); - for (int i = 0; i < maxSignatureSize; i++) { - int childIndex = i; - boolean varArg = false; - if (childIndex >= node.getChildren().size() - 1) { - if (hasVarArgs) { - childIndex = node.getChildren().size() - 1; - varArg = hasVarArgs; - } else if (childIndex >= node.getChildren().size()) { - break; - } - } - int varArgsIndex = varArg ? Math.abs(childIndex - i) : -1; - NodeChildData child = node.getChildren().get(childIndex); - boolean shortCircuit = shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, varArgsIndex)); - executions.add(new NodeExecutionData(child, varArgsIndex, shortCircuit)); - } - return executions; + return nodeData; } private List parseFields(List typeHierarchy, List elements) { @@ -452,28 +278,7 @@ return fields; } - private void resolveChildren(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 List parseChildren(NodeData parent, List elements, final List typeHierarchy) { + 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); @@ -498,7 +303,6 @@ List typeHierarchyReversed = new ArrayList<>(typeHierarchy); Collections.reverse(typeHierarchyReversed); for (TypeElement type : typeHierarchyReversed) { - AnnotationMirror nodeClassMirror = Utils.findAnnotationMirror(processingEnv, type, NodeContainer.class); AnnotationMirror nodeChildrenMirror = Utils.findAnnotationMirror(processingEnv, type, NodeChildren.class); TypeMirror nodeClassType = type.getSuperclass(); @@ -506,10 +310,6 @@ nodeClassType = null; } - if (nodeClassMirror != null) { - nodeClassType = inheritType(nodeClassMirror, "value", nodeClassType); - } - List children = Utils.collectAnnotations(context, nodeChildrenMirror, "value", type, NodeChild.class); int index = 0; for (AnnotationMirror childMirror : children) { @@ -533,11 +333,13 @@ Element getter = findGetter(elements, name, childType); - NodeChildData nodeChild = new NodeChildData(parent, type, childMirror, name, childType, originalChildType, getter, cardinality); + NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality); parsedChildren.add(nodeChild); - verifyNodeChild(nodeChild); + if (nodeChild.getNodeType() == null) { + nodeChild.addError("No valid node type could be resoleved."); + } if (nodeChild.hasErrors()) { continue; } @@ -599,153 +401,182 @@ return filteredChildren; } - private void parseMethods(final NodeData node, List elements) { - node.setShortCircuits(new ShortCircuitParser(context, node).parse(elements)); - node.setSpecializationListeners(new SpecializationListenerParser(context, node).parse(elements)); - List generics = new GenericParser(context, node).parse(elements); - List specializations = new SpecializationMethodParser(context, node).parse(elements); - node.setCasts(new CreateCastParser(context, node).parse(elements)); + 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; + } - List allSpecializations = new ArrayList<>(); - allSpecializations.addAll(generics); - allSpecializations.addAll(specializations); + 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; + } - node.setSpecializations(allSpecializations); + 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 List splitNodeData(NodeData node) { - SortedMap> groupedSpecializations = groupByNodeId(node.getSpecializations()); - SortedMap> groupedListeners = groupByNodeId(node.getSpecializationListeners()); - SortedMap> groupedCasts = groupByNodeId(node.getCasts()); - - Set ids = new TreeSet<>(); - ids.addAll(groupedSpecializations.keySet()); - ids.addAll(groupedListeners.keySet()); + private static Map> groupExecutableTypes(List executableTypes) { + Map> groupedTypes = new TreeMap<>(); + for (ExecutableTypeData type : executableTypes) { + int evaluatedCount = type.getEvaluatedCount(); - List splitted = new ArrayList<>(); - for (String id : ids) { - List specializations = groupedSpecializations.get(id); - List listeners = groupedListeners.get(id); - List casts = groupedCasts.get(id); - - if (specializations == null) { - specializations = new ArrayList<>(); + List types = groupedTypes.get(evaluatedCount); + if (types == null) { + types = new ArrayList<>(); + groupedTypes.put(evaluatedCount, types); } - - if (listeners == null) { - listeners = new ArrayList<>(); - } - - String nodeId = node.getNodeId(); - if (nodeId.endsWith("Node") && !nodeId.equals("Node")) { - nodeId = nodeId.substring(0, nodeId.length() - 4); - } - String newNodeId = nodeId + Utils.firstLetterUpperCase(id); - NodeData copy = new NodeData(node, id, newNodeId); - - copy.setSpecializations(specializations); - copy.setSpecializationListeners(listeners); - copy.setCasts(casts); - - splitted.add(copy); + types.add(type); } - node.setSpecializations(new ArrayList()); - node.setSpecializationListeners(new ArrayList()); - node.setCasts(new ArrayList()); - - return splitted; + for (List types : groupedTypes.values()) { + Collections.sort(types); + } + return groupedTypes; } - private void finalizeSpecializations(List elements, final NodeData node) { - List specializations = new ArrayList<>(node.getSpecializations()); + 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())); + } + } + } + } - if (specializations.isEmpty()) { + private void initializeSpecializations(List elements, final NodeData node) { + if (node.getSpecializations().isEmpty()) { return; } - for (SpecializationData specialization : specializations) { - matchGuards(elements, specialization); - } - - List generics = new ArrayList<>(); - for (SpecializationData spec : specializations) { - if (spec.isGeneric()) { - generics.add(spec); + for (SpecializationData specialization : node.getSpecializations()) { + if (!specialization.isSpecialized()) { + continue; } - } - - if (generics.size() == 1 && specializations.size() == 1) { - for (SpecializationData generic : generics) { - generic.addError("@%s defined but no @%s.", Generic.class.getSimpleName(), Specialization.class.getSimpleName()); - } - } - - SpecializationData genericSpecialization = null; - if (generics.size() > 1) { - for (SpecializationData generic : generics) { - generic.addError("Only @%s is allowed per operation.", Generic.class.getSimpleName()); - } - return; - } else if (generics.size() == 1) { - genericSpecialization = generics.get(0); - } else if (node.needsRewrites(context)) { - genericSpecialization = createGenericSpecialization(node, specializations); - specializations.add(genericSpecialization); + initializeGuards(elements, specialization); } - if (genericSpecialization != null) { - for (ActualParameter parameter : genericSpecialization.getReturnTypeAndParameters()) { - if (Utils.isObject(parameter.getType())) { - continue; - } - Set types = new HashSet<>(); - for (SpecializationData specialization : specializations) { - ActualParameter actualParameter = specialization.findParameter(parameter.getLocalName()); - if (actualParameter != null) { - types.add(Utils.getQualifiedName(actualParameter.getType())); - } - } - if (types.size() > 1) { - genericSpecialization.replaceParameter(parameter.getLocalName(), new ActualParameter(parameter, node.getTypeSystem().getGenericTypeData())); - } - } - TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", node, genericSpecialization.getSpecification(), null, null, genericSpecialization.getReturnType(), - genericSpecialization.getParameters()); - // should not use messages from generic specialization - uninializedMethod.getMessages().clear(); - specializations.add(new SpecializationData(uninializedMethod, false, true, false)); + 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()); } - Collections.sort(specializations); - - node.setSpecializations(specializations); - List needsId = new ArrayList<>(); - for (SpecializationData specialization : specializations) { + 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 { - needsId.add(specialization); + throw new AssertionError(); } } // verify specialization parameter length - if (verifySpecializationParameters(node)) { - List ids = calculateSpecializationIds(needsId); - for (int i = 0; i < ids.size(); i++) { - needsId.get(i).setId(ids.get(i)); - } + List ids = initializeSpecializationIds(needsId); + for (int i = 0; i < ids.size(); i++) { + needsId.get(i).setId(ids.get(i)); } - // calculate reachability + } + + private void initializeReachability(final NodeData node) { SpecializationData prev = null; - int polymorphicCombinations = 0; boolean reachable = true; - for (SpecializationData specialization : specializations) { - if (specialization.isUninitialized()) { + for (SpecializationData specialization : node.getSpecializations()) { + if (specialization.isUninitialized() || specialization.isPolymorphic()) { specialization.setReachable(true); continue; } @@ -758,199 +589,15 @@ if (!specialization.hasRewrite(context)) { reachable = false; } - if (!specialization.isGeneric()) { - int combinations = 1; - for (ActualParameter parameter : specialization.getParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } - TypeData type = parameter.getTypeSystemType(); - combinations *= node.getTypeSystem().lookupSourceTypes(type).size(); - } - polymorphicCombinations += combinations; - } - prev = specialization; } - - // initialize polymorphic depth - if (node.getPolymorphicDepth() < 0) { - node.setPolymorphicDepth(polymorphicCombinations - 1); - } - - // reduce polymorphicness if generic is not reachable - if (node.getGenericSpecialization() != null && !node.getGenericSpecialization().isReachable()) { - node.setPolymorphicDepth(1); - } - } - - private SpecializationData createGenericSpecialization(final NodeData node, List specializations) { - SpecializationData specialization = specializations.get(0); - GenericParser parser = new GenericParser(context, node); - MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, true, null); - specification.getImplicitRequiredTypes().clear(); - - List parameterTypes = new ArrayList<>(); - int signatureIndex = 1; - for (ParameterSpec spec : specification.getRequired()) { - parameterTypes.add(createGenericType(spec, specializations, signatureIndex)); - if (spec.isSignature()) { - signatureIndex++; - } - } - TypeMirror returnType = createGenericType(specification.getReturnType(), specializations, 0); - return parser.create("Generic", null, null, returnType, parameterTypes); - } - - 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 && !executable.hasUnexpectedValue(context)) { - genericType = types.iterator().next(); - } - } - if (genericType == null) { - genericType = child.findAnyGenericExecutableType(context).getType(); - } - return genericType.getPrimitiveType(); - } } - private void assignShortCircuitsToSpecializations(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()); - specializations.addAll(node.getPolymorphicSpecializations()); - - 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 void matchGuards(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 static List calculateSpecializationIds(List specializations) { + private static List initializeSpecializationIds(List specializations) { int lastSize = -1; List> signatureChunks = new ArrayList<>(); for (SpecializationData other : specializations) { - if (other.isUninitialized() || other.isGeneric()) { + if (!other.isSpecialized()) { continue; } List paramIds = new LinkedList<>(); @@ -1058,25 +705,370 @@ return signatures; } - private void verifyNode(NodeData nodeData, List elements) { - // verify order is not ambiguous - verifySpecializationOrder(nodeData); + 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; + } - verifyMissingAbstractMethods(nodeData, elements); + 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) { + SpecializationData specialization = node.getSpecializations().get(0); + GenericParser parser = new GenericParser(context, node); + MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, true, null); + specification.getImplicitRequiredTypes().clear(); + + 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); + return parser.create("Generic", null, null, returnType, parameterTypes); + } - verifyConstructors(nodeData); + 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 && !executable.hasUnexpectedValue(context)) { + genericType = types.iterator().next(); + } + } + if (genericType == null) { + genericType = child.findAnyGenericExecutableType(context).getType(); + } + return genericType.getPrimitiveType(); + } + } - verifyNamingConvention(nodeData.getShortCircuits(), "needs"); + 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; + } - verifySpecializationThrows(nodeData); + 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 verifyNodeChild(NodeChildData nodeChild) { - if (nodeChild.getNodeType() == null) { - nodeChild.addError("No valid node type could be resoleved."); + 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; } - // FIXME verify node child - // FIXME verify node type set + + 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) { @@ -1087,7 +1079,6 @@ } List elements = new ArrayList<>(originalElements); - Set unusedElements = new HashSet<>(elements); for (TemplateMethod method : nodeData.getAllTemplateMethods()) { unusedElements.remove(method.getMethod()); @@ -1112,6 +1103,33 @@ } } + 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. @@ -1152,104 +1170,6 @@ return constructor.getParameters().size() == 1 && Utils.typeEquals(constructor.getParameters().get(0).asType(), context.getTruffleTypes().getSourceSection()); } - private static boolean verifySpecializationParameters(NodeData nodeData) { - boolean valid = true; - int args = -1; - for (SpecializationData specializationData : nodeData.getSpecializations()) { - int signatureArgs = 0; - for (ActualParameter param : specializationData.getParameters()) { - if (param.getSpecification().isSignature()) { - signatureArgs++; - } - } - if (args != -1 && args != signatureArgs) { - valid = false; - break; - } - args = signatureArgs; - } - if (!valid) { - for (SpecializationData specialization : nodeData.getSpecializations()) { - specialization.addError("All specializations must have the same number of arguments."); - } - } - return valid; - } - - 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 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 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 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 AnnotationMirror findFirstAnnotation(List elements, Class annotation) { for (Element element : elements) { AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, element, annotation); @@ -1289,61 +1209,13 @@ return null; } - 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; + 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 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 SortedMap> groupByNodeId(List methods) { - SortedMap> grouped = new TreeMap<>(); - for (M m : methods) { - List list = grouped.get(m.getId()); - if (list == null) { - list = new ArrayList<>(); - grouped.put(m.getId(), list); - } - list.add(m); - } - return grouped; - } - - private static List findSuperClasses(List collection, TypeElement element) { - if (element.getSuperclass() != null) { - TypeElement superElement = Utils.fromTypeMirror(element.getSuperclass()); - if (superElement != null) { - findSuperClasses(collection, superElement); - } - } - collection.add(element); return collection; } diff -r 25ecb47a6d0e -r 5a0c694ef735 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 Tue Jan 07 12:22:47 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java Tue Jan 07 18:52:32 2014 +0100 @@ -33,24 +33,25 @@ public class SpecializationData extends TemplateMethod { + public enum SpecializationKind { + UNINITIALIZED, SPECIALIZED, POLYMORPHIC, GENERIC + } + + private final NodeData node; private final int order; - private final boolean generic; - private final boolean polymorphic; - private final boolean uninitialized; + 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 NodeData node; private boolean reachable; - public SpecializationData(TemplateMethod template, int order, List exceptions) { + public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind, int order, List exceptions) { super(template); + this.node = node; this.order = order; - this.generic = false; - this.uninitialized = false; - this.polymorphic = false; + this.kind = kind; this.exceptions = exceptions; for (SpecializationThrowsData exception : exceptions) { @@ -58,13 +59,8 @@ } } - public SpecializationData(TemplateMethod template, boolean generic, boolean uninitialized, boolean polymorphic) { - super(template); - this.order = Specialization.DEFAULT_ORDER; - this.generic = generic; - this.uninitialized = uninitialized; - this.polymorphic = polymorphic; - this.exceptions = Collections.emptyList(); + public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind) { + this(node, template, kind, Specialization.DEFAULT_ORDER, new ArrayList()); } public void setReachable(boolean reachable) { @@ -76,7 +72,7 @@ } public boolean isPolymorphic() { - return polymorphic; + return kind == SpecializationKind.POLYMORPHIC; } @Override @@ -141,12 +137,12 @@ 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(); - } else if (isUninitialized() ^ m2.isUninitialized()) { - return isUninitialized() ? -1 : 1; - } else if (isGeneric() ^ m2.isGeneric()) { - return isGeneric() ? 1 : -1; } if (getTemplate() != m2.getTemplate()) { @@ -160,10 +156,6 @@ return node; } - public void setNode(NodeData node) { - this.node = node; - } - public void setGuards(List guards) { this.guards = guards; } @@ -177,15 +169,15 @@ } public boolean isSpecialized() { - return !isGeneric() && !isUninitialized() && !isPolymorphic(); + return kind == SpecializationKind.SPECIALIZED; } public boolean isGeneric() { - return generic; + return kind == SpecializationKind.GENERIC; } public boolean isUninitialized() { - return uninitialized; + return kind == SpecializationKind.UNINITIALIZED; } public List getExceptions() { diff -r 25ecb47a6d0e -r 5a0c694ef735 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationListenerParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationListenerParser.java Tue Jan 07 12:22:47 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +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 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 SpecializationListenerParser extends NodeMethodParser { - - public SpecializationListenerParser(ProcessorContext context, NodeData node) { - super(context, node); - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - return createDefaultMethodSpec(method, mirror, true, null); - } - - @Override - protected ParameterSpec createReturnParameterSpec() { - return new ParameterSpec("void", getContext().getType(void.class)); - } - - @Override - public SpecializationListenerData create(TemplateMethod method, boolean invalid) { - return new SpecializationListenerData(method); - } - - @Override - public Class getAnnotationType() { - return SpecializationListener.class; - } - -} diff -r 25ecb47a6d0e -r 5a0c694ef735 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 Tue Jan 07 12:22:47 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java Tue Jan 07 18:52:32 2014 +0100 @@ -30,6 +30,7 @@ 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 { @@ -77,7 +78,7 @@ return Utils.compareByTypeHierarchy(o1.getJavaClass(), o2.getJavaClass()); } }); - SpecializationData specialization = new SpecializationData(method, order, exceptionData); + SpecializationData specialization = new SpecializationData(getNode(), method, SpecializationKind.SPECIALIZED, order, exceptionData); List guardDefs = Utils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards"); specialization.setGuardDefinitions(guardDefs); diff -r 25ecb47a6d0e -r 5a0c694ef735 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 Tue Jan 07 12:22:47 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java Tue Jan 07 18:52:32 2014 +0100 @@ -211,12 +211,10 @@ return prev; } + @SuppressWarnings("unused") public int getSignatureSize() { int signatureSize = 0; - for (ActualParameter parameter : getParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } + for (ActualParameter parameter : getSignatureParameters()) { signatureSize++; } return signatureSize; diff -r 25ecb47a6d0e -r 5a0c694ef735 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 Tue Jan 07 12:22:47 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java Tue Jan 07 18:52:32 2014 +0100 @@ -31,7 +31,6 @@ 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.typesystem.*; @@ -141,11 +140,6 @@ methodSpecification.applyTypeDefinitions("types"); String id = method.getSimpleName().toString(); - AnnotationMirror idAnnotation = Utils.findAnnotationMirror(context.getEnvironment(), method, NodeId.class); - if (idAnnotation != null) { - id = Utils.getAnnotationValue(String.class, idAnnotation, "value"); - } - TypeMirror returnType = method.getReturnType(); List parameterTypes = new ArrayList<>(); for (VariableElement var : method.getParameters()) { diff -r 25ecb47a6d0e -r 5a0c694ef735 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateParser.java Tue Jan 07 12:22:47 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +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.util.*; - -import com.oracle.truffle.dsl.processor.*; - -public abstract class TemplateParser extends AbstractParser { - - public TemplateParser(ProcessorContext c) { - super(c); - } - - 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); - } - } - } - -} diff -r 25ecb47a6d0e -r 5a0c694ef735 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 Tue Jan 07 12:22:47 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java Tue Jan 07 18:52:32 2014 +0100 @@ -35,7 +35,7 @@ import com.oracle.truffle.dsl.processor.*; import com.oracle.truffle.dsl.processor.template.*; -public class TypeSystemParser extends TemplateParser { +public class TypeSystemParser extends AbstractParser { public static final List> ANNOTATIONS = Arrays.asList(TypeSystem.class, ExpectError.class); @@ -115,6 +115,28 @@ 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()) { diff -r 25ecb47a6d0e -r 5a0c694ef735 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArithmeticNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArithmeticNode.java Tue Jan 07 12:22:47 2014 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArithmeticNode.java Tue Jan 07 18:52:32 2014 +0100 @@ -16,7 +16,7 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */