comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java @ 12391:7aa2a8c69ba3

TruffleDSL: improved code generation layout for implicit casts.
author Christian Humer <christian.humer@gmail.com>
date Thu, 03 Oct 2013 16:31:09 +0200
parents c287d13cb8b0
children 4e26955b6da2
comparison
equal deleted inserted replaced
12390:5151a7588384 12391:7aa2a8c69ba3
40 import com.oracle.truffle.dsl.processor.node.NodeChildData.ExecutionKind; 40 import com.oracle.truffle.dsl.processor.node.NodeChildData.ExecutionKind;
41 import com.oracle.truffle.dsl.processor.node.SpecializationGroup.TypeGuard; 41 import com.oracle.truffle.dsl.processor.node.SpecializationGroup.TypeGuard;
42 import com.oracle.truffle.dsl.processor.template.*; 42 import com.oracle.truffle.dsl.processor.template.*;
43 import com.oracle.truffle.dsl.processor.template.TemplateMethod.Signature; 43 import com.oracle.truffle.dsl.processor.template.TemplateMethod.Signature;
44 import com.oracle.truffle.dsl.processor.typesystem.*; 44 import com.oracle.truffle.dsl.processor.typesystem.*;
45 import com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBaseIterators.*;
45 46
46 public class NodeCodeGenerator extends CompilationUnitFactory<NodeData> { 47 public class NodeCodeGenerator extends CompilationUnitFactory<NodeData> {
47 48
48 private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode"; 49 private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode";
49 50
951 } 952 }
952 clazz.add(createCachedExecute(node, polymorph, genericCachedExecute)); 953 clazz.add(createCachedExecute(node, polymorph, genericCachedExecute));
953 } 954 }
954 } 955 }
955 956
957 for (CodeExecutableElement method : createImplicitChildrenAccessors(node, clazz)) {
958 clazz.add(method);
959 }
960
956 clazz.add(createGenericExecuteAndSpecialize(node, rootGroup)); 961 clazz.add(createGenericExecuteAndSpecialize(node, rootGroup));
957 clazz.add(createInfoMessage(node)); 962 clazz.add(createInfoMessage(node));
958 } 963 }
959 964
960 if (node.getGenericSpecialization() != null && node.getGenericSpecialization().isReachable()) { 965 if (node.getGenericSpecialization() != null && node.getGenericSpecialization().isReachable()) {
961 clazz.add(createGenericExecute(node, rootGroup)); 966 clazz.add(createGenericExecute(node, rootGroup));
962 } 967 }
968 }
969
970 private List<CodeExecutableElement> createImplicitChildrenAccessors(NodeData node, CodeTypeElement clazz) {
971 List<CodeExecutableElement> methods = new ArrayList<>();
972 Map<NodeChildData, Set<TypeData>> expectTypes = new HashMap<>();
973 for (ExecutableTypeData executableType : node.getExecutableTypes()) {
974 for (int i = 0; i < executableType.getEvaluatedCount(); i++) {
975 ActualParameter parameter = executableType.getSignatureParameter(i);
976 NodeChildData child = node.findChild(parameter.getSpecification().getName());
977 Set<TypeData> types = expectTypes.get(child);
978 if (types == null) {
979 types = new TreeSet<>();
980 expectTypes.put(child, types);
981 }
982 types.add(parameter.getTypeSystemType());
983 }
984 }
985
986 Map<NodeChildData, Set<TypeData>> visitedMap = new HashMap<>();
987 for (SpecializationData spec : node.getSpecializations()) {
988 for (ActualParameter param : spec.getParameters()) {
989 if (!param.getSpecification().isSignature()) {
990 continue;
991 }
992 NodeChildData child = node.findChild(param.getSpecification().getName());
993 Set<TypeData> visitedTypeData = visitedMap.get(child);
994 if (visitedTypeData == null) {
995 visitedTypeData = new TreeSet<>();
996 visitedMap.put(child, visitedTypeData);
997 }
998 if (visitedTypeData.contains(param.getTypeSystemType())) {
999 continue;
1000 }
1001 visitedTypeData.add(param.getTypeSystemType());
1002
1003 Set<TypeData> expect = expectTypes.get(child);
1004 if (expect == null) {
1005 expect = Collections.emptySet();
1006 }
1007
1008 methods.addAll(createExecuteChilds(param, expect));
1009 }
1010 }
1011 return methods;
963 } 1012 }
964 1013
965 private CodeTree truffleBooleanOption(CodeTreeBuilder parent, String name) { 1014 private CodeTree truffleBooleanOption(CodeTreeBuilder parent, String name) {
966 CodeTreeBuilder builder = parent.create(); 1015 CodeTreeBuilder builder = parent.create();
967 builder.staticReference(getContext().getTruffleTypes().getTruffleOptions(), name); 1016 builder.staticReference(getContext().getTruffleTypes().getTruffleOptions(), name);
1944 1993
1945 private CodeTree createExecutionExpresssions(CodeTreeBuilder parent, NodeChildData child, ExecutableTypeData sourceExecutable, ExecutableTypeData targetExecutable, ActualParameter param, 1994 private CodeTree createExecutionExpresssions(CodeTreeBuilder parent, NodeChildData child, ExecutableTypeData sourceExecutable, ExecutableTypeData targetExecutable, ActualParameter param,
1946 ActualParameter unexpectedParameter) { 1995 ActualParameter unexpectedParameter) {
1947 CodeTreeBuilder builder = parent.create(); 1996 CodeTreeBuilder builder = parent.create();
1948 1997
1949 TypeData type = param.getTypeSystemType(); 1998 ActualParameter sourceParameter = sourceExecutable.findParameter(param.getLocalName());
1950 List<TypeData> targetTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(type); 1999
1951 2000 String childExecuteName = createExecuteChildMethodName(param, sourceParameter != null);
1952 if (targetTypes.size() > 1) { 2001 if (childExecuteName != null) {
1953 boolean elseIf = false; 2002 builder.string(valueName(param));
1954 int index = 0; 2003 builder.string(" = ");
1955 for (TypeData typeData : targetTypes) { 2004 builder.startCall(childExecuteName);
1956 if (index < targetTypes.size() - 1) { 2005
1957 elseIf = builder.startIf(elseIf); 2006 for (ActualParameter parameters : sourceExecutable.getParameters()) {
1958 builder.string(typeName(param)).string(" == ").typeLiteral(typeData.getPrimitiveType()); 2007 if (parameters.getSpecification().isSignature()) {
1959 builder.end(); 2008 continue;
1960 builder.startBlock(); 2009 }
1961 } else { 2010 builder.string(parameters.getLocalName());
1962 builder.startElseBlock(); 2011 }
1963 } 2012
1964 2013 if (sourceParameter != null) {
1965 ExecutableTypeData implictExecutableTypeData = child.getNodeData().findExecutableType(typeData, targetExecutable.getEvaluatedCount()); 2014 builder.string(valueNameEvaluated(sourceParameter));
1966 ImplicitCastData cast = child.getNodeData().getTypeSystem().lookupCast(typeData, param.getTypeSystemType()); 2015 }
1967 CodeTree execute = createExecuteExpression(parent, child, sourceExecutable, implictExecutableTypeData, param, unexpectedParameter, cast); 2016
1968 builder.statement(execute); 2017 builder.string(typeName(param));
2018
2019 builder.end();
2020 } else {
2021 TypeData expectType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null;
2022 builder.tree(createExecuteExpression(parent, child, expectType, targetExecutable, param, unexpectedParameter, null));
2023 }
2024 return builder.getRoot();
2025 }
2026
2027 private String createExecuteChildMethodName(ActualParameter param, boolean expect) {
2028 NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName());
2029 List<TypeData> sourceTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
2030 if (sourceTypes.size() <= 1) {
2031 return null;
2032 }
2033 String prefix = expect ? "expect" : "execute";
2034 return prefix + Utils.firstLetterUpperCase(child.getName()) + Utils.firstLetterUpperCase(Utils.getSimpleName(param.getType())) + param.getIndex();
2035 }
2036
2037 private List<CodeExecutableElement> createExecuteChilds(ActualParameter param, Set<TypeData> expectTypes) {
2038 CodeExecutableElement executeMethod = createExecuteChild(param, null);
2039 if (executeMethod == null) {
2040 return Collections.emptyList();
2041 }
2042 List<CodeExecutableElement> childs = new ArrayList<>();
2043 childs.add(executeMethod);
2044
2045 for (TypeData expectType : expectTypes) {
2046 CodeExecutableElement method = createExecuteChild(param, expectType);
2047 if (method != null) {
2048 childs.add(method);
2049 }
2050 }
2051 return childs;
2052 }
2053
2054 private CodeExecutableElement createExecuteChild(ActualParameter param, TypeData expectType) {
2055 String childExecuteName = createExecuteChildMethodName(param, expectType != null);
2056 if (childExecuteName == null) {
2057 return null;
2058 }
2059
2060 NodeData node = getModel().getNode();
2061 NodeChildData child = node.findChild(param.getSpecification().getName());
2062 List<TypeData> sourceTypes = node.getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
2063 assert sourceTypes.size() >= 1;
2064
2065 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, expectType != null ? STATIC : FINAL), param.getType(), childExecuteName);
2066
2067 method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue"));
2068 if (expectType != null) {
2069 method.addParameter(new CodeVariableElement(expectType.getPrimitiveType(), valueNameEvaluated(param)));
2070 }
2071 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), typeName(param)));
2072 CodeTreeBuilder builder = method.createBuilder();
2073
2074 builder.declaration(param.getType(), valueName(param));
2075
2076 boolean unexpected = false;
2077 boolean elseIf = false;
2078 int index = 0;
2079 for (TypeData typeData : sourceTypes) {
2080 if (index < sourceTypes.size() - 1) {
2081 elseIf = builder.startIf(elseIf);
2082 builder.string(typeName(param)).string(" == ").typeLiteral(typeData.getPrimitiveType());
1969 builder.end(); 2083 builder.end();
1970 index++; 2084 builder.startBlock();
1971 } 2085 } else {
1972 } else { 2086 builder.startElseBlock();
1973 builder.tree(createExecuteExpression(parent, child, sourceExecutable, targetExecutable, param, unexpectedParameter, null)); 2087 }
1974 } 2088
1975 return builder.getRoot(); 2089 ExecutableTypeData implictExecutableTypeData = child.getNodeData().findExecutableType(typeData, child.getExecuteWith().size());
1976 } 2090 if (!unexpected && implictExecutableTypeData.hasUnexpectedValue(getContext())) {
1977 2091 unexpected = true;
1978 private CodeTree createExecuteExpression(CodeTreeBuilder parent, NodeChildData child, ExecutableTypeData sourceExecutable, ExecutableTypeData targetExecutable, 2092 }
1979 ActualParameter targetParameter, ActualParameter unexpectedParameter, ImplicitCastData cast) { 2093 ImplicitCastData cast = child.getNodeData().getTypeSystem().lookupCast(typeData, param.getTypeSystemType());
2094 CodeTree execute = createExecuteExpression(builder, child, expectType, implictExecutableTypeData, param, null, cast);
2095 builder.statement(execute);
2096 builder.end();
2097 index++;
2098 }
2099
2100 builder.startReturn().string(valueName(param)).end();
2101
2102 if (unexpected) {
2103 method.getThrownTypes().add(getContext().getTruffleTypes().getUnexpectedValueException());
2104 }
2105
2106 return method;
2107 }
2108
2109 private CodeTree createExecuteExpression(CodeTreeBuilder parent, NodeChildData child, TypeData expectType, ExecutableTypeData targetExecutable, ActualParameter targetParameter,
2110 ActualParameter unexpectedParameter, ImplicitCastData cast) {
1980 CodeTreeBuilder builder = parent.create(); 2111 CodeTreeBuilder builder = parent.create();
1981 builder.string(valueName(targetParameter)); 2112 builder.string(valueName(targetParameter));
1982 builder.string(" = "); 2113 builder.string(" = ");
1983 if (cast != null) { 2114 if (cast != null) {
1984 startCallTypeSystemMethod(getContext(), builder, child.getNodeData(), cast.getMethodName()); 2115 startCallTypeSystemMethod(getContext(), builder, child.getNodeData(), cast.getMethodName());
1987 if (targetExecutable.getType().needsCastTo(context, targetParameter.getTypeSystemType()) && cast == null) { 2118 if (targetExecutable.getType().needsCastTo(context, targetParameter.getTypeSystemType()) && cast == null) {
1988 startCallTypeSystemMethod(getContext(), builder, child.getNodeData(), TypeSystemCodeGenerator.expectTypeMethodName(targetParameter.getTypeSystemType())); 2119 startCallTypeSystemMethod(getContext(), builder, child.getNodeData(), TypeSystemCodeGenerator.expectTypeMethodName(targetParameter.getTypeSystemType()));
1989 } 2120 }
1990 2121
1991 NodeData node = getModel().getNode(); 2122 NodeData node = getModel().getNode();
1992 ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName()); 2123 if (expectType == null) {
1993 if (sourceParameter == null) {
1994 builder.tree(createExecuteChildExpression(builder, child, targetParameter, targetExecutable, unexpectedParameter)); 2124 builder.tree(createExecuteChildExpression(builder, child, targetParameter, targetExecutable, unexpectedParameter));
1995 } else { 2125 } else {
1996 CodeTree var = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter)); 2126 CodeTree var = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter));
1997 builder.tree(createExpectExecutableType(node, sourceParameter.getTypeSystemType(), targetExecutable, var)); 2127 builder.tree(createExpectExecutableType(node, expectType, targetExecutable, var));
1998 } 2128 }
1999 2129
2000 if (targetExecutable.getType().needsCastTo(context, targetParameter.getTypeSystemType())) { 2130 if (targetExecutable.getType().needsCastTo(context, targetParameter.getTypeSystemType())) {
2001 builder.end().end(); 2131 builder.end().end();
2002 } 2132 }