Mercurial > hg > graal-compiler
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 } |