comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java @ 18785:93016f2f3f16

Truffle-DSL: optimize generated code for nodes with a single specialization. (GRAAL-602 #resolve)
author Christian Humer <christian.humer@gmail.com>
date Mon, 05 Jan 2015 20:23:22 +0100
parents f4d78e4a878d
children 6fe1d34a7b6e
comparison
equal deleted inserted replaced
18784:3c7d543d758d 18785:93016f2f3f16
57 private final ProcessorContext context; 57 private final ProcessorContext context;
58 private final NodeData node; 58 private final NodeData node;
59 private final TypeSystemData typeSystem; 59 private final TypeSystemData typeSystem;
60 private final TypeData genericType; 60 private final TypeData genericType;
61 private final DSLOptions options; 61 private final DSLOptions options;
62 private final boolean singleSpecializable;
62 63
63 public NodeGenFactory(ProcessorContext context, NodeData node) { 64 public NodeGenFactory(ProcessorContext context, NodeData node) {
64 this.context = context; 65 this.context = context;
65 this.node = node; 66 this.node = node;
66 this.typeSystem = node.getTypeSystem(); 67 this.typeSystem = node.getTypeSystem();
67 this.genericType = typeSystem.getGenericTypeData(); 68 this.genericType = typeSystem.getGenericTypeData();
68 this.options = typeSystem.getOptions(); 69 this.options = typeSystem.getOptions();
70 this.singleSpecializable = isSingleSpecializableImpl();
69 } 71 }
70 72
71 public static String nodeTypeName(NodeData node) { 73 public static String nodeTypeName(NodeData node) {
72 return resolveNodeId(node) + "NodeGen"; 74 return resolveNodeId(node) + "NodeGen";
73 } 75 }
83 public static TypeMirror nodeType(NodeData node) { 85 public static TypeMirror nodeType(NodeData node) {
84 return new GeneratedTypeMirror(ElementUtils.getPackageName(node.getTemplateType()), nodeTypeName(node)); 86 return new GeneratedTypeMirror(ElementUtils.getPackageName(node.getTemplateType()), nodeTypeName(node));
85 } 87 }
86 88
87 private static String specializationTypeName(SpecializationData specialization) { 89 private static String specializationTypeName(SpecializationData specialization) {
88 return specialization.getId() + "Node_"; 90 String id;
89 } 91 if (specialization == null) {
90 92 id = "Base";
91 private static TypeMirror specializationType(SpecializationData specialization) { 93 } else {
92 return new GeneratedTypeMirror(ElementUtils.getPackageName(specialization.getNode().getTemplateType()) + "." + nodeTypeName(specialization.getNode()), specializationTypeName(specialization)); 94 id = specialization.getId();
95 }
96 return id + "Node_";
97 }
98
99 private TypeMirror specializationType(SpecializationData specialization) {
100 return new GeneratedTypeMirror(ElementUtils.getPackageName(node.getTemplateType()) + "." + nodeTypeName(node), specializationTypeName(specialization));
93 } 101 }
94 102
95 private static String polymorphicTypeProfileFieldName(NodeExecutionData execution) { 103 private static String polymorphicTypeProfileFieldName(NodeExecutionData execution) {
96 return execution.getName() + "Type" + NAME_SUFFIX; 104 return execution.getName() + "Type" + NAME_SUFFIX;
97 } 105 }
158 for (NodeExecutionData execution : node.getChildExecutions()) { 166 for (NodeExecutionData execution : node.getChildExecutions()) {
159 clazz.add(createNodeField(PRIVATE, execution.getNodeType(), nodeFieldName(execution), Child.class)); 167 clazz.add(createNodeField(PRIVATE, execution.getNodeType(), nodeFieldName(execution), Child.class));
160 } 168 }
161 169
162 for (NodeExecutionData execution : node.getChildExecutions()) { 170 for (NodeExecutionData execution : node.getChildExecutions()) {
163 if (resolveSpecializedExecutables(execution, node.findSpecializedTypes(execution), options.polymorphicTypeBoxingElimination()).isEmpty()) { 171 if (!resolvePolymorphicExecutables(execution).isEmpty()) {
164 continue; 172 clazz.add(createNodeField(PRIVATE, getType(Class.class), polymorphicTypeProfileFieldName(execution), CompilationFinal.class));
165 } 173 }
166 clazz.add(createNodeField(PRIVATE, getType(Class.class), polymorphicTypeProfileFieldName(execution), CompilationFinal.class));
167 } 174 }
168 175
169 for (SpecializationData specialization : node.getSpecializations()) { 176 for (SpecializationData specialization : node.getSpecializations()) {
170 if (mayBeExcluded(specialization)) { 177 if (mayBeExcluded(specialization)) {
171 clazz.add(createNodeField(PRIVATE, getType(boolean.class), excludedFieldName(specialization), CompilationFinal.class)); 178 clazz.add(createNodeField(PRIVATE, getType(boolean.class), excludedFieldName(specialization), CompilationFinal.class));
172 } 179 }
173 } 180 }
174 181
175 clazz.add(createNodeField(PRIVATE, TypeSystemNodeFactory.nodeType(node.getTypeSystem()), specializationStartFieldName(), Child.class));
176 clazz.add(createMethodGetSpecializationNode()); 182 clazz.add(createMethodGetSpecializationNode());
177 clazz.add(createDeepCopyMethod()); 183 clazz.add(createDeepCopyMethod());
178 clazz.add(createGetCostMethod()); 184 clazz.add(createGetCostMethod());
179 185
180 Collection<TypeData> specializedTypes = node.findSpecializedReturnTypes(); 186 Collection<TypeData> specializedTypes = node.findSpecializedReturnTypes();
182 if (shouldImplementExecutableType(specializedTypes, execType)) { 188 if (shouldImplementExecutableType(specializedTypes, execType)) {
183 clazz.add(createExecutableTypeOverride(execType)); 189 clazz.add(createExecutableTypeOverride(execType));
184 } 190 }
185 } 191 }
186 192
187 SpecializationData initialSpecialization = createSpecializations(clazz); 193 SpecializationData specializationStart = createSpecializations(clazz);
194 SpecializationData finalSpecialization = singleSpecializable ? specializationStart : null;
195
196 clazz.add(createNodeField(PRIVATE, specializationType(finalSpecialization), specializationStartFieldName(), Child.class));
188 197
189 for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) { 198 for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) {
190 CodeTreeBuilder builder = ((CodeExecutableElement) constructor).appendBuilder(); 199 CodeTreeBuilder builder = ((CodeExecutableElement) constructor).appendBuilder();
191 builder.startStatement(); 200 builder.startStatement();
192 builder.string("this.").string(specializationStartFieldName()); 201 builder.string("this.").string(specializationStartFieldName());
193 builder.string(" = ").tree(createCallCreateMethod(initialSpecialization, "this", null)); 202 builder.string(" = ").tree(createCallCreateMethod(specializationStart, "this", null));
194 builder.end(); 203 builder.end();
195 } 204 }
196 205
197 return clazz; 206 return clazz;
198 } 207 }
267 } 276 }
268 277
269 private SpecializationData createSpecializations(CodeTypeElement clazz) { 278 private SpecializationData createSpecializations(CodeTypeElement clazz) {
270 List<SpecializationData> reachableSpecializations = getReachableSpecializations(); 279 List<SpecializationData> reachableSpecializations = getReachableSpecializations();
271 280
272 if (isSingleSpecializable(reachableSpecializations)) { 281 if (singleSpecializable) {
273 SpecializationData single = reachableSpecializations.get(0); 282 SpecializationData single = reachableSpecializations.get(0);
274 clazz.add(createSingleSpecialization(single)); 283 clazz.add(createSingleSpecialization(single));
275 return single; 284 return single;
276 } else { 285 } else {
277 CodeTypeElement baseSpecialization = clazz.add(createBaseSpecialization()); 286 CodeTypeElement baseSpecialization = clazz.add(createBaseSpecialization());
299 } 308 }
300 309
301 // create specialization 310 // create specialization
302 311
303 private CodeTypeElement createBaseSpecialization() { 312 private CodeTypeElement createBaseSpecialization() {
304 CodeTypeElement clazz = createClass(node, null, modifiers(PRIVATE, ABSTRACT, STATIC), "BaseNode_", TypeSystemNodeFactory.nodeType(typeSystem)); 313 CodeTypeElement clazz = createClass(node, null, modifiers(PRIVATE, ABSTRACT, STATIC), specializationTypeName(null), TypeSystemNodeFactory.nodeType(typeSystem));
305 314
306 clazz.addOptional(createSpecializationConstructor(clazz, null, null)); 315 clazz.addOptional(createSpecializationConstructor(clazz, null, null));
307 clazz.add(new CodeVariableElement(modifiers(PROTECTED, FINAL), nodeType(node), "root")); 316 clazz.add(new CodeVariableElement(modifiers(PROTECTED, FINAL), nodeType(node), "root"));
308 317
309 clazz.addOptional(createUnsupported()); 318 clazz.addOptional(createUnsupported());
334 CodeTypeElement clazz = createClass(node, specialization, modifiers(PRIVATE, STATIC, FINAL), specializationTypeName(specialization), TypeSystemNodeFactory.nodeType(typeSystem)); 343 CodeTypeElement clazz = createClass(node, specialization, modifiers(PRIVATE, STATIC, FINAL), specializationTypeName(specialization), TypeSystemNodeFactory.nodeType(typeSystem));
335 CodeExecutableElement constructor = clazz.addOptional(createSpecializationConstructor(clazz, null, "0")); 344 CodeExecutableElement constructor = clazz.addOptional(createSpecializationConstructor(clazz, null, "0"));
336 clazz.add(new CodeVariableElement(modifiers(PROTECTED, FINAL), nodeType(node), "root")); 345 clazz.add(new CodeVariableElement(modifiers(PROTECTED, FINAL), nodeType(node), "root"));
337 TypeData returnType = specialization.getReturnType().getTypeSystemType(); 346 TypeData returnType = specialization.getReturnType().getTypeSystemType();
338 Set<Integer> evaluatedCount = getEvaluatedCounts(); 347 Set<Integer> evaluatedCount = getEvaluatedCounts();
348
349 TypeData specializedType = returnType;
350 if (!isTypeBoxingEliminated(specialization)) {
351 specializedType = genericType;
352 }
353
339 for (int evaluated : evaluatedCount) { 354 for (int evaluated : evaluatedCount) {
340 clazz.add(createFastPathExecuteMethod(specialization, null, evaluated)); 355 if (evaluated != 0) {
341 } 356 clazz.add(createFastPathExecuteMethod(specialization, null, evaluated));
342 if (isTypeBoxingEliminated(specialization)) { 357 }
343 clazz.add(createFastPathExecuteMethod(specialization, returnType, 0)); 358 }
344 } 359
345 clazz.add(createFastPathWrapExecuteMethod(genericType, null)); 360 clazz.add(createFastPathExecuteMethod(specialization, specializedType, 0));
361 if (!specializedType.isGeneric()) {
362 clazz.add(createFastPathWrapExecuteMethod(genericType, returnType));
363 }
364
365 ExecutableTypeData voidExecutableType = node.findExecutableType(typeSystem.getVoidType(), 0);
366 if (voidExecutableType != null && isTypeBoxingOptimized(options.voidBoxingOptimization(), returnType)) {
367 clazz.add(createFastPathWrapVoidMethod(returnType));
368 }
346 369
347 clazz.addOptional(createUnsupported()); 370 clazz.addOptional(createUnsupported());
348 clazz.addOptional(createSpecializationCreateMethod(specialization, constructor)); 371 clazz.addOptional(createSpecializationCreateMethod(specialization, constructor));
349 clazz.add(createGetSuppliedChildren()); 372 clazz.add(createGetSuppliedChildren());
350 373
693 builder.end(); 716 builder.end();
694 717
695 return method; 718 return method;
696 } 719 }
697 720
698 private boolean isSingleSpecializable(List<SpecializationData> reachableSpecializations) { 721 private boolean isSingleSpecializableImpl() {
722 List<SpecializationData> reachableSpecializations = getReachableSpecializations();
699 if (reachableSpecializations.size() != 1) { 723 if (reachableSpecializations.size() != 1) {
700 return false; 724 return false;
701 } 725 }
702 return !reachableSpecializations.get(0).hasRewrite(context); 726 for (Parameter parameter : reachableSpecializations.get(0).getSignatureParameters()) {
727 TypeData type = parameter.getTypeSystemType();
728 if (type != null && type.hasImplicitSourceTypes()) {
729 return false;
730 }
731 }
732 return true;
703 } 733 }
704 734
705 private List<SpecializationData> getReachableSpecializations() { 735 private List<SpecializationData> getReachableSpecializations() {
706 List<SpecializationData> specializations = new ArrayList<>(); 736 List<SpecializationData> specializations = new ArrayList<>();
707 for (SpecializationData specialization : node.getSpecializations()) { 737 for (SpecializationData specialization : node.getSpecializations()) {
1014 1044
1015 private CodeTree createCallCreateMethod(SpecializationData specialization, String rootName, LocalContext currentValues) { 1045 private CodeTree createCallCreateMethod(SpecializationData specialization, String rootName, LocalContext currentValues) {
1016 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); 1046 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
1017 1047
1018 TypeMirror specializationType = specializationType(specialization); 1048 TypeMirror specializationType = specializationType(specialization);
1019 if (options.useLazyClassLoading()) { 1049 if (useLazyClassLoading()) {
1020 builder.startStaticCall(specializationType(specialization), "create"); 1050 builder.startStaticCall(specializationType(specialization), "create");
1021 } else { 1051 } else {
1022 builder.startNew(specializationType); 1052 builder.startNew(specializationType);
1023 } 1053 }
1024 if (rootName != null) { 1054 if (rootName != null) {
1039 1069
1040 return builder.build(); 1070 return builder.build();
1041 } 1071 }
1042 1072
1043 private Element createSpecializationCreateMethod(SpecializationData specialization, CodeExecutableElement constructor) { 1073 private Element createSpecializationCreateMethod(SpecializationData specialization, CodeExecutableElement constructor) {
1044 if (!options.useLazyClassLoading()) { 1074 if (!useLazyClassLoading()) {
1045 return null; 1075 return null;
1046 } 1076 }
1047 1077
1048 CodeExecutableElement executable = CodeExecutableElement.clone(context.getEnvironment(), constructor); 1078 CodeExecutableElement executable = CodeExecutableElement.clone(context.getEnvironment(), constructor);
1049 1079 executable.setReturnType(specializationType(null));
1050 TypeMirror specializationType = specializationType(specialization);
1051
1052 executable.setReturnType(TypeSystemNodeFactory.nodeType(typeSystem));
1053 executable.setSimpleName(CodeNames.of("create")); 1080 executable.setSimpleName(CodeNames.of("create"));
1054 executable.getModifiers().add(STATIC); 1081 executable.getModifiers().add(STATIC);
1055 1082
1056 CodeTreeBuilder builder = executable.createBuilder(); 1083 CodeTreeBuilder builder = executable.createBuilder();
1057 builder.startReturn().startNew(specializationType); 1084 builder.startReturn().startNew(specializationType(specialization));
1058 for (VariableElement parameter : executable.getParameters()) { 1085 for (VariableElement parameter : executable.getParameters()) {
1059 builder.string(parameter.getSimpleName().toString()); 1086 builder.string(parameter.getSimpleName().toString());
1060 } 1087 }
1061 builder.end().end(); 1088 builder.end().end();
1062 return executable; 1089 return executable;
1090 }
1091
1092 private boolean useLazyClassLoading() {
1093 return options.useLazyClassLoading() && !singleSpecializable;
1063 } 1094 }
1064 1095
1065 private static String implicitClassFieldName(NodeExecutionData execution) { 1096 private static String implicitClassFieldName(NodeExecutionData execution) {
1066 return execution.getName() + "ImplicitType"; 1097 return execution.getName() + "ImplicitType";
1067 } 1098 }
1131 } 1162 }
1132 } 1163 }
1133 1164
1134 private CodeTree createCallNext(TypeData forType, LocalContext currentValues) { 1165 private CodeTree createCallNext(TypeData forType, LocalContext currentValues) {
1135 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); 1166 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
1136 builder.startCall("next", TypeSystemNodeFactory.executeName(null)); 1167 if (singleSpecializable) {
1168 builder.startCall("unsupported");
1169 } else {
1170 builder.startCall("next", TypeSystemNodeFactory.executeName(null));
1171 }
1137 currentValues.addReferencesTo(builder, FRAME_VALUE); 1172 currentValues.addReferencesTo(builder, FRAME_VALUE);
1138 builder.end(); 1173 builder.end();
1139 return TypeSystemCodeGenerator.expect(genericType, forType, builder.build()); 1174 return TypeSystemCodeGenerator.expect(genericType, forType, builder.build());
1140 } 1175 }
1141 1176
1142 private static CodeTree createCallDelegate(String methodName, String reason, TypeData forType, LocalContext currentValues) { 1177 private CodeTree createCallRemove(String reason, TypeData forType, LocalContext currentValues) {
1178 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
1179 if (singleSpecializable) {
1180 builder.startCall("unsupported");
1181 } else {
1182 builder.startCall("remove");
1183 builder.doubleQuote(reason);
1184 }
1185 currentValues.addReferencesTo(builder, FRAME_VALUE);
1186 builder.end();
1187 return TypeSystemCodeGenerator.expect(genericType, forType, builder.build());
1188 }
1189
1190 private static CodeTree createCallDelegate(String methodName, TypeData forType, LocalContext currentValues) {
1143 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); 1191 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
1144 builder.startCall(methodName); 1192 builder.startCall(methodName);
1145 if (reason != null) {
1146 builder.doubleQuote(reason);
1147 }
1148 currentValues.addReferencesTo(builder, FRAME_VALUE); 1193 currentValues.addReferencesTo(builder, FRAME_VALUE);
1149 builder.end(); 1194 builder.end();
1150 1195
1151 TypeData executedType = forType.getTypeSystem().getGenericTypeData(); 1196 TypeData executedType = forType.getTypeSystem().getGenericTypeData();
1152 return TypeSystemCodeGenerator.expect(executedType, forType, builder.build()); 1197 return TypeSystemCodeGenerator.expect(executedType, forType, builder.build());
1209 } 1254 }
1210 } 1255 }
1211 1256
1212 LocalContext originalValues = currentLocals.copy(); 1257 LocalContext originalValues = currentLocals.copy();
1213 if (specialization == null) { 1258 if (specialization == null) {
1214 builder.startReturn().tree(createCallDelegate("acceptAndExecute", null, type, currentLocals)).end(); 1259 builder.startReturn().tree(createCallDelegate("acceptAndExecute", type, currentLocals)).end();
1215 } else if (specialization.isPolymorphic()) { 1260 } else if (specialization.isPolymorphic()) {
1216 builder.startReturn().tree(createCallNext(type, currentLocals)).end(); 1261 builder.startReturn().tree(createCallNext(type, currentLocals)).end();
1217 } else if (specialization.isUninitialized()) { 1262 } else if (specialization.isUninitialized()) {
1218 builder.startReturn().tree(createCallDelegate("uninitialized", null, type, currentLocals)).end(); 1263 builder.startReturn().tree(createCallDelegate("uninitialized", type, currentLocals)).end();
1219 } else { 1264 } else {
1220 final TypeData finalType = type; 1265 final TypeData finalType = type;
1221 SpecializationGroup group = SpecializationGroup.create(specialization); 1266 SpecializationGroup group = SpecializationGroup.create(specialization);
1222 SpecializationExecution executionFactory = new SpecializationExecution() { 1267 SpecializationExecution executionFactory = new SpecializationExecution() {
1223 public CodeTree createExecute(SpecializationData s, LocalContext values) { 1268 public CodeTree createExecute(SpecializationData s, LocalContext values) {
1480 1525
1481 private boolean isExecuteChildShared(NodeExecutionData execution, TypeData targetType) { 1526 private boolean isExecuteChildShared(NodeExecutionData execution, TypeData targetType) {
1482 if (targetType.isVoid()) { 1527 if (targetType.isVoid()) {
1483 return false; 1528 return false;
1484 } else if (targetType.isGeneric()) { 1529 } else if (targetType.isGeneric()) {
1485 if (isSingleSpecializable(getReachableSpecializations())) { 1530 return resolvePolymorphicExecutables(execution).size() >= 1;
1486 return false;
1487 }
1488 return resolveSpecializedExecutables(execution, node.findSpecializedTypes(execution), options.polymorphicTypeBoxingElimination()).size() >= 1;
1489 } else { 1531 } else {
1490 if (!isTypeBoxingOptimized(options.monomorphicTypeBoxingOptimization(), targetType)) { 1532 if (!isTypeBoxingOptimized(options.monomorphicTypeBoxingOptimization(), targetType)) {
1491 return false; 1533 return false;
1492 } 1534 }
1493 if (!targetType.hasImplicitSourceTypes()) { 1535 if (!targetType.hasImplicitSourceTypes()) {
1521 } else { 1563 } else {
1522 executeChild = createExecuteChild(execution, targetValue, currentValues, false); 1564 executeChild = createExecuteChild(execution, targetValue, currentValues, false);
1523 } 1565 }
1524 1566
1525 builder.tree(createTryExecuteChild(targetValue, executeChild, shortCircuit == null, hasUnexpected)); 1567 builder.tree(createTryExecuteChild(targetValue, executeChild, shortCircuit == null, hasUnexpected));
1568
1569 if (shortCircuit != null) {
1570 currentValues.setShortCircuitValue(execution, shortCircuit.accessWith(null));
1571 }
1572
1526 builder.end(); 1573 builder.end();
1527 if (hasUnexpected) { 1574 if (hasUnexpected) {
1528 builder.startCatchBlock(getType(UnexpectedResultException.class), "ex"); 1575 builder.startCatchBlock(getType(UnexpectedResultException.class), "ex");
1529
1530 LocalContext slowPathValues = currentValues.copy(); 1576 LocalContext slowPathValues = currentValues.copy();
1577
1531 slowPathValues.setValue(execution, targetValue.makeGeneric().accessWith(CodeTreeBuilder.singleString("ex.getResult()"))); 1578 slowPathValues.setValue(execution, targetValue.makeGeneric().accessWith(CodeTreeBuilder.singleString("ex.getResult()")));
1532 boolean found = false; 1579 boolean found = false;
1533 for (NodeExecutionData otherExecution : node.getChildExecutions()) { 1580 for (NodeExecutionData otherExecution : node.getChildExecutions()) {
1534 if (found) { 1581 if (found) {
1535 LocalVariable childEvaluatedValue = slowPathValues.createValue(otherExecution, genericType); 1582 LocalVariable childEvaluatedValue = slowPathValues.createValue(otherExecution, genericType);
1543 } 1590 }
1544 builder.startReturn().tree(createCallNext(returnType, slowPathValues)).end(); 1591 builder.startReturn().tree(createCallNext(returnType, slowPathValues)).end();
1545 builder.end(); 1592 builder.end();
1546 } 1593 }
1547 1594
1548 if (shortCircuit != null) {
1549 currentValues.setShortCircuitValue(execution, shortCircuit.accessWith(null));
1550 }
1551 return createShortCircuit(targetValue, shortCircuit, builder.build()); 1595 return createShortCircuit(targetValue, shortCircuit, builder.build());
1552 } 1596 }
1553 1597
1554 private static CodeTree createShortCircuit(LocalVariable targetValue, LocalVariable shortCircuitValue, CodeTree tryExecute) { 1598 private static CodeTree createShortCircuit(LocalVariable targetValue, LocalVariable shortCircuitValue, CodeTree tryExecute) {
1555 if (shortCircuitValue == null) { 1599 if (shortCircuitValue == null) {
1661 ExecutableTypeData genericExecutableType = execution.getChild().getNodeData().findAnyGenericExecutableType(context, execution.getChild().getExecuteWith().size()); 1705 ExecutableTypeData genericExecutableType = execution.getChild().getNodeData().findAnyGenericExecutableType(context, execution.getChild().getExecuteWith().size());
1662 if (genericExecutableType == null) { 1706 if (genericExecutableType == null) {
1663 throw new AssertionError("At least one generic executable method must be available."); 1707 throw new AssertionError("At least one generic executable method must be available.");
1664 } 1708 }
1665 1709
1666 Set<TypeData> specializedTypes = new HashSet<>(); 1710 List<ExecutableTypeData> specializedExecutables = resolvePolymorphicExecutables(execution);
1667 for (TypeData type : node.findSpecializedTypes(execution)) {
1668 specializedTypes.addAll(type.getImplicitSourceTypes());
1669 }
1670
1671 List<ExecutableTypeData> specializedExecutables = resolveSpecializedExecutables(execution, specializedTypes, options.polymorphicTypeBoxingElimination());
1672 Collections.sort(specializedExecutables, new Comparator<ExecutableTypeData>() { 1711 Collections.sort(specializedExecutables, new Comparator<ExecutableTypeData>() {
1673 public int compare(ExecutableTypeData o1, ExecutableTypeData o2) { 1712 public int compare(ExecutableTypeData o1, ExecutableTypeData o2) {
1674 return o1.getType().compareTo(o2.getType()); 1713 return o1.getType().compareTo(o2.getType());
1675 } 1714 }
1676 }); 1715 });
1677 1716
1678 CodeTree assignment = createAssignmentStart(target, shared); 1717 CodeTree assignment = createAssignmentStart(target, shared);
1679 CodeTree executeGeneric = createSingleExecute(execution, target, currentValues, genericExecutableType); 1718 CodeTree executeGeneric = createSingleExecute(execution, target, currentValues, genericExecutableType);
1680 1719
1681 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); 1720 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
1682 if (specializedExecutables.isEmpty() || isSingleSpecializable(getReachableSpecializations())) { 1721 if (specializedExecutables.isEmpty()) {
1683 builder.tree(assignment); 1722 builder.tree(assignment);
1684 builder.tree(executeGeneric); 1723 builder.tree(executeGeneric);
1685 } else { 1724 } else {
1686 final CodeTreeBuilder polyChainBuilder = builder.create(); 1725 final CodeTreeBuilder polyChainBuilder = builder.create();
1687 final String profileField = polymorphicTypeProfileFieldName(execution); 1726 final String profileField = polymorphicTypeProfileFieldName(execution);
1745 } 1784 }
1746 } 1785 }
1747 return builder.build(); 1786 return builder.build();
1748 } 1787 }
1749 1788
1789 private List<ExecutableTypeData> resolvePolymorphicExecutables(NodeExecutionData execution) {
1790 if (singleSpecializable) {
1791 return Collections.emptyList();
1792 }
1793 Set<TypeData> specializedTypes = new HashSet<>();
1794 for (TypeData type : node.findSpecializedTypes(execution)) {
1795 specializedTypes.addAll(type.getImplicitSourceTypes());
1796 }
1797 return resolveSpecializedExecutables(execution, specializedTypes, options.polymorphicTypeBoxingElimination());
1798 }
1799
1750 private static CodeTree createAssignmentStart(LocalVariable target, boolean shared) { 1800 private static CodeTree createAssignmentStart(LocalVariable target, boolean shared) {
1751 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); 1801 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
1752 if (shared) { 1802 if (shared) {
1753 builder.string("return "); 1803 builder.string("return ");
1754 } else { 1804 } else {
1802 builder.end(); 1852 builder.end();
1803 } 1853 }
1804 return builder.build(); 1854 return builder.build();
1805 } 1855 }
1806 1856
1807 private static CodeTree createFastPathTryCatchRewriteException(SpecializationData specialization, TypeData forType, LocalContext currentValues, CodeTree execution) { 1857 private CodeTree createFastPathTryCatchRewriteException(SpecializationData specialization, TypeData forType, LocalContext currentValues, CodeTree execution) {
1808 if (specialization.getExceptions().isEmpty()) { 1858 if (specialization.getExceptions().isEmpty()) {
1809 return execution; 1859 return execution;
1810 } 1860 }
1811 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); 1861 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
1812 builder.startTryBlock(); 1862 builder.startTryBlock();
1816 exceptionTypes[i] = specialization.getExceptions().get(i).getJavaClass(); 1866 exceptionTypes[i] = specialization.getExceptions().get(i).getJavaClass();
1817 } 1867 }
1818 builder.end().startCatchBlock(exceptionTypes, "ex"); 1868 builder.end().startCatchBlock(exceptionTypes, "ex");
1819 builder.startStatement().tree(accessParent(excludedFieldName(specialization))).string(" = true").end(); 1869 builder.startStatement().tree(accessParent(excludedFieldName(specialization))).string(" = true").end();
1820 builder.startReturn(); 1870 builder.startReturn();
1821 builder.tree(createCallDelegate("remove", "threw rewrite exception", forType, currentValues)); 1871 builder.tree(createCallRemove("threw rewrite exception", forType, currentValues));
1822 builder.end(); 1872 builder.end();
1823 builder.end(); 1873 builder.end();
1824 return builder.build(); 1874 return builder.build();
1825 } 1875 }
1826 1876