changeset 11439:efe58aa92f86

Truffle-DSL: guards can now be declared using any base type or interface of the target value type.
author Christian Humer <christian.humer@gmail.com>
date Tue, 27 Aug 2013 22:08:26 +0200
parents b77721210bd6
children f406557f1a0d
files graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/GuardsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeContainerTest.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeData.java
diffstat 9 files changed, 263 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/GuardsTest.java	Tue Aug 27 18:11:35 2013 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/GuardsTest.java	Tue Aug 27 22:08:26 2013 +0200
@@ -29,7 +29,16 @@
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GlobalFlagGuardFactory;
+import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GuardWithBaseClassFactory;
+import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GuardWithBaseInterfaceFactory;
+import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GuardWithBoxedPrimitiveFactory;
+import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GuardWithObjectFactory;
 import com.oracle.truffle.api.dsl.test.GuardsTestFactory.InvocationGuardFactory;
+import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestGuardResolve1Factory;
+import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestGuardResolve2Factory;
+import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestGuardResolve3Factory;
+import com.oracle.truffle.api.dsl.test.NodeContainerTest.Str;
+import com.oracle.truffle.api.dsl.test.NodeContainerTest.StrBase;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
 
@@ -107,4 +116,159 @@
         }
     }
 
+    @Test
+    public void testGuardWithBaseClass() {
+        TestRootNode<?> root = createRoot(GuardWithBaseClassFactory.getInstance());
+
+        assertEquals(42, executeWith(root, new Str("42")));
+    }
+
+    @NodeChild("expression")
+    public abstract static class GuardWithBaseClass extends ValueNode {
+
+        boolean baseGuard(StrBase base) {
+            return true;
+        }
+
+        @Specialization(guards = "baseGuard")
+        int doSpecialized(Str value0) {
+            return 42;
+        }
+    }
+
+    @Test
+    public void testGuardWithBaseInterface() {
+        TestRootNode<?> root = createRoot(GuardWithBaseInterfaceFactory.getInstance());
+
+        assertEquals(42, executeWith(root, "anything"));
+    }
+
+    @NodeChild("expression")
+    public abstract static class GuardWithBaseInterface extends ValueNode {
+
+        boolean baseGuard(CharSequence base) {
+            return true;
+        }
+
+        @Specialization(guards = "baseGuard")
+        int doSpecialized(String value0) {
+            return 42;
+        }
+    }
+
+    @Test
+    public void testGuardWithPrimitive() {
+        TestRootNode<?> root = createRoot(GuardWithBoxedPrimitiveFactory.getInstance());
+
+        assertEquals(42, executeWith(root, 42));
+    }
+
+    @NodeChild("expression")
+    public abstract static class GuardWithBoxedPrimitive extends ValueNode {
+
+        boolean baseGuard(Integer primitive) {
+            return true;
+        }
+
+        @Specialization(guards = "baseGuard")
+        int doSpecialized(int value0) {
+            return value0;
+        }
+    }
+
+    @Test
+    public void testGuardWithObject() {
+        TestRootNode<?> root = createRoot(GuardWithObjectFactory.getInstance());
+
+        assertEquals(42, executeWith(root, 42));
+    }
+
+    @NodeChild("expression")
+    public abstract static class GuardWithObject extends ValueNode {
+
+        boolean baseGuard(Object primitive) {
+            return true;
+        }
+
+        @Specialization(guards = "baseGuard")
+        int doSpecialized(int value0) {
+            return value0;
+        }
+    }
+
+    @Test
+    public void testGuardResolve1() {
+        TestRootNode<?> root = createRoot(TestGuardResolve1Factory.getInstance());
+
+        assertEquals(42, executeWith(root, 42));
+    }
+
+    @NodeChild("expression")
+    public abstract static class TestGuardResolve1 extends ValueNode {
+
+        boolean guard(Object primitive) {
+            return false;
+        }
+
+        boolean guard(int primitive) {
+            return true;
+        }
+
+        @Specialization(guards = "guard")
+        int doSpecialized(int value0) {
+            return value0;
+        }
+    }
+
+    @Test
+    public void testGuardResolve2() {
+        TestRootNode<?> root = createRoot(TestGuardResolve2Factory.getInstance());
+        assertEquals(42, executeWith(root, new Str("")));
+    }
+
+    @NodeChild("expression")
+    public abstract static class TestGuardResolve2 extends ValueNode {
+
+        boolean guard(Object primitive) {
+            return false;
+        }
+
+        boolean guard(StrBase primitive) {
+            return true;
+        }
+
+        @Specialization(guards = "guard")
+        int doSpecialized(Str value0) {
+            return 42;
+        }
+    }
+
+    @Test
+    public void testGuardResolve3() {
+        TestRootNode<?> root = createRoot(TestGuardResolve3Factory.getInstance());
+
+        assertEquals(42, executeWith(root, new Str("")));
+    }
+
+    @NodeChild("expression")
+    public abstract static class TestGuardResolve3 extends ValueNode {
+
+        boolean guard(Object primitive) {
+            return false;
+        }
+
+        boolean guard(StrBase primitive) {
+            return false;
+        }
+
+        boolean guard(Str primitive) {
+            return true;
+        }
+
+        @Specialization(guards = "guard")
+        int doSpecialized(Str value0) {
+            return 42;
+        }
+    }
+
 }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeContainerTest.java	Tue Aug 27 18:11:35 2013 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeContainerTest.java	Tue Aug 27 22:08:26 2013 +0200
@@ -96,8 +96,12 @@
         assertSame(context, executeWith(node));
     }
 
+    static class StrBase {
+
+    }
+
     @NodeContainer(BuiltinNode.class)
-    static class Str {
+    static class Str extends StrBase {
 
         private final String internal;
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java	Tue Aug 27 18:11:35 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java	Tue Aug 27 22:08:26 2013 +0200
@@ -32,7 +32,7 @@
 import javax.lang.model.util.*;
 
 import com.oracle.truffle.dsl.processor.ast.*;
-import com.oracle.truffle.dsl.processor.ast.CodeTypeMirror.*;
+import com.oracle.truffle.dsl.processor.ast.CodeTypeMirror.DeclaredCodeTypeMirror;
 import com.oracle.truffle.dsl.processor.compiler.*;
 
 /**
@@ -50,6 +50,19 @@
         return null;
     }
 
+    public static boolean needsCastTo(ProcessorContext context, TypeMirror sourceType, TypeMirror targetType) {
+        if (typeEquals(sourceType, targetType)) {
+            return false;
+        } else if (isObject(targetType)) {
+            return false;
+        } else if (isVoid(targetType)) {
+            return false;
+        } else if (isAssignable(context, sourceType, targetType)) {
+            return false;
+        }
+        return true;
+    }
+
     public static VariableElement findVariableElement(DeclaredType type, String name) {
         List<? extends VariableElement> elements = ElementFilter.fieldsIn(type.asElement().getEnclosedElements());
         for (VariableElement variableElement : elements) {
@@ -502,6 +515,24 @@
         return types;
     }
 
+    public static List<TypeMirror> getAssignableTypes(ProcessorContext context, TypeMirror type) {
+        if (isPrimitive(type)) {
+            return Arrays.asList(type, boxType(context, type), context.getType(Object.class));
+        } else if (type.getKind() == TypeKind.ARRAY) {
+            return Arrays.asList(type, context.getType(Object.class));
+        } else if (type.getKind() == TypeKind.DECLARED) {
+            List<TypeElement> types = getSuperTypes(fromTypeMirror(type));
+            List<TypeMirror> mirrors = new ArrayList<>(types.size());
+            mirrors.add(type);
+            for (TypeElement typeElement : types) {
+                mirrors.add(typeElement.asType());
+            }
+            return mirrors;
+        } else {
+            return Collections.emptyList();
+        }
+    }
+
     public static List<TypeElement> getSuperTypes(TypeElement element) {
         List<TypeElement> types = new ArrayList<>();
         List<TypeElement> superTypes = null;
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Tue Aug 27 18:11:35 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Tue Aug 27 22:08:26 2013 +0200
@@ -258,15 +258,15 @@
             if (valueParameter == null) {
                 valueParameter = targetParameter;
             }
-            TypeData targetType = targetParameter.getTypeSystemType();
+            TypeMirror targetType = targetParameter.getType();
 
             if (targetParameter.isImplicit() || valueParameter.isImplicit()) {
                 continue;
             }
 
-            TypeData valueType = null;
+            TypeMirror valueType = null;
             if (valueParameter != null) {
-                valueType = valueParameter.getTypeSystemType();
+                valueType = valueParameter.getType();
             }
 
             if (signatureIndex < customSignatureValueNames.length && targetParameter.getSpecification().isSignature()) {
@@ -283,14 +283,8 @@
                 builder.end();
             } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) {
                 builder.string("ex.getResult()");
-            } else if (targetType == null || targetType.isGeneric() || (valueType != null && valueType.equalsType(targetType))) {
+            } else if (!Utils.needsCastTo(getContext(), valueType, targetType)) {
                 builder.startGroup();
-
-                if (valueType != null && sourceMethod.getMethodName().equals(targetMethod.getMethodName()) && !valueType.isGeneric() && targetType.isGeneric()) {
-                    builder.string("(");
-                    builder.type(targetType.getPrimitiveType());
-                    builder.string(") ");
-                }
                 builder.string(valueName(targetParameter));
                 builder.end();
             } else {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java	Tue Aug 27 18:11:35 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java	Tue Aug 27 22:08:26 2013 +0200
@@ -24,6 +24,7 @@
 
 import javax.lang.model.type.*;
 
+import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.typesystem.*;
 
 public class ActualParameter {
@@ -104,4 +105,9 @@
     public ActualParameter getPreviousParameter() {
         return method.getPreviousParam(this);
     }
+
+    @Override
+    public String toString() {
+        return Utils.getSimpleName(type);
+    }
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java	Tue Aug 27 18:11:35 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java	Tue Aug 27 22:08:26 2013 +0200
@@ -278,20 +278,23 @@
     }
 
     public int compareBySignature(TemplateMethod compareMethod) {
-        TypeSystemData typeSystem = getTemplate().getTypeSystem();
+        final TypeSystemData typeSystem = getTemplate().getTypeSystem();
         if (typeSystem != compareMethod.getTemplate().getTypeSystem()) {
             throw new IllegalStateException("Cannot compare two methods with different type systems.");
         }
 
-        Signature signature1 = getSignature();
-        Signature signature2 = compareMethod.getSignature();
+        List<TypeMirror> signature1 = getSignatureTypes();
+        List<TypeMirror> signature2 = compareMethod.getSignatureTypes();
         if (signature1.size() != signature2.size()) {
             return signature2.size() - signature1.size();
         }
 
         int result = 0;
         for (int i = 1; i < signature1.size(); i++) {
-            int typeResult = compareActualParameter(typeSystem, signature1.get(i), signature2.get(i));
+            TypeMirror t1 = signature1.get(i);
+            TypeMirror t2 = signature2.get(i);
+
+            int typeResult = compareParameter(typeSystem, t1, t2);
             if (result == 0) {
                 result = typeResult;
             } else if (typeResult != 0 && Math.signum(result) != Math.signum(typeResult)) {
@@ -300,16 +303,44 @@
             }
         }
         if (result == 0 && signature1.size() > 0) {
-            result = compareActualParameter(typeSystem, signature1.get(0), signature2.get(0));
+            result = compareParameter(typeSystem, signature1.get(0), signature2.get(0));
         }
 
         return result;
     }
 
-    private static int compareActualParameter(TypeSystemData typeSystem, TypeData t1, TypeData t2) {
-        int index1 = typeSystem.findType(t1);
-        int index2 = typeSystem.findType(t2);
-        return index1 - index2;
+    private static int compareParameter(TypeSystemData data, TypeMirror signature1, TypeMirror signature2) {
+        if (Utils.typeEquals(signature1, signature2)) {
+            return 0;
+        }
+
+        int index1 = data.findType(signature1);
+        int index2 = data.findType(signature2);
+        if (index1 != -1 && index2 != -1) {
+            return index1 - index2;
+        }
+
+        if (signature1.getKind() == TypeKind.DECLARED && signature2.getKind() == TypeKind.DECLARED) {
+            TypeElement element1 = Utils.fromTypeMirror(signature1);
+            TypeElement element2 = Utils.fromTypeMirror(signature2);
+
+            if (Utils.getDirectSuperTypes(element1).contains(element2)) {
+                return -1;
+            } else if (Utils.getDirectSuperTypes(element2).contains(element1)) {
+                return 1;
+            }
+        }
+        return Utils.getSimpleName(signature1).compareTo(Utils.getSimpleName(signature2));
+    }
+
+    public List<TypeMirror> getSignatureTypes() {
+        List<TypeMirror> types = new ArrayList<>();
+        for (ActualParameter param : getReturnTypeAndParameters()) {
+            if (param.getSpecification().isSignature()) {
+                types.add(param.getType());
+            }
+        }
+        return types;
     }
 
     public static class Signature implements Iterable<TypeData>, Comparable<Signature> {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardData.java	Tue Aug 27 18:11:35 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardData.java	Tue Aug 27 22:08:26 2013 +0200
@@ -60,7 +60,7 @@
 
     @Override
     public String toString() {
-        return getMethodName();
+        return getMethodName() + getParameters().toString();
     }
 
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java	Tue Aug 27 18:11:35 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java	Tue Aug 27 22:08:26 2013 +0200
@@ -26,6 +26,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.node.*;
@@ -58,7 +59,8 @@
         spec.getRequired().clear();
 
         for (ActualParameter parameter : specialization.getRequiredParameters()) {
-            ParameterSpec paramSpec = new ParameterSpec(parameter.getLocalName(), parameter.getType(), getNode().getTypeSystem().getGenericType());
+            List<TypeMirror> assignableTypes = Utils.getAssignableTypes(getContext(), parameter.getType());
+            ParameterSpec paramSpec = new ParameterSpec(parameter.getLocalName(), assignableTypes);
             paramSpec.setSignature(true);
             spec.addRequired(paramSpec);
         }
@@ -89,7 +91,13 @@
             if (specializationParameter == null) {
                 newParameters.add(parameter);
             } else {
-                newParameters.add(new ActualParameter(specializationParameter.getSpecification(), parameter.getTypeSystemType(), specializationParameter.getIndex(), parameter.isImplicit()));
+                ActualParameter p;
+                if (parameter.getTypeSystemType() != null) {
+                    p = new ActualParameter(specializationParameter.getSpecification(), parameter.getTypeSystemType(), specializationParameter.getIndex(), parameter.isImplicit());
+                } else {
+                    p = new ActualParameter(specializationParameter.getSpecification(), parameter.getType(), specializationParameter.getIndex(), parameter.isImplicit());
+                }
+                newParameters.add(p);
             }
         }
         guard.setParameters(newParameters);
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeData.java	Tue Aug 27 18:11:35 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeData.java	Tue Aug 27 22:08:26 2013 +0200
@@ -120,16 +120,7 @@
     }
 
     public boolean needsCastTo(ProcessorContext context, TypeData targetType) {
-        if (this.equals(targetType)) {
-            return false;
-        } else if (targetType.isGeneric()) {
-            return false;
-        } else if (targetType.isVoid()) {
-            return false;
-        } else if (Utils.isAssignable(context, getPrimitiveType(), targetType.getPrimitiveType())) {
-            return false;
-        }
-        return true;
+        return Utils.needsCastTo(context, getPrimitiveType(), targetType.getPrimitiveType());
     }
 
     public boolean isPrimitive() {