# HG changeset patch # User Christian Humer # Date 1429017168 -7200 # Node ID 18c0f02fa4d2ee8493f392964f0f6bd511bd0baa # Parent 37ea76052733fa9d47dd4e0af78ac309dd8ee41c Truffle-DSL: make type systems optional. diff -r 37ea76052733 -r 18c0f02fa4d2 CHANGELOG.md --- a/CHANGELOG.md Tue Apr 14 22:12:03 2015 +0200 +++ b/CHANGELOG.md Tue Apr 14 15:12:48 2015 +0200 @@ -36,6 +36,10 @@ * Changed syntax and semantics of Specialization#assumptions and Specialization#guards. They now use a Java like expression syntax. * Changed guard expressions that do not bind any dynamic parameter are invoked just once per specialization instantiation. They are now asserted to be true on the fast path. * Renamed @ImportGuards to @ImportStatic. +* Changed declaring a @TypeSystemReference for a node that contains specializations is not mandatory anymore. +* Changed types used in specializations are not restricted on types declared in the type system anymore. +* Changed nodes that declare all execute methods with the same number of evaluated arguments as specialization arguments do not require @NodeChild annotations anymore. +* Changed types used in checks and casts are not mandatory to be declared in the type system. ## Version 0.6 19-Dec-2014, [Repository Revision](http://hg.openjdk.java.net/graal/graal/shortlog/graal-0.6) diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ArrayTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ArrayTest.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ArrayTest.java Tue Apr 14 15:12:48 2015 +0200 @@ -26,7 +26,6 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.dsl.internal.*; import com.oracle.truffle.api.dsl.test.ArrayTestFactory.TestNode1NodeGen; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; @@ -97,7 +96,6 @@ } @TypeSystem({int.class, int[].class, double[].class, String[].class, Object[].class}) - @DSLOptions(useNewLayout = true) public static class ArrayTypeSystem { @ImplicitCast diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java Tue Apr 14 15:12:48 2015 +0200 @@ -175,8 +175,7 @@ abstract void executeVoid(); @Specialization - int doInt(int a) { - return a; + void doInt(@SuppressWarnings("unused") int a) { } } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NoTypeSystemTest.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/NoTypeSystemTest.java Tue Apr 14 15:12:48 2015 +0200 @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl.test; + +import org.junit.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.JustFrameTestNodeGen; +import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.NoParameterTestNodeGen; +import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.ObjectInterfaceNodeGen; +import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.ObjectPrimitiveTestNodeGen; +import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.ObjectStringTestNodeGen; +import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.PrimitiveTestNodeGen; +import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.TypesNotInTypeSystemTestNodeGen; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public class NoTypeSystemTest { + + abstract static class NoParameterTestNode extends Node { + abstract void execute(); + + @Specialization + void s1() { + } + } + + @Test + public void testNoParameter() { + NoParameterTestNodeGen.create().execute(); + } + + abstract static class JustFrameTestNode extends Node { + + abstract void execute(VirtualFrame frames); + + @Specialization + void s1(@SuppressWarnings("unused") VirtualFrame frame) { + } + } + + @Test + public void testJustFrame() { + JustFrameTestNodeGen.create().execute(null); + } + + abstract static class PrimitiveTestNode extends Node { + + abstract int execute(int primitive); + + @Specialization + int test(int primitive) { + return primitive; + } + + } + + @Test + public void testPrimitive() { + Assert.assertEquals(42, PrimitiveTestNodeGen.create().execute(42)); + } + + abstract static class ObjectInterfaceNode extends Node { + + abstract CharSequence execute(Object operand); + + @Specialization + CharSequence s1(CharSequence operandSpecial) { + return operandSpecial; + } + } + + @Test + public void testObjectInterface() { + Assert.assertEquals("42", ObjectInterfaceNodeGen.create().execute("42")); + } + + abstract static class ObjectPrimitiveTestNode extends Node { + + abstract int execute(Object primitive); + + @Specialization + int s1(int primitive) { + return primitive; + } + + } + + @Test + public void testObjectPrimitiveTest() { + Assert.assertEquals(42, ObjectPrimitiveTestNodeGen.create().execute(42)); + } + + abstract static class ObjectStringTestNode extends Node { + + abstract String execute(Object operand); + + @Specialization + String s1(String operand) { + return operand; + } + } + + @Test + public void testObjectStringTest() { + Assert.assertEquals("42", ObjectStringTestNodeGen.create().execute("42")); + } + + abstract static class TypesNotInTypeSystemTest extends Node { + + abstract Object execute(Object primitive); + + abstract int executeInt(Object primitive) throws UnexpectedResultException; + + abstract double executeDouble(Object primitive) throws UnexpectedResultException; + + abstract String executeString(Object primitive) throws UnexpectedResultException; + + abstract int[] executeIntArray(Object primitive) throws UnexpectedResultException; + + abstract void executeVoid(Object primitive) throws UnexpectedResultException; + + abstract void executeChar(Object primitive) throws UnexpectedResultException; + + abstract int executeInt(int primitive) throws UnexpectedResultException; + + abstract double executeDouble(double primitive) throws UnexpectedResultException; + + abstract String executeString(String primitive) throws UnexpectedResultException; + + abstract int[] executeIntArray(int[] primitive) throws UnexpectedResultException; + + abstract void executeChar(char primitive) throws UnexpectedResultException; + + @Specialization + int s1(int primitive) { + return primitive; + } + + @Specialization + double s2(double primitive) { + return (int) primitive; + } + + @Specialization + String s3(String object) { + return object; + } + + @Specialization + int[] s4(int[] object) { + return object; + } + + @Specialization + void s5(@SuppressWarnings("unused") char object) { + } + + } + + // make nodes replacable + private static T createRoot(final T node) { + new RootNode() { + @Child T child = node; + + @Override + public Object execute(VirtualFrame frame) { + return null; + } + }.adoptChildren(); + return node; + } + + @Test + public void testTypesNotInTypeSystem() throws UnexpectedResultException { + int[] someArray = {1, 2, 3}; + Assert.assertEquals(42, createTypesNotInTypeSystem().execute(42)); + Assert.assertEquals(42d, createTypesNotInTypeSystem().execute(42d)); + Assert.assertEquals(someArray, createTypesNotInTypeSystem().execute(someArray)); + Assert.assertNull(createTypesNotInTypeSystem().execute((char) 42)); + + Assert.assertEquals(42, createTypesNotInTypeSystem().executeInt((Object) 42)); + Assert.assertEquals(42d, createTypesNotInTypeSystem().executeDouble((Object) 42d), 0d); + Assert.assertEquals(someArray, createTypesNotInTypeSystem().executeIntArray((Object) someArray)); + createTypesNotInTypeSystem().executeChar((Object) (char) 42); + + Assert.assertEquals(42, createTypesNotInTypeSystem().executeInt(42)); + Assert.assertEquals(42d, createTypesNotInTypeSystem().executeDouble(42d), 0d); + Assert.assertEquals(someArray, createTypesNotInTypeSystem().executeIntArray(someArray)); + createTypesNotInTypeSystem().executeChar((char) 42); + + try { + createTypesNotInTypeSystem().executeInt("a"); + Assert.fail(); + } catch (UnexpectedResultException e) { + } + + try { + createTypesNotInTypeSystem().executeDouble("a"); + Assert.fail(); + } catch (UnexpectedResultException e) { + } + + try { + createTypesNotInTypeSystem().executeIntArray("a"); + Assert.fail(); + } catch (UnexpectedResultException e) { + } + + createTypesNotInTypeSystem().executeChar("a"); + + } + + private static TypesNotInTypeSystemTest createTypesNotInTypeSystem() { + return createRoot(TypesNotInTypeSystemTestNodeGen.create()); + } + + abstract static class ErrorImpossibleTypes1 extends Node { + + abstract int execute(int primitive); + + @Specialization + int test(int primitive) { + return primitive; + } + + @ExpectError("The provided return type \"Object\" does not match expected return type \"int\".%") + @Specialization + Object s2(int arg0) { + return arg0; + } + } + + abstract static class ErrorImpossibleTypes2 extends Node { + + abstract int execute(int primitive); + + @Specialization + int test(int primitive) { + return primitive; + } + + @ExpectError("Method signature (Object) does not match to the expected signature: %") + @Specialization + int s2(Object arg0) { + return (int) arg0; + } + } + + @ExpectError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. " + + "The following execute methods do not provide all evaluated values for the expected signature size 1: [execute()].") + abstract static class ErrorMissingNodeChild1 extends Node { + + abstract int execute(); + + @Specialization + int s1(int arg0) { + return arg0; + } + } + + @ExpectError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. " + + "The following execute methods do not provide all evaluated values for the expected signature size 2: [execute(int)].") + @NodeChild + abstract static class ErrorMissingNodeChild2 extends Node { + + abstract int execute(int arg0); + + @Specialization + int s1(int arg0, int arg1) { + return arg0 + arg1; + } + } + + @ExpectError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. " + + "The following execute methods do not provide all evaluated values for the expected signature size 1: [execute()].") + abstract static class ErrorMissingNodeChild3 extends Node { + + abstract int execute(); + + abstract int execute(int arg0); + + @Specialization + int s1(int arg0) { + return arg0; + } + + } + + @ExpectError("Unnecessary @NodeChild declaration. All evaluated child values are provided as parameters in execute methods.") + @NodeChild + abstract static class ErrorAdditionalNodeChild1 extends Node { + + abstract int execute(int arg0); + + @Specialization + int s1(int arg0) { + return arg0; + } + } + + @NodeChild + @ExpectError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. " + + "The following execute methods do not provide all evaluated values for the expected signature size 2: [execute(int)].") + abstract static class ErrorAdditionalNodeChild2 extends Node { + + abstract int execute(int arg0); + + @Specialization + int s1(int arg0, int arg1) { + return arg0 + arg1; + } + } + +} diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeChildTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeChildTest.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeChildTest.java Tue Apr 14 15:12:48 2015 +0200 @@ -71,10 +71,11 @@ } + @ExpectError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. " + + "The following execute methods do not provide all evaluated values for the expected signature size 3:%") @NodeChildren({@NodeChild(value = "child2", type = ValueNode.class)}) abstract static class Child2Node extends Base1Node { - // TODO this is an error to fix @ExpectError("Method signature (int, int, int) does not match to the expected signature:%") @Specialization int intField(int child0, int child1, int child2) { diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemErrorsTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemErrorsTest.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemErrorsTest.java Tue Apr 14 15:12:48 2015 +0200 @@ -102,15 +102,6 @@ } } - @TypeSystem({boolean.class}) - public static class CastError3 { - @ExpectError("The type 'int' is not declared in the @TypeSystem.") - @TypeCast(int.class) - public static int asInt(Object value) { - return (int) value; - } - } - @TypeSystem({int.class}) public static class CastError4 { @ExpectError("@TypeCast annotated method asInt must be public and static.") @@ -129,15 +120,6 @@ } } - @TypeSystem({boolean.class}) - public static class CheckError1 { - @ExpectError("The type 'int' is not declared in the @TypeSystem.") - @TypeCheck(int.class) - public static boolean isInt(Object value) { - return value instanceof Integer; - } - } - @TypeSystem({int.class}) public static class CheckError2 { @ExpectError("@TypeCheck annotated method isInt must be public and static.") diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java Tue Apr 14 15:12:48 2015 +0200 @@ -88,6 +88,10 @@ return (DeclaredType) ElementUtils.getType(environment, element); } + public boolean isType(TypeMirror type, Class clazz) { + return ElementUtils.typeEquals(type, getType(clazz)); + } + public TypeMirror getType(Class element) { return ElementUtils.getType(environment, element); } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/GeneratorUtils.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/GeneratorUtils.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/GeneratorUtils.java Tue Apr 14 15:12:48 2015 +0200 @@ -85,14 +85,14 @@ return method; } - public static boolean isTypeBoxingOptimized(TypeBoxingOptimization boxing, TypeData type) { + public static boolean isTypeBoxingOptimized(TypeBoxingOptimization boxing, TypeMirror type) { switch (boxing) { case NONE: return false; case ALWAYS: - return !type.isGeneric() && !type.isVoid(); + return !ElementUtils.isObject(type) && !ElementUtils.isVoid(type); case PRIMITIVE: - return type.isPrimitive(); + return ElementUtils.isPrimitive(type); default: throw new AssertionError(); } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/ImplicitCastNodeFactory.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/ImplicitCastNodeFactory.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/ImplicitCastNodeFactory.java Tue Apr 14 15:12:48 2015 +0200 @@ -44,31 +44,30 @@ public class ImplicitCastNodeFactory { private final ProcessorContext context; - private final TypeData forType; + private final TypeMirror forType; private final TypeSystemData typeSystem; private final DSLOptions options; - private final List sourceTypes; + private final List sourceTypes; - public ImplicitCastNodeFactory(ProcessorContext context, TypeData forType) { + public ImplicitCastNodeFactory(ProcessorContext context, TypeSystemData typeSystem, TypeMirror forType) { this.context = context; this.forType = forType; - this.typeSystem = forType.getTypeSystem(); + this.typeSystem = typeSystem; this.options = typeSystem.getOptions(); this.sourceTypes = typeSystem.lookupSourceTypes(forType); } - public static String typeName(TypeData type) { - return "Implicit" + getTypeId(type.getBoxedType()) + "Cast"; + public static String typeName(TypeMirror type) { + return "Implicit" + getTypeId(type) + "Cast"; } - public static TypeMirror type(TypeData type) { - TypeSystemData typeSystem = type.getTypeSystem(); + public static TypeMirror type(TypeSystemData typeSystem, TypeMirror type) { String typeSystemName = TypeSystemCodeGenerator.typeName(typeSystem); return new GeneratedTypeMirror(ElementUtils.getPackageName(typeSystem.getTemplateType()) + "." + typeSystemName, typeName(type)); } - public static CodeTree create(TypeData type, CodeTree value) { - return CodeTreeBuilder.createBuilder().startStaticCall(type(type), "create").tree(value).end().build(); + public static CodeTree create(TypeSystemData typeSystem, TypeMirror type, CodeTree value) { + return CodeTreeBuilder.createBuilder().startStaticCall(type(typeSystem, type), "create").tree(value).end().build(); } public static CodeTree cast(String nodeName, CodeTree value) { @@ -79,8 +78,8 @@ return CodeTreeBuilder.createBuilder().startCall(nodeName, "check").tree(value).end().build(); } - private static String seenFieldName(TypeData type) { - return "seen" + getTypeId(type.getBoxedType()); + private static String seenFieldName(TypeMirror type) { + return "seen" + getTypeId(type); } public CodeTypeElement create() { @@ -88,7 +87,7 @@ TypeMirror baseType = context.getType(Object.class); CodeTypeElement clazz = GeneratorUtils.createClass(typeSystem, null, modifiers(PUBLIC, FINAL, STATIC), typeName, baseType); - for (TypeData sourceType : sourceTypes) { + for (TypeMirror sourceType : sourceTypes) { CodeVariableElement hasSeen = new CodeVariableElement(modifiers(PUBLIC), context.getType(boolean.class), seenFieldName(sourceType)); hasSeen.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(CompilationFinal.class))); clazz.add(hasSeen); @@ -113,7 +112,7 @@ CodeTreeBuilder builder = method.createBuilder(); builder.startReturn(); String operator = ""; - for (TypeData sourceType : sourceTypes) { + for (TypeMirror sourceType : sourceTypes) { builder.string(operator); builder.string(seenFieldName(sourceType)); operator = " ^ "; @@ -129,15 +128,15 @@ private Element createCreate(CodeTypeElement clazz) { String methodName = "create"; CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), clazz.asType(), methodName); - method.addParameter(new CodeVariableElement(typeSystem.getGenericType(), "value")); + method.addParameter(new CodeVariableElement(context.getType(Object.class), "value")); CodeTreeBuilder builder = method.createBuilder(); builder.declaration(clazz.asType(), "newCast", builder.create().startNew(clazz.asType()).end()); - for (TypeData sourceType : sourceTypes) { + for (TypeMirror sourceType : sourceTypes) { String seenField = seenFieldName(sourceType); builder.startStatement(); - builder.string("newCast.").string(seenField).string(" = ").tree(TypeSystemCodeGenerator.check(sourceType, "value")); + builder.string("newCast.").string(seenField).string(" = ").tree(TypeSystemCodeGenerator.check(typeSystem, sourceType, "value")); builder.end(); } builder.startReturn().string("newCast").end(); @@ -150,7 +149,7 @@ method.addParameter(new CodeVariableElement(clazz.asType(), "otherCast")); CodeTreeBuilder builder = method.createBuilder(); - for (TypeData sourceType : sourceTypes) { + for (TypeMirror sourceType : sourceTypes) { String seenField = seenFieldName(sourceType); builder.startStatement(); builder.string("this.").string(seenField).string(" |= ").string("otherCast.").string(seenField); @@ -162,13 +161,13 @@ private Element createCheck() { String methodName = "check"; CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(boolean.class), methodName); - method.addParameter(new CodeVariableElement(typeSystem.getGenericType(), "value")); + method.addParameter(new CodeVariableElement(context.getType(Object.class), "value")); CodeTreeBuilder builder = method.createBuilder(); boolean elseIf = false; - for (TypeData sourceType : sourceTypes) { + for (TypeMirror sourceType : sourceTypes) { elseIf = builder.startIf(elseIf); - builder.string(seenFieldName(sourceType)).string(" && ").tree(TypeSystemCodeGenerator.check(sourceType, "value")); + builder.string(seenFieldName(sourceType)).string(" && ").tree(TypeSystemCodeGenerator.check(typeSystem, sourceType, "value")); builder.end(); builder.startBlock().returnTrue().end(); } @@ -178,8 +177,8 @@ private Element createCast(boolean expect) { String methodName = expect ? "expect" : "cast"; - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), forType.getPrimitiveType(), methodName); - method.addParameter(new CodeVariableElement(typeSystem.getGenericType(), "value")); + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), forType, methodName); + method.addParameter(new CodeVariableElement(context.getType(Object.class), "value")); if (expect) { method.getThrownTypes().add(context.getType(UnexpectedResultException.class)); } @@ -187,16 +186,16 @@ CodeTreeBuilder builder = method.createBuilder(); boolean elseIf = false; - for (TypeData sourceType : sourceTypes) { + for (TypeMirror sourceType : sourceTypes) { elseIf = builder.startIf(elseIf); - builder.string(seenFieldName(sourceType)).string(" && ").tree(TypeSystemCodeGenerator.check(sourceType, "value")); + builder.string(seenFieldName(sourceType)).string(" && ").tree(TypeSystemCodeGenerator.check(typeSystem, sourceType, "value")); builder.end(); builder.startBlock(); builder.startReturn(); - CodeTree castTree = TypeSystemCodeGenerator.cast(sourceType, "value"); + CodeTree castTree = TypeSystemCodeGenerator.cast(typeSystem, sourceType, "value"); ImplicitCastData cast = typeSystem.lookupCast(sourceType, forType); if (cast != null) { - builder.tree(TypeSystemCodeGenerator.invokeImplicitCast(cast, castTree)); + builder.tree(TypeSystemCodeGenerator.invokeImplicitCast(typeSystem, cast, castTree)); } else { builder.tree(castTree); } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java Tue Apr 14 15:12:48 2015 +0200 @@ -61,16 +61,19 @@ private final ProcessorContext context; private final NodeData node; private final TypeSystemData typeSystem; - private final TypeData genericType; + private final TypeMirror genericType; + private final TypeMirror voidType; private final DSLOptions options; private final boolean singleSpecializable; private final int varArgsThreshold; + private final Set expectedTypes = new HashSet<>(); public NodeGenFactory(ProcessorContext context, NodeData node) { this.context = context; this.node = node; this.typeSystem = node.getTypeSystem(); - this.genericType = typeSystem.getGenericTypeData(); + this.genericType = context.getType(Object.class); + this.voidType = context.getType(void.class); this.options = typeSystem.getOptions(); this.singleSpecializable = isSingleSpecializableImpl(); this.varArgsThreshold = calculateVarArgsThreshold(); @@ -139,8 +142,8 @@ return "exclude" + specialization.getId() + NAME_SUFFIX; } - private static String executeChildMethodName(NodeExecutionData execution, TypeData type) { - return "execute" + ElementUtils.firstLetterUpperCase(execution.getName()) + (type.isGeneric() ? "" : getTypeId(type.getBoxedType())) + NAME_SUFFIX; + private static String executeChildMethodName(NodeExecutionData execution, TypeMirror type) { + return "execute" + ElementUtils.firstLetterUpperCase(execution.getName()) + (ElementUtils.isObject(type) ? "" : getTypeId(type)) + NAME_SUFFIX; } private CodeTree accessParent(String name) { @@ -186,7 +189,9 @@ } for (NodeExecutionData execution : node.getChildExecutions()) { - clazz.add(createNodeField(PRIVATE, execution.getNodeType(), nodeFieldName(execution), Child.class)); + if (execution.getChild() != null) { + clazz.add(createNodeField(PRIVATE, execution.getNodeType(), nodeFieldName(execution), Child.class)); + } } for (NodeExecutionData execution : node.getChildExecutions()) { @@ -201,7 +206,7 @@ } } - Collection specializedTypes = node.findSpecializedReturnTypes(); + Collection specializedTypes = node.findSpecializedReturnTypes(); List implementedExecutables = new ArrayList<>(); for (ExecutableTypeData execType : node.getExecutableTypes()) { if (shouldImplementExecutableType(specializedTypes, execType)) { @@ -235,6 +240,12 @@ } } + for (TypeMirror type : ElementUtils.uniqueSortedTypes(expectedTypes)) { + if (!typeSystem.hasType(type)) { + clazz.addOptional(TypeSystemCodeGenerator.createExpectMethod(PRIVATE, typeSystem, context.getType(Object.class), type)); + } + } + return clazz; } @@ -295,7 +306,7 @@ CodeTree nameTree = CodeTreeBuilder.singleString(name); CodeTreeBuilder callBuilder = builder.create(); callBuilder.string(name).string(" != null ? "); - callBuilder.tree(callTemplateMethod(null, createCast, nameTree)); + callBuilder.tree(callMethod(null, createCast.getMethod(), nameTree)); callBuilder.string(" : null"); name += "_"; builder.declaration(child.getNodeType(), name, callBuilder.build()); @@ -305,6 +316,9 @@ } for (NodeExecutionData execution : node.getChildExecutions()) { + if (execution.getChild() == null) { + continue; + } CreateCastData createCast = node.findCast(execution.getChild().getName()); builder.startStatement(); @@ -315,18 +329,18 @@ accessorBuilder.string(name); if (execution.isIndexed()) { - accessorBuilder.string("[").string(String.valueOf(execution.getIndex())).string("]"); + accessorBuilder.string("[").string(String.valueOf(execution.getChildIndex())).string("]"); } CodeTree accessor = accessorBuilder.build(); if (createCast != null && execution.getChild().getCardinality().isOne()) { - accessor = callTemplateMethod(null, createCast, accessor); + accessor = callMethod(null, createCast.getMethod(), accessor); } if (execution.isIndexed()) { CodeTreeBuilder nullCheck = builder.create(); - nullCheck.string(name).string(" != null && ").string(String.valueOf(execution.getIndex())).string(" < ").string(name).string(".length").string(" ? "); + nullCheck.string(name).string(" != null && ").string(String.valueOf(execution.getChildIndex())).string(" < ").string(name).string(".length").string(" ? "); nullCheck.tree(accessor); nullCheck.string(" : null"); accessor = nullCheck.build(); @@ -378,8 +392,8 @@ SpecializationData specialization = reachableSpecializations.get(0); for (Parameter parameter : specialization.getSignatureParameters()) { - TypeData type = parameter.getTypeSystemType(); - if (type != null && type.hasImplicitSourceTypes()) { + TypeMirror type = parameter.getType(); + if (type != null && typeSystem.hasImplicitSourceTypes(type)) { return true; } } @@ -410,9 +424,9 @@ } for (NodeExecutionData execution : node.getChildExecutions()) { - Collection specializedTypes = node.findSpecializedTypes(execution); + Collection specializedTypes = node.findSpecializedTypes(execution); specializedTypes.add(genericType); - for (TypeData specializedType : specializedTypes) { + for (TypeMirror specializedType : specializedTypes) { if (isExecuteChildShared(execution, specializedType)) { clazz.add(createExecuteChildMethod(execution, specializedType)); } @@ -428,10 +442,10 @@ CodeExecutableElement constructor = clazz.addOptional(createSpecializationConstructor(clazz, specialization, null)); for (Parameter p : specialization.getSignatureParameters()) { - TypeData targetType = p.getTypeSystemType(); - if (targetType.hasImplicitSourceTypes()) { + TypeMirror targetType = p.getType(); + if (typeSystem.hasImplicitSourceTypes(targetType)) { NodeExecutionData execution = p.getSpecification().getExecution(); - CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, p.getTypeSystemType()); + CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, p.getType()); if (implicitProfile != null) { implicitProfile.getModifiers().add(PRIVATE); implicitProfile.getModifiers().add(FINAL); @@ -449,21 +463,21 @@ clazz.addOptional(createIsSameMethod(specialization)); clazz.addOptional(createIsIdenticalMethod(specialization)); - TypeData returnType = specialization.getReturnType().getTypeSystemType(); + TypeMirror returnType = specialization.getReturnType().getType(); int signatureSize = specialization.getSignatureSize(); clazz.add(createFastPathExecuteMethod(specialization, null, signatureSize)); if (isTypeBoxingEliminated(specialization)) { - clazz.add(createFastPathExecuteMethod(specialization, returnType, 0)); - - if (signatureSize > 0 && !returnType.isGeneric()) { - clazz.add(createFastPathWrapExecuteMethod(genericType, returnType)); - } - - ExecutableTypeData voidExecutableType = node.findExecutableType(typeSystem.getVoidType(), 0); - if (voidExecutableType != null && isTypeBoxingOptimized(options.voidBoxingOptimization(), returnType)) { - clazz.add(createFastPathWrapVoidMethod(returnType)); + if (node.getMinimalEvaluatedParameters() == 0 || signatureSize == 0) { + clazz.add(createFastPathExecuteMethod(specialization, returnType, 0)); + if (signatureSize > 0 && !isObject(returnType)) { + clazz.add(createFastPathWrapExecuteMethod(genericType, returnType)); + } + ExecutableTypeData voidExecutableType = node.findExecutableType(voidType, 0); + if (voidExecutableType != null && isTypeBoxingOptimized(options.voidBoxingOptimization(), returnType)) { + clazz.add(createFastPathWrapVoidMethod(returnType)); + } } } @@ -517,7 +531,7 @@ } }; - builder.tree(createGuardAndCast(group, typeSystem.getGenericTypeData(), currentLocals, executionFactory)); + builder.tree(createGuardAndCast(group, genericType, currentLocals, executionFactory)); builder.returnFalse(); return method; } @@ -533,7 +547,7 @@ if (execution == null) { continue; } - CodeVariableElement var = createImplicitProfileParameter(execution, parameter.getTypeSystemType()); + CodeVariableElement var = createImplicitProfileParameter(execution, parameter.getType()); if (var != null) { profiles.add(var); } @@ -605,8 +619,9 @@ return executable; } - private Element createFastPathWrapVoidMethod(TypeData wrap) { - CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), typeSystem.getVoidType().getPrimitiveType(), TypeSystemNodeFactory.executeName(typeSystem.getVoidType())); + private Element createFastPathWrapVoidMethod(TypeMirror wrap) { + + CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), voidType, TypeSystemNodeFactory.executeName(voidType)); executable.addParameter(new CodeVariableElement(getType(Frame.class), FRAME_VALUE)); executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); CodeTreeBuilder builder = executable.createBuilder(); @@ -619,8 +634,8 @@ return executable; } - private Element createFastPathWrapExecuteMethod(TypeData override, TypeData wrap) { - CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), override.getPrimitiveType(), TypeSystemNodeFactory.executeName(override)); + private Element createFastPathWrapExecuteMethod(TypeMirror override, TypeMirror wrap) { + CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), override, TypeSystemNodeFactory.executeName(override)); executable.addParameter(new CodeVariableElement(getType(Frame.class), FRAME_VALUE)); executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); CodeTreeBuilder builder = executable.createBuilder(); @@ -758,11 +773,11 @@ } TypeBoxingOptimization optimization = options.monomorphicTypeBoxingOptimization(); - if (isTypeBoxingOptimized(optimization, specialization.getReturnType().getTypeSystemType())) { + if (isTypeBoxingOptimized(optimization, specialization.getReturnType().getType())) { return true; } for (Parameter p : specialization.getSignatureParameters()) { - if (isTypeBoxingOptimized(optimization, p.getTypeSystemType())) { + if (isTypeBoxingOptimized(optimization, p.getType())) { return true; } } @@ -772,7 +787,7 @@ private Set getEvaluatedCounts() { Set evaluatedCount = new TreeSet<>(); - Collection returnSpecializedTypes = node.findSpecializedReturnTypes(); + Collection returnSpecializedTypes = node.findSpecializedReturnTypes(); for (ExecutableTypeData execType : node.getExecutableTypes()) { if (shouldImplementExecutableType(returnSpecializedTypes, execType)) { evaluatedCount.add(execType.getEvaluatedCount()); @@ -788,7 +803,7 @@ } LocalContext locals = LocalContext.load(this); - CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), genericType.getPrimitiveType(), "unsupported", FRAME_VALUE); + CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), genericType, "unsupported", FRAME_VALUE); method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); CodeTreeBuilder builder = method.createBuilder(); @@ -808,8 +823,8 @@ SpecializationData specialization = reachableSpecializations.get(0); for (Parameter parameter : specialization.getSignatureParameters()) { - TypeData type = parameter.getTypeSystemType(); - if (type != null && type.hasImplicitSourceTypes()) { + TypeMirror type = parameter.getType(); + if (type != null && typeSystem.hasImplicitSourceTypes(type)) { return false; } } @@ -853,22 +868,23 @@ private CodeExecutableElement createExecutableTypeOverride(List implementedExecutables, ExecutableTypeData execType) { final String varArgsName = "args"; - final TypeData returnType = execType.getType(); - final TypeData executedType = execType.getEvaluatedCount() > 0 ? null : returnType; - - CodeExecutableElement method = cloneExecutableTypeOverride(execType, varArgsName); - LocalContext locals = LocalContext.load(this, execType.getSignatureSize(), Integer.MAX_VALUE); + final TypeMirror returnType = execType.getReturnType(); + final TypeMirror executedType = execType.getEvaluatedCount() > 0 ? null : returnType; + + LocalContext locals = LocalContext.load(this, execType.getEvaluatedCount(), Integer.MAX_VALUE); + CodeExecutableElement method = cloneExecutableTypeOverride(locals, execType, varArgsName); // rename varargs parameter int signatureIndex = 0; - for (Parameter parameter : execType.getSignatureParameters()) { - LocalVariable var = locals.get(parameter, signatureIndex); + for (TypeMirror parameter : execType.getEvaluatedParameters()) { + LocalVariable var = locals.getValue(signatureIndex); if (var != null) { - if (parameter.isTypeVarArgs()) { - var = var.accessWith(CodeTreeBuilder.singleString(varArgsName + "[" + parameter.getTypeVarArgsIndex() + "]")); + int varArgsIndex = execType.getVarArgsIndex(execType.getParameterIndex(signatureIndex)); + if (varArgsIndex >= 0) { + var = var.accessWith(CodeTreeBuilder.singleString(varArgsName + "[" + varArgsIndex + "]")); } - if (!parameter.getTypeSystemType().isGeneric()) { - var = var.newType(parameter.getTypeSystemType()); + if (!isObject(parameter)) { + var = var.newType(parameter); } locals.setValue(node.getChildExecutions().get(signatureIndex), var); } @@ -876,12 +892,12 @@ signatureIndex++; } - Parameter frame = execType.getFrame(); + TypeMirror frame = execType.getFrameParameter(); CodeTreeBuilder builder = method.createBuilder(); if (singleSpecializable) { LocalVariable frameVar = null; if (frame != null) { - frameVar = locals.get(FRAME_VALUE).newType(frame.getType()); + frameVar = locals.get(FRAME_VALUE).newType(frame); } method.getThrownTypes().clear(); locals.set(FRAME_VALUE, frameVar); @@ -889,9 +905,9 @@ SpecializationData specialization = getReachableSpecializations().iterator().next(); ExecutableTypeData wrappedExecutableType = findWrappedExecutable(specialization, implementedExecutables, execType); if (wrappedExecutableType != null) { - builder.startReturn().tree(callTemplateMethod(null, wrappedExecutableType, locals)).end(); + builder.startReturn().tree(callExecuteMethod(null, wrappedExecutableType, locals)).end(); } else { - builder.tree(createFastPath(builder, specialization, execType.getType(), locals)); + builder.tree(createFastPath(builder, specialization, execType.getReturnType(), locals)); } } else { // create acceptAndExecute @@ -900,23 +916,23 @@ if (frame == null) { executeBuilder.nullLiteral(); } else { - executeBuilder.string(frame.getLocalName()); + executeBuilder.string(locals.get(FRAME_VALUE).getName()); } locals.addReferencesTo(executeBuilder); executeBuilder.end(); - boolean hasExecutedUnexpected = executedType != null && !executedType.isGeneric() && !executedType.isVoid(); + boolean hasExecutedUnexpected = executedType != null && !isObject(executedType) && !isVoid(executedType); CodeTreeBuilder contentBuilder = builder.create(); contentBuilder.startReturn(); if (!hasExecutedUnexpected && !execType.hasUnexpectedValue(context)) { - if (executedType == null || executedType.needsCastTo(returnType)) { - contentBuilder.cast(returnType.getPrimitiveType(), executeBuilder.build()); + if (executedType == null || needsCastTo(executedType, returnType)) { + contentBuilder.cast(returnType, executeBuilder.build()); } else { contentBuilder.tree(executeBuilder.build()); } } else { - contentBuilder.tree(TypeSystemCodeGenerator.expect(executedType, returnType, executeBuilder.build())); + contentBuilder.tree(expect(executedType, returnType, executeBuilder.build())); } contentBuilder.end(); // try catch assert if unexpected value is not expected @@ -940,12 +956,12 @@ } private static ExecutableTypeData findWrappedExecutable(SpecializationData specialization, List implementedExecutables, ExecutableTypeData executedType) { - if (specialization.getReturnType().getTypeSystemType() == executedType.getType()) { + if (specialization.getReturnType().getType() == executedType.getReturnType()) { return null; } for (ExecutableTypeData otherType : implementedExecutables) { if (otherType != executedType && // - otherType.getType() == specialization.getReturnType().getTypeSystemType() && // + otherType.getReturnType() == specialization.getReturnType().getType() && // otherType.getEvaluatedCount() == executedType.getEvaluatedCount()) { return otherType; } @@ -953,43 +969,50 @@ return null; } - private CodeExecutableElement cloneExecutableTypeOverride(ExecutableTypeData execType, final String varArgsName) throws AssertionError { + private CodeExecutableElement cloneExecutableTypeOverride(LocalContext locals, ExecutableTypeData execType, final String varArgsName) throws AssertionError { CodeExecutableElement method = CodeExecutableElement.clone(context.getEnvironment(), execType.getMethod()); method.getAnnotationMirrors().clear(); method.getModifiers().remove(Modifier.ABSTRACT); - if (!execType.getMethod().isVarArgs() && execType.getParameters().size() != method.getParameters().size()) { - throw new AssertionError("Should be verified in the parser"); + // align argument names + int parameterIndex = 0; + if (execType.getFrameParameter() != null) { + CodeVariableElement frameParameter = (CodeVariableElement) method.getParameters().get(0); + frameParameter.setName(FRAME_VALUE); + frameParameter.getAnnotationMirrors().clear(); + parameterIndex++; } - // align argument names - int index = 0; - for (Parameter parameter : execType.getParameters()) { - CodeVariableElement var = (CodeVariableElement) method.getParameters().get(index); - if (parameter.isTypeVarArgs()) { + for (int signatureIndex = 0; signatureIndex < execType.getEvaluatedCount(); signatureIndex++) { + CodeVariableElement var = (CodeVariableElement) method.getParameters().get(parameterIndex); + if (signatureIndex < node.getSignatureSize()) { + if (execType.getVarArgsIndex(parameterIndex) >= 0) { + var.getAnnotationMirrors().clear(); + var.setName(varArgsName); + break; + } + var.setName(locals.getValue(signatureIndex).getName()); var.getAnnotationMirrors().clear(); - var.setName(varArgsName); - break; + } else { + var.setName("other" + signatureIndex); } - var.setName(LocalVariable.fromParameter(parameter).createParameter().getName()); - var.getAnnotationMirrors().clear(); - index++; + parameterIndex++; } return method; } - private boolean shouldImplementExecutableType(Collection specializedTypes, ExecutableTypeData execType) { - TypeData type = execType.getType(); + private boolean shouldImplementExecutableType(Collection specializedTypes, ExecutableTypeData execType) { + TypeMirror type = execType.getReturnType(); Set modifiers = execType.getMethod().getModifiers(); if (modifiers.contains(FINAL) || modifiers.contains(STATIC) || modifiers.contains(PRIVATE)) { return false; } else if (execType.isAbstract()) { return true; - } else if (type.isGeneric()) { + } else if (ElementUtils.isObject(type)) { return true; - } else if (type.isVoid()) { - for (TypeData specializedType : specializedTypes) { + } else if (ElementUtils.isVoid(type)) { + for (TypeMirror specializedType : specializedTypes) { if (isTypeBoxingOptimized(options.voidBoxingOptimization(), specializedType)) { return true; } @@ -1021,7 +1044,7 @@ return childField; } - private static List resolveSpecializedExecutables(NodeExecutionData execution, Collection types, TypeBoxingOptimization optimization) { + private static List resolveSpecializedExecutables(NodeExecutionData execution, Collection types, TypeBoxingOptimization optimization) { if (optimization == TypeBoxingOptimization.NONE) { return Collections.emptyList(); } else if (types.isEmpty()) { @@ -1029,10 +1052,13 @@ } List executables = new ArrayList<>(); - for (TypeData type : types) { + for (TypeMirror type : types) { if (!isTypeBoxingOptimized(optimization, type)) { continue; } + if (execution.getChild() == null) { + continue; + } ExecutableTypeData foundType = execution.getChild().getNodeData().findExecutableType(type, execution.getChild().getExecuteWith().size()); if (foundType != null) { executables.add(foundType); @@ -1041,15 +1067,15 @@ return executables; } - private static CodeTree callTemplateMethod(CodeTree receiver, TemplateMethod method, CodeTree... boundValues) { + private static CodeTree callMethod(CodeTree receiver, ExecutableElement method, CodeTree... boundValues) { CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); - if (method.getMethod().getModifiers().contains(STATIC)) { - builder.startStaticCall(method.getMethod().getEnclosingElement().asType(), method.getMethodName()); + if (method.getModifiers().contains(STATIC)) { + builder.startStaticCall(method.getEnclosingElement().asType(), method.getSimpleName().toString()); } else { - builder.startCall(receiver, method.getMethodName()); + builder.startCall(receiver, method.getSimpleName().toString()); } int index = -1; - for (Parameter parameter : method.getParameters()) { + for (VariableElement parameter : method.getParameters()) { index++; if (index < boundValues.length) { CodeTree tree = boundValues[index]; @@ -1059,13 +1085,39 @@ } } - builder.defaultValue(parameter.getType()); + builder.defaultValue(parameter.asType()); } builder.end(); return builder.build(); } - private static CodeTree callTemplateMethod(CodeTree receiver, TemplateMethod method, LocalContext currentValues) { + private CodeTree callExecuteMethod(NodeExecutionData execution, ExecutableTypeData method, LocalContext currentValues) { + CodeTree receiver = execution != null ? accessParent(nodeFieldName(execution)) : null; + List executeWith = execution != null ? execution.getChild().getExecuteWith() : null; + + List values = new ArrayList<>(); + if (method.getFrameParameter() != null) { + LocalVariable frameLocal = currentValues.get(FRAME_VALUE); + if (frameLocal == null) { + values.add(CodeTreeBuilder.singleString("null")); + } else { + values.add(createTypeSafeReference(frameLocal, method.getFrameParameter())); + } + } + for (int parameterIndex = 0; parameterIndex < method.getEvaluatedCount(); parameterIndex++) { + TypeMirror targetParameter = method.getEvaluatedParameters().get(parameterIndex); + LocalVariable variable; + if (executeWith != null && parameterIndex < executeWith.size()) { + variable = currentValues.getValue(executeWith.get(parameterIndex)); + } else { + variable = currentValues.getValue(parameterIndex); + } + values.add(createTypeSafeReference(variable, targetParameter)); + } + return callMethod(receiver, method.getMethod(), values.toArray(new CodeTree[values.size()])); + } + + private CodeTree callTemplateMethod(CodeTree receiver, TemplateMethod method, LocalContext currentValues) { CodeTree[] bindings = new CodeTree[method.getParameters().size()]; int signatureIndex = 0; @@ -1078,20 +1130,28 @@ } if (var != null) { - CodeTree valueReference = var.createReference(); - if (parameter.getTypeSystemType() != null && var.getType() != null && var.getType().needsCastTo(parameter.getTypeSystemType())) { - valueReference = TypeSystemCodeGenerator.cast(parameter.getTypeSystemType(), valueReference); - } else if (ElementUtils.needsCastTo(var.getTypeMirror(), parameter.getType())) { - valueReference = CodeTreeBuilder.createBuilder().cast(parameter.getType(), valueReference).build(); - } - bindings[i] = valueReference; + bindings[i] = createTypeSafeReference(var, parameter.getType()); } if (parameter.getSpecification().isSignature()) { signatureIndex++; } } - return callTemplateMethod(receiver, method, bindings); + return callMethod(receiver, method.getMethod(), bindings); + } + + private CodeTree createTypeSafeReference(LocalVariable var, TypeMirror targetType) { + CodeTree valueReference = var.createReference(); + TypeMirror sourceType = var.getTypeMirror(); + if (targetType == null || sourceType == null) { + return valueReference; + } + if (needsCastTo(sourceType, targetType)) { + valueReference = TypeSystemCodeGenerator.cast(typeSystem, targetType, valueReference); + } else if (ElementUtils.needsCastTo(sourceType, targetType)) { + valueReference = CodeTreeBuilder.createBuilder().cast(targetType, valueReference).build(); + } + return valueReference; } private SpecializationGroup createSpecializationGroups() { @@ -1125,7 +1185,7 @@ String varName = name + specialization.getIndex(); TypeMirror type = assumption.getExpression().getResolvedType(); builder.declaration(type, varName, assumptions); - currentValues.set(name, new LocalVariable(null, type, varName, null, null)); + currentValues.set(name, new LocalVariable(type, varName, null, null)); } builder.startIf(); @@ -1189,14 +1249,14 @@ return builder.build(); } - private boolean hasFallthrough(SpecializationGroup group, TypeData forType, LocalContext currentValues, boolean fastPath, List ignoreGuards) { + private boolean hasFallthrough(SpecializationGroup group, TypeMirror forType, LocalContext currentValues, boolean fastPath, List ignoreGuards) { for (TypeGuard guard : group.getTypeGuards()) { if (currentValues.getValue(guard.getSignatureIndex()) == null) { // not evaluated return true; } LocalVariable value = currentValues.getValue(guard.getSignatureIndex()); - if (value.getType().needsCastTo(guard.getType())) { + if (needsCastTo(value.getTypeMirror(), guard.getType())) { return true; } } @@ -1265,7 +1325,11 @@ if (execution.isShortCircuit()) { builder.nullLiteral(); } - builder.tree(accessParent(nodeFieldName(execution))); + if (execution.getChild() == null) { + builder.nullLiteral(); + } else { + builder.tree(accessParent(nodeFieldName(execution))); + } } builder.end(); return builder.build(); @@ -1289,7 +1353,7 @@ } if (currentValues != null) { for (Parameter p : specialization.getSignatureParameters()) { - CodeVariableElement var = createImplicitProfileParameter(p.getSpecification().getExecution(), p.getTypeSystemType()); + CodeVariableElement var = createImplicitProfileParameter(p.getSpecification().getExecution(), p.getType()); if (var != null) { LocalVariable variable = currentValues.get(p.getLocalName()); if (variable == null) { @@ -1370,19 +1434,19 @@ for (Parameter p : specialization.getSignatureParameters()) { NodeExecutionData execution = p.getSpecification().getExecution(); - CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, p.getTypeSystemType()); + CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, p.getType()); if (implicitProfile != null) { - LocalVariable var = LocalVariable.fromParameter(p).makeGeneric(); + LocalVariable var = LocalVariable.fromParameter(p).makeGeneric(context); String implicitFieldName = implicitProfile.getName(); if (options.implicitCastOptimization().isDuplicateTail()) { constructor.addParameter(var.createParameter()); - CodeTree implicitType = TypeSystemCodeGenerator.implicitType(p.getTypeSystemType(), var.createReference()); + CodeTree implicitType = TypeSystemCodeGenerator.implicitType(typeSystem, p.getType(), var.createReference()); builder.startStatement().string("this.").string(implicitFieldName).string(" = ").tree(implicitType).end(); } else if (options.implicitCastOptimization().isMergeCasts()) { // use node that supports polymorphism constructor.addParameter(var.createParameter()); - builder.startStatement().string("this.").string(implicitFieldName).string(" = ").tree(ImplicitCastNodeFactory.create(p.getTypeSystemType(), var.createReference())).end(); + builder.startStatement().string("this.").string(implicitFieldName).string(" = ").tree(ImplicitCastNodeFactory.create(typeSystem, p.getType(), var.createReference())).end(); } else { throw new AssertionError(); } @@ -1443,7 +1507,7 @@ return builder.build(); } - private CodeTree createCallNext(TypeData forType, LocalContext currentValues) { + private CodeTree createCallNext(TypeMirror forType, LocalContext currentValues) { if (singleSpecializable) { return createThrowUnsupported(currentValues); } @@ -1451,10 +1515,10 @@ callBuilder.startCall("next", TypeSystemNodeFactory.executeName(null)); currentValues.addReferencesTo(callBuilder, FRAME_VALUE); callBuilder.end(); - return CodeTreeBuilder.createBuilder().startReturn().tree(TypeSystemCodeGenerator.expect(genericType, forType, callBuilder.build())).end().build(); + return CodeTreeBuilder.createBuilder().startReturn().tree(expect(genericType, forType, callBuilder.build())).end().build(); } - private CodeTree createCallRemove(String reason, TypeData forType, LocalContext currentValues) { + private CodeTree createCallRemove(String reason, TypeMirror forType, LocalContext currentValues) { if (singleSpecializable) { return createThrowUnsupported(currentValues); } @@ -1467,12 +1531,12 @@ builder = builder.create(); builder.startReturn(); - builder.tree(TypeSystemCodeGenerator.expect(genericType, forType, call)); + builder.tree(expect(genericType, forType, call)); builder.end(); return builder.build(); } - private static CodeTree createCallDelegate(String methodName, String reason, TypeData forType, LocalContext currentValues) { + private CodeTree createCallDelegate(String methodName, String reason, TypeMirror forType, LocalContext currentValues) { CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); builder.startCall(methodName); if (reason != null) { @@ -1481,21 +1545,28 @@ currentValues.addReferencesTo(builder, FRAME_VALUE); builder.end(); - TypeData executedType = forType.getTypeSystem().getGenericTypeData(); - return TypeSystemCodeGenerator.expect(executedType, forType, builder.build()); + return expect(genericType, forType, builder.build()); } - private Set findSpecializedExecutableTypes(NodeExecutionData execution, TypeData type) { + private CodeTree expect(TypeMirror sourceType, TypeMirror forType, CodeTree tree) { + expectedTypes.add(forType); + return TypeSystemCodeGenerator.expect(typeSystem, sourceType, forType, tree); + } + + private Set findSpecializedExecutableTypes(NodeExecutionData execution, TypeMirror type) { + if (execution.getChild() == null) { + return Collections.emptySet(); + } ExecutableTypeData executableType = resolveExecutableType(execution.getChild(), type); Set executedTypes = new HashSet<>(); executedTypes.add(executableType); - if (type.hasImplicitSourceTypes()) { - executedTypes.addAll(resolveSpecializedExecutables(execution, type.getImplicitSourceTypes(), options.implicitTypeBoxingOptimization())); + if (typeSystem.hasImplicitSourceTypes(type)) { + executedTypes.addAll(resolveSpecializedExecutables(execution, typeSystem.lookupSourceTypes(type), options.implicitTypeBoxingOptimization())); } return executedTypes; } - private ExecutableTypeData resolveExecutableType(NodeChildData child, TypeData type) { + private ExecutableTypeData resolveExecutableType(NodeChildData child, TypeMirror type) { int executeWithCount = child.getExecuteWith().size(); ExecutableTypeData executableType = child.getNodeData().findExecutableType(type, executeWithCount); if (executableType == null) { @@ -1504,27 +1575,27 @@ return executableType; } - private boolean hasUnexpectedResult(NodeExecutionData execution, TypeData type) { + private boolean hasUnexpectedResult(NodeExecutionData execution, TypeMirror type) { for (ExecutableTypeData executableType : findSpecializedExecutableTypes(execution, type)) { - if (executableType != null && (executableType.hasUnexpectedValue(context) || executableType.getType().needsCastTo(type))) { + if (executableType != null && (executableType.hasUnexpectedValue(context) || needsCastTo(executableType.getReturnType(), type))) { return true; } } return false; } - private Element createFastPathExecuteMethod(SpecializationData specialization, final TypeData forType, int evaluatedArguments) { - TypeData type = forType == null ? genericType : forType; + private Element createFastPathExecuteMethod(SpecializationData specialization, final TypeMirror forType, int evaluatedArguments) { + TypeMirror type = forType == null ? genericType : forType; LocalContext currentLocals = LocalContext.load(this, evaluatedArguments, varArgsThreshold); if (specialization != null) { currentLocals.loadFastPathState(specialization); } - CodeExecutableElement executable = currentLocals.createMethod(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemNodeFactory.executeName(forType), FRAME_VALUE); + CodeExecutableElement executable = currentLocals.createMethod(modifiers(PUBLIC), type, TypeSystemNodeFactory.executeName(forType), FRAME_VALUE); executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); - if (!type.isGeneric()) { + if (!isObject(type)) { executable.getThrownTypes().add(getType(UnexpectedResultException.class)); } @@ -1534,17 +1605,17 @@ return executable; } - private CodeTree createFastPath(CodeTreeBuilder parent, SpecializationData specialization, TypeData type, LocalContext currentLocals) { + private CodeTree createFastPath(CodeTreeBuilder parent, SpecializationData specialization, TypeMirror type, LocalContext currentLocals) { final CodeTreeBuilder builder = parent.create(); for (NodeExecutionData execution : node.getChildExecutions()) { LocalVariable var = currentLocals.getValue(execution); if (var == null) { - TypeData targetType; + TypeMirror targetType; if (specialization == null) { targetType = genericType; } else { - targetType = specialization.findParameterOrDie(execution).getTypeSystemType(); + targetType = specialization.findParameterOrDie(execution).getType(); } LocalVariable shortCircuit = resolveShortCircuit(specialization, execution, currentLocals); LocalVariable value = currentLocals.createValue(execution, targetType).nextName(); @@ -1561,7 +1632,7 @@ } else if (specialization.isUninitialized()) { builder.startReturn().tree(createCallDelegate("uninitialized", null, type, currentLocals)).end(); } else { - final TypeData finalType = type; + final TypeMirror finalType = type; SpecializationGroup group = SpecializationGroup.create(specialization); SpecializationBody executionFactory = new SpecializationBody(true, true) { @Override @@ -1605,7 +1676,7 @@ return shortCircuitIndex; } - private CodeTree createFastPathExecute(CodeTreeBuilder parent, final TypeData forType, SpecializationData specialization, LocalContext currentValues) { + private CodeTree createFastPathExecute(CodeTreeBuilder parent, final TypeMirror forType, SpecializationData specialization, LocalContext currentValues) { CodeTreeBuilder builder = parent.create(); int ifCount = 0; if (specialization.isFallback()) { @@ -1642,21 +1713,37 @@ builder.end(); } - execute.startReturn(); if (specialization.getMethod() == null) { + execute.startReturn(); execute.startCall("unsupported"); currentValues.addReferencesTo(execute, FRAME_VALUE); execute.end(); + execute.end(); } else { + boolean doReturn = !isVoid(specialization.getMethod().getReturnType()); + if (doReturn) { + execute.startReturn(); + } else { + execute.startStatement(); + } execute.tree(callTemplateMethod(accessParent(null), specialization, currentValues)); + execute.end(); + if (!doReturn) { + if (isVoid(forType)) { + execute.returnStatement(); + } else { + execute.startReturn(); + execute.defaultValue(forType); + execute.end(); + } + } } - execute.end(); builder.tree(createFastPathTryCatchRewriteException(specialization, forType, currentValues, execute.build())); builder.end(ifCount); return builder.build(); } - private CodeTree createGuardAndCast(SpecializationGroup group, TypeData forType, LocalContext currentValues, SpecializationBody execution) { + private CodeTree createGuardAndCast(SpecializationGroup group, TypeMirror forType, LocalContext currentValues, SpecializationBody execution) { CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); Set castGuards; @@ -1780,10 +1867,10 @@ return false; } - private CodeExecutableElement createExecuteChildMethod(NodeExecutionData execution, TypeData targetType) { + private CodeExecutableElement createExecuteChildMethod(NodeExecutionData execution, TypeMirror targetType) { LocalContext locals = LocalContext.load(this, 0, varArgsThreshold); - CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), targetType.getPrimitiveType(), executeChildMethodName(execution, targetType), FRAME_VALUE); + CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), targetType, executeChildMethodName(execution, targetType), FRAME_VALUE); if (hasUnexpectedResult(execution, targetType)) { method.getThrownTypes().add(getType(UnexpectedResultException.class)); } @@ -1810,30 +1897,30 @@ return method; } - private CodeVariableElement createImplicitProfileParameter(NodeExecutionData execution, TypeData targetType) { - if (targetType.hasImplicitSourceTypes()) { + private CodeVariableElement createImplicitProfileParameter(NodeExecutionData execution, TypeMirror targetType) { + if (typeSystem.hasImplicitSourceTypes(targetType)) { switch (options.implicitCastOptimization()) { case NONE: return null; case DUPLICATE_TAIL: return new CodeVariableElement(getType(Class.class), implicitClassFieldName(execution)); case MERGE_CASTS: - return new CodeVariableElement(ImplicitCastNodeFactory.type(targetType), implicitNodeFieldName(execution)); + return new CodeVariableElement(ImplicitCastNodeFactory.type(typeSystem, targetType), implicitNodeFieldName(execution)); } } return null; } - private boolean isExecuteChildShared(NodeExecutionData execution, TypeData targetType) { - if (targetType.isVoid()) { + private boolean isExecuteChildShared(NodeExecutionData execution, TypeMirror targetType) { + if (isVoid(targetType)) { return false; - } else if (targetType.isGeneric()) { + } else if (isObject(targetType)) { return resolvePolymorphicExecutables(execution).size() >= 1; } else { if (!isTypeBoxingOptimized(options.monomorphicTypeBoxingOptimization(), targetType)) { return false; } - if (!targetType.hasImplicitSourceTypes()) { + if (!typeSystem.hasImplicitSourceTypes(targetType)) { return false; } @@ -1841,25 +1928,25 @@ for (SpecializationData specialization : node.getSpecializations()) { List parameters = specialization.findByExecutionData(execution); for (Parameter parameter : parameters) { - if (targetType.equals(parameter.getTypeSystemType())) { + if (targetType.equals(parameter.getType())) { uses++; } } } if (uses > 1) { - return resolveSpecializedExecutables(execution, targetType.getImplicitSourceTypes(), options.implicitTypeBoxingOptimization()).size() > 1; + return resolveSpecializedExecutables(execution, typeSystem.lookupSourceTypes(targetType), options.implicitTypeBoxingOptimization()).size() > 1; } else { return false; } } } - private CodeTree createAssignExecuteChild(NodeExecutionData execution, TypeData returnType, LocalVariable targetValue, LocalVariable shortCircuit, LocalContext currentValues) { + private CodeTree createAssignExecuteChild(NodeExecutionData execution, TypeMirror returnType, LocalVariable targetValue, LocalVariable shortCircuit, LocalContext currentValues) { CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); - boolean hasUnexpected = hasUnexpectedResult(execution, targetValue.getType()); + boolean hasUnexpected = hasUnexpectedResult(execution, targetValue.getTypeMirror()); CodeTree executeChild; - if (isExecuteChildShared(execution, targetValue.getType())) { + if (isExecuteChildShared(execution, targetValue.getTypeMirror())) { executeChild = createCallSharedExecuteChild(execution, targetValue, currentValues); } else { executeChild = createExecuteChild(execution, targetValue, currentValues, false); @@ -1876,7 +1963,7 @@ builder.startCatchBlock(getType(UnexpectedResultException.class), "ex"); LocalContext slowPathValues = currentValues.copy(); - slowPathValues.setValue(execution, targetValue.makeGeneric().accessWith(CodeTreeBuilder.singleString("ex.getResult()"))); + slowPathValues.setValue(execution, targetValue.makeGeneric(context).accessWith(CodeTreeBuilder.singleString("ex.getResult()"))); boolean found = false; for (NodeExecutionData otherExecution : node.getChildExecutions()) { if (found) { @@ -1945,16 +2032,16 @@ } private CodeTree createCallSharedExecuteChild(NodeExecutionData execution, LocalVariable targetValue, LocalContext currentValues) { - if (!isExecuteChildShared(execution, targetValue.getType())) { + if (!isExecuteChildShared(execution, targetValue.getTypeMirror())) { throw new AssertionError("Execute child not shared with method but called."); } CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); builder.tree(targetValue.createReference()).string(" = "); - builder.startCall(executeChildMethodName(execution, targetValue.getType())); + builder.startCall(executeChildMethodName(execution, targetValue.getTypeMirror())); builder.string(FRAME_VALUE); - CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, targetValue.getType()); + CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, targetValue.getTypeMirror()); if (implicitProfile != null) { builder.string(implicitProfile.getName()); } @@ -1970,12 +2057,12 @@ CodeTree assignment = createAssignmentStart(target, shared); - final Set executableTypes = findSpecializedExecutableTypes(execution, target.getType()); + final Set executableTypes = findSpecializedExecutableTypes(execution, target.getTypeMirror()); if (executableTypes.isEmpty()) { throw new AssertionError(); // cannot execute child - } else if (executableTypes.size() == 1 && !target.getType().hasImplicitSourceTypes()) { + } else if (executableTypes.size() == 1 && !typeSystem.hasImplicitSourceTypes(target.getTypeMirror())) { ExecutableTypeData executableType = executableTypes.iterator().next(); - if (target.getType().isGeneric() && executableType.getEvaluatedCount() == 0) { + if (isObject(target.getTypeMirror()) && executableType.getEvaluatedCount() == 0) { return createPolymorphicExecuteChild(execution, target, currentValues, shared); } else { builder.tree(assignment); @@ -1997,9 +2084,8 @@ } private CodeTree createSingleExecute(NodeExecutionData execution, LocalVariable target, LocalContext currentValues, ExecutableTypeData executableType) { - CodeTree accessChild = accessParent(nodeFieldName(execution)); - CodeTree execute = callTemplateMethod(accessChild, executableType, currentValues); - return TypeSystemCodeGenerator.expect(executableType.getType(), target.getType(), execute); + CodeTree execute = callExecuteMethod(execution, executableType, currentValues); + return expect(executableType.getReturnType(), target.getTypeMirror(), execute); } private CodeTree createPolymorphicExecuteChild(NodeExecutionData execution, LocalVariable target, LocalContext currentValues, boolean shared) throws AssertionError { @@ -2011,7 +2097,7 @@ List specializedExecutables = resolvePolymorphicExecutables(execution); Collections.sort(specializedExecutables, new Comparator() { public int compare(ExecutableTypeData o1, ExecutableTypeData o2) { - return o1.getType().compareTo(o2.getType()); + return compareType(o1.getReturnType(), o2.getReturnType()); } }); @@ -2034,7 +2120,7 @@ for (ExecutableTypeData executableType : specializedExecutables) { hasSpecializedTypes = polyChainBuilder.startIf(hasSpecializedTypes); polyChainBuilder.string(profileField); - polyChainBuilder.string(" == ").typeLiteral(executableType.getType().getPrimitiveType()); + polyChainBuilder.string(" == ").typeLiteral(executableType.getReturnType()); polyChainBuilder.end(); polyChainBuilder.startBlock(); polyChainBuilder.startStatement(); @@ -2048,20 +2134,20 @@ polyChainBuilder.startElseIf().string(profileField).string(" == null").end(); polyChainBuilder.startBlock(); polyChainBuilder.tree(createTransferToInterpreterAndInvalidate()); - polyChainBuilder.declaration(genericExecutableType.getType().getPrimitiveType(), valueFieldName, executeGeneric); + polyChainBuilder.declaration(genericExecutableType.getReturnType(), valueFieldName, executeGeneric); hasSpecializedTypes = false; for (ExecutableTypeData executableType : specializedExecutables) { hasSpecializedTypes = polyChainBuilder.startIf(hasSpecializedTypes); - polyChainBuilder.tree(TypeSystemCodeGenerator.check(executableType.getType(), CodeTreeBuilder.singleString(valueFieldName))); + polyChainBuilder.tree(TypeSystemCodeGenerator.check(typeSystem, executableType.getReturnType(), CodeTreeBuilder.singleString(valueFieldName))); polyChainBuilder.end(); polyChainBuilder.startBlock(); - polyChainBuilder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(executableType.getType().getPrimitiveType()).end(); + polyChainBuilder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(executableType.getReturnType()).end(); polyChainBuilder.end(); } polyChainBuilder.startElseBlock(); - polyChainBuilder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(genericType.getPrimitiveType()).end(); + polyChainBuilder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(genericType).end(); polyChainBuilder.end(); polyChainBuilder.startReturn().string(valueFieldName).end(); polyChainBuilder.end(); @@ -2077,7 +2163,7 @@ builder.tree(executePolymorphic); builder.end(); builder.startCatchBlock(getType(UnexpectedResultException.class), "ex"); - builder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(genericType.getPrimitiveType()).end(); + builder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(genericType).end(); builder.startReturn().string("ex.getResult()").end(); builder.end(); } else { @@ -2091,9 +2177,9 @@ if (singleSpecializable) { return Collections.emptyList(); } - Set specializedTypes = new HashSet<>(); - for (TypeData type : node.findSpecializedTypes(execution)) { - specializedTypes.addAll(type.getImplicitSourceTypes()); + Set specializedTypes = new HashSet<>(); + for (TypeMirror type : node.findSpecializedTypes(execution)) { + specializedTypes.addAll(typeSystem.lookupSourceTypes(type)); } return resolveSpecializedExecutables(execution, specializedTypes, options.polymorphicTypeBoxingElimination()); } @@ -2110,23 +2196,22 @@ private CodeTree createExecuteChildDuplicateTail(CodeTreeBuilder parent, NodeExecutionData execution, CodeTree assignment, LocalVariable target, LocalContext currentValues) { CodeTreeBuilder builder = parent.create(); - List sourceTypes = target.getType().getImplicitSourceTypes(); + List sourceTypes = typeSystem.lookupSourceTypes(target.getTypeMirror()); String implicitClassFieldName = implicitClassFieldName(execution); - String nodeFieldName = nodeFieldName(execution); List executableTypes = resolveSpecializedExecutables(execution, sourceTypes, options.implicitTypeBoxingOptimization()); boolean elseIf = false; for (ExecutableTypeData executableType : executableTypes) { elseIf = builder.startIf(elseIf); - builder.string(implicitClassFieldName).string(" == ").typeLiteral(executableType.getType().getPrimitiveType()); + builder.string(implicitClassFieldName).string(" == ").typeLiteral(executableType.getReturnType()); builder.end(); builder.startBlock(); builder.startStatement().tree(assignment); - CodeTree execute = callTemplateMethod(accessParent(nodeFieldName), executableType, currentValues); - ImplicitCastData cast = typeSystem.lookupCast(executableType.getType(), target.getType()); + CodeTree execute = callExecuteMethod(execution, executableType, currentValues); + ImplicitCastData cast = typeSystem.lookupCast(executableType.getReturnType(), target.getTypeMirror()); if (cast != null) { - execute = callTemplateMethod(null, cast, execute); + execute = callMethod(null, cast.getMethod(), execute); } builder.tree(execute); builder.end(); @@ -2137,13 +2222,13 @@ builder.startElseBlock(); } - LocalVariable genericValue = target.makeGeneric().nextName(); - builder.tree(createAssignExecuteChild(execution, genericValue.getType(), genericValue, null, currentValues)); + LocalVariable genericValue = target.makeGeneric(context).nextName(); + builder.tree(createAssignExecuteChild(execution, genericValue.getTypeMirror(), genericValue, null, currentValues)); if (executableTypes.size() == sourceTypes.size()) { builder.startThrow().startNew(getType(UnexpectedResultException.class)).tree(genericValue.createReference()).end().end(); } else { builder.startStatement().tree(assignment); - builder.tree(TypeSystemCodeGenerator.implicitExpect(target.getType(), genericValue.createReference(), implicitClassFieldName)); + builder.tree(TypeSystemCodeGenerator.implicitExpect(typeSystem, target.getTypeMirror(), genericValue.createReference(), implicitClassFieldName)); builder.end(); } @@ -2153,7 +2238,7 @@ return builder.build(); } - private CodeTree createFastPathTryCatchRewriteException(SpecializationData specialization, TypeData forType, LocalContext currentValues, CodeTree execution) { + private CodeTree createFastPathTryCatchRewriteException(SpecializationData specialization, TypeMirror forType, LocalContext currentValues, CodeTree execution) { if (specialization.getExceptions().isEmpty()) { return execution; } @@ -2248,8 +2333,8 @@ for (TypeGuard typeGuard : typeGuards) { int signatureIndex = typeGuard.getSignatureIndex(); LocalVariable value = currentValues.getValue(signatureIndex); - TypeData targetType = typeGuard.getType(); - if (!value.getType().needsCastTo(targetType)) { + TypeMirror targetType = typeGuard.getType(); + if (!ElementUtils.needsCastTo(value.getTypeMirror(), targetType)) { continue; } NodeExecutionData execution = node.getChildExecutions().get(signatureIndex); @@ -2264,7 +2349,7 @@ if (shortCircuit != null) { checkBuilder.string("("); CodeTreeBuilder referenceBuilder = checkBuilder.create(); - if (!shortCircuit.getType().isPrimitive()) { + if (!ElementUtils.isPrimitive(shortCircuit.getTypeMirror())) { referenceBuilder.string("(boolean) "); } referenceBuilder.tree(shortCircuit.createReference()); @@ -2276,15 +2361,15 @@ List sourceTypes = typeSystem.lookupByTargetType(targetType); CodeTree valueReference = value.createReference(); if (sourceTypes.isEmpty()) { - checkBuilder.tree(TypeSystemCodeGenerator.check(targetType, value.createReference())); - castBuilder.tree(TypeSystemCodeGenerator.cast(targetType, valueReference)); + checkBuilder.tree(TypeSystemCodeGenerator.check(typeSystem, targetType, value.createReference())); + castBuilder.tree(TypeSystemCodeGenerator.cast(typeSystem, targetType, valueReference)); } else { ImplicitCastOptimization opt = options.implicitCastOptimization(); if (specializationExecution.isFastPath() && !opt.isNone()) { if (opt.isDuplicateTail()) { String typeHintField = implicitClassFieldName(execution); - checkBuilder.tree(TypeSystemCodeGenerator.implicitCheck(targetType, valueReference, typeHintField)); - castBuilder.tree(TypeSystemCodeGenerator.implicitCast(targetType, valueReference, typeHintField)); + checkBuilder.tree(TypeSystemCodeGenerator.implicitCheck(typeSystem, targetType, valueReference, typeHintField)); + castBuilder.tree(TypeSystemCodeGenerator.implicitCast(typeSystem, targetType, valueReference, typeHintField)); } else if (opt.isMergeCasts()) { checkBuilder.tree(ImplicitCastNodeFactory.check(implicitNodeFieldName(execution), valueReference)); castBuilder.tree(ImplicitCastNodeFactory.cast(implicitNodeFieldName(execution), valueReference)); @@ -2292,14 +2377,14 @@ throw new AssertionError("implicit cast opt"); } } else { - checkBuilder.tree(TypeSystemCodeGenerator.implicitCheck(targetType, valueReference, null)); - castBuilder.tree(TypeSystemCodeGenerator.implicitCast(targetType, valueReference, null)); + checkBuilder.tree(TypeSystemCodeGenerator.implicitCheck(typeSystem, targetType, valueReference, null)); + castBuilder.tree(TypeSystemCodeGenerator.implicitCast(typeSystem, targetType, valueReference, null)); } } if (shortCircuit != null) { checkBuilder.string(")"); - castBuilder.string(" : ").defaultValue(targetType.getPrimitiveType()); + castBuilder.string(" : ").defaultValue(targetType); } if (castGuards == null || castGuards.contains(typeGuard)) { @@ -2329,7 +2414,7 @@ String varName = name + specialization.getIndex(); TypeMirror type = cache.getParameter().getType(); builder.declaration(type, varName, initializer); - currentValues.set(name, new LocalVariable(null, type, varName, null, null)); + currentValues.set(name, new LocalVariable(type, varName, null, null)); } public static final class LocalContext { @@ -2345,13 +2430,13 @@ for (CacheExpression cache : specialization.getCaches()) { Parameter cacheParameter = cache.getParameter(); String name = cacheParameter.getVariableElement().getSimpleName().toString(); - set(cacheParameter.getLocalName(), new LocalVariable(cacheParameter.getTypeSystemType(), cacheParameter.getType(), name, CodeTreeBuilder.singleString("this." + name), null)); + set(cacheParameter.getLocalName(), new LocalVariable(cacheParameter.getType(), name, CodeTreeBuilder.singleString("this." + name), null)); } for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) { String name = assumptionName(assumption); TypeMirror type = assumption.getExpression().getResolvedType(); - set(name, new LocalVariable(null, type, name, CodeTreeBuilder.singleString("this." + name), null)); + set(name, new LocalVariable(type, name, CodeTreeBuilder.singleString("this." + name), null)); } } @@ -2382,12 +2467,12 @@ } @SuppressWarnings("static-method") - public LocalVariable createValue(NodeExecutionData execution, TypeData type) { - return new LocalVariable(type, type.getPrimitiveType(), valueName(execution), null, null); + public LocalVariable createValue(NodeExecutionData execution, TypeMirror type) { + return new LocalVariable(type, valueName(execution), null, null); } public LocalVariable createShortCircuitValue(NodeExecutionData execution) { - return new LocalVariable(factory.typeSystem.getBooleanType(), factory.getType(boolean.class), shortCircuitName(execution), null, null); + return new LocalVariable(factory.getType(boolean.class), shortCircuitName(execution), null, null); } private static String valueName(NodeExecutionData execution) { @@ -2424,7 +2509,12 @@ } public LocalVariable getValue(int signatureIndex) { - return getValue(factory.node.getChildExecutions().get(signatureIndex)); + List childExecutions = factory.node.getChildExecutions(); + if (signatureIndex < childExecutions.size()) { + return getValue(childExecutions.get(signatureIndex)); + } else { + return null; + } } public void removeValue(String id) { @@ -2458,11 +2548,11 @@ } private void loadValues(int evaluatedArguments, int varargsThreshold) { - values.put(FRAME_VALUE, new LocalVariable(null, factory.getType(Frame.class), FRAME_VALUE, null, null)); + values.put(FRAME_VALUE, new LocalVariable(factory.getType(Frame.class), FRAME_VALUE, null, null)); for (NodeFieldData field : factory.node.getFields()) { String fieldName = fieldValueName(field); - values.put(fieldName, new LocalVariable(null, field.getType(), fieldName, factory.accessParent(field.getName()), null)); + values.put(fieldName, new LocalVariable(field.getType(), fieldName, factory.accessParent(field.getName()), null)); } boolean varargs = needsVarargs(false, varargsThreshold); @@ -2473,7 +2563,7 @@ } NodeExecutionData execution = childExecutions.get(i); if (execution.isShortCircuit()) { - LocalVariable shortCircuit = createShortCircuitValue(execution).makeGeneric(); + LocalVariable shortCircuit = createShortCircuitValue(execution).makeGeneric(factory.context); if (varargs) { shortCircuit = shortCircuit.accessWith(createReadVarargs(i)); } @@ -2562,7 +2652,6 @@ public static final class LocalVariable { - private final TypeData type; private final TypeMirror typeMirror; private final CodeTree accessorTree; private final String name; @@ -2576,22 +2665,17 @@ } else { name = createName(execution); } - return new LocalVariable(parameter.getTypeSystemType(), parameter.getType(), name, null, null); + return new LocalVariable(parameter.getType(), name, null, null); } - private LocalVariable(TypeData type, TypeMirror typeMirror, String name, CodeTree accessorTree, LocalVariable previous) { + private LocalVariable(TypeMirror typeMirror, String name, CodeTree accessorTree, LocalVariable previous) { Objects.requireNonNull(typeMirror); this.typeMirror = typeMirror; this.accessorTree = accessorTree; - this.type = type; this.name = name; this.previous = previous; } - public TypeData getType() { - return type; - } - public String getShortCircuitName() { return "has" + ElementUtils.firstLetterUpperCase(getName()); } @@ -2631,24 +2715,20 @@ } } - public LocalVariable newType(TypeData newType) { - return new LocalVariable(newType, newType.getPrimitiveType(), name, accessorTree, this); - } - public LocalVariable newType(TypeMirror newType) { - return new LocalVariable(type, newType, name, accessorTree, this); + return new LocalVariable(newType, name, accessorTree, this); } public LocalVariable accessWith(CodeTree tree) { - return new LocalVariable(type, typeMirror, name, tree, this); + return new LocalVariable(typeMirror, name, tree, this); } public LocalVariable nextName() { - return new LocalVariable(type, typeMirror, createNextName(name), accessorTree, this); + return new LocalVariable(typeMirror, createNextName(name), accessorTree, this); } public LocalVariable makeOriginal() { - return new LocalVariable(type, typeMirror, name, accessorTree, null); + return new LocalVariable(typeMirror, name, accessorTree, null); } public LocalVariable original() { @@ -2659,8 +2739,8 @@ return variable; } - public LocalVariable makeGeneric() { - return newType(type.getTypeSystem().getGenericTypeData()); + public LocalVariable makeGeneric(ProcessorContext context) { + return newType(context.getType(Object.class)); } @Override diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java Tue Apr 14 15:12:48 2015 +0200 @@ -22,12 +22,13 @@ */ package com.oracle.truffle.dsl.processor.generator; +import static com.oracle.truffle.dsl.processor.generator.GeneratorUtils.*; import static com.oracle.truffle.dsl.processor.java.ElementUtils.*; -import static com.oracle.truffle.dsl.processor.generator.GeneratorUtils.*; import static javax.lang.model.element.Modifier.*; import java.util.*; +import javax.lang.model.element.*; import javax.lang.model.type.*; import com.oracle.truffle.api.nodes.*; @@ -38,64 +39,47 @@ public class TypeSystemCodeGenerator extends CodeTypeElementFactory { - public static CodeTree cast(TypeData type, String content) { - return cast(type, CodeTreeBuilder.singleString(content)); + private static final String LOCAL_VALUE = "value"; + + public static CodeTree cast(TypeSystemData typeSystem, TypeMirror type, String content) { + return cast(typeSystem, type, CodeTreeBuilder.singleString(content)); } - public static CodeTree implicitType(TypeData type, CodeTree value) { - if (type.isGeneric()) { + public static CodeTree implicitType(TypeSystemData typeSystem, TypeMirror type, CodeTree value) { + if (ElementUtils.isObject(type)) { return value; } CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); - TypeSystemData typeSystem = type.getTypeSystem(); - builder.startStaticCall(createTypeSystemGen(typeSystem), getImplicitClass(type)).tree(value); + builder.startStaticCall(createTypeSystemGen(typeSystem), getImplicitClass(typeSystem, type)).tree(value); builder.end(); return builder.build(); } - public static CodeTree invokeImplicitCast(ImplicitCastData cast, CodeTree expression) { + public static CodeTree invokeImplicitCast(TypeSystemData typeSystem, ImplicitCastData cast, CodeTree expression) { CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); - TypeSystemData typeSystem = cast.getTargetType().getTypeSystem(); builder.startStaticCall(createTypeSystemGen(typeSystem), cast.getMethodName()).tree(expression); builder.end(); return builder.build(); } - public static CodeTree implicitCheck(TypeData type, CodeTree value, String typeHint) { - if (type.isGeneric()) { + public static CodeTree implicitCheck(TypeSystemData typeSystem, TypeMirror type, CodeTree value, String typeHint) { + return callImplictMethod(typeSystem, type, isImplicitTypeMethodName(typeSystem, type), value, typeHint); + } + + public static CodeTree implicitExpect(TypeSystemData typeSystem, TypeMirror type, CodeTree value, String typeHint) { + return callImplictMethod(typeSystem, type, expectImplicitTypeMethodName(typeSystem, type), value, typeHint); + } + + public static CodeTree implicitCast(TypeSystemData typeSystem, TypeMirror type, CodeTree value, String typeHint) { + return callImplictMethod(typeSystem, type, asImplicitTypeMethodName(typeSystem, type), value, typeHint); + } + + private static CodeTree callImplictMethod(TypeSystemData typeSystem, TypeMirror type, String methodName, CodeTree value, String typeHint) { + if (ElementUtils.isObject(type)) { return value; } CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); - TypeSystemData typeSystem = type.getTypeSystem(); - builder.startStaticCall(createTypeSystemGen(typeSystem), isImplicitTypeMethodName(type)).tree(value); - if (typeHint != null) { - builder.string(typeHint); - } - builder.end(); - return builder.build(); - } - - public static CodeTree implicitExpect(TypeData type, CodeTree value, String typeHint) { - if (type.isGeneric()) { - return value; - } - CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); - TypeSystemData typeSystem = type.getTypeSystem(); - builder.startStaticCall(createTypeSystemGen(typeSystem), expectImplicitTypeMethodName(type)).tree(value); - if (typeHint != null) { - builder.string(typeHint); - } - builder.end(); - return builder.build(); - } - - public static CodeTree implicitCast(TypeData type, CodeTree value, String typeHint) { - if (type.isGeneric()) { - return value; - } - CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); - TypeSystemData typeSystem = type.getTypeSystem(); - builder.startStaticCall(createTypeSystemGen(typeSystem), asImplicitTypeMethodName(type)).tree(value); + builder.startStaticCall(createTypeSystemGen(typeSystem), methodName).tree(value); if (typeHint != null) { builder.string(typeHint); } @@ -103,36 +87,57 @@ return builder.build(); } - public static CodeTree cast(TypeData type, CodeTree content) { - if (type.isGeneric()) { + public static CodeTree cast(TypeSystemData typeSystem, TypeMirror type, CodeTree content) { + if (ElementUtils.isObject(type)) { return content; } CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); - TypeSystemData typeSystem = type.getTypeSystem(); - if (type.isDefaultCast()) { - builder.cast(type.getPrimitiveType(), content); + TypeCastData cast = typeSystem.getCast(type); + if (cast == null) { + builder.cast(type, content); } else { - builder.startStaticCall(typeSystem.getTemplateType().asType(), type.getTypeCasts().get(0).getMethodName()).tree(content).end(); + builder.startStaticCall(typeSystem.getTemplateType().asType(), cast.getMethodName()).tree(content).end(); } return builder.build(); } - public static CodeTree expect(TypeData type, CodeTree content) { - if (type.isGeneric() || type.isVoid()) { + public static CodeTree expect(TypeSystemData typeSystem, TypeMirror type, CodeTree content) { + if (ElementUtils.isObject(type) || ElementUtils.isVoid(type)) { return content; } CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); - TypeSystemData typeSystem = type.getTypeSystem(); - builder.startStaticCall(createTypeSystemGen(typeSystem), expectTypeMethodName(type)).tree(content).end(); + if (typeSystem.hasType(type)) { + builder.startStaticCall(createTypeSystemGen(typeSystem), expectTypeMethodName(typeSystem, type)).tree(content).end(); + } else { + builder.startCall(expectTypeMethodName(typeSystem, type)).tree(content).end(); + } + return builder.build(); } - public static CodeTree expect(TypeData sourceType, TypeData targetType, CodeTree content) { - if (sourceType != null && !sourceType.needsCastTo(targetType)) { + public static CodeExecutableElement createExpectMethod(Modifier visibility, TypeSystemData typeSystem, TypeMirror sourceType, TypeMirror expectedType) { + if (ElementUtils.isObject(expectedType) || ElementUtils.isVoid(expectedType)) { + return null; + } + CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), expectedType, TypeSystemCodeGenerator.expectTypeMethodName(typeSystem, expectedType)); + method.setVisibility(visibility); + method.addParameter(new CodeVariableElement(sourceType, LOCAL_VALUE)); + method.addThrownType(typeSystem.getContext().getTruffleTypes().getUnexpectedValueException()); + + CodeTreeBuilder body = method.createBuilder(); + body.startIf().tree(check(typeSystem, expectedType, LOCAL_VALUE)).end().startBlock(); + body.startReturn().tree(cast(typeSystem, expectedType, LOCAL_VALUE)).end(); + body.end(); + body.startThrow().startNew(typeSystem.getContext().getTruffleTypes().getUnexpectedValueException()).string(LOCAL_VALUE).end().end(); + return method; + } + + public static CodeTree expect(TypeSystemData typeSystem, TypeMirror sourceType, TypeMirror targetType, CodeTree content) { + if (sourceType != null && !ElementUtils.needsCastTo(sourceType, targetType)) { return content; } else { - return expect(targetType, content); + return expect(typeSystem, targetType, content); } } @@ -140,51 +145,55 @@ return new GeneratedTypeMirror(ElementUtils.getPackageName(typeSystem.getTemplateType()), typeName(typeSystem)); } - public static CodeTree check(TypeData type, String content) { - return check(type, CodeTreeBuilder.singleString(content)); + public static CodeTree check(TypeSystemData typeSystem, TypeMirror type, String content) { + return check(typeSystem, type, CodeTreeBuilder.singleString(content)); } - public static CodeTree check(TypeData type, CodeTree content) { - if (type.isGeneric()) { + public static CodeTree check(TypeSystemData typeSystem, TypeMirror type, CodeTree content) { + if (ElementUtils.isObject(type)) { return content; } CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); - TypeSystemData typeSystem = type.getTypeSystem(); - if (type.isDefaultCheck()) { - builder.instanceOf(content, type.getBoxedType()); + TypeCheckData check = typeSystem.getCheck(type); + if (check == null) { + builder.instanceOf(content, ElementUtils.boxType(typeSystem.getContext(), type)); } else { - builder.startStaticCall(typeSystem.getTemplateType().asType(), type.getTypeChecks().get(0).getMethodName()).tree(content).end(); + builder.startStaticCall(typeSystem.getTemplateType().asType(), check.getMethodName()).tree(content).end(); } return builder.build(); } - public static String isTypeMethodName(TypeData type) { - return "is" + ElementUtils.getTypeId(type.getBoxedType()); + public static String isTypeMethodName(TypeSystemData typeSystem, TypeMirror type) { + return "is" + getTypeId(typeSystem, type); } - static String isImplicitTypeMethodName(TypeData type) { - return "isImplicit" + ElementUtils.getTypeId(type.getBoxedType()); + private static String getTypeId(TypeSystemData typeSystem, TypeMirror type) { + return ElementUtils.getTypeId(typeSystem.boxType(type)); } - public static String asTypeMethodName(TypeData type) { - return "as" + ElementUtils.getTypeId(type.getBoxedType()); + static String isImplicitTypeMethodName(TypeSystemData typeSystem, TypeMirror type) { + return "isImplicit" + getTypeId(typeSystem, type); } - static String asImplicitTypeMethodName(TypeData type) { - return "asImplicit" + ElementUtils.getTypeId(type.getBoxedType()); + public static String asTypeMethodName(TypeSystemData typeSystem, TypeMirror type) { + return "as" + getTypeId(typeSystem, type); + } + + static String asImplicitTypeMethodName(TypeSystemData typeSystem, TypeMirror type) { + return "asImplicit" + getTypeId(typeSystem, type); } - static String expectImplicitTypeMethodName(TypeData type) { - return "expectImplicit" + ElementUtils.getTypeId(type.getBoxedType()); + static String expectImplicitTypeMethodName(TypeSystemData typeSystem, TypeMirror type) { + return "expectImplicit" + getTypeId(typeSystem, type); } - static String getImplicitClass(TypeData type) { - return "getImplicit" + ElementUtils.getTypeId(type.getBoxedType()) + "Class"; + static String getImplicitClass(TypeSystemData typeSystem, TypeMirror type) { + return "getImplicit" + getTypeId(typeSystem, type) + "Class"; } - public static String expectTypeMethodName(TypeData type) { - return "expect" + ElementUtils.getTypeId(type.getBoxedType()); + public static String expectTypeMethodName(TypeSystemData typeSystem, TypeMirror type) { + return "expect" + getTypeId(typeSystem, type); } static String typeName(TypeSystemData typeSystem) { @@ -203,11 +212,8 @@ clazz.add(new TypeSystemNodeFactory(context, typeSystem).create()); if (typeSystem.getOptions().implicitCastOptimization().isMergeCasts()) { - for (TypeData type : typeSystem.getTypes()) { - List sourceTypes = typeSystem.lookupSourceTypes(type); - if (sourceTypes.size() > 1) { - clazz.add(new ImplicitCastNodeFactory(context, type).create()); - } + for (TypeMirror type : typeSystem.lookupTargetTypes()) { + clazz.add(new ImplicitCastNodeFactory(context, typeSystem, type).create()); } } return clazz; @@ -215,8 +221,6 @@ private static class TypeClassFactory { - private static final String LOCAL_VALUE = "value"; - private final ProcessorContext context; private final TypeSystemData typeSystem; @@ -233,50 +237,35 @@ CodeVariableElement singleton = createSingleton(clazz); clazz.add(singleton); - for (TypeData type : typeSystem.getTypes()) { - if (type.isVoid() || type.isGeneric()) { + for (TypeMirror type : typeSystem.getLegacyTypes()) { + if (ElementUtils.isVoid(type) || ElementUtils.isObject(type)) { continue; } clazz.addOptional(createIsTypeMethod(type)); clazz.addOptional(createAsTypeMethod(type)); + clazz.addOptional(createExpectTypeMethod(type, context.getType(Object.class))); - for (TypeData sourceType : collectExpectSourceTypes(type)) { - clazz.addOptional(createExpectTypeMethod(type, sourceType)); - } + } - if (type.hasImplicitSourceTypes()) { - clazz.add(createAsImplicitTypeMethod(type, false)); - if (typeSystem.getOptions().implicitCastOptimization().isNone()) { - clazz.add(createExpectImplicitTypeMethod(type, false)); - } - clazz.add(createIsImplicitTypeMethod(type, false)); + List lookupTargetTypes = typeSystem.lookupTargetTypes(); + for (TypeMirror type : lookupTargetTypes) { + clazz.add(createAsImplicitTypeMethod(type, false)); + if (typeSystem.getOptions().implicitCastOptimization().isNone()) { + clazz.add(createExpectImplicitTypeMethod(type, false)); + } + clazz.add(createIsImplicitTypeMethod(type, false)); - if (typeSystem.getOptions().implicitCastOptimization().isDuplicateTail()) { - clazz.add(createAsImplicitTypeMethod(type, true)); - clazz.add(createExpectImplicitTypeMethod(type, true)); - clazz.add(createIsImplicitTypeMethod(type, true)); - clazz.add(createGetImplicitClass(type)); - } + if (typeSystem.getOptions().implicitCastOptimization().isDuplicateTail()) { + clazz.add(createAsImplicitTypeMethod(type, true)); + clazz.add(createExpectImplicitTypeMethod(type, true)); + clazz.add(createIsImplicitTypeMethod(type, true)); + clazz.add(createGetImplicitClass(type)); } } - return clazz; } - private static List collectExpectSourceTypes(TypeData type) { - Set sourceTypes = new HashSet<>(); - sourceTypes.add(type.getTypeSystem().getGenericTypeData()); - for (TypeCastData cast : type.getTypeCasts()) { - sourceTypes.add(cast.getSourceType()); - } - for (TypeCheckData cast : type.getTypeChecks()) { - sourceTypes.add(cast.getCheckedType()); - } - sourceTypes.remove(type); - return new ArrayList<>(sourceTypes); - } - private CodeVariableElement createSingleton(CodeTypeElement clazz) { CodeVariableElement field = new CodeVariableElement(modifiers(PUBLIC, STATIC, FINAL), clazz.asType(), singletonName(typeSystem)); field.createInitBuilder().startNew(clazz.asType()).end(); @@ -287,24 +276,24 @@ return field; } - private CodeExecutableElement createIsImplicitTypeMethod(TypeData type, boolean typed) { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(boolean.class), TypeSystemCodeGenerator.isImplicitTypeMethodName(type)); + private CodeExecutableElement createIsImplicitTypeMethod(TypeMirror type, boolean typed) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(boolean.class), TypeSystemCodeGenerator.isImplicitTypeMethodName(typeSystem, type)); method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE)); if (typed) { method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint")); } CodeTreeBuilder builder = method.createBuilder(); - List sourceTypes = typeSystem.lookupSourceTypes(type); + List sourceTypes = typeSystem.lookupSourceTypes(type); builder.startReturn(); String sep = ""; - for (TypeData sourceType : sourceTypes) { + for (TypeMirror sourceType : sourceTypes) { builder.string(sep); if (typed) { - builder.string("(typeHint == ").typeLiteral(sourceType.getPrimitiveType()).string(" && "); + builder.string("(typeHint == ").typeLiteral(sourceType).string(" && "); } - builder.tree(check(sourceType, LOCAL_VALUE)); + builder.tree(check(typeSystem, sourceType, LOCAL_VALUE)); if (typed) { builder.string(")"); } @@ -321,24 +310,24 @@ return method; } - private CodeExecutableElement createAsImplicitTypeMethod(TypeData type, boolean useTypeHint) { - String name = asImplicitTypeMethodName(type); - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type.getPrimitiveType(), name); + private CodeExecutableElement createAsImplicitTypeMethod(TypeMirror type, boolean useTypeHint) { + String name = asImplicitTypeMethodName(typeSystem, type); + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type, name); method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE)); if (useTypeHint) { method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint")); } - List sourceTypes = typeSystem.lookupSourceTypes(type); + List sourceTypes = typeSystem.lookupSourceTypes(type); CodeTreeBuilder builder = method.createBuilder(); boolean elseIf = false; - for (TypeData sourceType : sourceTypes) { + for (TypeMirror sourceType : sourceTypes) { elseIf = builder.startIf(elseIf); if (useTypeHint) { - builder.string("typeHint == ").typeLiteral(sourceType.getPrimitiveType()); + builder.string("typeHint == ").typeLiteral(sourceType); } else { - builder.tree(check(sourceType, LOCAL_VALUE)); + builder.tree(check(typeSystem, sourceType, LOCAL_VALUE)); } builder.end().startBlock(); @@ -348,7 +337,7 @@ if (cast != null) { builder.startCall(cast.getMethodName()); } - builder.tree(cast(sourceType, LOCAL_VALUE)).end(); + builder.tree(cast(typeSystem, sourceType, LOCAL_VALUE)).end(); if (cast != null) { builder.end(); } @@ -363,26 +352,26 @@ return method; } - private CodeExecutableElement createExpectImplicitTypeMethod(TypeData type, boolean useTypeHint) { - String name = expectImplicitTypeMethodName(type); - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type.getPrimitiveType(), name); + private CodeExecutableElement createExpectImplicitTypeMethod(TypeMirror type, boolean useTypeHint) { + String name = expectImplicitTypeMethodName(typeSystem, type); + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type, name); method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE)); if (useTypeHint) { method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint")); } method.getThrownTypes().add(context.getType(UnexpectedResultException.class)); - List sourceTypes = typeSystem.lookupSourceTypes(type); + List sourceTypes = typeSystem.lookupSourceTypes(type); CodeTreeBuilder builder = method.createBuilder(); boolean elseIf = false; - for (TypeData sourceType : sourceTypes) { + for (TypeMirror sourceType : sourceTypes) { elseIf = builder.startIf(elseIf); if (useTypeHint) { - builder.string("typeHint == ").typeLiteral(sourceType.getPrimitiveType()); + builder.string("typeHint == ").typeLiteral(sourceType); builder.string(" && "); } - builder.tree(check(sourceType, LOCAL_VALUE)); + builder.tree(check(typeSystem, sourceType, LOCAL_VALUE)); builder.end().startBlock(); @@ -391,7 +380,7 @@ if (cast != null) { builder.startCall(cast.getMethodName()); } - builder.tree(cast(sourceType, LOCAL_VALUE)).end(); + builder.tree(cast(typeSystem, sourceType, LOCAL_VALUE)).end(); if (cast != null) { builder.end(); } @@ -405,18 +394,18 @@ return method; } - private CodeExecutableElement createGetImplicitClass(TypeData type) { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(Class.class), TypeSystemCodeGenerator.getImplicitClass(type)); + private CodeExecutableElement createGetImplicitClass(TypeMirror type) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(Class.class), TypeSystemCodeGenerator.getImplicitClass(typeSystem, type)); method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE)); - List sourceTypes = typeSystem.lookupSourceTypes(type); + List sourceTypes = typeSystem.lookupSourceTypes(type); CodeTreeBuilder builder = method.createBuilder(); boolean elseIf = false; - for (TypeData sourceType : sourceTypes) { + for (TypeMirror sourceType : sourceTypes) { elseIf = builder.startIf(elseIf); - builder.tree(check(sourceType, LOCAL_VALUE)).end(); + builder.tree(check(typeSystem, sourceType, LOCAL_VALUE)).end(); builder.end().startBlock(); - builder.startReturn().typeLiteral(sourceType.getPrimitiveType()).end(); + builder.startReturn().typeLiteral(sourceType).end(); builder.end(); } @@ -428,50 +417,39 @@ return method; } - private CodeExecutableElement createIsTypeMethod(TypeData type) { - if (!type.getTypeChecks().isEmpty()) { + private CodeExecutableElement createIsTypeMethod(TypeMirror type) { + if (typeSystem.getCheck(type) != null) { return null; } - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(boolean.class), TypeSystemCodeGenerator.isTypeMethodName(type)); + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(boolean.class), TypeSystemCodeGenerator.isTypeMethodName(typeSystem, type)); method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE)); CodeTreeBuilder body = method.createBuilder(); - body.startReturn().tree(check(type, LOCAL_VALUE)).end(); + body.startReturn().tree(check(typeSystem, type, LOCAL_VALUE)).end(); return method; } - private CodeExecutableElement createAsTypeMethod(TypeData type) { - if (!type.getTypeCasts().isEmpty()) { + private CodeExecutableElement createAsTypeMethod(TypeMirror type) { + if (typeSystem.getCast(type) != null) { return null; } - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asTypeMethodName(type)); + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type, TypeSystemCodeGenerator.asTypeMethodName(typeSystem, type)); method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE)); CodeTreeBuilder body = method.createBuilder(); - String assertMessage = typeName(typeSystem) + "." + asTypeMethodName(type) + ": " + ElementUtils.getSimpleName(type.getBoxedType()) + " expected"; - body.startAssert().tree(check(type, LOCAL_VALUE)).string(" : ").doubleQuote(assertMessage).end(); - body.startReturn().tree(cast(type, LOCAL_VALUE)).end(); + String assertMessage = typeName(typeSystem) + "." + asTypeMethodName(typeSystem, type) + ": " + ElementUtils.getSimpleName(type) + " expected"; + body.startAssert().tree(check(typeSystem, type, LOCAL_VALUE)).string(" : ").doubleQuote(assertMessage).end(); + body.startReturn().tree(cast(typeSystem, type, LOCAL_VALUE)).end(); return method; } - private CodeExecutableElement createExpectTypeMethod(TypeData expectedType, TypeData sourceType) { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), expectedType.getPrimitiveType(), TypeSystemCodeGenerator.expectTypeMethodName(expectedType)); - method.addParameter(new CodeVariableElement(sourceType.getPrimitiveType(), LOCAL_VALUE)); - method.addThrownType(context.getTruffleTypes().getUnexpectedValueException()); - - CodeTreeBuilder body = method.createBuilder(); - body.startIf().tree(check(expectedType, LOCAL_VALUE)).end().startBlock(); - body.startReturn().tree(cast(expectedType, LOCAL_VALUE)).end().end(); - body.end(); // if-block - body.startThrow().startNew(context.getTruffleTypes().getUnexpectedValueException()).string(LOCAL_VALUE).end().end(); - - return method; + private CodeExecutableElement createExpectTypeMethod(TypeMirror expectedType, TypeMirror sourceType) { + return createExpectMethod(Modifier.PUBLIC, typeSystem, sourceType, expectedType); } - } } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemNodeFactory.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemNodeFactory.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemNodeFactory.java Tue Apr 14 15:12:48 2015 +0200 @@ -50,8 +50,12 @@ } public static TypeMirror nodeType(TypeSystemData typeSystem) { - TypeMirror parentType = TypeSystemCodeGenerator.createTypeSystemGen(typeSystem); - return new GeneratedTypeMirror(getQualifiedName(parentType), typeName(typeSystem)); + if (typeSystem.isDefault()) { + return typeSystem.getContext().getType(SpecializationNode.class); + } else { + TypeMirror parentType = TypeSystemCodeGenerator.createTypeSystemGen(typeSystem); + return new GeneratedTypeMirror(getQualifiedName(parentType), typeName(typeSystem)); + } } public static String typeName(TypeSystemData typeSystem) { @@ -62,17 +66,17 @@ return "acceptAndExecute"; } - public static String executeName(TypeData type) { + public static String executeName(TypeMirror type) { if (type == null) { return acceptAndExecuteName(); - } else if (type.isGeneric()) { + } else if (ElementUtils.isObject(type)) { return "executeGeneric"; } else { - return "execute" + getTypeId(type.getBoxedType()); + return "execute" + getTypeId(type); } } - public static String voidBoxingExecuteName(TypeData type) { + public static String voidBoxingExecuteName(TypeMirror type) { return executeName(type) + "Void"; } @@ -85,7 +89,7 @@ clazz.add(GeneratorUtils.createSuperConstructor(context, clazz, constructor)); } - for (TypeData type : typeSystem.getTypes()) { + for (TypeMirror type : typeSystem.getLegacyTypes()) { clazz.add(createExecuteMethod(type)); if (GeneratorUtils.isTypeBoxingOptimized(options.voidBoxingOptimization(), type)) { clazz.add(createVoidBoxingExecuteMethod(type)); @@ -94,10 +98,10 @@ return clazz; } - private Element createVoidBoxingExecuteMethod(TypeData type) { - TypeData voidType = typeSystem.getVoidType(); + private Element createVoidBoxingExecuteMethod(TypeMirror type) { + TypeMirror voidType = context.getType(void.class); String methodName = voidBoxingExecuteName(type); - CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), voidType.getPrimitiveType(), methodName); + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), voidType, methodName); method.addParameter(new CodeVariableElement(context.getType(Frame.class), "frame")); CodeTreeBuilder builder = method.createBuilder(); @@ -110,21 +114,21 @@ return method; } - private Element createExecuteMethod(TypeData type) { - TypeData genericType = typeSystem.getGenericTypeData(); + private Element createExecuteMethod(TypeMirror type) { + TypeMirror genericType = context.getType(Object.class); String methodName = executeName(type); - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), methodName); + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type, methodName); method.addParameter(new CodeVariableElement(context.getType(Frame.class), "frame")); - if (type.isGeneric()) { + if (ElementUtils.isObject(type)) { method.getModifiers().add(ABSTRACT); } else { CodeTreeBuilder builder = method.createBuilder(); CodeTree executeGeneric = builder.create().startCall(executeName(genericType)).string("frame").end().build(); - if (!type.isVoid()) { + if (!ElementUtils.isVoid(type)) { method.getThrownTypes().add(context.getType(UnexpectedResultException.class)); } - builder.startReturn().tree(TypeSystemCodeGenerator.expect(type, executeGeneric)).end(); + builder.startReturn().tree(TypeSystemCodeGenerator.expect(typeSystem, type, executeGeneric)).end(); } return method; diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java Tue Apr 14 15:12:48 2015 +0200 @@ -225,8 +225,14 @@ } public static boolean isAssignable(TypeMirror from, TypeMirror to) { + if (typeEquals(from, to)) { + return true; + } else if (isVoid(to)) { + return true; + } else if (isObject(to)) { + return true; + } ProcessorContext context = ProcessorContext.getInstance(); - if (!(from instanceof CodeTypeMirror) && !(to instanceof CodeTypeMirror)) { return context.getEnvironment().getTypeUtils().isAssignable(context.reloadType(from), context.reloadType(to)); } else { @@ -1122,4 +1128,82 @@ throw new AssertionError("unsupported element type"); } } + + public static List sortTypes(List list) { + Collections.sort(list, new Comparator() { + public int compare(TypeMirror o1, TypeMirror o2) { + return compareType(o1, o2); + } + }); + return list; + } + + public static int compareType(TypeMirror signature1, TypeMirror signature2) { + if (signature1 == null) { + return 1; + } else if (signature2 == null) { + return -1; + } + + if (ElementUtils.typeEquals(signature1, signature2)) { + return 0; + } + + if (signature1.getKind() == TypeKind.DECLARED && signature2.getKind() == TypeKind.DECLARED) { + TypeElement element1 = ElementUtils.fromTypeMirror(signature1); + TypeElement element2 = ElementUtils.fromTypeMirror(signature2); + + if (ElementUtils.getDirectSuperTypes(element1).contains(element2)) { + return -1; + } else if (ElementUtils.getDirectSuperTypes(element2).contains(element1)) { + return 1; + } + } + return ElementUtils.getSimpleName(signature1).compareTo(ElementUtils.getSimpleName(signature2)); + } + + public static List uniqueSortedTypes(Collection types) { + if (types.isEmpty()) { + return Collections.emptyList(); + } else if (types.size() <= 1) { + if (types instanceof List) { + return (List) types; + } else { + return new ArrayList<>(types); + } + } + Map sourceTypes = new HashMap<>(); + for (TypeMirror type : types) { + sourceTypes.put(ElementUtils.getTypeId(type), type); + } + return sortTypes(new ArrayList<>(sourceTypes.values())); + } + + public static int compareMethod(ExecutableElement method1, ExecutableElement method2) { + List parameters1 = method1.getParameters(); + List parameters2 = method2.getParameters(); + if (parameters1.size() != parameters2.size()) { + return Integer.compare(parameters1.size(), parameters2.size()); + } + + int result = 0; + for (int i = 0; i < parameters1.size(); i++) { + VariableElement var1 = parameters1.get(i); + VariableElement var2 = parameters2.get(i); + result = compareType(var1.asType(), var2.asType()); + if (result != 0) { + return result; + } + } + + result = method1.getSimpleName().toString().compareTo(method2.getSimpleName().toString()); + if (result == 0) { + // if still no difference sort by enclosing type name + TypeElement enclosingType1 = ElementUtils.findNearestEnclosingType(method1); + TypeElement enclosingType2 = ElementUtils.findNearestEnclosingType(method2); + result = enclosingType1.getQualifiedName().toString().compareTo(enclosingType2.getQualifiedName().toString()); + } + return result; + } + } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeExecutableElement.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeExecutableElement.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeExecutableElement.java Tue Apr 14 15:12:48 2015 +0200 @@ -58,6 +58,14 @@ } } + public void setVisibility(Modifier visibility) { + ElementUtils.setVisibility(getModifiers(), visibility); + } + + public Modifier getVisibility() { + return ElementUtils.getVisibility(getModifiers()); + } + /* Support JDK8 langtools. */ public boolean isDefault() { return false; diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java Tue Apr 14 15:12:48 2015 +0200 @@ -22,67 +22,111 @@ */ package com.oracle.truffle.dsl.processor.model; +import java.util.*; + import javax.lang.model.element.*; +import javax.lang.model.type.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.dsl.processor.*; import com.oracle.truffle.dsl.processor.java.*; -public class ExecutableTypeData extends TemplateMethod { +public class ExecutableTypeData extends MessageContainer implements Comparable { - private final TypeSystemData typeSystem; - private final TypeData type; + private final ExecutableElement method; + private final TypeMirror frameParameter; + private final List evaluatedParameters; + + public ExecutableTypeData(ExecutableElement method, int signatureSize, List frameTypes) { + this.method = method; + TypeMirror foundFrameParameter = null; + List parameters = method.getParameters(); - public ExecutableTypeData(TemplateMethod method, ExecutableElement executable, TypeSystemData typeSystem, TypeData type) { - super(method, executable); - this.typeSystem = typeSystem; - this.type = type; - if (executable.getParameters().size() < method.getMethod().getParameters().size()) { - throw new IllegalArgumentException(String.format("Method parameter count mismatch %s != %s.", executable.getParameters(), method.getMethod().getParameters())); + int parameterIndex = 0; + evaluatedParameters = new ArrayList<>(); + if (!parameters.isEmpty()) { + TypeMirror firstParameter = parameters.get(0).asType(); + for (TypeMirror frameType : frameTypes) { + if (ElementUtils.typeEquals(firstParameter, frameType)) { + foundFrameParameter = firstParameter; + parameterIndex++; + break; + } + } } + + int numberParameters = Math.max(parameters.size() - parameterIndex, signatureSize); + for (int i = 0; i < numberParameters; i++) { + TypeMirror parameter; + if (method.isVarArgs() && parameterIndex >= parameters.size() - 1) { + ArrayType varArgsArray = (ArrayType) parameters.get(parameters.size() - 1).asType(); + parameter = varArgsArray.getComponentType(); + } else if (parameterIndex < parameters.size()) { + parameter = parameters.get(parameterIndex).asType(); + } else { + break; + } + parameterIndex++; + evaluatedParameters.add(parameter); + } + this.frameParameter = foundFrameParameter; } - public TypeData getType() { - return type; + public ExecutableElement getMethod() { + return method; + } + + public String getName() { + return method.getSimpleName().toString(); + } + + @Override + public Element getMessageElement() { + return method; + } + + public List getEvaluatedParameters() { + return evaluatedParameters; } - public TypeSystemData getTypeSystem() { - return typeSystem; + public int getVarArgsIndex(int parameterIndex) { + if (method.isVarArgs()) { + int index = parameterIndex - (method.getParameters().size() - 1); + return index; + } + return -1; + } + + public int getParameterIndex(int signatureIndex) { + return frameParameter != null ? signatureIndex + 1 : signatureIndex; + } + + public TypeMirror getFrameParameter() { + return frameParameter; + } + + public TypeMirror getReturnType() { + return method.getReturnType(); } public boolean hasUnexpectedValue(ProcessorContext context) { - return ElementUtils.canThrowType(getMethod().getThrownTypes(), context.getType(UnexpectedResultException.class)); + return ElementUtils.canThrowType(method.getThrownTypes(), context.getType(UnexpectedResultException.class)); } public boolean isFinal() { - return getMethod().getModifiers().contains(Modifier.FINAL); + return method.getModifiers().contains(Modifier.FINAL); } public boolean isAbstract() { - return getMethod().getModifiers().contains(Modifier.ABSTRACT); + return method.getModifiers().contains(Modifier.ABSTRACT); } public int getEvaluatedCount() { - int count = 0; - for (Parameter parameter : getParameters()) { - if (parameter.getSpecification().isSignature()) { - count++; - } - } - return count; + return evaluatedParameters.size(); } - @Override - public int hashCode() { - return type.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof ExecutableTypeData) { - return type.equals(((ExecutableTypeData) obj).type); - } - return super.equals(obj); + public int compareTo(ExecutableTypeData o) { + return ElementUtils.compareMethod(method, o.getMethod()); } } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ImplicitCastData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ImplicitCastData.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ImplicitCastData.java Tue Apr 14 15:12:48 2015 +0200 @@ -22,35 +22,29 @@ */ package com.oracle.truffle.dsl.processor.model; +import javax.lang.model.type.*; + public class ImplicitCastData extends TemplateMethod { - private final TypeData sourceType; - private final TypeData targetType; + private final TypeMirror sourceType; + private final TypeMirror targetType; - public ImplicitCastData(TemplateMethod method, TypeData sourceType, TypeData targetType) { + public ImplicitCastData(TemplateMethod method, TypeMirror sourceType, TypeMirror targetType) { super(method); this.sourceType = sourceType; this.targetType = targetType; } - public TypeData getSourceType() { + public TypeMirror getSourceType() { return sourceType; } - public TypeData getTargetType() { + public TypeMirror getTargetType() { return targetType; } @Override public int compareTo(TemplateMethod o) { - if (o instanceof ImplicitCastData && sourceType != null) { - // implicit casts are ordered by source type since - // its also the order in which they are checked. - TypeData otherSourceType = ((ImplicitCastData) o).getSourceType(); - if (otherSourceType != null) { - return this.sourceType.compareTo(otherSourceType); - } - } return super.compareTo(o); } } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MethodSpec.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MethodSpec.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MethodSpec.java Tue Apr 14 15:12:48 2015 +0200 @@ -103,8 +103,8 @@ int defIndex = 0; for (ParameterSpec spec : getAll()) { - List allowedTypes = spec.getAllowedTypes(); - List types = spec.getAllowedTypes(); + Collection allowedTypes = spec.getAllowedTypes(); + Collection types = spec.getAllowedTypes(); if (types != null && allowedTypes.size() > 1) { TypeDef foundDef = null; for (TypeDef def : typeDefs) { @@ -189,7 +189,7 @@ if (foundTypeDef != null) { builder.append("<" + foundTypeDef.getName() + ">"); } else if (spec.getAllowedTypes().size() >= 1) { - builder.append(ElementUtils.getSimpleName(spec.getAllowedTypes().get(0))); + builder.append(ElementUtils.getSimpleName(spec.getAllowedTypes().iterator().next())); } else { builder.append("void"); } @@ -207,15 +207,15 @@ static final class TypeDef { - private final List types; + private final Collection types; private final String name; - private TypeDef(List types, String name) { + private TypeDef(Collection types, String name) { this.types = types; this.name = name; } - public List getTypes() { + public Collection getTypes() { return types; } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeChildData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeChildData.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeChildData.java Tue Apr 14 15:12:48 2015 +0200 @@ -74,7 +74,7 @@ this.executeWith = executeWith; } - public ExecutableTypeData findExecutableType(TypeData targetType) { + public ExecutableTypeData findExecutableType(TypeMirror targetType) { return childNode.findExecutableType(targetType, getExecuteWith().size()); } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java Tue Apr 14 15:12:48 2015 +0200 @@ -63,7 +63,7 @@ this.fields = new ArrayList<>(); this.children = new ArrayList<>(); this.childExecutions = new ArrayList<>(); - this.thisExecution = new NodeExecutionData(new NodeChildData(null, null, "this", getNodeType(), getNodeType(), null, Cardinality.ONE), -1, false); + this.thisExecution = new NodeExecutionData(new NodeChildData(null, null, "this", getNodeType(), getNodeType(), null, Cardinality.ONE), -1, -1, false); this.thisExecution.getChild().setNode(this); this.generateFactory = generateFactory; } @@ -105,15 +105,15 @@ return childExecutions; } - public Set findSpecializedTypes(NodeExecutionData execution) { - Set types = new HashSet<>(); + public Set findSpecializedTypes(NodeExecutionData execution) { + Set types = new HashSet<>(); for (SpecializationData specialization : getSpecializations()) { if (!specialization.isSpecialized()) { continue; } List parameters = specialization.findByExecutionData(execution); for (Parameter parameter : parameters) { - TypeData type = parameter.getTypeSystemType(); + TypeMirror type = parameter.getType(); if (type == null) { throw new AssertionError(); } @@ -123,13 +123,13 @@ return types; } - public Collection findSpecializedReturnTypes() { - Set types = new HashSet<>(); + public Collection findSpecializedReturnTypes() { + Set types = new HashSet<>(); for (SpecializationData specialization : getSpecializations()) { if (!specialization.isSpecialized()) { continue; } - types.add(specialization.getReturnType().getTypeSystemType()); + types.add(specialization.getReturnType().getType()); } return types; } @@ -233,7 +233,7 @@ public boolean supportsFrame() { if (executableTypes != null) { for (ExecutableTypeData execType : getExecutableTypes(-1)) { - if (execType.findParameter(TemplateMethod.FRAME_NAME) == null) { + if (execType.getFrameParameter() == null) { return false; } } @@ -258,7 +258,7 @@ } for (NodeExecutionData execution : childExecutions) { - if (execution.getName().equals(childName) && (execution.getIndex() == -1 || execution.getIndex() == index)) { + if (execution.getName().equals(childName) && (execution.getChildIndex() == -1 || execution.getChildIndex() == index)) { return execution; } } @@ -284,17 +284,25 @@ return enclosingNodes; } - public List getAllTemplateMethods() { - List methods = new ArrayList<>(); + public List getAllTemplateMethods() { + List methods = new ArrayList<>(); for (SpecializationData specialization : getSpecializations()) { - methods.add(specialization); + methods.add(specialization.getMethod()); + } + + for (ExecutableTypeData execType : getExecutableTypes()) { + methods.add(execType.getMethod()); } - methods.addAll(getExecutableTypes()); - methods.addAll(getShortCircuits()); + for (ShortCircuitData shortcircuit : getShortCircuits()) { + methods.add(shortcircuit.getMethod()); + } + if (getCasts() != null) { - methods.addAll(getCasts()); + for (CreateCastData castData : getCasts()) { + methods.add(castData.getMethod()); + } } return methods; @@ -303,13 +311,13 @@ public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context, int evaluatedCount) { List types = findGenericExecutableTypes(context, evaluatedCount); for (ExecutableTypeData type : types) { - if (type.getType().isGeneric()) { + if (context.isType(type.getReturnType(), Object.class)) { return type; } } for (ExecutableTypeData type : types) { - if (!type.getType().isVoid()) { + if (!context.isType(type.getReturnType(), void.class)) { return type; } } @@ -349,9 +357,9 @@ return types; } - public ExecutableTypeData findExecutableType(TypeData prmitiveType, int evaluatedCount) { + public ExecutableTypeData findExecutableType(TypeMirror primitiveType, int evaluatedCount) { for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) { - if (ElementUtils.typeEquals(type.getType().getPrimitiveType(), prmitiveType.getPrimitiveType())) { + if (ElementUtils.typeEquals(type.getReturnType(), primitiveType)) { return type; } } @@ -496,6 +504,14 @@ return shortCircuits; } + public int getMinimalEvaluatedParameters() { + int minimalEvaluatedParameters = Integer.MAX_VALUE; + for (ExecutableTypeData type : getExecutableTypes()) { + minimalEvaluatedParameters = Math.min(minimalEvaluatedParameters, type.getEvaluatedCount()); + } + return minimalEvaluatedParameters; + } + public void setExecutableTypes(Map> executableTypes) { this.executableTypes = executableTypes; } @@ -520,4 +536,29 @@ return getNodeId().compareTo(o.getNodeId()); } + public List getPossibleTypes(NodeExecutionData execution) { + List types = new ArrayList<>(); + + // add types possible through return types and evaluated parameters in execute methods + if (execution.getChild() != null) { + for (ExecutableTypeData executable : execution.getChild().getNodeData().getExecutableTypes()) { + if (executable.hasUnexpectedValue(getContext())) { + continue; + } + types.add(executable.getReturnType()); + } + } + + int executionIndex = execution.getIndex(); + if (executionIndex >= 0) { + for (ExecutableTypeData typeData : getExecutableTypes()) { + if (executionIndex < typeData.getEvaluatedCount()) { + types.add(typeData.getEvaluatedParameters().get(executionIndex)); + } + } + } + + return ElementUtils.uniqueSortedTypes(types); + } + } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeExecutionData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeExecutionData.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeExecutionData.java Tue Apr 14 15:12:48 2015 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.truffle.dsl.processor.model; +import java.util.*; + import javax.lang.model.type.*; import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality; @@ -31,17 +33,28 @@ private final NodeChildData child; private final String name; private final int index; + private final int childIndex; private final boolean shortCircuit; + private final List typeRestrictions = new ArrayList<>(); - public NodeExecutionData(NodeChildData child, int index, boolean shortCircuit) { + public NodeExecutionData(NodeChildData child, int index, int childIndex, boolean shortCircuit) { this.child = child; this.index = index; + this.childIndex = childIndex; this.shortCircuit = shortCircuit; this.name = createName(); } private String createName() { - return createName(child.getName(), index); + return child != null ? createName(child.getName(), childIndex) : ("arg" + index); + } + + public int getIndex() { + return index; + } + + public List getTypeRestrictions() { + return typeRestrictions; } public TypeMirror getNodeType() { @@ -62,12 +75,12 @@ return child; } - public int getIndex() { - return index; + public int getChildIndex() { + return childIndex; } public boolean isIndexed() { - return index > -1; + return childIndex > -1; } public boolean isShortCircuit() { @@ -75,7 +88,7 @@ } public String getIndexedName() { - return createIndexedName(child, index); + return createIndexedName(child, childIndex); } public static String createIndexedName(NodeChildData child, int varArgsIndex) { diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java Tue Apr 14 15:12:48 2015 +0200 @@ -28,19 +28,17 @@ public final class Parameter { private final ParameterSpec specification; - private TypeData typeSystemType; private TemplateMethod method; private String localName; private final int specificationVarArgsIndex; private final int typeVarArgsIndex; - private final VariableElement variableElement; + private final TypeMirror type; public Parameter(ParameterSpec specification, VariableElement variableElement, int specificationVarArgsIndex, int typeVarArgsIndex) { this.specification = specification; this.variableElement = variableElement; - this.typeSystemType = null; - + this.type = variableElement.asType(); this.specificationVarArgsIndex = specificationVarArgsIndex; String valueName = specification.getName() + "Value"; @@ -51,22 +49,22 @@ this.localName = valueName; } - public Parameter(ParameterSpec specification, TypeData actualType, VariableElement variableElement, int specificationIndex, int varArgsIndex) { - this(specification, variableElement, specificationIndex, varArgsIndex); - this.typeSystemType = actualType; - } - - public Parameter(Parameter parameter, TypeData otherType) { - this(parameter.specification, otherType, parameter.variableElement, parameter.specificationVarArgsIndex, parameter.typeVarArgsIndex); - } - public Parameter(Parameter parameter) { this.specification = parameter.specification; - this.typeSystemType = parameter.typeSystemType; this.specificationVarArgsIndex = parameter.specificationVarArgsIndex; this.localName = parameter.localName; this.typeVarArgsIndex = parameter.typeVarArgsIndex; this.variableElement = parameter.variableElement; + this.type = parameter.type; + } + + public Parameter(Parameter parameter, TypeMirror newType) { + this.specification = parameter.specification; + this.specificationVarArgsIndex = parameter.specificationVarArgsIndex; + this.localName = parameter.localName; + this.typeVarArgsIndex = parameter.typeVarArgsIndex; + this.variableElement = parameter.variableElement; + this.type = newType; } public void setLocalName(String localName) { @@ -102,11 +100,7 @@ } public TypeMirror getType() { - return variableElement.asType(); - } - - public TypeData getTypeSystemType() { - return typeSystemType; + return type; } public boolean isTypeVarArgs() { diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java Tue Apr 14 15:12:48 2015 +0200 @@ -33,45 +33,46 @@ public class ParameterSpec { private final String name; - private final List allowedTypes; - private final Set allowedTypesIdentifier; + private final Collection allowedTypes; + private final boolean anyType; /** Type is bound to local final variable. */ private boolean local; private boolean signature; + private boolean allowSubclasses = true; /** Optional bound execution of node. */ private NodeExecutionData execution; private TypeDef typeDefinition; - public ParameterSpec(String name, List allowedTypes, Set typeIdentifiers) { + public ParameterSpec(String name, Collection allowedTypes) { this.name = name; this.allowedTypes = allowedTypes; - this.allowedTypesIdentifier = typeIdentifiers; + boolean anyTypeTemp = false; + for (TypeMirror type : allowedTypes) { + if (ElementUtils.isObject(type)) { + anyTypeTemp = true; + break; + } + } + this.anyType = anyTypeTemp; } - public ParameterSpec(String name, List allowedTypes) { - this.name = name; - this.allowedTypes = allowedTypes; - Set typeIdentifiers = new HashSet<>(); - for (TypeMirror type : allowedTypes) { - typeIdentifiers.add(ElementUtils.getUniqueIdentifier(type)); - } - this.allowedTypesIdentifier = typeIdentifiers; + public ParameterSpec(ParameterSpec original, TypeMirror newType) { + this(original.name, newType); + this.local = original.local; + this.signature = original.signature; + this.execution = original.execution; + this.typeDefinition = original.typeDefinition; + this.allowSubclasses = original.allowSubclasses; } public ParameterSpec(String name, TypeMirror type) { - this(name, Arrays.asList(type), new HashSet<>(Arrays.asList(ElementUtils.getUniqueIdentifier(type)))); + this(name, Arrays.asList(type)); } - public ParameterSpec(ParameterSpec o, List allowedTypes, Set typeIdentifiers) { - this.name = o.name; - this.local = o.local; - this.typeDefinition = o.typeDefinition; - this.execution = o.execution; - this.signature = o.signature; - this.allowedTypes = allowedTypes; - this.allowedTypesIdentifier = typeIdentifiers; + public void setAllowSubclasses(boolean allowSubclasses) { + this.allowSubclasses = allowSubclasses; } public NodeExecutionData getExecution() { @@ -111,15 +112,28 @@ return name; } - public List getAllowedTypes() { + public Collection getAllowedTypes() { return allowedTypes; } public boolean matches(VariableElement variable) { - if (allowedTypesIdentifier != null) { - return allowedTypesIdentifier.contains(ElementUtils.getUniqueIdentifier(variable.asType())); + if (anyType) { + return true; + } else { + for (TypeMirror type : allowedTypes) { + if (ElementUtils.typeEquals(variable.asType(), type)) { + return true; + } + } + if (allowSubclasses) { + for (TypeMirror type : allowedTypes) { + if (ElementUtils.isAssignable(variable.asType(), type)) { + return true; + } + } + } } - return true; + return false; } @Override @@ -132,7 +146,7 @@ if (typeDefinition != null) { builder.append("<" + typeDefinition.getName() + ">"); } else if (getAllowedTypes().size() >= 1) { - builder.append(ElementUtils.getSimpleName(getAllowedTypes().get(0))); + builder.append(ElementUtils.getSimpleName(getAllowedTypes().iterator().next())); } else { builder.append("void"); } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java Tue Apr 14 15:12:48 2015 +0200 @@ -25,6 +25,7 @@ import java.util.*; import javax.lang.model.element.*; +import javax.lang.model.type.*; import com.oracle.truffle.dsl.processor.*; import com.oracle.truffle.dsl.processor.expression.*; @@ -201,17 +202,18 @@ for (Parameter parameter : getSignatureParameters()) { NodeChildData child = parameter.getSpecification().getExecution().getChild(); - ExecutableTypeData type = child.findExecutableType(parameter.getTypeSystemType()); - if (type == null) { - type = child.findAnyGenericExecutableType(context); + if (child != null) { + ExecutableTypeData type = child.findExecutableType(parameter.getType()); + if (type == null) { + type = child.findAnyGenericExecutableType(context); + } + if (type.hasUnexpectedValue(context)) { + return true; + } + if (ElementUtils.needsCastTo(type.getReturnType(), parameter.getType())) { + return true; + } } - if (type.hasUnexpectedValue(context)) { - return true; - } - if (type.getReturnType().getTypeSystemType().needsCastTo(parameter.getTypeSystemType())) { - return true; - } - } return false; } @@ -356,11 +358,12 @@ Iterator currentSignature = getSignatureParameters().iterator(); Iterator prevSignature = prev.getSignatureParameters().iterator(); + TypeSystemData typeSystem = prev.getNode().getTypeSystem(); while (currentSignature.hasNext() && prevSignature.hasNext()) { - TypeData currentType = currentSignature.next().getTypeSystemType(); - TypeData prevType = prevSignature.next().getTypeSystemType(); + TypeMirror currentType = currentSignature.next().getType(); + TypeMirror prevType = prevSignature.next().getType(); - if (!currentType.isImplicitSubtypeOf(prevType)) { + if (!typeSystem.isImplicitSubtypeOf(currentType, prevType)) { return true; } } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java Tue Apr 14 15:12:48 2015 +0200 @@ -228,9 +228,9 @@ public TypeSignature getTypeSignature() { TypeSignature signature = new TypeSignature(); - signature.types.add(getReturnType().getTypeSystemType()); + signature.types.add(getReturnType().getType()); for (Parameter parameter : getSignatureParameters()) { - TypeData typeData = parameter.getTypeSystemType(); + TypeMirror typeData = parameter.getType(); if (typeData != null) { signature.types.add(typeData); } @@ -250,8 +250,8 @@ if (signatureIndex >= signature.size()) { break; } - TypeData newType = signature.get(signatureIndex++); - if (!parameter.getTypeSystemType().equals(newType)) { + TypeMirror newType = signature.get(signatureIndex++); + if (!ElementUtils.typeEquals(newType, parameter.getType())) { replaceParameter(parameter.getLocalName(), new Parameter(parameter, newType)); } } @@ -278,11 +278,6 @@ } public int compareBySignature(TemplateMethod compareMethod) { - final TypeSystemData typeSystem = getTemplate().getTypeSystem(); - if (typeSystem != compareMethod.getTemplate().getTypeSystem()) { - throw new IllegalStateException("Cannot compare two methods with different type systems."); - } - List signature1 = getSignatureTypes(this); List signature2 = getSignatureTypes(compareMethod); @@ -290,7 +285,7 @@ for (int i = 0; i < Math.max(signature1.size(), signature2.size()); i++) { TypeMirror t1 = i < signature1.size() ? signature1.get(i) : null; TypeMirror t2 = i < signature2.size() ? signature2.get(i) : null; - result = compareParameter(typeSystem, t1, t2); + result = ElementUtils.compareType(t1, t2); if (result != 0) { break; } @@ -299,37 +294,6 @@ return result; } - protected static int compareParameter(TypeSystemData data, TypeMirror signature1, TypeMirror signature2) { - if (signature1 == null) { - return 1; - } else if (signature2 == null) { - return -1; - } - - if (ElementUtils.typeEquals(signature1, signature2)) { - return 0; - } - - int index1 = data.findType(signature1); - int index2 = data.findType(signature2); - if (index1 != -1 && index2 != -1) { - return index1 - index2; - } - - // TODO this version if subclass of should be improved. - if (signature1.getKind() == TypeKind.DECLARED && signature2.getKind() == TypeKind.DECLARED) { - TypeElement element1 = ElementUtils.fromTypeMirror(signature1); - TypeElement element2 = ElementUtils.fromTypeMirror(signature2); - - if (ElementUtils.getDirectSuperTypes(element1).contains(element2)) { - return -1; - } else if (ElementUtils.getDirectSuperTypes(element2).contains(element1)) { - return 1; - } - } - return ElementUtils.getSimpleName(signature1).compareTo(ElementUtils.getSimpleName(signature2)); - } - public static List getSignatureTypes(TemplateMethod method) { List types = new ArrayList<>(); for (Parameter param : method.getSignatureParameters()) { @@ -338,15 +302,15 @@ return types; } - public static class TypeSignature implements Iterable, Comparable { + public static class TypeSignature implements Iterable { - private final List types; + private final List types; public TypeSignature() { this.types = new ArrayList<>(); } - public TypeSignature(List signature) { + public TypeSignature(List signature) { this.types = signature; } @@ -359,32 +323,10 @@ return types.size(); } - public TypeData get(int index) { + public TypeMirror get(int index) { return types.get(index); } - public int compareTo(TypeSignature other) { - if (this == other) { - return 0; - } else if (types.size() != other.types.size()) { - return types.size() - other.types.size(); - } else if (types.isEmpty()) { - return 0; - } - - for (int i = 0; i < types.size(); i++) { - TypeData type1 = types.get(i); - TypeData type2 = other.types.get(i); - - int comparison = type1.compareTo(type2); - if (comparison != 0) { - return comparison; - } - } - - return 0; - } - @Override public boolean equals(Object obj) { if (obj instanceof TypeSignature) { @@ -393,7 +335,7 @@ return super.equals(obj); } - public Iterator iterator() { + public Iterator iterator() { return types.iterator(); } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCastData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCastData.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCastData.java Tue Apr 14 15:12:48 2015 +0200 @@ -22,26 +22,24 @@ */ package com.oracle.truffle.dsl.processor.model; +import javax.lang.model.type.*; + public class TypeCastData extends TemplateMethod { - private final TypeData targetType; - private final TypeData sourceType; + private final TypeMirror targetType; + private final TypeMirror sourceType; - public TypeCastData(TemplateMethod method, TypeData sourceType, TypeData targetType) { + public TypeCastData(TemplateMethod method, TypeMirror sourceType, TypeMirror targetType) { super(method); this.sourceType = sourceType; this.targetType = targetType; } - public boolean isGeneric() { - return sourceType.isGeneric(); - } - - public TypeData getSourceType() { + public TypeMirror getSourceType() { return sourceType; } - public TypeData getTargetType() { + public TypeMirror getTargetType() { return targetType; } } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCheckData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCheckData.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCheckData.java Tue Apr 14 15:12:48 2015 +0200 @@ -22,26 +22,24 @@ */ package com.oracle.truffle.dsl.processor.model; +import javax.lang.model.type.*; + public class TypeCheckData extends TemplateMethod { - private final TypeData checkedType; - private final TypeData valueType; + private final TypeMirror checkedType; + private final TypeMirror valueType; - public TypeCheckData(TemplateMethod method, TypeData checkedType, TypeData valueType) { + public TypeCheckData(TemplateMethod method, TypeMirror checkedType, TypeMirror valueType) { super(method); this.checkedType = checkedType; this.valueType = valueType; } - public boolean isGeneric() { - return valueType.isGeneric(); - } - - public TypeData getCheckedType() { + public TypeMirror getCheckedType() { return checkedType; } - public TypeData getValueType() { + public TypeMirror getValueType() { return valueType; } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeData.java Tue Apr 14 22:12:03 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,181 +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.model; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.java.*; - -public class TypeData extends MessageContainer implements Comparable { - - private final TypeSystemData typeSystem; - private final AnnotationValue annotationValue; - private final TypeMirror primitiveType; - private final TypeMirror boxedType; - - private final int index; - private final List typeCasts = new ArrayList<>(); - private final List typeChecks = new ArrayList<>(); - - public TypeData(TypeSystemData typeSystem, int index, AnnotationValue value, TypeMirror primitiveType, TypeMirror boxedType) { - this.index = index; - this.typeSystem = typeSystem; - this.annotationValue = value; - this.primitiveType = primitiveType; - this.boxedType = boxedType; - } - - public int getIndex() { - return index; - } - - public boolean isDefaultCast() { - return getTypeCasts().isEmpty(); - } - - public boolean isDefaultCheck() { - return getTypeChecks().isEmpty(); - } - - @Override - public Element getMessageElement() { - return typeSystem.getMessageElement(); - } - - @Override - public AnnotationMirror getMessageAnnotation() { - return typeSystem.getMessageAnnotation(); - } - - @Override - public AnnotationValue getMessageAnnotationValue() { - return annotationValue; - } - - public void addTypeCast(TypeCastData typeCast) { - this.typeCasts.add(typeCast); - } - - public void addTypeCheck(TypeCheckData typeCheck) { - this.typeChecks.add(typeCheck); - } - - public List getTypeCasts() { - return typeCasts; - } - - public List getTypeChecks() { - return typeChecks; - } - - public TypeSystemData getTypeSystem() { - return typeSystem; - } - - public TypeMirror getPrimitiveType() { - return primitiveType; - } - - public TypeMirror getBoxedType() { - return boxedType; - } - - public boolean isGeneric() { - return ElementUtils.typeEquals(boxedType, getTypeSystem().getGenericType()); - } - - public boolean isVoid() { - if (getTypeSystem().getVoidType() == null) { - return false; - } - return ElementUtils.typeEquals(boxedType, getTypeSystem().getVoidType().getBoxedType()); - } - - public int compareTo(TypeData o) { - if (this.equals(o)) { - return 0; - } - return index - o.index; - } - - @Override - public int hashCode() { - return Objects.hash(index, primitiveType); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof TypeData)) { - return false; - } - TypeData otherType = (TypeData) obj; - return index == otherType.index && ElementUtils.typeEquals(primitiveType, otherType.primitiveType); - } - - @Override - public String toString() { - return getClass().getSimpleName() + "[" + ElementUtils.getSimpleName(primitiveType) + "]"; - } - - public boolean equalsType(TypeData actualTypeData) { - return ElementUtils.typeEquals(boxedType, actualTypeData.boxedType); - } - - public boolean needsCastTo(TypeData targetType) { - return ElementUtils.needsCastTo(getPrimitiveType(), targetType.getPrimitiveType()); - } - - public boolean needsCastTo(TypeMirror targetType) { - return ElementUtils.needsCastTo(getPrimitiveType(), targetType); - } - - public boolean isPrimitive() { - return ElementUtils.isPrimitive(getPrimitiveType()); - } - - public List getImplicitSourceTypes() { - return getTypeSystem().lookupSourceTypes(this); - } - - public boolean hasImplicitSourceTypes() { - return getTypeSystem().hasImplicitSourceTypes(this); - } - - public boolean isImplicitSubtypeOf(TypeData other) { - List casts = other.getTypeSystem().lookupByTargetType(other); - for (ImplicitCastData cast : casts) { - if (isSubtypeOf(cast.getSourceType())) { - return true; - } - } - return isSubtypeOf(other); - } - - public boolean isSubtypeOf(TypeData other) { - return ElementUtils.isSubtype(boxedType, other.boxedType); - } - -} diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java Tue Apr 14 15:12:48 2015 +0200 @@ -33,24 +33,24 @@ public class TypeSystemData extends Template { - private List types; - private List primitiveTypeMirrors = new ArrayList<>(); - private List boxedTypeMirrors = new ArrayList<>(); - private Map cachedTypes = new HashMap<>(); + private final List implicitCasts = new ArrayList<>(); + private final List casts = new ArrayList<>(); + private final List checks = new ArrayList<>(); + private final List legacyTypes = new ArrayList<>(); - private List implicitCasts; - private List casts; - private List checks; + private Set legacyTypeIds; - private TypeMirror genericType; - private TypeData booleanType; - private TypeData voidType; + private final boolean isDefault; + private final DSLOptions options; - private DSLOptions options; - - public TypeSystemData(ProcessorContext context, TypeElement templateType, AnnotationMirror annotation, DSLOptions options) { + public TypeSystemData(ProcessorContext context, TypeElement templateType, AnnotationMirror annotation, DSLOptions options, boolean isDefault) { super(context, templateType, annotation); this.options = options; + this.isDefault = isDefault; + } + + public boolean isDefault() { + return isDefault; } public DSLOptions getOptions() { @@ -62,48 +62,43 @@ return this; } - public void setTypes(List types) { - this.types = types; - if (types != null) { - for (TypeData typeData : types) { - primitiveTypeMirrors.add(typeData.getPrimitiveType()); - boxedTypeMirrors.add(typeData.getBoxedType()); - cachedTypes.put(ElementUtils.getUniqueIdentifier(typeData.getPrimitiveType()), typeData); - cachedTypes.put(ElementUtils.getUniqueIdentifier(typeData.getBoxedType()), typeData); + public List getLegacyTypes() { + return legacyTypes; + } + + public TypeCastData getCast(TypeMirror targetType) { + for (TypeCastData cast : casts) { + if (ElementUtils.typeEquals(cast.getTargetType(), targetType)) { + return cast; } } + return null; } - public void setImplicitCasts(List implicitCasts) { - this.implicitCasts = implicitCasts; + public TypeCheckData getCheck(TypeMirror type) { + for (TypeCheckData check : checks) { + if (ElementUtils.typeEquals(check.getCheckedType(), type)) { + return check; + } + } + return null; } public List getImplicitCasts() { return implicitCasts; } - public void setCasts(List casts) { - this.casts = casts; + public List getCasts() { + return casts; } - public void setChecks(List checks) { - this.checks = checks; - } - - public void setGenericType(TypeMirror genericType) { - this.genericType = genericType; - } - - public void setVoidType(TypeData voidType) { - this.voidType = voidType; + public List getChecks() { + return checks; } @Override protected List findChildContainers() { List sinks = new ArrayList<>(); - if (types != null) { - sinks.addAll(types); - } if (checks != null) { sinks.addAll(checks); } @@ -116,75 +111,25 @@ return sinks; } - public TypeData getVoidType() { - return voidType; - } - - public List getBoxedTypeMirrors() { - return boxedTypeMirrors; - } - - public List getPrimitiveTypeMirrors() { - return primitiveTypeMirrors; - } - - public Set getTypeIdentifiers() { - return cachedTypes.keySet(); - } - - public List getTypes() { - return types; - } - - public TypeMirror getGenericType() { - return genericType; + @Override + public String toString() { + return getClass().getSimpleName() + "[template = " + ElementUtils.getSimpleName(getTemplateType()) + "]"; } - public TypeData getGenericTypeData() { - TypeData result = types.get(types.size() - 2); - assert result.getBoxedType() == genericType; - return result; - } - - public TypeData findTypeData(TypeMirror type) { - if (ElementUtils.typeEquals(voidType.getPrimitiveType(), type)) { - return voidType; - } - - int index = findType(type); - if (index == -1) { - return null; - } - return types.get(index); - } - - public int findType(TypeMirror type) { - TypeData data = cachedTypes.get(ElementUtils.getUniqueIdentifier(type)); - if (data != null) { - return data.getIndex(); - } - return -1; - } - - @Override - public String toString() { - return getClass().getSimpleName() + "[template = " + ElementUtils.getSimpleName(getTemplateType()) + ", types = " + types + "]"; - } - - public List lookupByTargetType(TypeData targetType) { + public List lookupByTargetType(TypeMirror targetType) { if (getImplicitCasts() == null) { return Collections.emptyList(); } List foundCasts = new ArrayList<>(); for (ImplicitCastData cast : getImplicitCasts()) { - if (cast.getTargetType().equals(targetType)) { + if (ElementUtils.typeEquals(cast.getTargetType(), targetType)) { foundCasts.add(cast); } } return foundCasts; } - public ImplicitCastData lookupCast(TypeData sourceType, TypeData targetType) { + public ImplicitCastData lookupCast(TypeMirror sourceType, TypeMirror targetType) { if (getImplicitCasts() == null) { return null; } @@ -196,38 +141,59 @@ return null; } - public boolean hasImplicitSourceTypes(TypeData targetType) { + public boolean hasImplicitSourceTypes(TypeMirror targetType) { if (getImplicitCasts() == null) { return false; } for (ImplicitCastData cast : getImplicitCasts()) { - if (cast.getTargetType() == targetType) { + if (ElementUtils.typeEquals(cast.getTargetType(), targetType)) { return true; } } return false; } - public List lookupSourceTypes(TypeData type) { - List sourceTypes = new ArrayList<>(); - sourceTypes.add(type); - if (getImplicitCasts() != null) { - for (ImplicitCastData cast : getImplicitCasts()) { - if (cast.getTargetType() == type) { - sourceTypes.add(cast.getSourceType()); - } + public List lookupTargetTypes() { + List sourceTypes = new ArrayList<>(); + for (ImplicitCastData cast : getImplicitCasts()) { + sourceTypes.add(cast.getTargetType()); + } + return ElementUtils.uniqueSortedTypes(sourceTypes); + } + + public List lookupSourceTypes(TypeMirror targetType) { + List sourceTypes = new ArrayList<>(); + sourceTypes.add(targetType); + for (ImplicitCastData cast : getImplicitCasts()) { + if (ElementUtils.typeEquals(cast.getTargetType(), targetType)) { + sourceTypes.add(cast.getSourceType()); } } - Collections.sort(sourceTypes); return sourceTypes; } - public TypeData getBooleanType() { - return booleanType; + public boolean isImplicitSubtypeOf(TypeMirror source, TypeMirror target) { + List targetCasts = lookupByTargetType(target); + for (ImplicitCastData cast : targetCasts) { + if (ElementUtils.isSubtype(boxType(source), boxType(cast.getSourceType()))) { + return true; + } + } + return ElementUtils.isSubtype(boxType(source), boxType(target)); } - public void setBooleanType(TypeData booleanType) { - this.booleanType = booleanType; + public TypeMirror boxType(TypeMirror type) { + return ElementUtils.boxType(getContext(), type); + } + + public boolean hasType(TypeMirror type) { + if (legacyTypeIds == null) { + legacyTypeIds = new HashSet<>(); + for (TypeMirror legacyType : legacyTypes) { + legacyTypeIds.add(ElementUtils.getTypeId(legacyType)); + } + } + return legacyTypeIds.contains(ElementUtils.getTypeId(type)); } } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/CreateCastParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/CreateCastParser.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/CreateCastParser.java Tue Apr 14 15:12:48 2015 +0200 @@ -59,7 +59,7 @@ baseType = foundChild.getOriginalType(); } - MethodSpec spec = new MethodSpec(new InheritsParameterSpec("child", baseType)); + MethodSpec spec = new MethodSpec(new ParameterSpec("child", baseType)); addDefaultFieldMethodSpec(spec); ParameterSpec childSpec = new ParameterSpec("castedChild", baseType); childSpec.setSignature(true); @@ -96,22 +96,4 @@ return cast; } - private static class InheritsParameterSpec extends ParameterSpec { - - public InheritsParameterSpec(String name, TypeMirror... allowedTypes) { - super(name, Arrays.asList(allowedTypes), null); - } - - @Override - public boolean matches(VariableElement variable) { - boolean found = false; - for (TypeMirror specType : getAllowedTypes()) { - if (ElementUtils.isAssignable(variable.asType(), specType)) { - found = true; - break; - } - } - return found; - } - } } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java Tue Apr 14 22:12:03 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,122 +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.parser; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.java.*; -import com.oracle.truffle.dsl.processor.model.*; - -public class ExecutableTypeMethodParser extends NodeMethodParser { - - private final List frameTypes; - private final NodeChildData child; - - public ExecutableTypeMethodParser(ProcessorContext context, NodeData node, NodeChildData child, List frameTypes) { - super(context, node); - this.child = child; - this.frameTypes = frameTypes; - setParseNullOnError(false); - getParser().setEmitErrors(false); - getParser().setUseVarArgs(true); - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - MethodSpec spec = createDefaultMethodSpec(method, mirror, false, null); - List requiredSpecs = new ArrayList<>(spec.getRequired()); - spec.getRequired().clear(); - - TypeSystemData typeSystem = getNode().getTypeSystem(); - List allowedTypes = typeSystem.getPrimitiveTypeMirrors(); - Set allowedIdentifiers = typeSystem.getTypeIdentifiers(); - - if (child != null) { - for (NodeExecutionData executeWith : child.getExecuteWith()) { - ParameterSpec parameter = spec.addRequired(new ParameterSpec(executeWith.getName(), allowedTypes, allowedIdentifiers)); - parameter.setExecution(executeWith); - parameter.setSignature(true); - } - } else { - for (ParameterSpec originalSpec : requiredSpecs) { - spec.addRequired(new ParameterSpec(originalSpec, allowedTypes, allowedIdentifiers)); - } - } - - spec.setIgnoreAdditionalSpecifications(true); - spec.setIgnoreAdditionalParameters(true); - spec.setVariableRequiredParameters(true); - // varargs - ParameterSpec otherParameters = new ParameterSpec("other", allowedTypes, allowedIdentifiers); - otherParameters.setSignature(true); - spec.addRequired(otherParameters); - return spec; - } - - @Override - protected void addDefaultFrame(MethodSpec methodSpec) { - methodSpec.addOptional(new ParameterSpec("frame", frameTypes)); - } - - @Override - protected List nodeTypeMirrors(NodeData nodeData) { - return getNode().getTypeSystem().getPrimitiveTypeMirrors(); - } - - @Override - protected Set nodeTypeIdentifiers(NodeData nodeData) { - return getNode().getTypeSystem().getTypeIdentifiers(); - } - - @Override - public final boolean isParsable(ExecutableElement method) { - if (method.getModifiers().contains(Modifier.STATIC)) { - return false; - } else if (method.getModifiers().contains(Modifier.NATIVE)) { - return false; - } else if (ElementUtils.findAnnotationMirror(getContext().getEnvironment(), method, Specialization.class) != null) { - return false; - } else if (method.getModifiers().contains(Modifier.PRIVATE)) { - return false; - } - return method.getSimpleName().toString().startsWith("execute"); - } - - @Override - public ExecutableTypeData create(TemplateMethod method, boolean invalid) { - TypeData resolvedType = method.getReturnType().getTypeSystemType(); - return new ExecutableTypeData(method, method.getMethod(), getNode().getTypeSystem(), resolvedType); - } - - @Override - public Class getAnnotationType() { - return null; - } - -} diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GenericParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GenericParser.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GenericParser.java Tue Apr 14 15:12:48 2015 +0200 @@ -23,14 +23,11 @@ package com.oracle.truffle.dsl.processor.parser; import java.lang.annotation.*; -import java.util.*; import javax.lang.model.element.*; -import javax.lang.model.type.*; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.java.*; import com.oracle.truffle.dsl.processor.model.*; import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind; @@ -47,17 +44,9 @@ @Override protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) { - List execTypes = execution.getChild().findGenericExecutableTypes(getContext()); - List types = new ArrayList<>(); - Set typeIds = new HashSet<>(); - for (ExecutableTypeData type : execTypes) { - TypeMirror typeMirror = type.getType().getPrimitiveType(); - types.add(typeMirror); - typeIds.add(ElementUtils.getUniqueIdentifier(typeMirror)); - } - ParameterSpec spec = new ParameterSpec(execution.getName(), types, typeIds); - spec.setExecution(execution); - return spec; + ParameterSpec parameterSpec = super.createValueParameterSpec(execution); + parameterSpec.setAllowSubclasses(false); + return parameterSpec; } @Override diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ImplicitCastParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ImplicitCastParser.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ImplicitCastParser.java Tue Apr 14 15:12:48 2015 +0200 @@ -23,13 +23,13 @@ package com.oracle.truffle.dsl.processor.parser; import java.lang.annotation.*; -import java.util.*; import javax.lang.model.element.*; import javax.lang.model.type.*; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; import com.oracle.truffle.dsl.processor.model.*; public class ImplicitCastParser extends TypeSystemMethodParser { @@ -45,10 +45,8 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - List types = getTypeSystem().getPrimitiveTypeMirrors(); - Set identifiers = getTypeSystem().getTypeIdentifiers(); - MethodSpec spec = new MethodSpec(new ParameterSpec("target", types, identifiers)); - spec.addRequired(new ParameterSpec("source", types, identifiers)).setSignature(true); + MethodSpec spec = new MethodSpec(new ParameterSpec("target", getContext().getType(Object.class))); + spec.addRequired(new ParameterSpec("source", getContext().getType(Object.class))).setSignature(true); return spec; } @@ -61,10 +59,10 @@ Parameter target = method.findParameter("targetValue"); Parameter source = method.findParameter("sourceValue"); - TypeData targetType = target.getTypeSystemType(); - TypeData sourceType = source.getTypeSystemType(); + TypeMirror targetType = target.getType(); + TypeMirror sourceType = source.getType(); - if (targetType.equals(sourceType)) { + if (ElementUtils.typeEquals(targetType, sourceType)) { method.addError("Target type and source type of an @%s must not be the same type.", ImplicitCast.class.getSimpleName()); } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java Tue Apr 14 15:12:48 2015 +0200 @@ -48,10 +48,6 @@ return template; } - public TypeSystemData getTypeSystem() { - return template.getTypeSystem(); - } - public boolean isEmitErrors() { return emitErrors; } @@ -135,7 +131,7 @@ * end matching the required arguments, parsing fails. Parameters prior to the parsed required * ones are cut and used to parse the optional parameters. */ - private List parseParameters(MethodSpec spec, List parameterTypes, boolean varArgs) { + private static List parseParameters(MethodSpec spec, List parameterTypes, boolean varArgs) { List parsedRequired = null; int offset = 0; for (; offset <= parameterTypes.size(); offset++) { @@ -166,7 +162,7 @@ return finalParameters; } - private List parseParametersOptional(MethodSpec spec, List types) { + private static List parseParametersOptional(MethodSpec spec, List types) { List parsedParams = new ArrayList<>(); int typeStartIndex = 0; @@ -191,7 +187,7 @@ return parsedParams; } - private List parseParametersRequired(MethodSpec spec, List types, boolean typeVarArgs) { + private static List parseParametersRequired(MethodSpec spec, List types, boolean typeVarArgs) { List parsedParams = new ArrayList<>(); List specifications = spec.getRequired(); boolean specVarArgs = spec.isVariableRequiredParameters(); @@ -248,7 +244,7 @@ return parsedParams; } - private Parameter matchAnnotatedParameter(MethodSpec spec, VariableElement variable) { + private static Parameter matchAnnotatedParameter(MethodSpec spec, VariableElement variable) { for (ParameterSpec parameterSpec : spec.getAnnotations()) { if (parameterSpec.matches(variable)) { Parameter matchedParameter = matchParameter(parameterSpec, variable, -1, -1); @@ -286,7 +282,7 @@ } } - private Parameter matchParameter(ParameterSpec specification, VariableElement variable, int specificationIndex, int varArgsIndex) { + private static Parameter matchParameter(ParameterSpec specification, VariableElement variable, int specificationIndex, int varArgsIndex) { TypeMirror resolvedType = variable.asType(); if (hasError(resolvedType)) { return null; @@ -296,12 +292,6 @@ return null; } - TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType); - if (resolvedTypeData != null) { - return new Parameter(specification, resolvedTypeData, variable, specificationIndex, varArgsIndex); - } else { - return new Parameter(specification, variable, specificationIndex, varArgsIndex); - } + return new Parameter(specification, variable, specificationIndex, varArgsIndex); } - } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java Tue Apr 14 15:12:48 2015 +0200 @@ -42,26 +42,25 @@ } protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) { - NodeData childNode = execution.getChild().getNodeData(); - ParameterSpec spec = new ParameterSpec(execution.getName(), nodeTypeMirrors(childNode), nodeTypeIdentifiers(childNode)); + ParameterSpec spec = new ParameterSpec(execution.getName(), getPossibleParameterTypes(execution)); spec.setExecution(execution); return spec; } - protected List nodeTypeMirrors(NodeData nodeData) { - return nodeData.getTypeSystem().getPrimitiveTypeMirrors(); - } - - protected Set nodeTypeIdentifiers(NodeData nodeData) { - return nodeData.getTypeSystem().getTypeIdentifiers(); + protected Collection getPossibleParameterTypes(NodeExecutionData execution) { + return getNode().getPossibleTypes(execution); } protected ParameterSpec createReturnParameterSpec() { - ParameterSpec returnValue = new ParameterSpec("returnValue", nodeTypeMirrors(getNode()), nodeTypeIdentifiers(getNode())); + ParameterSpec returnValue = new ParameterSpec("returnValue", getPossibleReturnTypes()); returnValue.setExecution(getNode().getThisExecution()); return returnValue; } + protected Collection getPossibleReturnTypes() { + return getNode().getPossibleTypes(getNode().getThisExecution()); + } + @Override public boolean isParsable(ExecutableElement method) { if (getAnnotationType() != null) { diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java Tue Apr 14 15:12:48 2015 +0200 @@ -32,7 +32,7 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.dsl.NodeField; +import com.oracle.truffle.api.dsl.internal.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.dsl.processor.*; import com.oracle.truffle.dsl.processor.expression.*; @@ -45,6 +45,7 @@ import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind; import com.oracle.truffle.dsl.processor.model.TemplateMethod.TypeSignature; +@DSLOptions public class NodeParser extends AbstractParser { public static final List> ANNOTATIONS = Arrays.asList(Fallback.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, NodeChild.class, @@ -145,8 +146,8 @@ node.getFields().addAll(parseFields(lookupTypes, members)); node.getChildren().addAll(parseChildren(lookupTypes, members)); - node.getChildExecutions().addAll(parseExecutions(node.getChildren(), members)); - node.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, node, null, context.getFrameTypes()).parse(members))); + node.getChildExecutions().addAll(parseExecutions(node.getFields(), node.getChildren(), members)); + node.setExecutableTypes(groupExecutableTypes(parseExecutableTypeData(members, node.getChildExecutions().size(), context.getFrameTypes()))); initializeExecutableTypes(node); initializeImportGuards(node, lookupTypes, members); @@ -256,20 +257,19 @@ private NodeData parseNodeData(TypeElement templateType, List typeHierarchy) { AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); - if (typeSystemMirror == null) { - NodeData nodeData = new NodeData(context, templateType); - nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), ElementUtils.getQualifiedName(templateType)); - return nodeData; + TypeSystemData typeSystem = null; + if (typeSystemMirror != null) { + TypeMirror typeSystemType = ElementUtils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value"); + typeSystem = (TypeSystemData) context.getTemplate(typeSystemType, true); + if (typeSystem == null) { + NodeData nodeData = new NodeData(context, templateType); + nodeData.addError("The used type system '%s' is invalid. Fix errors in the type system first.", ElementUtils.getQualifiedName(typeSystemType)); + return nodeData; + } + } else { + // default dummy type system + typeSystem = new TypeSystemData(context, templateType, null, NodeParser.class.getAnnotation(DSLOptions.class), true); } - - TypeMirror typeSystemType = ElementUtils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value"); - final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSystemType, true); - if (typeSystem == null) { - NodeData nodeData = new NodeData(context, templateType); - nodeData.addError("The used type system '%s' is invalid. Fix errors in the type system first.", ElementUtils.getQualifiedName(typeSystemType)); - return nodeData; - } - AnnotationMirror nodeInfoMirror = findFirstAnnotation(typeHierarchy, NodeInfo.class); String shortName = null; if (nodeInfoMirror != null) { @@ -406,11 +406,7 @@ return filteredChildren; } - private List parseExecutions(List children, List elements) { - if (children == null) { - return null; - } - + private List parseExecutions(List fields, List children, List elements) { // pre-parse short circuits Set shortCircuits = new HashSet<>(); List methods = ElementFilter.methodsIn(elements); @@ -433,6 +429,13 @@ } } + List nonGetterFields = new ArrayList<>(); + for (NodeFieldData field : fields) { + if (field.getGetter() == null && field.isGenerated()) { + nonGetterFields.add(field); + } + } + TypeMirror cacheAnnotation = context.getType(Cached.class); List frameTypes = context.getFrameTypes(); // pre-parse specializations to find signature size @@ -443,34 +446,40 @@ } int currentArgumentIndex = 0; boolean skipShortCircuit = false; - outer: for (VariableElement var : method.getParameters()) { + parameter: for (VariableElement var : method.getParameters()) { + if (skipShortCircuit) { + skipShortCircuit = false; + continue parameter; + } TypeMirror type = var.asType(); if (currentArgumentIndex == 0) { // skip optionals for (TypeMirror frameType : frameTypes) { if (ElementUtils.typeEquals(type, frameType)) { - continue outer; + continue parameter; + } + } + } + + if (currentArgumentIndex < nonGetterFields.size()) { + for (NodeFieldData field : nonGetterFields) { + if (ElementUtils.typeEquals(var.asType(), field.getType())) { + continue parameter; } } } if (ElementUtils.findAnnotationMirror(var.getAnnotationMirrors(), cacheAnnotation) != null) { - continue outer; + continue parameter; } int childIndex = currentArgumentIndex < children.size() ? currentArgumentIndex : children.size() - 1; - if (childIndex == -1) { - continue; - } - if (!skipShortCircuit) { + if (childIndex != -1) { NodeChildData child = children.get(childIndex); if (shortCircuits.contains(NodeExecutionData.createIndexedName(child, currentArgumentIndex - childIndex))) { skipShortCircuit = true; - continue; } - } else { - skipShortCircuit = false; } currentArgumentIndex++; @@ -480,24 +489,65 @@ List executions = new ArrayList<>(); for (int i = 0; i < maxSignatureSize; i++) { + boolean varArgParameter = false; int childIndex = i; - boolean varArg = false; - if (childIndex >= children.size() - 1) { + if (i >= children.size() - 1) { if (hasVarArgs) { - childIndex = children.size() - 1; - varArg = hasVarArgs; - } else if (childIndex >= children.size()) { - break; + varArgParameter = hasVarArgs; + childIndex = Math.min(i, children.size() - 1); + } else if (i >= children.size()) { + childIndex = -1; } } - int varArgsIndex = varArg ? Math.abs(childIndex - i) : -1; - NodeChildData child = children.get(childIndex); - boolean shortCircuit = shortCircuits.contains(NodeExecutionData.createIndexedName(child, varArgsIndex)); - executions.add(new NodeExecutionData(child, varArgsIndex, shortCircuit)); + int varArgsIndex = -1; + boolean shortCircuit = false; + NodeChildData child = null; + if (childIndex != -1) { + varArgsIndex = varArgParameter ? Math.abs(childIndex - i) : -1; + child = children.get(childIndex); + shortCircuit = shortCircuits.contains(NodeExecutionData.createIndexedName(child, varArgsIndex)); + } + executions.add(new NodeExecutionData(child, i, varArgsIndex, shortCircuit)); } return executions; } + private List parseExecutableTypeData(List elements, int signatureSize, List frameTypes) { + List typeData = new ArrayList<>(); + for (ExecutableElement method : ElementFilter.methodsIn(elements)) { + Set modifiers = method.getModifiers(); + if (modifiers.contains(Modifier.PRIVATE) || modifiers.contains(Modifier.STATIC)) { + continue; + } + if (!method.getSimpleName().toString().startsWith("execute")) { + continue; + } + if (ElementUtils.findAnnotationMirror(context.getEnvironment(), method, Specialization.class) != null) { + continue; + } + + ExecutableTypeData executableType = new ExecutableTypeData(method, signatureSize, context.getFrameTypes()); + + if (executableType.getFrameParameter() != null) { + boolean supportedType = false; + for (TypeMirror type : frameTypes) { + if (ElementUtils.isAssignable(type, executableType.getFrameParameter())) { + supportedType = true; + break; + } + } + if (!supportedType) { + continue; + } + } + + typeData.add(executableType); + } + + Collections.sort(typeData); + return typeData; + } + private void initializeExecutableTypes(NodeData node) { List allExecutes = node.getExecutableTypes(); @@ -507,10 +557,10 @@ for (ExecutableTypeData execute : allExecutes) { evaluatedCounts.add(execute.getEvaluatedCount()); - Parameter frame = execute.getFrame(); + TypeMirror frame = execute.getFrameParameter(); TypeMirror resolvedFrameType; if (frame != null) { - resolvedFrameType = frame.getType(); + resolvedFrameType = frame; if (frameType == null) { frameType = resolvedFrameType; } else if (!ElementUtils.typeEquals(frameType, resolvedFrameType)) { @@ -540,7 +590,7 @@ int voidCount = 0; for (ExecutableTypeData executableTypeData : genericExecutes) { if (!executableTypeData.getMethod().getModifiers().contains(Modifier.FINAL)) { - if (ElementUtils.isVoid(executableTypeData.getReturnType().getType())) { + if (ElementUtils.isVoid(executableTypeData.getReturnType())) { voidCount++; } else { genericCount++; @@ -552,16 +602,16 @@ if (voidCount > 1) { List methodSignatures = new ArrayList<>(); for (ExecutableTypeData type : genericExecutes) { - if (type.getType().isVoid()) { - methodSignatures.add(type.createReferenceName()); + if (context.isType(type.getReturnType(), void.class)) { + methodSignatures.add(ElementUtils.createReferenceName(type.getMethod())); } } node.addWarning("Multiple accessible and overridable generic execute methods found %s. Remove all but one or mark all but one as final.", methodSignatures); } else if (genericCount > 1) { List methodSignatures = new ArrayList<>(); for (ExecutableTypeData type : genericExecutes) { - if (!type.getType().isVoid()) { - methodSignatures.add(type.createReferenceName()); + if (!context.isType(type.getReturnType(), void.class)) { + methodSignatures.add(ElementUtils.createReferenceName(type.getMethod())); } } node.addWarning("Multiple accessible and overridable generic execute methods found %s. Remove all but one or mark all but one as final.", methodSignatures); @@ -577,6 +627,35 @@ + "signature 'public abstract {Type} execute(VirtualFrame)' and must not throw any checked exceptions."); } + int nodeChildDeclarations = 0; + int nodeChildDeclarationsRequired = 0; + List executions = node.getChildExecutions(); + for (NodeExecutionData execution : executions) { + if (execution.getChild() == null) { + nodeChildDeclarationsRequired = execution.getIndex() + 1; + } else { + nodeChildDeclarations++; + } + } + + List requireNodeChildDeclarations = new ArrayList<>(); + for (ExecutableTypeData type : allExecutes) { + if (type.getEvaluatedCount() < nodeChildDeclarationsRequired) { + requireNodeChildDeclarations.add(ElementUtils.createReferenceName(type.getMethod())); + } + } + + if (!requireNodeChildDeclarations.isEmpty()) { + node.addError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. " + + "The following execute methods do not provide all evaluated values for the expected signature size %s: %s.", executions.size(), requireNodeChildDeclarations); + } + + if (nodeChildDeclarations > 0 && executions.size() == node.getMinimalEvaluatedParameters()) { + for (NodeChildData child : node.getChildren()) { + child.addError("Unnecessary @NodeChild declaration. All evaluated child values are provided as parameters in execute methods."); + } + } + } private static Map> groupExecutableTypes(List executableTypes) { @@ -608,10 +687,6 @@ child.setNode(fieldNodeData); if (fieldNodeData == null || fieldNodeData.hasErrors()) { child.addError("Node type '%s' is invalid or not a subclass of Node.", ElementUtils.getQualifiedName(nodeType)); - } else if (!ElementUtils.typeEquals(fieldNodeData.getTypeSystem().getTemplateType().asType(), (node.getTypeSystem().getTemplateType().asType()))) { - child.addError("The @%s of the node and the @%s of the @%s does not match. %s != %s. ", TypeSystem.class.getSimpleName(), TypeSystem.class.getSimpleName(), - NodeChild.class.getSimpleName(), ElementUtils.getSimpleName(node.getTypeSystem().getTemplateType()), - ElementUtils.getSimpleName(fieldNodeData.getTypeSystem().getTemplateType())); } else { List types = child.findGenericExecutableTypes(context); if (types.isEmpty()) { @@ -680,7 +755,11 @@ if (node.hasErrors()) { return node; } - node.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, node, child, createAllowedChildFrameTypes(parentNode)).parse(members))); + List frameTypes = Collections.emptyList(); + if (parentNode.getFrameType() != null) { + frameTypes = Arrays.asList(parentNode.getFrameType()); + } + node.setExecutableTypes(groupExecutableTypes(parseExecutableTypeData(members, child.getExecuteWith().size(), frameTypes))); node.setFrameType(parentNode.getFrameType()); return node; } @@ -1159,13 +1238,13 @@ List parameterTypes = new ArrayList<>(); int signatureIndex = 1; for (ParameterSpec spec : specification.getRequired()) { - parameterTypes.add(new CodeVariableElement(createGenericType(spec, node.getSpecializations(), signatureIndex), "arg" + signatureIndex)); + parameterTypes.add(new CodeVariableElement(createGenericType(node, spec), "arg" + signatureIndex)); if (spec.isSignature()) { signatureIndex++; } } - TypeMirror returnType = createGenericType(specification.getReturnType(), node.getSpecializations(), 0); + TypeMirror returnType = createGenericType(node, specification.getReturnType()); SpecializationData generic = parser.create("Generic", TemplateMethod.NO_NATURAL_ORDER, null, null, returnType, parameterTypes); if (generic == null) { throw new RuntimeException("Unable to create generic signature for node " + node.getNodeId() + " with " + parameterTypes + ". Specification " + specification + "."); @@ -1174,41 +1253,22 @@ return generic; } - private TypeMirror createGenericType(ParameterSpec spec, List specializations, int signatureIndex) { + private TypeMirror createGenericType(NodeData node, ParameterSpec spec) { NodeExecutionData execution = spec.getExecution(); + Collection allowedTypes; if (execution == null) { - if (spec.getAllowedTypes().size() == 1) { - return spec.getAllowedTypes().get(0); - } else { - return ElementUtils.getCommonSuperType(context, spec.getAllowedTypes().toArray(new TypeMirror[0])); - } + allowedTypes = spec.getAllowedTypes(); } 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) { - TypeData singleType = types.iterator().next(); - ExecutableTypeData executable = child.findExecutableType(singleType); - if (executable != null && (signatureIndex == 0 || !executable.hasUnexpectedValue(context))) { - genericType = singleType; - } - } - if (genericType == null) { - ExecutableTypeData type = child.findAnyGenericExecutableType(context); - if (type == null) { - throw new AssertionError("No generic type not yet catched by parser."); - } - genericType = type.getType(); - } - return genericType.getPrimitiveType(); + allowedTypes = node.getPossibleTypes(execution); + } + if (allowedTypes.size() == 1) { + return allowedTypes.iterator().next(); + } else { + return ElementUtils.getCommonSuperType(context, allowedTypes.toArray(new TypeMirror[allowedTypes.size()])); } } - private static void initializeUninitialized(final NodeData node) { + private void initializeUninitialized(final NodeData node) { SpecializationData generic = node.getGenericSpecialization(); if (generic == null) { return; @@ -1225,7 +1285,7 @@ } } if (types.size() > 1) { - generic.replaceParameter(parameter.getLocalName(), new Parameter(parameter, node.getTypeSystem().getGenericTypeData())); + generic.replaceParameter(parameter.getLocalName(), new Parameter(parameter, context.getType(Object.class))); } } TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", -1, node, generic.getSpecification(), null, null, generic.getReturnType(), generic.getParameters()); @@ -1241,14 +1301,14 @@ SpecializationData generic = node.getGenericSpecialization(); - List polymorphicSignature = new ArrayList<>(); + List polymorphicSignature = new ArrayList<>(); List updatePolymorphic = Arrays.asList(); for (Parameter genericParameter : updatePolymorphic) { if (!genericParameter.getSpecification().isSignature()) { continue; } - Set usedTypes = new HashSet<>(); + Set usedTypes = new HashSet<>(); for (SpecializationData specialization : node.getSpecializations()) { if (!specialization.isSpecialized()) { continue; @@ -1257,14 +1317,14 @@ if (parameter == null) { throw new AssertionError("Parameter existed in generic specialization but not in specialized. param = " + genericParameter.getLocalName()); } - usedTypes.add(parameter.getTypeSystemType()); + usedTypes.add(parameter.getType()); } - TypeData polymorphicType; + TypeMirror polymorphicType; if (usedTypes.size() == 1) { polymorphicType = usedTypes.iterator().next(); } else { - polymorphicType = node.getTypeSystem().getGenericTypeData(); + polymorphicType = context.getType(Object.class); } polymorphicSignature.add(polymorphicType); } @@ -1370,7 +1430,7 @@ ExecutableTypeData found = null; List executableElements = execution.getChild().findGenericExecutableTypes(context); for (ExecutableTypeData executable : executableElements) { - if (executable.getType().equalsType(parameter.getTypeSystemType())) { + if (ElementUtils.typeEquals(executable.getReturnType(), parameter.getType())) { found = executable; break; } @@ -1429,8 +1489,8 @@ List elements = new ArrayList<>(originalElements); Set unusedElements = new HashSet<>(elements); - for (TemplateMethod method : nodeData.getAllTemplateMethods()) { - unusedElements.remove(method.getMethod()); + for (ExecutableElement method : nodeData.getAllTemplateMethods()) { + unusedElements.remove(method); } for (NodeFieldData field : nodeData.getFields()) { diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java Tue Apr 14 15:12:48 2015 +0200 @@ -24,6 +24,8 @@ import java.util.*; +import javax.lang.model.type.*; + import com.oracle.truffle.dsl.processor.model.*; import com.oracle.truffle.dsl.processor.model.TemplateMethod.TypeSignature; @@ -299,9 +301,9 @@ public static final class TypeGuard { private final int signatureIndex; - private final TypeData type; + private final TypeMirror type; - public TypeGuard(TypeData type, int signatureIndex) { + public TypeGuard(TypeMirror type, int signatureIndex) { this.type = type; this.signatureIndex = signatureIndex; } @@ -338,7 +340,7 @@ return signatureIndex; } - public TypeData getType() { + public TypeMirror getType() { return type; } } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCastParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCastParser.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCastParser.java Tue Apr 14 15:12:48 2015 +0200 @@ -41,15 +41,17 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { TypeMirror targetTypeMirror = ElementUtils.getAnnotationValue(TypeMirror.class, mirror, "value"); - MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", targetTypeMirror)); - spec.addRequired(new ParameterSpec("value", getTypeSystem().getGenericType())); + ParameterSpec returnTypeSpec = new ParameterSpec("returnType", targetTypeMirror); + returnTypeSpec.setAllowSubclasses(false); + MethodSpec spec = new MethodSpec(returnTypeSpec); + spec.addRequired(new ParameterSpec("value", getContext().getType(Object.class))); return spec; } @Override public TypeCastData create(TemplateMethod method, boolean invalid) { - TypeData targetType = resolveCastOrCheck(method); - TypeData sourceType = getTypeSystem().getGenericTypeData(); + TypeMirror targetType = resolveCastOrCheck(method); + TypeMirror sourceType = getContext().getType(Object.class); return new TypeCastData(method, sourceType, targetType); } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCheckParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCheckParser.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCheckParser.java Tue Apr 14 15:12:48 2015 +0200 @@ -25,6 +25,7 @@ import java.lang.annotation.*; import javax.lang.model.element.*; +import javax.lang.model.type.*; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.dsl.processor.*; @@ -39,13 +40,13 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", getContext().getType(boolean.class))); - spec.addRequired(new ParameterSpec("value", getTypeSystem().getGenericType())); + spec.addRequired(new ParameterSpec("value", getContext().getType(Object.class))); return spec; } @Override public TypeCheckData create(TemplateMethod method, boolean invalid) { - TypeData targetType = resolveCastOrCheck(method); + TypeMirror targetType = resolveCastOrCheck(method); return new TypeCheckData(method, targetType, targetType); } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemMethodParser.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemMethodParser.java Tue Apr 14 15:12:48 2015 +0200 @@ -25,7 +25,6 @@ import javax.lang.model.element.*; import javax.lang.model.type.*; -import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.dsl.processor.*; import com.oracle.truffle.dsl.processor.java.*; import com.oracle.truffle.dsl.processor.model.*; @@ -41,18 +40,13 @@ return ElementUtils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null; } - protected final TypeData resolveCastOrCheck(TemplateMethod method) { + protected final TypeMirror resolveCastOrCheck(TemplateMethod method) { Class annotationType = getAnnotationType(); TypeMirror targetTypeMirror = ElementUtils.getAnnotationValue(TypeMirror.class, method.getMessageAnnotation(), "value"); - TypeData targetType = getTypeSystem().findTypeData(targetTypeMirror); - if (targetType == null) { - method.addError("The type '%s' is not declared in the @%s.", ElementUtils.getSimpleName(targetTypeMirror), TypeSystem.class.getSimpleName()); - return null; - } if (!method.getMethod().getModifiers().contains(Modifier.PUBLIC) || !method.getMethod().getModifiers().contains(Modifier.STATIC)) { method.addError("@%s annotated method %s must be public and static.", annotationType.getSimpleName(), method.getMethodName()); } - return targetType; + return targetTypeMirror; } } diff -r 37ea76052733 -r 18c0f02fa4d2 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java Tue Apr 14 15:12:48 2015 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.truffle.dsl.processor.parser; -import static com.oracle.truffle.dsl.processor.java.ElementUtils.*; - import java.lang.annotation.*; import java.util.*; @@ -33,7 +31,6 @@ import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.dsl.internal.*; -import com.oracle.truffle.dsl.processor.generator.*; import com.oracle.truffle.dsl.processor.java.*; import com.oracle.truffle.dsl.processor.model.*; @@ -57,7 +54,7 @@ } assert options != null; - TypeSystemData typeSystem = new TypeSystemData(context, templateType, templateTypeAnnotation, options); + TypeSystemData typeSystem = new TypeSystemData(context, templateType, templateTypeAnnotation, options, false); // annotation type on class path!? TypeElement annotationTypeElement = processingEnv.getElementUtils().getTypeElement(getAnnotationType().getCanonicalName()); @@ -75,24 +72,9 @@ return typeSystem; } - List types = parseTypes(typeSystem); - - TypeMirror genericType = context.getType(Object.class); - TypeData voidType = new TypeData(typeSystem, types.size(), null, context.getType(void.class), context.getType(Void.class)); - types.add(voidType); - - typeSystem.setTypes(types); if (typeSystem.hasErrors()) { return typeSystem; } - typeSystem.setGenericType(genericType); - typeSystem.setVoidType(voidType); - - TypeData booleanType = typeSystem.findTypeData(context.getType(boolean.class)); - if (booleanType == null) { - booleanType = new TypeData(typeSystem, types.size(), null, context.getType(boolean.class), context.getType(Boolean.class)); - } - typeSystem.setBooleanType(booleanType); verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class); @@ -105,25 +87,20 @@ return typeSystem; } - typeSystem.setImplicitCasts(implicitCasts); - typeSystem.setCasts(casts); - typeSystem.setChecks(checks); + List legacyTypes = ElementUtils.getAnnotationValueList(TypeMirror.class, typeSystem.getTemplateTypeAnnotation(), "value"); + typeSystem.getLegacyTypes().addAll(legacyTypes); + verifyTypes(typeSystem); + typeSystem.getLegacyTypes().add(context.getType(Object.class)); + typeSystem.getLegacyTypes().add(context.getType(void.class)); + verifyNamesUnique(typeSystem); + + typeSystem.getImplicitCasts().addAll(implicitCasts); + typeSystem.getCasts().addAll(casts); + typeSystem.getChecks().addAll(checks); if (typeSystem.hasErrors()) { return typeSystem; } - - for (TypeCheckData check : checks) { - check.getCheckedType().addTypeCheck(check); - } - - for (TypeCastData cast : casts) { - cast.getTargetType().addTypeCast(cast); - } - - verifyMethodSignatures(typeSystem); - verifyNamesUnique(typeSystem); - return typeSystem; } @@ -149,50 +126,28 @@ } } - private List parseTypes(TypeSystemData typeSystem) { - List types = new ArrayList<>(); - List typeMirrors = ElementUtils.getAnnotationValueList(TypeMirror.class, typeSystem.getTemplateTypeAnnotation(), "value"); - if (typeMirrors.isEmpty()) { - typeSystem.addError("At least one type must be defined."); - return types; - } - - final AnnotationValue annotationValue = ElementUtils.getAnnotationValue(typeSystem.getTemplateTypeAnnotation(), "value"); - final TypeMirror objectType = context.getType(Object.class); - - int index = 0; - for (TypeMirror primitiveType : typeMirrors) { - TypeMirror primitive = ElementUtils.fillInGenericWildcards(primitiveType); - - TypeMirror boxedType = ElementUtils.boxType(context, primitive); - TypeData typeData = new TypeData(typeSystem, index, annotationValue, primitive, boxedType); - - if (isPrimitiveWrapper(primitive)) { - typeData.addError("Types must not contain primitive wrapper types."); + private void verifyTypes(TypeSystemData typeSystem) { + for (TypeMirror type : typeSystem.getLegacyTypes()) { + if (isPrimitiveWrapper(type)) { + typeSystem.addError("Types must not contain primitive wrapper types."); } - if (ElementUtils.typeEquals(boxedType, objectType)) { - typeData.addError("Types must not contain the generic type java.lang.Object."); + if (ElementUtils.typeEquals(type, context.getType(Object.class))) { + typeSystem.addError("Types must not contain the generic type java.lang.Object."); } - - types.add(typeData); - index++; } - verifyTypeOrder(types); - - types.add(new TypeData(typeSystem, index, annotationValue, objectType, objectType)); - return types; + verifyTypeOrder(typeSystem); } - private static void verifyTypeOrder(List types) { + private static void verifyTypeOrder(TypeSystemData typeSystem) { Map> invalidTypes = new HashMap<>(); - for (int i = types.size() - 1; i >= 0; i--) { - TypeData typeData = types.get(i); - TypeMirror type = typeData.getBoxedType(); + for (int i = typeSystem.getLegacyTypes().size() - 1; i >= 0; i--) { + TypeMirror typeData = typeSystem.getLegacyTypes().get(i); + TypeMirror type = typeSystem.boxType(typeData); if (invalidTypes.containsKey(ElementUtils.getQualifiedName(type))) { - typeData.addError("Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", invalidTypes.get(ElementUtils.getQualifiedName(type)), + typeSystem.addError("Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", invalidTypes.get(ElementUtils.getQualifiedName(type)), ElementUtils.getQualifiedName(type)); } TypeElement element = ElementUtils.fromTypeMirror(type); @@ -200,7 +155,7 @@ if (element != null) { nextInvalidTypes.addAll(ElementUtils.getQualifiedSuperTypeNames(element)); } - nextInvalidTypes.add(getQualifiedName(type)); + nextInvalidTypes.add(ElementUtils.getQualifiedName(type)); for (String qualifiedName : nextInvalidTypes) { List inheritedTypes = invalidTypes.get(qualifiedName); @@ -208,7 +163,7 @@ inheritedTypes = new ArrayList<>(); invalidTypes.put(qualifiedName, inheritedTypes); } - inheritedTypes.add(ElementUtils.getQualifiedName(typeData.getBoxedType())); + inheritedTypes.add(ElementUtils.getQualifiedName(typeSystem.boxType(typeData))); } } } @@ -226,64 +181,11 @@ return false; } - private void verifyMethodSignatures(TypeSystemData typeSystem) { - Set generatedIsMethodNames = new HashSet<>(); - Set generatedAsMethodNames = new HashSet<>(); - Set generatedExpectMethodNames = new HashSet<>(); - - for (TypeData typeData : typeSystem.getTypes()) { - generatedIsMethodNames.add(TypeSystemCodeGenerator.isTypeMethodName(typeData)); - generatedAsMethodNames.add(TypeSystemCodeGenerator.asTypeMethodName(typeData)); - generatedExpectMethodNames.add(TypeSystemCodeGenerator.expectTypeMethodName(typeData)); - } - - List methods = ElementFilter.methodsIn(typeSystem.getTemplateType().getEnclosedElements()); - for (ExecutableElement method : methods) { - if (method.getModifiers().contains(Modifier.PRIVATE)) { - // will not conflict overridden methods - continue; - } else if (method.getParameters().size() != 1) { - continue; - } - String methodName = method.getSimpleName().toString(); - if (generatedIsMethodNames.contains(methodName)) { - verifyIsMethod(typeSystem, method); - } else if (generatedAsMethodNames.contains(methodName)) { - verifyAsMethod(typeSystem, method); - } else if (generatedExpectMethodNames.contains(methodName)) { - verifyExpectMethod(typeSystem); - } - } - } - - private boolean verifyIsMethod(TypeSystemData typeSystem, ExecutableElement method) { - AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, TypeCheck.class); - if (mirror == null) { - typeSystem.addError("Method starting with the pattern is${typeName} must be annotated with @%s.", TypeCheck.class.getSimpleName()); - return false; - } - return true; - } - - private boolean verifyAsMethod(TypeSystemData typeSystem, ExecutableElement method) { - AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, TypeCast.class); - if (mirror == null) { - typeSystem.addError("Method starting with the pattern as${typeName} must be annotated with @%s.", TypeCast.class.getSimpleName()); - return false; - } - return true; - } - - private static boolean verifyExpectMethod(TypeSystemData typeSystem) { - typeSystem.addError("Method starting with the pattern expect${typeName} must not be declared manually."); - return false; - } - private static void verifyNamesUnique(TypeSystemData typeSystem) { Set usedNames = new HashSet<>(); - for (TypeData type : typeSystem.getTypes()) { - String boxedName = ElementUtils.getSimpleName(type.getBoxedType()); - String primitiveName = ElementUtils.getSimpleName(type.getPrimitiveType()); + for (TypeMirror type : typeSystem.getLegacyTypes()) { + String boxedName = ElementUtils.getSimpleName(typeSystem.boxType(type)); + String primitiveName = ElementUtils.getSimpleName(type); if (usedNames.contains(boxedName)) { typeSystem.addError("Two types result in the same boxed name: %s.", boxedName); } else if (usedNames.contains(primitiveName)) { @@ -293,4 +195,5 @@ usedNames.add(primitiveName); } } + }