Mercurial > hg > graal-jvmci-8
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 |