Mercurial > hg > graal-jvmci-8
comparison graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java @ 9217:61ba6fc21ba4
Sourcegen can now generate execute methods of signature execute(frame, evaluatedValue).
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Mon, 15 Apr 2013 18:50:19 +0200 |
parents | bd067a48a9c2 |
children | 797bb88bf004 |
comparison
equal
deleted
inserted
replaced
9216:8b9ea2f5c36e | 9217:61ba6fc21ba4 |
---|---|
86 } | 86 } |
87 if (spec.isLocal()) { | 87 if (spec.isLocal()) { |
88 continue; | 88 continue; |
89 } | 89 } |
90 | 90 |
91 method.addParameter(new CodeVariableElement(parameter.getActualType(), valueName(parameter))); | 91 method.addParameter(new CodeVariableElement(parameter.getType(), valueName(parameter))); |
92 } | 92 } |
93 } | 93 } |
94 | 94 |
95 private static void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, boolean includeImplicit) { | 95 private static void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, |
96 boolean includeImplicit) { | |
96 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { | 97 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { |
97 builder.string("frameValue"); | 98 builder.string("frameValue"); |
98 } | 99 } |
99 for (ActualParameter parameter : specialization.getParameters()) { | 100 for (ActualParameter parameter : specialization.getParameters()) { |
100 ParameterSpec spec = parameter.getSpecification(); | 101 ParameterSpec spec = parameter.getSpecification(); |
107 } | 108 } |
108 if (parameter.getSpecification().isLocal()) { | 109 if (parameter.getSpecification().isLocal()) { |
109 continue; | 110 continue; |
110 } | 111 } |
111 | 112 |
113 ActualParameter sourceParameter = source.findParameter(parameter.getLocalName()); | |
114 | |
112 if (unexpectedValueName != null && parameter.getLocalName().equals(unexpectedValueName)) { | 115 if (unexpectedValueName != null && parameter.getLocalName().equals(unexpectedValueName)) { |
113 builder.cast(parameter.getActualType(), CodeTreeBuilder.singleString("ex.getResult()")); | 116 builder.cast(parameter.getType(), CodeTreeBuilder.singleString("ex.getResult()")); |
117 } else if (sourceParameter != null) { | |
118 builder.string(valueName(sourceParameter, parameter)); | |
114 } else { | 119 } else { |
115 builder.string(valueName(parameter)); | 120 builder.string(valueName(parameter)); |
116 } | 121 } |
122 } | |
123 } | |
124 | |
125 private static String valueName(ActualParameter sourceParameter, ActualParameter targetParameter) { | |
126 if (sourceParameter != null) { | |
127 if (!sourceParameter.getSpecification().isSignature()) { | |
128 return valueName(targetParameter); | |
129 } else if (sourceParameter.getTypeSystemType() != null && targetParameter.getTypeSystemType() != null) { | |
130 if (sourceParameter.getTypeSystemType().needsCastTo(targetParameter.getTypeSystemType())) { | |
131 return castValueName(targetParameter); | |
132 } | |
133 } | |
134 return valueName(targetParameter); | |
135 } else { | |
136 return valueName(targetParameter); | |
117 } | 137 } |
118 } | 138 } |
119 | 139 |
120 private static CodeTree createTemplateMethodCall(CodeTreeBuilder parent, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName) { | 140 private static CodeTree createTemplateMethodCall(CodeTreeBuilder parent, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName) { |
121 CodeTreeBuilder builder = parent.create(); | 141 CodeTreeBuilder builder = parent.create(); |
127 if (method == null) { | 147 if (method == null) { |
128 throw new IllegalStateException("Cannot call synthetic operation methods."); | 148 throw new IllegalStateException("Cannot call synthetic operation methods."); |
129 } | 149 } |
130 TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement()); | 150 TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement()); |
131 NodeData node = (NodeData) targetMethod.getTemplate(); | 151 NodeData node = (NodeData) targetMethod.getTemplate(); |
132 TypeSystemData typeSystem = node.getTypeSystem(); | |
133 | 152 |
134 boolean accessible = targetMethod.canBeAccessedByInstanceOf(node.getNodeType()); | 153 boolean accessible = targetMethod.canBeAccessedByInstanceOf(node.getNodeType()); |
135 if (accessible) { | 154 if (accessible) { |
136 if (builder.findMethod().getModifiers().contains(STATIC)) { | 155 if (builder.findMethod().getModifiers().contains(STATIC)) { |
137 if (method.getModifiers().contains(STATIC)) { | 156 if (method.getModifiers().contains(STATIC)) { |
138 builder.type(targetClass.asType()); | 157 builder.type(targetClass.asType()); |
139 } else { | 158 } else { |
140 builder.string(THIS_NODE_LOCAL_VAR_NAME); | 159 builder.string(THIS_NODE_LOCAL_VAR_NAME); |
141 } | 160 } |
142 } else { | 161 } else { |
143 builder.string("super"); | 162 if (targetMethod instanceof ExecutableTypeData) { |
163 builder.string("this"); | |
164 } else { | |
165 builder.string("super"); | |
166 } | |
144 } | 167 } |
145 } else { | 168 } else { |
146 if (method.getModifiers().contains(STATIC)) { | 169 if (method.getModifiers().contains(STATIC)) { |
147 builder.type(targetClass.asType()); | 170 builder.type(targetClass.asType()); |
148 } else { | 171 } else { |
154 } | 177 } |
155 } | 178 } |
156 ActualParameter sourceParameter = sourceMethod.findParameter(parameter.getLocalName()); | 179 ActualParameter sourceParameter = sourceMethod.findParameter(parameter.getLocalName()); |
157 assert parameter != null; | 180 assert parameter != null; |
158 | 181 |
159 if (castedValues) { | 182 if (castedValues && sourceParameter != null) { |
160 NodeFieldData field = node.findField(parameter.getSpecification().getName()); | 183 builder.string(valueName(sourceParameter, parameter)); |
161 if (field == null) { | |
162 builder.string(valueName(parameter)); | |
163 } else { | |
164 if (Utils.typeEquals(sourceParameter.getActualType(), parameter.getActualType())) { | |
165 builder.string(valueName(parameter)); | |
166 } else { | |
167 builder.string(castValueName(parameter)); | |
168 } | |
169 } | |
170 } else { | 184 } else { |
171 builder.string(valueName(parameter)); | 185 builder.string(valueName(parameter)); |
172 } | 186 } |
173 } | 187 } |
174 } | 188 } |
178 for (ActualParameter targetParameter : targetMethod.getParameters()) { | 192 for (ActualParameter targetParameter : targetMethod.getParameters()) { |
179 ActualParameter valueParameter = sourceMethod.findParameter(targetParameter.getLocalName()); | 193 ActualParameter valueParameter = sourceMethod.findParameter(targetParameter.getLocalName()); |
180 if (valueParameter == null) { | 194 if (valueParameter == null) { |
181 valueParameter = targetParameter; | 195 valueParameter = targetParameter; |
182 } | 196 } |
183 TypeData targetType = targetParameter.getActualTypeData(typeSystem); | 197 TypeData targetType = targetParameter.getTypeSystemType(); |
184 | 198 |
185 if (targetParameter.isImplicit() || valueParameter.isImplicit()) { | 199 if (targetParameter.isImplicit() || valueParameter.isImplicit()) { |
186 continue; | 200 continue; |
187 } | 201 } |
188 | 202 |
189 TypeData valueType = null; | 203 TypeData valueType = null; |
190 if (valueParameter != null) { | 204 if (valueParameter != null) { |
191 valueType = valueParameter.getActualTypeData(typeSystem); | 205 valueType = valueParameter.getTypeSystemType(); |
192 } | 206 } |
193 | 207 |
194 if (targetParameter.getSpecification().isLocal()) { | 208 if (targetParameter.getSpecification().isLocal()) { |
195 builder.startGroup(); | 209 builder.startGroup(); |
196 if (builder.findMethod().getModifiers().contains(Modifier.STATIC)) { | 210 if (builder.findMethod().getModifiers().contains(Modifier.STATIC)) { |
201 builder.string(targetParameter.getSpecification().getName()); | 215 builder.string(targetParameter.getSpecification().getName()); |
202 builder.end(); | 216 builder.end(); |
203 } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) { | 217 } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) { |
204 builder.string("ex.getResult()"); | 218 builder.string("ex.getResult()"); |
205 } else if (targetType == null || targetType.isGeneric() || (valueType != null && valueType.equalsType(targetType))) { | 219 } else if (targetType == null || targetType.isGeneric() || (valueType != null && valueType.equalsType(targetType))) { |
220 builder.startGroup(); | |
221 | |
222 if (valueType != null && sourceMethod.getMethodName().equals(targetMethod.getMethodName()) && !valueType.isGeneric() && targetType.isGeneric()) { | |
223 builder.string("("); | |
224 builder.type(targetType.getPrimitiveType()); | |
225 builder.string(") "); | |
226 } | |
206 builder.string(valueName(targetParameter)); | 227 builder.string(valueName(targetParameter)); |
228 builder.end(); | |
207 } else { | 229 } else { |
208 builder.string(castValueName(targetParameter)); | 230 builder.string(castValueName(targetParameter)); |
209 } | 231 } |
210 } | 232 } |
211 | 233 |
241 prev = current; | 263 prev = current; |
242 } | 264 } |
243 return prefix; | 265 return prefix; |
244 } | 266 } |
245 | 267 |
246 private static CodeTree createCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder parent, NodeData node, String methodName, String value) { | 268 private static CodeTree createCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder parent, NodeData node, String methodName, CodeTree value) { |
247 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 269 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
248 startCallTypeSystemMethod(context, builder, node, methodName); | 270 startCallTypeSystemMethod(context, builder, node, methodName); |
249 builder.string(value); | 271 builder.tree(value); |
250 builder.end().end(); | 272 builder.end().end(); |
251 return builder.getRoot(); | 273 return builder.getRoot(); |
252 } | 274 } |
253 | 275 |
254 private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body, NodeData node, String methodName) { | 276 private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body, NodeData node, String methodName) { |
279 for (ActualParameter parameter : guard.getParameters()) { | 301 for (ActualParameter parameter : guard.getParameters()) { |
280 NodeFieldData field = node.findField(parameter.getSpecification().getName()); | 302 NodeFieldData field = node.findField(parameter.getSpecification().getName()); |
281 if (field == null) { | 303 if (field == null) { |
282 continue; | 304 continue; |
283 } | 305 } |
284 TypeData typeData = parameter.getActualTypeData(node.getTypeSystem()); | 306 TypeData typeData = parameter.getTypeSystemType(); |
285 if (typeData != null && !typeData.isGeneric()) { | 307 if (typeData != null && !typeData.isGeneric()) { |
286 valuesNeedsCast.add(parameter.getLocalName()); | 308 valuesNeedsCast.add(parameter.getLocalName()); |
287 } | 309 } |
288 } | 310 } |
289 } | 311 } |
343 private CodeTree createCasts(CodeTreeBuilder parent, Set<String> castWhiteList, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) { | 365 private CodeTree createCasts(CodeTreeBuilder parent, Set<String> castWhiteList, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) { |
344 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 366 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
345 // Implict guards based on method signature | 367 // Implict guards based on method signature |
346 for (ActualParameter guardedParam : guardedSpecialization.getParameters()) { | 368 for (ActualParameter guardedParam : guardedSpecialization.getParameters()) { |
347 NodeFieldData field = guardedSpecialization.getNode().findField(guardedParam.getSpecification().getName()); | 369 NodeFieldData field = guardedSpecialization.getNode().findField(guardedParam.getSpecification().getName()); |
348 if (field == null || field.getKind() == FieldKind.FIELD) { | 370 if (field == null || field.getKind() == FieldKind.FINAL_FIELD) { |
349 continue; | 371 continue; |
350 } | 372 } |
351 ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName()); | 373 ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName()); |
352 | 374 |
353 if (castWhiteList != null && !castWhiteList.contains(guardedParam.getLocalName())) { | 375 if (castWhiteList != null && !castWhiteList.contains(guardedParam.getLocalName())) { |
368 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 390 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
369 // Implict guards based on method signature | 391 // Implict guards based on method signature |
370 String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; | 392 String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; |
371 for (ActualParameter guardedParam : guardedSpecialization.getParameters()) { | 393 for (ActualParameter guardedParam : guardedSpecialization.getParameters()) { |
372 NodeFieldData field = guardedSpecialization.getNode().findField(guardedParam.getSpecification().getName()); | 394 NodeFieldData field = guardedSpecialization.getNode().findField(guardedParam.getSpecification().getName()); |
373 if (field == null || field.getKind() == FieldKind.FIELD) { | 395 if (field == null || field.getKind() == FieldKind.FINAL_FIELD) { |
374 continue; | 396 continue; |
375 } | 397 } |
376 ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName()); | 398 ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName()); |
377 | 399 |
378 CodeTree implicitGuard = createImplicitGuard(builder, field, valueParam, guardedParam); | 400 CodeTree implicitGuard = createImplicitGuard(builder, field, valueParam, guardedParam); |
390 | 412 |
391 private CodeTree createImplicitGuard(CodeTreeBuilder parent, NodeFieldData field, ActualParameter source, ActualParameter target) { | 413 private CodeTree createImplicitGuard(CodeTreeBuilder parent, NodeFieldData field, ActualParameter source, ActualParameter target) { |
392 NodeData node = field.getNodeData(); | 414 NodeData node = field.getNodeData(); |
393 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 415 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
394 | 416 |
395 TypeData targetType = target.getActualTypeData(node.getTypeSystem()); | 417 TypeData targetType = target.getTypeSystemType(); |
396 TypeData sourceType = source.getActualTypeData(node.getTypeSystem()); | 418 TypeData sourceType = source.getTypeSystemType(); |
397 | 419 |
398 if (targetType.equalsType(sourceType) || targetType.isGeneric()) { | 420 if (targetType.equalsType(sourceType) || targetType.isGeneric()) { |
399 return null; | 421 return null; |
400 } | 422 } |
401 | 423 |
407 builder.string("("); | 429 builder.string("("); |
408 builder.string("!").string(valueName(shortCircuit)); | 430 builder.string("!").string(valueName(shortCircuit)); |
409 builder.string(" || "); | 431 builder.string(" || "); |
410 } | 432 } |
411 | 433 |
412 startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(target.getActualTypeData(node.getTypeSystem()))); | 434 startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(target.getTypeSystemType())); |
413 builder.string(valueName(source)); | 435 builder.string(valueName(source)); |
414 builder.end().end(); // call | 436 builder.end().end(); // call |
415 | 437 |
416 if (field.isShortCircuit()) { | 438 if (field.isShortCircuit()) { |
417 builder.string(")"); | 439 builder.string(")"); |
422 return builder.getRoot(); | 444 return builder.getRoot(); |
423 } | 445 } |
424 | 446 |
425 private CodeTree createCast(CodeTreeBuilder parent, NodeFieldData field, ActualParameter source, ActualParameter target) { | 447 private CodeTree createCast(CodeTreeBuilder parent, NodeFieldData field, ActualParameter source, ActualParameter target) { |
426 NodeData node = field.getNodeData(); | 448 NodeData node = field.getNodeData(); |
427 TypeSystemData typeSystem = node.getTypeSystem(); | 449 TypeData sourceType = source.getTypeSystemType(); |
428 | 450 TypeData targetType = target.getTypeSystemType(); |
429 TypeData sourceType = source.getActualTypeData(typeSystem); | 451 |
430 TypeData targetType = target.getActualTypeData(typeSystem); | 452 if (!sourceType.needsCastTo(targetType)) { |
431 | |
432 if (targetType.equalsType(sourceType) || targetType.isGeneric()) { | |
433 return null; | 453 return null; |
434 } | 454 } |
435 | 455 |
436 CodeTree condition = null; | 456 CodeTree condition = null; |
437 if (field.isShortCircuit()) { | 457 if (field.isShortCircuit()) { |
438 ActualParameter shortCircuit = target.getPreviousParameter(); | 458 ActualParameter shortCircuit = target.getPreviousParameter(); |
439 assert shortCircuit != null; | 459 assert shortCircuit != null; |
440 condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); | 460 condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); |
441 } | 461 } |
442 | 462 |
443 CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), valueName(target)); | 463 CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), CodeTreeBuilder.singleString(valueName(target))); |
444 | 464 |
445 return createLazyAssignment(parent, castValueName(target), target.getActualType(), condition, value); | 465 return createLazyAssignment(parent, castValueName(target), target.getType(), condition, value); |
446 } | 466 } |
447 | 467 |
448 /** | 468 /** |
449 * <pre> | 469 * <pre> |
450 * variant1 $condition != null | 470 * variant1 $condition != null |
666 assert !node.getSpecializations().isEmpty(); | 686 assert !node.getSpecializations().isEmpty(); |
667 SpecializationData data = node.getSpecializations().get(0); | 687 SpecializationData data = node.getSpecializations().get(0); |
668 for (ActualParameter parameter : data.getParameters()) { | 688 for (ActualParameter parameter : data.getParameters()) { |
669 ParameterSpec spec = parameter.getSpecification(); | 689 ParameterSpec spec = parameter.getSpecification(); |
670 NodeFieldData field = node.findField(spec.getName()); | 690 NodeFieldData field = node.findField(spec.getName()); |
671 if (field == null || field.getKind() == FieldKind.FIELD) { | 691 if (field == null || field.getKind() == FieldKind.FINAL_FIELD) { |
672 continue; | 692 continue; |
673 } | 693 } |
674 | 694 |
675 TypeMirror type; | 695 TypeMirror type; |
676 if (field.getKind() == FieldKind.CHILDREN && field.getType().getKind() == TypeKind.ARRAY) { | 696 if (field.getKind() == FieldKind.CHILDREN && field.getType().getKind() == TypeKind.ARRAY) { |
990 | 1010 |
991 return method; | 1011 return method; |
992 } | 1012 } |
993 | 1013 |
994 private List<CodeExecutableElement> createGeneratedGenericMethod(NodeData node) { | 1014 private List<CodeExecutableElement> createGeneratedGenericMethod(NodeData node) { |
995 TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getActualType(); | 1015 TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType(); |
996 if (node.needsRewrites(context)) { | 1016 if (node.needsRewrites(context)) { |
997 List<CodeExecutableElement> methods = new ArrayList<>(); | 1017 List<CodeExecutableElement> methods = new ArrayList<>(); |
998 | 1018 |
999 List<SpecializationData> specializations = node.getSpecializations(); | 1019 List<SpecializationData> specializations = node.getSpecializations(); |
1000 SpecializationData prev = null; | 1020 SpecializationData prev = null; |
1035 if (next != null) { | 1055 if (next != null) { |
1036 CodeTreeBuilder nextBuilder = builder.create(); | 1056 CodeTreeBuilder nextBuilder = builder.create(); |
1037 | 1057 |
1038 nextBuilder.startReturn().startCall(generatedGenericMethodName(next)); | 1058 nextBuilder.startReturn().startCall(generatedGenericMethodName(next)); |
1039 nextBuilder.string(THIS_NODE_LOCAL_VAR_NAME); | 1059 nextBuilder.string(THIS_NODE_LOCAL_VAR_NAME); |
1040 addInternalValueParameterNames(nextBuilder, next, null, true, true); | 1060 addInternalValueParameterNames(nextBuilder, next, next, null, true, true); |
1041 nextBuilder.end().end(); | 1061 nextBuilder.end().end(); |
1042 | 1062 |
1043 invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, true, invokeMethod, nextBuilder.getRoot()); | 1063 invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, true, invokeMethod, nextBuilder.getRoot()); |
1044 } | 1064 } |
1045 | 1065 |
1067 for (SpecializationThrowsData exception : specialization.getExceptions()) { | 1087 for (SpecializationThrowsData exception : specialization.getExceptions()) { |
1068 builder.end().startCatchBlock(exception.getJavaClass(), "ex" + level); | 1088 builder.end().startCatchBlock(exception.getJavaClass(), "ex" + level); |
1069 | 1089 |
1070 builder.startReturn().startCall(generatedGenericMethodName(exception.getTransitionTo())); | 1090 builder.startReturn().startCall(generatedGenericMethodName(exception.getTransitionTo())); |
1071 builder.string(THIS_NODE_LOCAL_VAR_NAME); | 1091 builder.string(THIS_NODE_LOCAL_VAR_NAME); |
1072 addInternalValueParameterNames(builder, exception.getTransitionTo(), null, true, true); | 1092 addInternalValueParameterNames(builder, exception.getTransitionTo(), exception.getTransitionTo(), null, true, true); |
1073 builder.end().end(); | 1093 builder.end().end(); |
1074 } | 1094 } |
1075 builder.end(); | 1095 builder.end(); |
1076 } | 1096 } |
1077 } | 1097 } |
1102 if (superConstructor != null) { | 1122 if (superConstructor != null) { |
1103 clazz.add(superConstructor); | 1123 clazz.add(superConstructor); |
1104 } | 1124 } |
1105 } | 1125 } |
1106 | 1126 |
1107 TypeData primaryType = specialization.getReturnType().getActualTypeData(node.getTypeSystem()); | |
1108 | |
1109 for (ExecutableTypeData execType : node.getExecutableTypes()) { | 1127 for (ExecutableTypeData execType : node.getExecutableTypes()) { |
1110 if (execType.isFinal()) { | 1128 if (execType.isFinal()) { |
1111 continue; | 1129 continue; |
1112 } | 1130 } |
1113 | 1131 CodeExecutableElement executeMethod = createExecutableTypeOverride(execType); |
1114 if (primaryType == execType.getType()) { | 1132 clazz.add(executeMethod); |
1115 CodeExecutableElement executeMethod = createExecutableTypeOverride(execType); | 1133 CodeTreeBuilder builder = executeMethod.createBuilder(); |
1116 clazz.add(executeMethod); | 1134 CodeTree result = createExecuteBody(builder, specialization, execType); |
1117 executeMethod.setBodyTree(createFunctionalExecute(executeMethod.createBuilder(), specialization)); | 1135 if (result != null) { |
1118 } else if (needsCastingExecuteMethod(execType, primaryType)) { | 1136 builder.tree(result); |
1119 CodeExecutableElement executeMethod = createExecutableTypeOverride(execType); | 1137 } else { |
1120 clazz.add(executeMethod); | 1138 clazz.remove(executeMethod); |
1121 executeMethod.setBodyTree(createCastingExecute(executeMethod.createBuilder(), specialization, execType.getType())); | 1139 } |
1122 } | |
1123 | |
1124 } | 1140 } |
1125 | 1141 |
1126 if (node.needsRewrites(getContext()) && !specialization.isGeneric() && !specialization.isUninitialized()) { | 1142 if (node.needsRewrites(getContext()) && !specialization.isGeneric() && !specialization.isUninitialized()) { |
1127 buildSpecializeAndExecute(clazz, specialization); | 1143 buildSpecializeAndExecute(clazz, specialization); |
1128 } | 1144 } |
1129 } | 1145 } |
1130 | 1146 |
1147 private CodeTree createExecuteBody(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData execType) { | |
1148 TypeData primaryType = specialization.getReturnType().getTypeSystemType(); | |
1149 | |
1150 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | |
1151 | |
1152 ExecutableTypeData foundEvaluatedPrimaryType = findFunctionalExecutableType(specialization, execType.getEvaluatedCount()); | |
1153 | |
1154 if (execType == foundEvaluatedPrimaryType || foundEvaluatedPrimaryType == null) { | |
1155 builder.tree(createFunctionalExecute(builder, specialization, execType)); | |
1156 } else if (needsCastingExecuteMethod(execType, primaryType)) { | |
1157 builder.tree(createCastingExecute(builder, specialization, execType, foundEvaluatedPrimaryType)); | |
1158 } else { | |
1159 return null; | |
1160 } | |
1161 | |
1162 return builder.getRoot(); | |
1163 } | |
1164 | |
1131 private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType) { | 1165 private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType) { |
1132 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod()); | 1166 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod()); |
1133 if (method.getParameters().size() == 1) { | 1167 |
1134 CodeVariableElement var = CodeVariableElement.clone(method.getParameters().get(0)); | 1168 int i = 0; |
1135 var.setName("frameValue"); | 1169 for (VariableElement param : method.getParameters()) { |
1136 method.getParameters().set(0, var); | 1170 CodeVariableElement var = CodeVariableElement.clone(param); |
1137 } | 1171 var.setName(valueName(execType.getParameters().get(i))); |
1172 method.getParameters().set(i, var); | |
1173 i++; | |
1174 } | |
1175 | |
1176 method.getAnnotationMirrors().clear(); | |
1138 method.getModifiers().remove(Modifier.ABSTRACT); | 1177 method.getModifiers().remove(Modifier.ABSTRACT); |
1139 return method; | 1178 return method; |
1140 } | 1179 } |
1141 | 1180 |
1142 private boolean needsCastingExecuteMethod(ExecutableTypeData execType, TypeData primaryType) { | 1181 private boolean needsCastingExecuteMethod(ExecutableTypeData execType, TypeData primaryType) { |
1150 return true; | 1189 return true; |
1151 } | 1190 } |
1152 return false; | 1191 return false; |
1153 } | 1192 } |
1154 | 1193 |
1155 private CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, TypeData type) { | 1194 private ExecutableTypeData findFunctionalExecutableType(SpecializationData specialization, int evaluatedCount) { |
1195 TypeData primaryType = specialization.getReturnType().getTypeSystemType(); | |
1196 List<ExecutableTypeData> otherTypes = specialization.getNode().getExecutableTypes(evaluatedCount); | |
1197 | |
1198 List<ExecutableTypeData> filteredTypes = new ArrayList<>(); | |
1199 for (ExecutableTypeData compareType : otherTypes) { | |
1200 if (!Utils.typeEquals(compareType.getType().getPrimitiveType(), primaryType.getPrimitiveType())) { | |
1201 continue; | |
1202 } | |
1203 filteredTypes.add(compareType); | |
1204 } | |
1205 | |
1206 for (ExecutableTypeData compareType : filteredTypes) { | |
1207 if (compareType.startsWithSignature(specialization)) { | |
1208 return compareType; | |
1209 } | |
1210 } | |
1211 | |
1212 for (ExecutableTypeData compareType : otherTypes) { | |
1213 if (compareType.startsWithSignature(specialization)) { | |
1214 return compareType; | |
1215 } | |
1216 } | |
1217 | |
1218 return null; | |
1219 } | |
1220 | |
1221 private CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) { | |
1222 TypeData type = executable.getType(); | |
1156 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 1223 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
1157 NodeData node = specialization.getNode(); | 1224 NodeData node = specialization.getNode(); |
1158 TypeSystemData typeSystem = node.getTypeSystem(); | |
1159 | 1225 |
1160 ExecutableTypeData castedType = node.findExecutableType(type); | 1226 ExecutableTypeData castedType = node.findExecutableType(type); |
1161 TypeData primaryType = specialization.getReturnType().getActualTypeData(typeSystem); | 1227 TypeData primaryType = castExecutable.getType(); |
1162 ExecutableTypeData execType = specialization.getNode().findExecutableType(primaryType); | 1228 |
1163 | 1229 boolean needsTry = castExecutable.hasUnexpectedValue(getContext()); |
1164 boolean needsTry = execType.hasUnexpectedValue(getContext()); | |
1165 boolean returnVoid = type.isVoid(); | 1230 boolean returnVoid = type.isVoid(); |
1166 | 1231 |
1167 CodeTree primaryExecuteCall = null; | 1232 List<ActualParameter> executeParameters = new ArrayList<>(); |
1168 | 1233 for (ActualParameter sourceParameter : executable.getParameters()) { |
1169 CodeTreeBuilder executeBuilder = new CodeTreeBuilder(builder); | 1234 NodeFieldData field = specialization.getNode().findField(sourceParameter.getSpecification().getName()); |
1170 buildExecute(executeBuilder, null, null, execType); | 1235 if (field == null || field.getKind() == FieldKind.FINAL_FIELD) { |
1171 primaryExecuteCall = executeBuilder.getRoot(); | 1236 continue; |
1172 | 1237 } |
1238 | |
1239 ActualParameter targetParameter = castExecutable.findParameter(sourceParameter.getLocalName()); | |
1240 if (targetParameter != null) { | |
1241 TypeData sourceType = sourceParameter.getTypeSystemType(); | |
1242 TypeData targetType = targetParameter.getTypeSystemType(); | |
1243 if (sourceType.needsCastTo(targetType)) { | |
1244 executeParameters.add(targetParameter); | |
1245 } | |
1246 } | |
1247 } | |
1248 | |
1249 builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null, true)); | |
1250 | |
1251 CodeTree primaryExecuteCall = createTemplateMethodCall(builder, executable, castExecutable, null); | |
1173 if (needsTry) { | 1252 if (needsTry) { |
1174 if (!returnVoid) { | 1253 if (!returnVoid) { |
1175 builder.declaration(primaryType.getPrimitiveType(), "value"); | 1254 builder.declaration(primaryType.getPrimitiveType(), "value"); |
1176 } | 1255 } |
1177 builder.startTryBlock(); | 1256 builder.startTryBlock(); |
1234 builder.tree(value); | 1313 builder.tree(value); |
1235 builder.end().end(); | 1314 builder.end().end(); |
1236 return builder.getRoot(); | 1315 return builder.getRoot(); |
1237 } | 1316 } |
1238 | 1317 |
1239 private CodeTree createFunctionalExecute(CodeTreeBuilder parent, SpecializationData specialization) { | 1318 private CodeTree createFunctionalExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable) { |
1240 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 1319 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
1241 if (specialization.isUninitialized()) { | 1320 if (specialization.isUninitialized()) { |
1242 builder.tree(createDeoptimize(builder)); | 1321 builder.tree(createDeoptimize(builder)); |
1243 } | 1322 } |
1244 | 1323 |
1245 builder.tree(createExecuteChildren(builder, specialization)); | 1324 builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null, false)); |
1246 | 1325 |
1247 CodeTree executeNode; | 1326 CodeTree executeNode; |
1248 if (specialization.isUninitialized()) { | 1327 if (specialization.isUninitialized()) { |
1249 builder.tree(createSpecializeCall(builder, specialization)); | 1328 builder.tree(createSpecializeCall(builder, executable, specialization)); |
1250 } | 1329 } |
1251 executeNode = createExecute(builder, specialization); | 1330 executeNode = createExecute(builder, executable, specialization); |
1252 | 1331 |
1253 SpecializationData next = specialization.findNextSpecialization(); | 1332 SpecializationData next = specialization.findNextSpecialization(); |
1254 CodeTree returnSpecialized = null; | 1333 CodeTree returnSpecialized = null; |
1255 if (next != null) { | 1334 if (next != null) { |
1256 returnSpecialized = createReturnSpecializeAndExecute(builder, next, null); | 1335 returnSpecialized = createReturnSpecializeAndExecute(builder, executable, next, null); |
1257 } | 1336 } |
1258 builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized)); | 1337 builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized)); |
1259 | 1338 |
1260 return builder.getRoot(); | 1339 return builder.getRoot(); |
1261 } | 1340 } |
1266 builder.startStaticCall(getContext().getTruffleTypes().getTruffleIntrinsics(), "deoptimize").end(); | 1345 builder.startStaticCall(getContext().getTruffleTypes().getTruffleIntrinsics(), "deoptimize").end(); |
1267 builder.end(); | 1346 builder.end(); |
1268 return builder.getRoot(); | 1347 return builder.getRoot(); |
1269 } | 1348 } |
1270 | 1349 |
1271 private CodeTree createSpecializeCall(CodeTreeBuilder parent, SpecializationData specialization) { | 1350 private CodeTree createSpecializeCall(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) { |
1272 NodeData node = specialization.getNode(); | 1351 NodeData node = specialization.getNode(); |
1273 | 1352 |
1274 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 1353 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
1275 emitSpecializationListeners(builder, node); | 1354 emitSpecializationListeners(builder, node); |
1276 | 1355 |
1278 builder.startCall("replace"); | 1357 builder.startCall("replace"); |
1279 if (node.needsRewrites(getContext())) { | 1358 if (node.needsRewrites(getContext())) { |
1280 builder.startCall(factoryClassName(node), "specialize"); | 1359 builder.startCall(factoryClassName(node), "specialize"); |
1281 builder.string("this"); | 1360 builder.string("this"); |
1282 builder.typeLiteral(builder.findMethod().getEnclosingElement().asType()); | 1361 builder.typeLiteral(builder.findMethod().getEnclosingElement().asType()); |
1283 addInternalValueParameterNames(builder, specialization, null, true, true); | 1362 addInternalValueParameterNames(builder, executable, specialization, null, true, true); |
1284 builder.end(); // call replace, call specialize | 1363 builder.end(); // call replace, call specialize |
1285 } else { | 1364 } else { |
1286 builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end(); | 1365 builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end(); |
1287 } | 1366 } |
1288 builder.end().end(); | 1367 builder.end().end(); |
1289 return builder.getRoot(); | 1368 return builder.getRoot(); |
1290 } | 1369 } |
1291 | 1370 |
1292 private CodeTree createExecute(CodeTreeBuilder parent, SpecializationData specialization) { | 1371 private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) { |
1293 NodeData node = specialization.getNode(); | 1372 NodeData node = specialization.getNode(); |
1294 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 1373 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
1295 if (!specialization.getExceptions().isEmpty()) { | 1374 if (!specialization.getExceptions().isEmpty()) { |
1296 builder.startTryBlock(); | 1375 builder.startTryBlock(); |
1297 } | 1376 } |
1298 | 1377 |
1378 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent); | |
1299 if (specialization.isUninitialized()) { | 1379 if (specialization.isUninitialized()) { |
1300 String genericMethodName = generatedGenericMethodName(null); | 1380 String genericMethodName = generatedGenericMethodName(null); |
1301 builder.startReturn().startCall(factoryClassName(node), genericMethodName); | 1381 returnBuilder.startCall(factoryClassName(node), genericMethodName); |
1302 builder.string("this"); | 1382 returnBuilder.string("this"); |
1303 addInternalValueParameterNames(builder, specialization, null, true, true); | 1383 addInternalValueParameterNames(returnBuilder, executable, specialization, null, true, true); |
1304 builder.end().end(); | 1384 returnBuilder.end(); |
1305 } else if (specialization.getMethod() == null && !node.needsRewrites(context)) { | 1385 } else if (specialization.getMethod() == null && !node.needsRewrites(context)) { |
1306 emitEncounteredSynthetic(builder); | 1386 emitEncounteredSynthetic(builder); |
1307 } else if (specialization.isGeneric()) { | 1387 } else if (specialization.isGeneric()) { |
1308 String genericMethodName; | 1388 String genericMethodName; |
1309 if (!specialization.isUseSpecializationsForGeneric()) { | 1389 if (!specialization.isUseSpecializationsForGeneric()) { |
1310 genericMethodName = generatedGenericMethodName(specialization); | 1390 genericMethodName = generatedGenericMethodName(specialization); |
1311 } else { | 1391 } else { |
1312 genericMethodName = generatedGenericMethodName(null); | 1392 genericMethodName = generatedGenericMethodName(null); |
1313 } | 1393 } |
1314 | 1394 |
1315 builder.startReturn().startCall(factoryClassName(node), genericMethodName); | 1395 returnBuilder.startCall(factoryClassName(node), genericMethodName); |
1316 builder.string("this"); | 1396 returnBuilder.string("this"); |
1317 addInternalValueParameterNames(builder, specialization, null, true, true); | 1397 addInternalValueParameterNames(returnBuilder, executable, specialization, null, true, true); |
1318 builder.end().end(); | 1398 returnBuilder.end(); |
1319 } else { | 1399 } else { |
1400 returnBuilder.tree(createTemplateMethodCall(returnBuilder, executable, specialization, null)); | |
1401 } | |
1402 | |
1403 if (!returnBuilder.isEmpty()) { | |
1320 builder.startReturn(); | 1404 builder.startReturn(); |
1321 builder.tree(createTemplateMethodCall(builder, specialization, specialization, null)); | 1405 |
1322 builder.end(); // return | 1406 TypeData targetType = node.getTypeSystem().findTypeData(builder.findMethod().getReturnType()); |
1407 TypeData sourceType = specialization.getReturnType().getTypeSystemType(); | |
1408 | |
1409 if (targetType == null || sourceType == null) { | |
1410 builder.tree(returnBuilder.getRoot()); | |
1411 } else if (sourceType.needsCastTo(targetType)) { | |
1412 builder.tree(createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.expectTypeMethodName(targetType), returnBuilder.getRoot())); | |
1413 } else { | |
1414 builder.tree(returnBuilder.getRoot()); | |
1415 } | |
1416 builder.end(); | |
1323 } | 1417 } |
1324 | 1418 |
1325 if (!specialization.getExceptions().isEmpty()) { | 1419 if (!specialization.getExceptions().isEmpty()) { |
1326 for (SpecializationThrowsData exception : specialization.getExceptions()) { | 1420 for (SpecializationThrowsData exception : specialization.getExceptions()) { |
1327 builder.end().startCatchBlock(exception.getJavaClass(), "ex"); | 1421 builder.end().startCatchBlock(exception.getJavaClass(), "ex"); |
1328 builder.tree(createReturnSpecializeAndExecute(parent, exception.getTransitionTo(), null)); | 1422 builder.tree(createReturnSpecializeAndExecute(parent, executable, exception.getTransitionTo(), null)); |
1329 } | 1423 } |
1330 builder.end(); | 1424 builder.end(); |
1331 } | 1425 } |
1332 return builder.getRoot(); | 1426 return builder.getRoot(); |
1333 } | 1427 } |
1334 | 1428 |
1335 private CodeTree createExecuteChildren(CodeTreeBuilder parent, SpecializationData specialization) { | 1429 private CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List<ActualParameter> targetParameters, |
1430 ActualParameter unexpectedParameter, boolean cast) { | |
1431 NodeData sourceNode = specialization.getNode(); | |
1432 | |
1336 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 1433 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
1337 | 1434 |
1338 for (ActualParameter parameter : specialization.getParameters()) { | 1435 for (ActualParameter targetParameter : targetParameters) { |
1339 NodeFieldData field = specialization.getNode().findField(parameter.getSpecification().getName()); | 1436 NodeFieldData field = sourceNode.findField(targetParameter.getSpecification().getName()); |
1340 if (field == null || field.getKind() == FieldKind.FIELD) { | 1437 if (field == null || field.getKind() == FieldKind.FINAL_FIELD) { |
1341 continue; | 1438 continue; |
1342 } | 1439 } |
1343 | 1440 TypeData targetType = targetParameter.getTypeSystemType(); |
1344 buildFieldExecute(builder, specialization, parameter, field, null); | 1441 |
1442 ExecutableTypeData targetExecutable = field.getNodeData().findExecutableType(targetType); | |
1443 | |
1444 ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName()); | |
1445 | |
1446 String targetVariableName; | |
1447 CodeTree executionExpression; | |
1448 if (cast || sourceParameter != null) { | |
1449 TypeData sourceType = sourceParameter.getTypeSystemType(); | |
1450 if (!sourceType.needsCastTo(targetType)) { | |
1451 continue; | |
1452 } | |
1453 executionExpression = createExpectType(sourceNode, targetExecutable, CodeTreeBuilder.singleString(valueName(targetParameter))); | |
1454 targetVariableName = castValueName(targetParameter); | |
1455 } else { | |
1456 if (sourceExecutable.findParameter(targetParameter.getLocalName()) == null) { | |
1457 executionExpression = createExecuteChildExpression(builder, field, targetParameter); | |
1458 targetVariableName = valueName(targetParameter); | |
1459 } else { | |
1460 continue; | |
1461 } | |
1462 } | |
1463 | |
1464 CodeTreeVariable executionVar = new CodeTreeVariable(); | |
1465 CodeTree shortCircuitTree = createShortCircuitTree(builder, executionVar, targetVariableName, sourceExecutable, specialization, targetParameter, unexpectedParameter); | |
1466 CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpression, targetVariableName, specialization, sourceExecutable, targetExecutable, targetParameter, | |
1467 shortCircuitTree != executionVar); | |
1468 | |
1469 executionVar.set(unexpectedTree); | |
1470 builder.tree(shortCircuitTree); | |
1345 } | 1471 } |
1346 return builder.getRoot(); | 1472 return builder.getRoot(); |
1347 } | 1473 } |
1348 | 1474 |
1349 private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) { | 1475 private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) { |
1352 builder.tree(createTemplateMethodCall(builder, listener, listener, null)); | 1478 builder.tree(createTemplateMethodCall(builder, listener, listener, null)); |
1353 builder.end(); // statement | 1479 builder.end(); // statement |
1354 } | 1480 } |
1355 } | 1481 } |
1356 | 1482 |
1357 private void buildFieldExecute(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter param, NodeFieldData field, ActualParameter exceptionParam) { | 1483 private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, SpecializationData specialization, ExecutableTypeData currentExecutable, |
1358 boolean shortCircuit = startShortCircuit(builder, specialization, param, exceptionParam); | 1484 ExecutableTypeData targetExecutable, ActualParameter param, boolean shortCircuit) { |
1359 ExecutableTypeData execType = field.getNodeData().findExecutableType(param.getActualTypeData(field.getNodeData().getTypeSystem())); | 1485 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
1360 boolean unexpected = execType.hasUnexpectedValue(getContext()); | 1486 boolean unexpected = targetExecutable.hasUnexpectedValue(getContext()); |
1361 | 1487 builder.startStatement(); |
1362 if (!shortCircuit && unexpected) { | 1488 |
1363 builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).end(); | 1489 if (!shortCircuit) { |
1490 builder.type(param.getType()).string(" ").string(targetVariableName); | |
1364 } | 1491 } |
1365 | 1492 |
1366 if (unexpected) { | 1493 if (unexpected) { |
1494 if (!shortCircuit) { | |
1495 builder.end(); | |
1496 } | |
1367 builder.startTryBlock(); | 1497 builder.startTryBlock(); |
1368 } | 1498 builder.startStatement(); |
1369 | 1499 builder.string(targetVariableName); |
1370 if (!shortCircuit && !unexpected) { | 1500 } else if (shortCircuit) { |
1371 builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).string(" = "); | 1501 builder.startStatement(); |
1372 } else { | 1502 builder.string(targetVariableName); |
1373 builder.startStatement().string(valueName(param)).string(" = "); | 1503 } |
1374 } | 1504 builder.string(" = "); |
1375 buildExecute(builder, param, field, execType); | 1505 builder.tree(body); |
1376 builder.end(); | 1506 builder.end(); |
1377 | 1507 |
1378 if (unexpected) { | 1508 if (unexpected) { |
1379 builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); | 1509 builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); |
1380 SpecializationData generic = specialization.getNode().getGenericSpecialization(); | 1510 SpecializationData generic = specialization.getNode().getGenericSpecialization(); |
1381 boolean execute = false; | 1511 ActualParameter genericParameter = generic.findParameter(param.getLocalName()); |
1382 for (ActualParameter exParam : generic.getParameters()) { | 1512 |
1383 NodeFieldData exField = generic.getNode().findField(exParam.getSpecification().getName()); | 1513 List<ActualParameter> genericParameters = generic.getParametersAfter(genericParameter); |
1384 if (exField == null || field.getKind() == FieldKind.FIELD) { | 1514 builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter, false)); |
1385 continue; | 1515 builder.tree(createReturnSpecializeAndExecute(builder, currentExecutable, specialization.findNextSpecialization(), param)); |
1386 } | |
1387 if (execute) { | |
1388 buildFieldExecute(builder, specialization.getNode().getGenericSpecialization(), exParam, exField, param); | |
1389 } else if (exParam.getLocalName().equals(param.getLocalName())) { | |
1390 execute = true; | |
1391 } | |
1392 } | |
1393 builder.tree(createReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), param)); | |
1394 builder.end(); // catch block | 1516 builder.end(); // catch block |
1395 } | 1517 } |
1396 | 1518 |
1397 endShortCircuit(builder, shortCircuit); | 1519 return builder.getRoot(); |
1398 builder.newLine(); | 1520 } |
1399 } | 1521 |
1400 | 1522 private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeFieldData targetField, ActualParameter sourceParameter) { |
1401 private void buildExecute(CodeTreeBuilder builder, ActualParameter parameter, NodeFieldData field, ExecutableTypeData execType) { | 1523 TypeData type = sourceParameter.getTypeSystemType(); |
1402 if (field != null) { | 1524 ExecutableTypeData execType = targetField.getNodeData().findExecutableType(type); |
1403 Element accessElement = field.getAccessElement(); | 1525 |
1526 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | |
1527 if (targetField != null) { | |
1528 Element accessElement = targetField.getAccessElement(); | |
1404 if (accessElement.getKind() == ElementKind.METHOD) { | 1529 if (accessElement.getKind() == ElementKind.METHOD) { |
1405 builder.startCall(accessElement.getSimpleName().toString()).end(); | 1530 builder.startCall(accessElement.getSimpleName().toString()).end(); |
1406 } else if (accessElement.getKind() == ElementKind.FIELD) { | 1531 } else if (accessElement.getKind() == ElementKind.FIELD) { |
1407 builder.string("this.").string(accessElement.getSimpleName().toString()); | 1532 builder.string("this.").string(accessElement.getSimpleName().toString()); |
1408 } else { | 1533 } else { |
1409 throw new AssertionError(); | 1534 throw new AssertionError(); |
1410 } | 1535 } |
1411 if (parameter.getSpecification().isIndexed()) { | 1536 if (sourceParameter.getSpecification().isIndexed()) { |
1412 builder.string("[" + parameter.getIndex() + "]"); | 1537 builder.string("[" + sourceParameter.getIndex() + "]"); |
1413 } | 1538 } |
1414 builder.string("."); | 1539 builder.string("."); |
1415 } | 1540 } |
1416 builder.startCall(execType.getMethodName()); | 1541 builder.startCall(execType.getMethodName()); |
1417 if (execType.getParameters().size() == 1) { | 1542 if (execType.getParameters().size() == 1) { |
1418 builder.string("frameValue"); | 1543 builder.string("frameValue"); |
1419 } | 1544 } |
1420 builder.end(); | 1545 builder.end(); |
1421 } | 1546 return builder.getRoot(); |
1422 | 1547 } |
1423 private boolean startShortCircuit(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter parameter, ActualParameter exceptionParam) { | 1548 |
1549 private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, ExecutableTypeData currentExecutable, SpecializationData specialization, | |
1550 ActualParameter parameter, ActualParameter exceptionParam) { | |
1551 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | |
1552 | |
1424 NodeFieldData forField = specialization.getNode().findField(parameter.getSpecification().getName()); | 1553 NodeFieldData forField = specialization.getNode().findField(parameter.getSpecification().getName()); |
1425 if (forField == null) { | 1554 if (forField == null) { |
1426 return false; | 1555 return body; |
1427 } | 1556 } |
1428 | 1557 |
1429 if (forField.getExecutionKind() != ExecutionKind.SHORT_CIRCUIT) { | 1558 if (forField.getExecutionKind() != ExecutionKind.SHORT_CIRCUIT) { |
1430 return false; | 1559 return body; |
1431 } | 1560 } |
1432 | 1561 |
1433 ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter); | 1562 ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter); |
1434 | 1563 |
1435 int shortCircuitIndex = 0; | 1564 int shortCircuitIndex = 0; |
1440 } | 1569 } |
1441 shortCircuitIndex++; | 1570 shortCircuitIndex++; |
1442 } | 1571 } |
1443 } | 1572 } |
1444 | 1573 |
1445 builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); | 1574 builder.startStatement().type(shortCircuitParam.getType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); |
1446 ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex); | 1575 ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex); |
1447 | 1576 |
1448 builder.tree(createTemplateMethodCall(builder, shortCircuitData, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null)); | 1577 builder.tree(createTemplateMethodCall(builder, currentExecutable, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null)); |
1449 | 1578 |
1450 builder.end(); // statement | 1579 builder.end(); // statement |
1451 | 1580 |
1452 builder.declaration(parameter.getActualType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getActualType())); | 1581 builder.declaration(parameter.getType(), targetVariableName, CodeTreeBuilder.createBuilder().defaultValue(parameter.getType())); |
1453 builder.startIf().string(shortCircuitParam.getLocalName()).end(); | 1582 builder.startIf().string(shortCircuitParam.getLocalName()).end(); |
1454 builder.startBlock(); | 1583 builder.startBlock(); |
1455 | 1584 builder.tree(body); |
1456 return true; | 1585 builder.end(); |
1457 } | 1586 |
1458 | 1587 return builder.getRoot(); |
1459 private void endShortCircuit(CodeTreeBuilder builder, boolean shortCircuit) { | 1588 } |
1460 if (shortCircuit) { | 1589 |
1461 builder.end(); | 1590 private CodeTree createReturnSpecializeAndExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData nextSpecialization, ActualParameter exceptionParam) { |
1462 } | |
1463 } | |
1464 | |
1465 private CodeTree createReturnSpecializeAndExecute(CodeTreeBuilder parent, SpecializationData nextSpecialization, ActualParameter exceptionParam) { | |
1466 CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); | 1591 CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); |
1467 specializeCall.startCall("specializeAndExecute"); | 1592 specializeCall.startCall("specializeAndExecute"); |
1468 specializeCall.string(nodeSpecializationClassName(nextSpecialization) + ".class"); | 1593 specializeCall.string(nodeSpecializationClassName(nextSpecialization) + ".class"); |
1469 addInternalValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, true); | 1594 addInternalValueParameterNames(specializeCall, executable, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, |
1595 true); | |
1470 specializeCall.end().end(); | 1596 specializeCall.end().end(); |
1471 | 1597 |
1472 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 1598 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
1473 builder.startReturn(); | 1599 builder.startReturn(); |
1474 builder.tree(specializeCall.getRoot()); | 1600 builder.tree(createExpectType(nextSpecialization.getNode(), executable, specializeCall.getRoot())); |
1475 builder.end(); | 1601 builder.end(); |
1602 | |
1476 return builder.getRoot(); | 1603 return builder.getRoot(); |
1477 } | 1604 } |
1478 | 1605 |
1479 private void buildSpecializeAndExecute(CodeTypeElement clazz, SpecializationData specialization) { | 1606 private void buildSpecializeAndExecute(CodeTypeElement clazz, SpecializationData specialization) { |
1480 NodeData node = specialization.getNode(); | 1607 NodeData node = specialization.getNode(); |
1481 TypeData returnType = specialization.getReturnType().getActualTypeData(node.getTypeSystem()); | 1608 TypeData returnType = node.getGenericSpecialization().getReturnType().getTypeSystemType(); |
1482 ExecutableTypeData returnExecutableType = node.findExecutableType(returnType); | |
1483 boolean canThrowUnexpected = returnExecutableType == null ? true : returnExecutableType.hasUnexpectedValue(getContext()); | |
1484 | 1609 |
1485 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), returnType.getPrimitiveType(), "specializeAndExecute"); | 1610 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), returnType.getPrimitiveType(), "specializeAndExecute"); |
1486 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); | 1611 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); |
1487 if (canThrowUnexpected) { | |
1488 method.addThrownType(getUnexpectedValueException()); | |
1489 } | |
1490 addInternalValueParameters(method, specialization.getNode().getGenericSpecialization(), true); | 1612 addInternalValueParameters(method, specialization.getNode().getGenericSpecialization(), true); |
1491 clazz.add(method); | 1613 clazz.add(method); |
1492 | 1614 |
1493 CodeTreeBuilder builder = method.createBuilder(); | 1615 CodeTreeBuilder builder = method.createBuilder(); |
1494 | 1616 |
1496 emitSpecializationListeners(builder, specialization.getNode()); | 1618 emitSpecializationListeners(builder, specialization.getNode()); |
1497 | 1619 |
1498 builder.startStatement(); | 1620 builder.startStatement(); |
1499 builder.startCall("replace"); | 1621 builder.startCall("replace"); |
1500 builder.startCall(factoryClassName(specialization.getNode()), "specialize").string("this").string("minimumState"); | 1622 builder.startCall(factoryClassName(specialization.getNode()), "specialize").string("this").string("minimumState"); |
1501 addInternalValueParameterNames(builder, specialization.getNode().getGenericSpecialization(), null, true, true); | 1623 addInternalValueParameterNames(builder, specialization.getNode().getGenericSpecialization(), specialization.getNode().getGenericSpecialization(), null, true, true); |
1502 builder.end(); | 1624 builder.end(); |
1503 builder.end(); // call replace | 1625 builder.end(); // call replace |
1504 builder.end(); // statement | 1626 builder.end(); // statement |
1505 | 1627 |
1506 String generatedMethodName; | 1628 String generatedMethodName; |
1512 ExecutableElement generatedGeneric = clazz.getEnclosingClass().getMethod(generatedMethodName); | 1634 ExecutableElement generatedGeneric = clazz.getEnclosingClass().getMethod(generatedMethodName); |
1513 | 1635 |
1514 CodeTreeBuilder genericExecute = CodeTreeBuilder.createBuilder(); | 1636 CodeTreeBuilder genericExecute = CodeTreeBuilder.createBuilder(); |
1515 genericExecute.startCall(factoryClassName(specialization.getNode()), generatedMethodName); | 1637 genericExecute.startCall(factoryClassName(specialization.getNode()), generatedMethodName); |
1516 genericExecute.string("this"); | 1638 genericExecute.string("this"); |
1517 addInternalValueParameterNames(genericExecute, specialization.getNode().getGenericSpecialization(), null, true, true); | 1639 addInternalValueParameterNames(genericExecute, specialization.getNode().getGenericSpecialization(), specialization.getNode().getGenericSpecialization(), null, true, true); |
1518 genericExecute.end(); // call generated generic | 1640 genericExecute.end(); // call generated generic |
1519 | 1641 |
1520 CodeTree genericInvocation = createExpectType(node, returnExecutableType, genericExecute.getRoot()); | 1642 CodeTree genericInvocation = genericExecute.getRoot(); |
1521 | 1643 |
1522 if (generatedGeneric != null && Utils.isVoid(generatedGeneric.getReturnType())) { | 1644 if (generatedGeneric != null && Utils.isVoid(generatedGeneric.getReturnType())) { |
1523 builder.statement(genericInvocation); | 1645 builder.statement(genericInvocation); |
1524 | 1646 |
1525 if (!Utils.isVoid(builder.findMethod().asType())) { | 1647 if (!Utils.isVoid(builder.findMethod().asType())) { |