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();