Mercurial > hg > truffle
comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java @ 10600:e93efe3ba5f4
Truffle-DSL: rewritten polymorphic optimization for simpler generated code.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Tue, 02 Jul 2013 14:51:05 +0200 |
parents | 79041ab43660 |
children | b8fe1fe004ec |
comparison
equal
deleted
inserted
replaced
10599:ebf5c5c23564 | 10600:e93efe3ba5f4 |
---|---|
33 | 33 |
34 import com.oracle.truffle.api.dsl.*; | 34 import com.oracle.truffle.api.dsl.*; |
35 import com.oracle.truffle.api.nodes.NodeInfo.Kind; | 35 import com.oracle.truffle.api.nodes.NodeInfo.Kind; |
36 import com.oracle.truffle.dsl.processor.*; | 36 import com.oracle.truffle.dsl.processor.*; |
37 import com.oracle.truffle.dsl.processor.ast.*; | 37 import com.oracle.truffle.dsl.processor.ast.*; |
38 import com.oracle.truffle.dsl.processor.node.NodeChildData.*; | 38 import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality; |
39 import com.oracle.truffle.dsl.processor.node.NodeChildData.ExecutionKind; | |
39 import com.oracle.truffle.dsl.processor.template.*; | 40 import com.oracle.truffle.dsl.processor.template.*; |
41 import com.oracle.truffle.dsl.processor.template.TemplateMethod.*; | |
40 import com.oracle.truffle.dsl.processor.typesystem.*; | 42 import com.oracle.truffle.dsl.processor.typesystem.*; |
41 | 43 |
42 public class NodeCodeGenerator extends CompilationUnitFactory<NodeData> { | 44 public class NodeCodeGenerator extends CompilationUnitFactory<NodeData> { |
43 | 45 |
44 private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode"; | 46 private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode"; |
75 if (nodeid.endsWith("Node") && !nodeid.equals("Node")) { | 77 if (nodeid.endsWith("Node") && !nodeid.equals("Node")) { |
76 nodeid = nodeid.substring(0, nodeid.length() - 4); | 78 nodeid = nodeid.substring(0, nodeid.length() - 4); |
77 } | 79 } |
78 | 80 |
79 String name = Utils.firstLetterUpperCase(nodeid); | 81 String name = Utils.firstLetterUpperCase(nodeid); |
80 int index = specialization == null ? 0 : node.getPolymorphicSpecializations().indexOf(specialization); | 82 if (specialization == node.getGenericPolymorphicSpecializtion()) { |
81 if (index == 0) { | |
82 name += "PolymorphicNode"; | 83 name += "PolymorphicNode"; |
83 } else { | 84 } else { |
84 name += "Polymorphic" + index + "Node"; | 85 name += "Polymorphic" + polymorphicIndex(node, specialization) + "Node"; |
85 } | 86 } |
86 return name; | 87 return name; |
87 } | 88 } |
88 | 89 |
89 private static String valueNameEvaluated(ActualParameter targetParameter) { | 90 private static String valueNameEvaluated(ActualParameter targetParameter) { |
94 return param.getLocalName(); | 95 return param.getLocalName(); |
95 } | 96 } |
96 | 97 |
97 private static String castValueName(ActualParameter parameter) { | 98 private static String castValueName(ActualParameter parameter) { |
98 return valueName(parameter) + "Cast"; | 99 return valueName(parameter) + "Cast"; |
100 } | |
101 | |
102 private static String executeCachedName(SpecializationData polymorphic) { | |
103 NodeData node = polymorphic.getNode(); | |
104 boolean generic = polymorphic == node.getGenericPolymorphicSpecializtion(); | |
105 | |
106 if (generic) { | |
107 return "executeCachedGeneric0"; | |
108 } else { | |
109 return "executeCached" + polymorphicIndex(node, polymorphic); | |
110 } | |
111 } | |
112 | |
113 private static int polymorphicIndex(NodeData node, SpecializationData polymorphic) { | |
114 int index = 0; | |
115 for (SpecializationData specialization : node.getPolymorphicSpecializations()) { | |
116 if (specialization == polymorphic) { | |
117 break; | |
118 } | |
119 if (specialization != node.getGenericPolymorphicSpecializtion()) { | |
120 index++; | |
121 } | |
122 } | |
123 return index; | |
99 } | 124 } |
100 | 125 |
101 private void addInternalValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame, boolean evaluated) { | 126 private void addInternalValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame, boolean evaluated) { |
102 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { | 127 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { |
103 method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue")); | 128 method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue")); |
658 clazz.add(createCreateGenericMethod(node, createVisibility)); | 683 clazz.add(createCreateGenericMethod(node, createVisibility)); |
659 } | 684 } |
660 | 685 |
661 createFactoryMethods(node, clazz, createVisibility); | 686 createFactoryMethods(node, clazz, createVisibility); |
662 | 687 |
663 PolymorphicNodeFactory generic = null; | 688 if (node.getPolymorphicDepth() > 1) { |
664 for (SpecializationData specialization : node.getPolymorphicSpecializations()) { | 689 PolymorphicNodeFactory generic = new PolymorphicNodeFactory(getContext(), generatedNode, true); |
665 PolymorphicNodeFactory polymorphicFactory = new PolymorphicNodeFactory(context, generic == null ? generatedNode : generic.getElement(), generic == null); | 690 add(generic, node.getGenericPolymorphicSpecializtion()); |
666 add(polymorphicFactory, specialization); | 691 |
667 if (generic == null) { | 692 for (SpecializationData specialization : node.getPolymorphicSpecializations()) { |
668 generic = polymorphicFactory; | 693 if (specialization == node.getGenericPolymorphicSpecializtion()) { |
694 continue; | |
695 } | |
696 add(new PolymorphicNodeFactory(context, generic.getElement(), false), specialization); | |
669 } | 697 } |
670 } | 698 } |
671 | |
672 for (SpecializationData specialization : node.getSpecializations()) { | 699 for (SpecializationData specialization : node.getSpecializations()) { |
673 if (!specialization.isReachable()) { | 700 if (!specialization.isReachable()) { |
674 continue; | 701 continue; |
675 } | 702 } |
676 add(new SpecializedNodeFactory(context, generatedNode), specialization); | 703 add(new SpecializedNodeFactory(context, generatedNode), specialization); |
1042 createConstructors(node, clazz); | 1069 createConstructors(node, clazz); |
1043 | 1070 |
1044 return clazz; | 1071 return clazz; |
1045 } | 1072 } |
1046 | 1073 |
1047 protected String typeGetterName(ActualParameter parameter) { | |
1048 return "get" + Utils.firstLetterUpperCase(parameter.getLocalName()) + "Type"; | |
1049 } | |
1050 | |
1051 @Override | 1074 @Override |
1052 protected void createChildren(SpecializationData specialization) { | 1075 protected void createChildren(SpecializationData specialization) { |
1053 NodeData node = specialization.getNode(); | 1076 NodeData node = specialization.getNode(); |
1054 CodeTypeElement clazz = getElement(); | 1077 CodeTypeElement clazz = getElement(); |
1055 | 1078 |
1065 setter.getParameters().add(new CodeVariableElement(clazz.asType(), "next0")); | 1088 setter.getParameters().add(new CodeVariableElement(clazz.asType(), "next0")); |
1066 CodeTreeBuilder builder = setter.createBuilder(); | 1089 CodeTreeBuilder builder = setter.createBuilder(); |
1067 builder.statement("this.next0 = adoptChild(next0)"); | 1090 builder.statement("this.next0 = adoptChild(next0)"); |
1068 clazz.add(setter); | 1091 clazz.add(setter); |
1069 | 1092 |
1070 createTypeGetters(clazz, node.getGenericSpecialization()); | 1093 createIsCompatible(clazz, null); |
1071 | 1094 |
1072 clazz.add(createCreateSpecialization(node)); | 1095 clazz.add(createCreateSpecialization(node)); |
1073 | 1096 |
1074 CodeExecutableElement genericCachedExecute = null; | 1097 CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getGenericPolymorphicSpecializtion(), null); |
1098 clazz.add(genericCachedExecute); | |
1075 for (SpecializationData polymorph : node.getPolymorphicSpecializations()) { | 1099 for (SpecializationData polymorph : node.getPolymorphicSpecializations()) { |
1076 CodeExecutableElement cachedExecute = createCachedExecute(node, polymorph, genericCachedExecute); | 1100 if (polymorph == node.getGenericPolymorphicSpecializtion()) { |
1077 clazz.add(cachedExecute); | 1101 continue; |
1078 if (genericCachedExecute == null) { | |
1079 genericCachedExecute = cachedExecute; | |
1080 } | 1102 } |
1103 clazz.add(createCachedExecute(node, polymorph, genericCachedExecute)); | |
1081 } | 1104 } |
1082 } | 1105 } |
1083 | 1106 |
1084 clazz.add(createGenericExecuteAndSpecialize(node)); | 1107 clazz.add(createGenericExecuteAndSpecialize(node)); |
1085 clazz.add(createInfoMessage(node)); | 1108 clazz.add(createInfoMessage(node)); |
1140 builder.startReturn().string("builder.toString()").end(); | 1163 builder.startReturn().string("builder.toString()").end(); |
1141 | 1164 |
1142 return method; | 1165 return method; |
1143 } | 1166 } |
1144 | 1167 |
1145 protected void createTypeGetters(CodeTypeElement clazz, SpecializationData specialization) { | 1168 protected void createIsCompatible(CodeTypeElement clazz, SpecializationData specialization) { |
1146 for (ActualParameter parameter : specialization.getReturnTypeAndParameters()) { | 1169 CodeExecutableElement isCompatible = new CodeExecutableElement(modifiers(PROTECTED), context.getType(boolean.class), "isCompatible0"); |
1147 if (!parameter.getSpecification().isSignature()) { | 1170 isCompatible.addParameter(new CodeVariableElement(getContext().getType(Class.class), "type")); |
1148 continue; | 1171 |
1149 } | 1172 if (specialization == null) { |
1150 CodeExecutableElement typeGetter = new CodeExecutableElement(modifiers(PROTECTED), context.getType(Class.class), typeGetterName(parameter)); | 1173 isCompatible.getModifiers().add(ABSTRACT); |
1151 CodeTreeBuilder builder = typeGetter.createBuilder(); | 1174 } else if (specialization.isGeneric()) { |
1152 builder.startReturn().typeLiteral(parameter.getType()).end(); | 1175 isCompatible.createBuilder().startThrow().startNew(getContext().getType(AssertionError.class)).end().end(); |
1153 clazz.add(typeGetter); | 1176 } else if (specialization.isPolymorphic()) { |
1154 } | 1177 isCompatible.createBuilder().startReturn().string("type != getClass() && next0.isCompatible0(type)").end(); |
1178 } else if (specialization.isUninitialized()) { | |
1179 isCompatible.createBuilder().returnTrue(); | |
1180 } else { | |
1181 NodeData node = specialization.getNode(); | |
1182 CodeTreeBuilder builder = isCompatible.createBuilder(); | |
1183 | |
1184 Signature specializationSignature = specialization.getSignature(); | |
1185 List<SpecializationData> compatible = new ArrayList<>(); | |
1186 for (SpecializationData polymorphic : node.getPolymorphicSpecializations()) { | |
1187 if (specializationSignature.isCompatibleTo(polymorphic.getSignature())) { | |
1188 compatible.add(polymorphic); | |
1189 } | |
1190 } | |
1191 | |
1192 if (compatible.isEmpty()) { | |
1193 builder.returnFalse(); | |
1194 } else { | |
1195 builder.startIf(); | |
1196 String and = ""; | |
1197 for (SpecializationData polymorphic : compatible) { | |
1198 builder.string(and); | |
1199 builder.string("type == ").string(nodePolymorphicClassName(node, polymorphic)).string(".class"); | |
1200 and = " || "; | |
1201 } | |
1202 builder.end().startBlock(); | |
1203 builder.startReturn().startCall("next0", "isCompatible0").string("type").end().end(); | |
1204 builder.end(); | |
1205 builder.returnFalse(); | |
1206 } | |
1207 } | |
1208 | |
1209 clazz.add(isCompatible); | |
1155 } | 1210 } |
1156 | 1211 |
1157 private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph, CodeExecutableElement genericPolymorphMethod) { | 1212 private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph, CodeExecutableElement genericPolymorphMethod) { |
1158 int index = node.getPolymorphicSpecializations().indexOf(polymorph); | 1213 String name = executeCachedName(polymorph); |
1159 assert index != -1; | |
1160 boolean generic = index == 0; | |
1161 | |
1162 String name = "executeCached" + index; | |
1163 CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED), polymorph.getReturnType().getType(), name); | 1214 CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED), polymorph.getReturnType().getType(), name); |
1164 addInternalValueParameters(cachedExecute, polymorph, true, true); | 1215 addInternalValueParameters(cachedExecute, polymorph, true, true); |
1165 | 1216 |
1166 if (generic) { | 1217 if (polymorph == node.getGenericPolymorphicSpecializtion()) { |
1167 cachedExecute.getModifiers().add(ABSTRACT); | 1218 cachedExecute.getModifiers().add(ABSTRACT); |
1168 } else { | 1219 } else { |
1169 SpecializationData genericPolymorph = node.getPolymorphicSpecializations().get(0); | 1220 SpecializationData genericPolymorph = node.getGenericPolymorphicSpecializtion(); |
1170 CodeTreeBuilder builder = cachedExecute.createBuilder(); | 1221 CodeTreeBuilder builder = cachedExecute.createBuilder(); |
1171 ExecutableTypeData genericExecutable = new ExecutableTypeData(genericPolymorph, genericPolymorphMethod, node.getTypeSystem(), genericPolymorph.getReturnType().getTypeSystemType()); | 1222 ExecutableTypeData genericExecutable = new ExecutableTypeData(genericPolymorph, genericPolymorphMethod, node.getTypeSystem(), genericPolymorph.getReturnType().getTypeSystemType()); |
1172 ExecutableTypeData specificExecutable = new ExecutableTypeData(polymorph, cachedExecute, node.getTypeSystem(), polymorph.getReturnType().getTypeSystemType()); | 1223 ExecutableTypeData specificExecutable = new ExecutableTypeData(polymorph, cachedExecute, node.getTypeSystem(), polymorph.getReturnType().getTypeSystemType()); |
1173 builder.tree(createCastingExecute(builder, polymorph, specificExecutable, genericExecutable)); | 1224 builder.tree(createCastingExecute(builder, polymorph, specificExecutable, genericExecutable)); |
1174 } | 1225 } |
1474 builder.end().startElseBlock(); | 1525 builder.end().startElseBlock(); |
1475 builder.statement("Node searchNode = super.getParent()"); | 1526 builder.statement("Node searchNode = super.getParent()"); |
1476 builder.startWhile().string("searchNode != null").end(); | 1527 builder.startWhile().string("searchNode != null").end(); |
1477 builder.startBlock(); | 1528 builder.startBlock(); |
1478 builder.statement("searchNode = searchNode.getParent()"); | 1529 builder.statement("searchNode = searchNode.getParent()"); |
1479 builder.startIf().instanceOf("searchNode", nodePolymorphicClassName(node, node.getPolymorphicSpecializations().get(0))).end(); | 1530 builder.startIf().instanceOf("searchNode", nodePolymorphicClassName(node, node.getGenericPolymorphicSpecializtion())).end(); |
1480 builder.startBlock().breakStatement().end(); | 1531 builder.startBlock().breakStatement().end(); |
1481 builder.end(); | 1532 builder.end(); |
1482 builder.startStatement().startCall("searchNode", "replace"); | 1533 builder.startStatement().startCall("searchNode", "replace"); |
1483 builder.startGroup().startNew(nodeSpecializationClassName(current)).startGroup().cast(baseClassName(node)).string("searchNode").end().end().end(); | 1534 builder.startGroup().startNew(nodeSpecializationClassName(current)).startGroup().cast(baseClassName(node)).string("searchNode").end().end().end(); |
1484 builder.string("message"); | 1535 builder.string("message"); |
1533 builder.end().end(); | 1584 builder.end().end(); |
1534 return builder.getRoot(); | 1585 return builder.getRoot(); |
1535 } | 1586 } |
1536 | 1587 |
1537 private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node) { | 1588 private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node) { |
1589 String className = nodePolymorphicClassName(node, node.getGenericPolymorphicSpecializtion()); | |
1538 CodeTreeBuilder builder = parent.create(); | 1590 CodeTreeBuilder builder = parent.create(); |
1539 builder.startStatement(); | 1591 builder.startStatement(); |
1540 builder.string(nodePolymorphicClassName(node, null)); | 1592 builder.string(className); |
1541 builder.string(" polymorphic = "); | 1593 builder.string(" polymorphic = "); |
1542 builder.startNew(nodePolymorphicClassName(node, null)).string("this").end(); | 1594 builder.startNew(className).string("this").end(); |
1543 builder.end(); | 1595 builder.end(); |
1544 for (NodeChildData child : node.getChildren()) { | 1596 for (NodeChildData child : node.getChildren()) { |
1545 builder.startStatement().string("this.").string(child.getName()).string(" = null").end(); | 1597 builder.startStatement().string("this.").string(child.getName()).string(" = null").end(); |
1546 } | 1598 } |
1547 builder.startStatement().startCall("super", "replace"); | 1599 builder.startStatement().startCall("super", "replace"); |
1774 } | 1826 } |
1775 | 1827 |
1776 private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, SpecializationData specialization, ActualParameter param) { | 1828 private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, SpecializationData specialization, ActualParameter param) { |
1777 NodeData node = specialization.getNode(); | 1829 NodeData node = specialization.getNode(); |
1778 assert !node.getPolymorphicSpecializations().isEmpty(); | 1830 assert !node.getPolymorphicSpecializations().isEmpty(); |
1779 SpecializationData generic = node.getPolymorphicSpecializations().get(0); | 1831 SpecializationData generic = node.getGenericPolymorphicSpecializtion(); |
1780 | 1832 |
1781 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 1833 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
1782 builder.startReturn(); | 1834 builder.startReturn(); |
1783 | 1835 |
1784 CodeTreeBuilder execute = new CodeTreeBuilder(builder); | 1836 CodeTreeBuilder execute = new CodeTreeBuilder(builder); |
1785 execute.startCall("next0", "executeCached0"); | 1837 execute.startCall("next0", executeCachedName(generic)); |
1786 addInternalValueParameterNames(execute, specialization, generic, param.getLocalName(), true, true); | 1838 addInternalValueParameterNames(execute, specialization, generic, param.getLocalName(), true, true); |
1787 execute.end(); | 1839 execute.end(); |
1788 | 1840 |
1789 TypeData sourceType = generic.getReturnType().getTypeSystemType(); | 1841 TypeData sourceType = generic.getReturnType().getTypeSystemType(); |
1790 TypeData targetType = specialization.getReturnType().getTypeSystemType(); | 1842 TypeData targetType = specialization.getReturnType().getTypeSystemType(); |
1963 return clazz; | 2015 return clazz; |
1964 } | 2016 } |
1965 | 2017 |
1966 @Override | 2018 @Override |
1967 protected void createChildren(SpecializationData specialization) { | 2019 protected void createChildren(SpecializationData specialization) { |
1968 // super.createChildren(specialization); | |
1969 CodeTypeElement clazz = getElement(); | 2020 CodeTypeElement clazz = getElement(); |
1970 | 2021 |
1971 createConstructors(clazz); | 2022 createConstructors(clazz); |
1972 createExecuteMethods(specialization); | 2023 createExecuteMethods(specialization); |
1973 | 2024 |
1974 if (generic) { | 2025 if (generic) { |
1975 getElement().add(createOptimizeTypes()); | 2026 getElement().add(createOptimizeTypes()); |
1976 createCachedExecuteMethods(specialization); | 2027 createCachedExecuteMethods(specialization); |
2028 createIsCompatible(clazz, specialization); | |
1977 } | 2029 } |
1978 } | 2030 } |
1979 | 2031 |
1980 private CodeExecutableElement createOptimizeTypes() { | 2032 private CodeExecutableElement createOptimizeTypes() { |
1981 NodeData node = getModel().getNode(); | 2033 NodeData node = getModel().getNode(); |
1982 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), getContext().getType(void.class), "optimizeTypes"); | 2034 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), getContext().getType(void.class), "optimizeTypes"); |
1983 CodeTreeBuilder builder = method.createBuilder(); | 2035 CodeTreeBuilder builder = method.createBuilder(); |
1984 builder.startStatement().string(baseClassName(node)).string(" node = this.next0").end(); | |
1985 TypeMirror classType = getContext().getType(Class.class); | |
1986 | |
1987 SpecializationData genericSpecialization = node.getGenericSpecialization(); | |
1988 | |
1989 CodeTreeBuilder whileBodyBuilder = builder.create(); | |
1990 for (ActualParameter parameter : node.getGenericSpecialization().getReturnTypeAndParameters()) { | |
1991 if (!parameter.getSpecification().isSignature()) { | |
1992 continue; | |
1993 } | |
1994 | |
1995 ActualParameter genericParameter = genericSpecialization.findParameter(parameter.getLocalName()); | |
1996 | |
1997 String name = parameter.getLocalName() + "Type"; | |
1998 | |
1999 builder.declaration(classType, name, builder.create().startCall("node", typeGetterName(parameter)).end().getRoot()); | |
2000 | |
2001 whileBodyBuilder.startIf().string(name).string(" != ").startCall("node", typeGetterName(parameter)).end().end(); | |
2002 whileBodyBuilder.startBlock(); | |
2003 whileBodyBuilder.startStatement().string(name).string(" = ").typeLiteral(genericParameter.getType()).end(); | |
2004 whileBodyBuilder.end(); | |
2005 } | |
2006 | |
2007 builder.startWhile().string("node != null && !(").instanceOf("node", nodeSpecializationClassName(node.getUninitializedSpecialization())).string(")").end(); | |
2008 builder.startBlock(); | |
2009 builder.tree(whileBodyBuilder.getRoot()); | |
2010 builder.statement("node = node.next0"); | |
2011 builder.end(); | |
2012 | 2036 |
2013 boolean elseIf = false; | 2037 boolean elseIf = false; |
2014 for (SpecializationData polymorph : node.getPolymorphicSpecializations()) { | 2038 for (SpecializationData polymorphic : node.getPolymorphicSpecializations()) { |
2015 elseIf = builder.startIf(elseIf); | 2039 String className = nodePolymorphicClassName(node, polymorphic); |
2016 String and = ""; | 2040 |
2041 String sep = ""; | |
2017 StringBuilder reason = new StringBuilder("Optimized polymorphic types for ("); | 2042 StringBuilder reason = new StringBuilder("Optimized polymorphic types for ("); |
2018 for (ActualParameter parameter : polymorph.getReturnTypeAndParameters()) { | 2043 for (ActualParameter parameter : polymorphic.getReturnTypeAndParameters()) { |
2019 if (!parameter.getSpecification().isSignature()) { | 2044 if (!parameter.getSpecification().isSignature()) { |
2020 continue; | 2045 continue; |
2021 } | 2046 } |
2022 String name = parameter.getLocalName() + "Type"; | 2047 reason.append(sep).append(Utils.getSimpleName(parameter.getType())); |
2023 builder.string(and).string(name).string(" == ").typeLiteral(parameter.getType()); | 2048 sep = ", "; |
2024 | |
2025 if (!and.isEmpty()) { | |
2026 reason.append(", "); | |
2027 } | |
2028 reason.append(Utils.getSimpleName(parameter.getType())); | |
2029 and = " && "; | |
2030 } | 2049 } |
2031 reason.append(")"); | 2050 reason.append(")"); |
2032 builder.end(); | 2051 |
2033 builder.startBlock(); | 2052 elseIf = builder.startIf(elseIf); |
2034 | 2053 builder.startCall("isCompatible0"); |
2035 String className = nodePolymorphicClassName(node, polymorph); | 2054 builder.startGroup().string(className).string(".class").end(); |
2036 builder.startIf().string("getClass() != ").string(className).string(".class").end(); | 2055 builder.end().end().startBlock(); |
2037 builder.startBlock(); | 2056 |
2038 builder.startStatement().startCall("super", "replace"); | 2057 builder.startStatement().startCall("super", "replace"); |
2039 builder.startNew(className).string("this").end(); | 2058 builder.startNew(className).string("this").end(); |
2040 builder.doubleQuote(reason.toString()); | 2059 builder.doubleQuote(reason.toString()); |
2041 builder.end().end(); // call | 2060 builder.end().end(); // call |
2042 builder.end(); // block | |
2043 builder.end(); | 2061 builder.end(); |
2044 } | 2062 } |
2045 return method; | 2063 return method; |
2046 } | 2064 } |
2047 } | 2065 } |
2096 CodeTypeElement clazz = getElement(); | 2114 CodeTypeElement clazz = getElement(); |
2097 createConstructors(clazz); | 2115 createConstructors(clazz); |
2098 | 2116 |
2099 NodeData node = specialization.getNode(); | 2117 NodeData node = specialization.getNode(); |
2100 | 2118 |
2101 if (!specialization.isGeneric() && !specialization.isUninitialized() && !specialization.isPolymorphic() && node.needsRewrites(getContext()) && node.getPolymorphicDepth() > 1) { | 2119 if (node.needsRewrites(getContext()) && node.getPolymorphicDepth() > 1) { |
2102 | 2120 createIsCompatible(clazz, specialization); |
2103 createTypeGetters(clazz, specialization); | |
2104 } | 2121 } |
2105 | 2122 |
2106 createExecuteMethods(specialization); | 2123 createExecuteMethods(specialization); |
2107 createCachedExecuteMethods(specialization); | 2124 createCachedExecuteMethods(specialization); |
2108 } | 2125 } |
2150 } | 2167 } |
2151 | 2168 |
2152 protected void createCachedExecuteMethods(SpecializationData specialization) { | 2169 protected void createCachedExecuteMethods(SpecializationData specialization) { |
2153 NodeData node = specialization.getNode(); | 2170 NodeData node = specialization.getNode(); |
2154 CodeTypeElement clazz = getElement(); | 2171 CodeTypeElement clazz = getElement(); |
2155 int index = 0; | |
2156 for (SpecializationData polymorphic : node.getPolymorphicSpecializations()) { | 2172 for (SpecializationData polymorphic : node.getPolymorphicSpecializations()) { |
2157 boolean matchFound = false; | 2173 if (!specialization.getSignature().isCompatibleTo(polymorphic.getSignature())) { |
2158 if (!specialization.isGeneric() && !specialization.isUninitialized() && !specialization.isPolymorphic()) { | 2174 continue; |
2159 matchFound = polymorphic.getSignature().hasAnyParameterMatch(specialization.getSignature()); | 2175 } |
2160 } | 2176 ExecutableElement executeCached = nodeGen.getMethod(executeCachedName(polymorphic)); |
2161 | 2177 ExecutableTypeData execType = new ExecutableTypeData(polymorphic, executeCached, node.getTypeSystem(), polymorphic.getReturnType().getTypeSystemType()); |
2162 if (matchFound || index == 0) { | 2178 |
2163 ExecutableElement executeCached = nodeGen.getMethod("executeCached" + index); | 2179 CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, false); |
2164 ExecutableTypeData execType = new ExecutableTypeData(polymorphic, executeCached, node.getTypeSystem(), polymorphic.getReturnType().getTypeSystemType()); | 2180 CodeTreeBuilder builder = executeMethod.createBuilder(); |
2165 | 2181 |
2166 CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, false); | 2182 if (specialization.isGeneric() || specialization.isPolymorphic()) { |
2167 CodeTreeBuilder builder = executeMethod.createBuilder(); | 2183 builder.startThrow().startNew(getContext().getType(AssertionError.class)); |
2168 | 2184 builder.doubleQuote("Should not be reached."); |
2169 if (specialization.isGeneric() || specialization.isPolymorphic()) { | 2185 builder.end().end(); |
2170 builder.startThrow().startNew(getContext().getType(AssertionError.class)); | 2186 } else if (specialization.isUninitialized()) { |
2171 builder.doubleQuote("Should not be reached."); | 2187 builder.tree(createAppendPolymorphic(builder, specialization)); |
2172 builder.end().end(); | 2188 } else { |
2173 } else if (specialization.isUninitialized()) { | 2189 CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder); |
2174 builder.tree(createAppendPolymorphic(builder, specialization)); | 2190 elseBuilder.startReturn().startCall("this.next0", executeCachedName(polymorphic)); |
2175 } else { | 2191 addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, true); |
2176 CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder); | 2192 elseBuilder.end().end(); |
2177 elseBuilder.startReturn().startCall("this.next0", "executeCached" + index); | 2193 CodeTreeBuilder execute = new CodeTreeBuilder(builder); |
2178 addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, true); | 2194 execute.tree(createGenericInvoke(builder, polymorphic, specialization)); |
2179 elseBuilder.end().end(); | 2195 boolean forceElse = !specialization.getExceptions().isEmpty(); |
2180 CodeTreeBuilder execute = new CodeTreeBuilder(builder); | 2196 builder.tree(createGuardAndCast(builder, null, polymorphic, specialization, true, execute.getRoot(), elseBuilder.getRoot(), true, forceElse)); |
2181 execute.tree(createGenericInvoke(builder, polymorphic, specialization)); | 2197 } |
2182 boolean forceElse = !specialization.getExceptions().isEmpty(); | 2198 clazz.add(executeMethod); |
2183 builder.tree(createGuardAndCast(builder, null, polymorphic, specialization, true, execute.getRoot(), elseBuilder.getRoot(), true, forceElse)); | |
2184 } | |
2185 clazz.add(executeMethod); | |
2186 } | |
2187 index++; | |
2188 } | 2199 } |
2189 } | 2200 } |
2190 | 2201 |
2191 private CodeTree createAppendPolymorphic(CodeTreeBuilder parent, SpecializationData specialization) { | 2202 private CodeTree createAppendPolymorphic(CodeTreeBuilder parent, SpecializationData specialization) { |
2192 NodeData node = specialization.getNode(); | 2203 NodeData node = specialization.getNode(); |
2193 String genericClassName = nodePolymorphicClassName(node, null); | 2204 String genericClassName = nodePolymorphicClassName(node, node.getGenericPolymorphicSpecializtion()); |
2194 | 2205 |
2195 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 2206 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
2196 builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end(); | 2207 builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end(); |
2197 | 2208 |
2198 builder.declaration(getContext().getTruffleTypes().getNode(), "searchNode", "super.getParent()"); | 2209 builder.declaration(getContext().getTruffleTypes().getNode(), "searchNode", "super.getParent()"); |
2374 builder.end(); | 2385 builder.end(); |
2375 } | 2386 } |
2376 | 2387 |
2377 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent); | 2388 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent); |
2378 if (specialization.isPolymorphic()) { | 2389 if (specialization.isPolymorphic()) { |
2379 int index = 0; | 2390 returnBuilder.startCall("next0", executeCachedName(specialization)); |
2380 if (executable.hasUnexpectedValue(getContext())) { | |
2381 index = specialization.getNode().getPolymorphicSpecializations().indexOf(specialization); | |
2382 } | |
2383 returnBuilder.startCall("next0", "executeCached" + index); | |
2384 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true); | 2391 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true); |
2385 returnBuilder.end(); | 2392 returnBuilder.end(); |
2386 } else if (specialization.isUninitialized()) { | 2393 } else if (specialization.isUninitialized()) { |
2387 returnBuilder.startCall("super", EXECUTE_SPECIALIZE_NAME); | 2394 returnBuilder.startCall("super", EXECUTE_SPECIALIZE_NAME); |
2388 returnBuilder.startGroup().string(nodeSpecializationClassName(specialization)).string(".class").end(); | 2395 returnBuilder.startGroup().string(nodeSpecializationClassName(specialization)).string(".class").end(); |