diff graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java @ 18761:a665483c3881

Truffle-DSL: new node layout implementation.
author Christian Humer <christian.humer@gmail.com>
date Mon, 29 Dec 2014 23:38:54 +0100
parents 3912400fc33a
children c0fb70634640
line wrap: on
line diff
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java	Mon Dec 29 23:38:50 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java	Mon Dec 29 23:38:54 2014 +0100
@@ -23,12 +23,14 @@
 package com.oracle.truffle.dsl.processor.generator;
 
 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.type.*;
 
+import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.java.*;
 import com.oracle.truffle.dsl.processor.java.model.*;
@@ -40,15 +42,15 @@
         return cast(type, CodeTreeBuilder.singleString(content));
     }
 
-    public static CodeTree implicitType(TypeData type, String valueName) {
+    public static CodeTree implicitType(TypeData type, CodeTree value) {
         if (type.isGeneric()) {
-            return CodeTreeBuilder.singleString(valueName);
+            return value;
         }
         CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
         TypeSystemData typeSystem = type.getTypeSystem();
-        builder.startStaticCall(createTypeSystemGen(typeSystem), getImplicitClass(type)).string(valueName);
+        builder.startStaticCall(createTypeSystemGen(typeSystem), getImplicitClass(type)).tree(value);
         builder.end();
-        return builder.getRoot();
+        return builder.build();
     }
 
     public static CodeTree invokeImplicitCast(ImplicitCastData cast, CodeTree expression) {
@@ -56,35 +58,49 @@
         TypeSystemData typeSystem = cast.getTargetType().getTypeSystem();
         builder.startStaticCall(createTypeSystemGen(typeSystem), cast.getMethodName()).tree(expression);
         builder.end();
-        return builder.getRoot();
+        return builder.build();
     }
 
-    public static CodeTree implicitCheck(TypeData type, String valueName, String typeHint) {
+    public static CodeTree implicitCheck(TypeData type, CodeTree value, String typeHint) {
         if (type.isGeneric()) {
-            return CodeTreeBuilder.singleString(valueName);
+            return value;
         }
         CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
         TypeSystemData typeSystem = type.getTypeSystem();
-        builder.startStaticCall(createTypeSystemGen(typeSystem), isImplicitTypeMethodName(type)).string(valueName);
+        builder.startStaticCall(createTypeSystemGen(typeSystem), isImplicitTypeMethodName(type)).tree(value);
         if (typeHint != null) {
             builder.string(typeHint);
         }
         builder.end();
-        return builder.getRoot();
+        return builder.build();
     }
 
-    public static CodeTree implicitCast(TypeData type, String valueName, String typeHint) {
+    public static CodeTree implicitExpect(TypeData type, CodeTree value, String typeHint) {
         if (type.isGeneric()) {
-            return CodeTreeBuilder.singleString(valueName);
+            return value;
         }
         CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
         TypeSystemData typeSystem = type.getTypeSystem();
-        builder.startStaticCall(createTypeSystemGen(typeSystem), asImplicitTypeMethodName(type)).string(valueName);
+        builder.startStaticCall(createTypeSystemGen(typeSystem), expectImplicitTypeMethodName(type)).tree(value);
         if (typeHint != null) {
             builder.string(typeHint);
         }
         builder.end();
-        return builder.getRoot();
+        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);
+        if (typeHint != null) {
+            builder.string(typeHint);
+        }
+        builder.end();
+        return builder.build();
     }
 
     public static CodeTree cast(TypeData type, CodeTree content) {
@@ -99,20 +115,28 @@
         } else {
             builder.startStaticCall(typeSystem.getTemplateType().asType(), type.getTypeCasts().get(0).getMethodName()).tree(content).end();
         }
-        return builder.getRoot();
+        return builder.build();
     }
 
     public static CodeTree expect(TypeData type, CodeTree content) {
-        if (type.isGeneric()) {
+        if (type.isGeneric() || type.isVoid()) {
             return content;
         }
         CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
         TypeSystemData typeSystem = type.getTypeSystem();
         builder.startStaticCall(createTypeSystemGen(typeSystem), expectTypeMethodName(type)).tree(content).end();
-        return builder.getRoot();
+        return builder.build();
     }
 
-    private static CodeTypeMirror createTypeSystemGen(TypeSystemData typeSystem) {
+    public static CodeTree expect(TypeData sourceType, TypeData targetType, CodeTree content) {
+        if (sourceType != null && !sourceType.needsCastTo(targetType)) {
+            return content;
+        } else {
+            return expect(targetType, content);
+        }
+    }
+
+    public static CodeTypeMirror createTypeSystemGen(TypeSystemData typeSystem) {
         return new GeneratedTypeMirror(ElementUtils.getPackageName(typeSystem.getTemplateType()), typeName(typeSystem));
     }
 
@@ -132,7 +156,7 @@
         } else {
             builder.startStaticCall(typeSystem.getTemplateType().asType(), type.getTypeChecks().get(0).getMethodName()).tree(content).end();
         }
-        return builder.getRoot();
+        return builder.build();
     }
 
     public static String isTypeMethodName(TypeData type) {
@@ -151,6 +175,10 @@
         return "asImplicit" + ElementUtils.getTypeId(type.getBoxedType());
     }
 
+    static String expectImplicitTypeMethodName(TypeData type) {
+        return "expectImplicit" + ElementUtils.getTypeId(type.getBoxedType());
+    }
+
     static String getImplicitClass(TypeData type) {
         return "getImplicit" + ElementUtils.getTypeId(type.getBoxedType()) + "Class";
     }
@@ -170,7 +198,21 @@
 
     @Override
     public CodeTypeElement create(ProcessorContext context, TypeSystemData typeSystem) {
-        return new TypeClassFactory(context, typeSystem).create();
+        CodeTypeElement clazz = new TypeClassFactory(context, typeSystem).create();
+
+        if (typeSystem.getOptions().useNewLayout()) {
+            clazz.add(new TypeSystemNodeFactory(context, typeSystem).create());
+
+            if (typeSystem.getOptions().implicitCastOptimization().isMergeCasts()) {
+                for (TypeData type : typeSystem.getTypes()) {
+                    List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
+                    if (sourceTypes.size() > 1) {
+                        clazz.add(new ImplicitCastNodeFactory(context, type).create());
+                    }
+                }
+            }
+        }
+        return clazz;
     }
 
     private static class TypeClassFactory {
@@ -187,16 +229,17 @@
 
         public CodeTypeElement create() {
             String name = typeName(typeSystem);
-            CodeTypeElement clazz = GeneratorUtils.createClass(typeSystem, modifiers(PUBLIC, FINAL), name, typeSystem.getTemplateType().asType(), false);
+            CodeTypeElement clazz = GeneratorUtils.createClass(typeSystem, null, modifiers(PUBLIC, FINAL), name, typeSystem.getTemplateType().asType());
 
-            clazz.add(GeneratorUtils.createConstructorUsingFields(context, modifiers(PROTECTED), clazz));
+            clazz.add(GeneratorUtils.createConstructorUsingFields(modifiers(PROTECTED), clazz));
             CodeVariableElement singleton = createSingleton(clazz);
             clazz.add(singleton);
 
             for (TypeData type : typeSystem.getTypes()) {
-                if (type.isGeneric() || type.isVoid()) {
+                if (type.isVoid() || type.isGeneric()) {
                     continue;
                 }
+
                 clazz.addOptional(createIsTypeMethod(type));
                 clazz.addOptional(createAsTypeMethod(type));
 
@@ -204,11 +247,20 @@
                     clazz.addOptional(createExpectTypeMethod(type, sourceType));
                 }
 
-                clazz.addOptional(createAsImplicitTypeMethod(type, true));
-                clazz.addOptional(createAsImplicitTypeMethod(type, false));
-                clazz.addOptional(createIsImplicitTypeMethod(type, true));
-                clazz.addOptional(createIsImplicitTypeMethod(type, false));
-                clazz.addOptional(createGetTypeIndex(type));
+                if (type.hasImplicitSourceTypes()) {
+                    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));
+                    }
+                }
             }
 
             return clazz;
@@ -238,10 +290,6 @@
         }
 
         private CodeExecutableElement createIsImplicitTypeMethod(TypeData type, boolean typed) {
-            List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type);
-            if (casts.isEmpty()) {
-                return null;
-            }
             CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(boolean.class), TypeSystemCodeGenerator.isImplicitTypeMethodName(type));
             method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
             if (typed) {
@@ -275,14 +323,11 @@
             return method;
         }
 
-        private CodeExecutableElement createAsImplicitTypeMethod(TypeData type, boolean typed) {
-            List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type);
-            if (casts.isEmpty()) {
-                return null;
-            }
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asImplicitTypeMethodName(type));
+        private CodeExecutableElement createAsImplicitTypeMethod(TypeData type, boolean useTypeHint) {
+            String name = asImplicitTypeMethodName(type);
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type.getPrimitiveType(), name);
             method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
-            if (typed) {
+            if (useTypeHint) {
                 method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint"));
             }
 
@@ -292,7 +337,7 @@
             boolean elseIf = false;
             for (TypeData sourceType : sourceTypes) {
                 elseIf = builder.startIf(elseIf);
-                if (typed) {
+                if (useTypeHint) {
                     builder.string("typeHint == ").typeLiteral(sourceType.getPrimitiveType());
                 } else {
                     builder.tree(check(sourceType, LOCAL_VALUE));
@@ -314,17 +359,55 @@
             }
 
             builder.startElseBlock();
-            builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
+            builder.tree(createTransferToInterpreterAndInvalidate());
             builder.startThrow().startNew(context.getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end();
             builder.end();
             return method;
         }
 
-        private CodeExecutableElement createGetTypeIndex(TypeData type) {
-            List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type);
-            if (casts.isEmpty()) {
-                return null;
+        private CodeExecutableElement createExpectImplicitTypeMethod(TypeData type, boolean useTypeHint) {
+            String name = expectImplicitTypeMethodName(type);
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type.getPrimitiveType(), 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<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
+
+            CodeTreeBuilder builder = method.createBuilder();
+            boolean elseIf = false;
+            for (TypeData sourceType : sourceTypes) {
+                elseIf = builder.startIf(elseIf);
+                if (useTypeHint) {
+                    builder.string("typeHint == ").typeLiteral(sourceType.getPrimitiveType());
+                    builder.string(" && ");
+                }
+                builder.tree(check(sourceType, LOCAL_VALUE));
+
+                builder.end().startBlock();
+
+                builder.startReturn();
+                ImplicitCastData cast = typeSystem.lookupCast(sourceType, type);
+                if (cast != null) {
+                    builder.startCall(cast.getMethodName());
+                }
+                builder.tree(cast(sourceType, LOCAL_VALUE)).end();
+                if (cast != null) {
+                    builder.end();
+                }
+                builder.end();
+                builder.end();
+            }
+
+            builder.startElseBlock();
+            builder.startThrow().startNew(context.getType(UnexpectedResultException.class)).string(LOCAL_VALUE).end().end();
+            builder.end();
+            return method;
+        }
+
+        private CodeExecutableElement createGetImplicitClass(TypeData type) {
             CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(Class.class), TypeSystemCodeGenerator.getImplicitClass(type));
             method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
 
@@ -340,7 +423,7 @@
             }
 
             builder.startElseBlock();
-            builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
+            builder.tree(createTransferToInterpreterAndInvalidate());
             builder.startThrow().startNew(context.getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end();
             builder.end();