Mercurial > hg > graal-jvmci-8
comparison graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java @ 7847:06a7cd6aaf00
Casting is now done on demand using local variables for explicit guards.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Tue, 19 Feb 2013 17:20:45 +0100 |
parents | 91cc98eae8ee |
children | 6e4fb0ccebb1 |
comparison
equal
deleted
inserted
replaced
7846:91cc98eae8ee | 7847:06a7cd6aaf00 |
---|---|
81 | 81 |
82 private static String valueName(NodeFieldData field) { | 82 private static String valueName(NodeFieldData field) { |
83 return field.getName() + "Value"; | 83 return field.getName() + "Value"; |
84 } | 84 } |
85 | 85 |
86 private static String valueName(TemplateMethod method, ActualParameter param) { | 86 private static String valueName(ActualParameter param) { |
87 NodeData node = (NodeData) method.getTemplate(); | 87 NodeData node = (NodeData) param.getMethod().getTemplate(); |
88 NodeFieldData field = node.findField(param.getSpecification().getName()); | 88 NodeFieldData field = node.findField(param.getSpecification().getName()); |
89 if (field != null) { | 89 if (field != null) { |
90 return valueName(field); | 90 return valueName(field); |
91 } else { | 91 } else { |
92 return param.getSpecification().getName(); | 92 return param.getSpecification().getName(); |
93 } | 93 } |
94 } | 94 } |
95 | 95 |
96 private static String castValueName(ActualParameter parameter) { | |
97 return valueName(parameter) + "Cast"; | |
98 } | |
99 | |
100 private static String castValueName(NodeFieldData field) { | |
101 return valueName(field) + "Cast"; | |
102 } | |
103 | |
96 private void addValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame) { | 104 private void addValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame) { |
97 if (forceFrame) { | 105 if (forceFrame) { |
98 method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frame")); | 106 method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frame")); |
99 } | 107 } |
100 for (ActualParameter parameter : specialization.getParameters()) { | 108 for (ActualParameter parameter : specialization.getParameters()) { |
101 ParameterSpec spec = parameter.getSpecification(); | 109 ParameterSpec spec = parameter.getSpecification(); |
102 if (forceFrame && spec.getName().equals("frame")) { | 110 if (forceFrame && spec.getName().equals("frame")) { |
103 continue; | 111 continue; |
104 } | 112 } |
105 method.addParameter(new CodeVariableElement(parameter.getActualType(), valueName(specialization, parameter))); | 113 method.addParameter(new CodeVariableElement(parameter.getActualType(), valueName(parameter))); |
106 } | 114 } |
107 } | 115 } |
108 | 116 |
109 private static void addValueParameterNames(CodeTreeBuilder builder, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame) { | 117 private static void addValueParameterNames(CodeTreeBuilder builder, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame) { |
110 if (forceFrame) { | 118 if (forceFrame) { |
117 } | 125 } |
118 | 126 |
119 if (unexpectedValueName != null && spec.getName().equals(unexpectedValueName)) { | 127 if (unexpectedValueName != null && spec.getName().equals(unexpectedValueName)) { |
120 builder.string("ex.getResult()"); | 128 builder.string("ex.getResult()"); |
121 } else { | 129 } else { |
122 builder.string(valueName(specialization, parameter)); | 130 builder.string(valueName(parameter)); |
123 } | 131 } |
124 } | 132 } |
125 } | 133 } |
126 | 134 |
127 private static void addValueParameterNamesWithCasts(ProcessorContext context, CodeTreeBuilder body, SpecializationData valueSpecialization, SpecializationData targetSpecialization) { | 135 private static void addValueParameterNamesWithCasts(CodeTreeBuilder body, SpecializationData valueSpecialization, SpecializationData targetSpecialization) { |
128 NodeData node = targetSpecialization.getNode(); | 136 NodeData node = targetSpecialization.getNode(); |
129 TypeSystemData typeSystem = node.getTypeSystem(); | 137 TypeSystemData typeSystem = node.getTypeSystem(); |
130 | 138 |
131 for (ActualParameter targetParameter : targetSpecialization.getParameters()) { | 139 for (ActualParameter targetParameter : targetSpecialization.getParameters()) { |
132 ActualParameter valueParameter = valueSpecialization.findParameter(targetParameter.getSpecification().getName()); | 140 ActualParameter valueParameter = valueSpecialization.findParameter(targetParameter.getSpecification().getName()); |
136 if (valueParameter != null) { | 144 if (valueParameter != null) { |
137 valueType = valueParameter.getActualTypeData(typeSystem); | 145 valueType = valueParameter.getActualTypeData(typeSystem); |
138 } | 146 } |
139 | 147 |
140 if (targetType == null || targetType.isGeneric() || (valueType != null && valueType.equalsType(targetType))) { | 148 if (targetType == null || targetType.isGeneric() || (valueType != null && valueType.equalsType(targetType))) { |
141 body.string(valueName(targetSpecialization, targetParameter)); | 149 body.string(valueName(targetParameter)); |
142 } else { | 150 } else { |
143 String methodName = TypeSystemCodeGenerator.asTypeMethodName(targetType); | 151 body.string(castValueName(targetParameter)); |
144 startCallTypeSystemMethod(context, body, node, methodName); | |
145 body.string(valueName(targetSpecialization, targetParameter)); | |
146 body.end().end(); | |
147 } | 152 } |
148 } | 153 } |
149 } | 154 } |
150 | 155 |
151 private static String genClassName(Template operation) { | 156 private static String genClassName(Template operation) { |
182 prev = current; | 187 prev = current; |
183 } | 188 } |
184 return prefix; | 189 return prefix; |
185 } | 190 } |
186 | 191 |
192 private static CodeTree createCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder parent, NodeData node, String methodName, String value) { | |
193 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | |
194 startCallTypeSystemMethod(context, builder, node, methodName); | |
195 builder.string(value); | |
196 builder.end().end(); | |
197 return builder.getRoot(); | |
198 } | |
199 | |
187 private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body, NodeData node, String methodName) { | 200 private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body, NodeData node, String methodName) { |
188 VariableElement singleton = TypeSystemCodeGenerator.findSingleton(context, node.getTypeSystem()); | 201 VariableElement singleton = TypeSystemCodeGenerator.findSingleton(context, node.getTypeSystem()); |
189 assert singleton != null; | 202 assert singleton != null; |
190 | 203 |
191 body.startGroup(); | 204 body.startGroup(); |
192 body.staticReference(singleton.getEnclosingElement().asType(), singleton.getSimpleName().toString()); | 205 body.staticReference(singleton.getEnclosingElement().asType(), singleton.getSimpleName().toString()); |
193 body.string(".").startCall(methodName); | 206 body.string(".").startCall(methodName); |
194 } | 207 } |
195 | 208 |
196 private static CodeTree createGuardAndCast(ProcessorContext context, CodeTreeBuilder parent, String prefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, | 209 private CodeTree createGuardAndCast(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, boolean onSpecialization, |
197 boolean onSpecialization, CodeTree guardedStatements, CodeTree elseStatements) { | 210 CodeTree guardedStatements, CodeTree elseStatements) { |
198 | 211 |
199 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 212 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
200 CodeTree implicitGuards = createImplicitGuards(context, parent, prefix, valueSpecialization, guardedSpecialization); | 213 CodeTree implicitGuards = createImplicitGuards(parent, conditionPrefix, valueSpecialization, guardedSpecialization); |
201 CodeTree explicitGuards = createExplicitGuards(context, parent, implicitGuards == null ? prefix : null, valueSpecialization, guardedSpecialization, onSpecialization); | 214 CodeTree explicitGuards = createExplicitGuards(parent, implicitGuards == null ? conditionPrefix : null, valueSpecialization, guardedSpecialization, onSpecialization); |
202 | 215 |
203 int ifCount = 0; | 216 int ifCount = 0; |
204 | 217 |
205 if (implicitGuards != null) { | 218 if (implicitGuards != null) { |
206 builder.startIf(); | 219 builder.startIf(); |
208 builder.end(); | 221 builder.end(); |
209 builder.startBlock(); | 222 builder.startBlock(); |
210 ifCount++; | 223 ifCount++; |
211 } | 224 } |
212 | 225 |
226 if (explicitGuards != null || !onSpecialization) { | |
227 builder.tree(createCasts(parent, valueSpecialization, guardedSpecialization)); | |
228 } | |
229 | |
213 if (explicitGuards != null) { | 230 if (explicitGuards != null) { |
214 builder.startIf(); | 231 builder.startIf(); |
215 builder.tree(explicitGuards); | 232 builder.tree(explicitGuards); |
216 builder.end(); | 233 builder.end(); |
217 builder.startBlock(); | 234 builder.startBlock(); |
218 ifCount++; | 235 ifCount++; |
219 } | 236 } |
220 | 237 |
221 if (implicitGuards == null && explicitGuards == null && prefix != null && !prefix.isEmpty()) { | 238 if (implicitGuards == null && explicitGuards == null && conditionPrefix != null && !conditionPrefix.isEmpty()) { |
222 builder.startIf().string(prefix).end().startBlock(); | 239 builder.startIf().string(conditionPrefix).end().startBlock(); |
223 ifCount++; | 240 ifCount++; |
224 } | 241 } |
225 | 242 |
226 builder.tree(guardedStatements); | 243 builder.tree(guardedStatements); |
227 | 244 |
233 } | 250 } |
234 | 251 |
235 return builder.getRoot(); | 252 return builder.getRoot(); |
236 } | 253 } |
237 | 254 |
238 private static CodeTree createExplicitGuards(ProcessorContext context, CodeTreeBuilder parent, String prefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, | 255 private static CodeTree createExplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, |
239 boolean onSpecialization) { | 256 boolean onSpecialization) { |
240 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 257 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
241 String andOperator = (prefix != null && !prefix.isEmpty()) ? (prefix + " && ") : ""; | 258 String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; |
242 if (guardedSpecialization.getGuards().length > 0) { | 259 if (guardedSpecialization.getGuards().length > 0) { |
243 // Explicitly specified guards | 260 // Explicitly specified guards |
244 for (SpecializationGuardData guard : guardedSpecialization.getGuards()) { | 261 for (SpecializationGuardData guard : guardedSpecialization.getGuards()) { |
245 if ((guard.isOnSpecialization() && onSpecialization) || (guard.isOnExecution() && !onSpecialization)) { | 262 if ((guard.isOnSpecialization() && onSpecialization) || (guard.isOnExecution() && !onSpecialization)) { |
246 builder.string(andOperator); | 263 builder.string(andOperator); |
247 | 264 |
248 startCallOperationMethod(builder, guard.getGuardDeclaration()); | 265 startCallOperationMethod(builder, guard.getGuardDeclaration()); |
249 addValueParameterNamesWithCasts(context, builder, valueSpecialization, guardedSpecialization); | 266 addValueParameterNamesWithCasts(builder, valueSpecialization, guardedSpecialization); |
250 | 267 |
251 builder.end().end(); // call | 268 builder.end().end(); // call |
252 andOperator = " && "; | 269 andOperator = " && "; |
253 } | 270 } |
254 } | 271 } |
255 } | 272 } |
256 | 273 |
257 return builder.isEmpty() ? null : builder.getRoot(); | 274 return builder.isEmpty() ? null : builder.getRoot(); |
258 } | 275 } |
259 | 276 |
260 private static CodeTree createImplicitGuards(ProcessorContext context, CodeTreeBuilder parent, String prefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) { | 277 private CodeTree createCasts(CodeTreeBuilder parent, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) { |
261 NodeData node = guardedSpecialization.getNode(); | 278 NodeData node = guardedSpecialization.getNode(); |
262 TypeSystemData typeSystem = node.getTypeSystem(); | |
263 | 279 |
264 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 280 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
265 // Implict guards based on method signature | 281 // Implict guards based on method signature |
266 String andOperator = (prefix != null && !prefix.isEmpty()) ? (prefix + " && ") : ""; | |
267 for (NodeFieldData field : node.getFields()) { | 282 for (NodeFieldData field : node.getFields()) { |
268 ActualParameter guardedParam = guardedSpecialization.findParameter(field.getName()); | 283 ActualParameter guardedParam = guardedSpecialization.findParameter(field.getName()); |
269 ActualParameter valueParam = valueSpecialization.findParameter(field.getName()); | 284 ActualParameter valueParam = valueSpecialization.findParameter(field.getName()); |
270 | 285 |
271 TypeData guardedType = guardedParam.getActualTypeData(typeSystem); | 286 CodeTree cast = createCast(parent, field, valueParam, guardedParam); |
272 TypeData valueType = valueParam.getActualTypeData(typeSystem); | 287 if (cast == null) { |
273 | |
274 if (guardedType.equalsType(valueType) || guardedType.isGeneric()) { | |
275 continue; | 288 continue; |
276 } | 289 } |
290 builder.tree(cast); | |
291 } | |
292 | |
293 return builder.getRoot(); | |
294 } | |
295 | |
296 private CodeTree createImplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) { | |
297 NodeData node = guardedSpecialization.getNode(); | |
298 | |
299 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | |
300 // Implict guards based on method signature | |
301 String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; | |
302 for (NodeFieldData field : node.getFields()) { | |
303 ActualParameter guardedParam = guardedSpecialization.findParameter(field.getName()); | |
304 ActualParameter valueParam = valueSpecialization.findParameter(field.getName()); | |
305 | |
306 CodeTree implicitGuard = createImplicitGuard(builder, field, valueParam, guardedParam); | |
307 if (implicitGuard == null) { | |
308 continue; | |
309 } | |
277 | 310 |
278 builder.string(andOperator); | 311 builder.string(andOperator); |
279 | 312 builder.tree(implicitGuard); |
280 builder.startGroup(); | |
281 | |
282 if (field.isShortCircuit()) { | |
283 ActualParameter shortCircuit = guardedSpecialization.getPreviousParam(guardedParam); | |
284 builder.string("("); | |
285 builder.string("!").string(valueName(guardedSpecialization, shortCircuit)); | |
286 builder.string(" || "); | |
287 } | |
288 | |
289 startCallTypeSystemMethod(context, builder, guardedSpecialization.getNode(), TypeSystemCodeGenerator.isTypeMethodName(guardedType)); | |
290 builder.string(valueName(guardedSpecialization, guardedParam)); | |
291 builder.end().end(); // call | |
292 | |
293 if (field.isShortCircuit()) { | |
294 builder.string(")"); | |
295 } | |
296 | |
297 builder.end(); // group | |
298 andOperator = " && "; | 313 andOperator = " && "; |
299 } | 314 } |
300 | 315 |
301 return builder.isEmpty() ? null : builder.getRoot(); | 316 return builder.isEmpty() ? null : builder.getRoot(); |
317 } | |
318 | |
319 private CodeTree createImplicitGuard(CodeTreeBuilder parent, NodeFieldData field, ActualParameter source, ActualParameter target) { | |
320 NodeData node = field.getNodeData(); | |
321 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | |
322 | |
323 TypeData targetType = target.getActualTypeData(node.getTypeSystem()); | |
324 TypeData sourceType = source.getActualTypeData(node.getTypeSystem()); | |
325 | |
326 if (targetType.equalsType(sourceType) || targetType.isGeneric()) { | |
327 return null; | |
328 } | |
329 | |
330 builder.startGroup(); | |
331 | |
332 if (field.isShortCircuit()) { | |
333 ActualParameter shortCircuit = target.getPreviousParameter(); | |
334 assert shortCircuit != null; | |
335 builder.string("("); | |
336 builder.string("!").string(valueName(shortCircuit)); | |
337 builder.string(" || "); | |
338 } | |
339 | |
340 startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(target.getActualTypeData(node.getTypeSystem()))); | |
341 builder.string(valueName(field)); | |
342 builder.end().end(); // call | |
343 | |
344 if (field.isShortCircuit()) { | |
345 builder.string(")"); | |
346 } | |
347 | |
348 builder.end(); // group | |
349 | |
350 return builder.getRoot(); | |
351 } | |
352 | |
353 private CodeTree createCast(CodeTreeBuilder parent, NodeFieldData field, ActualParameter source, ActualParameter target) { | |
354 NodeData node = field.getNodeData(); | |
355 TypeSystemData typeSystem = node.getTypeSystem(); | |
356 | |
357 TypeData sourceType = source.getActualTypeData(typeSystem); | |
358 TypeData targetType = target.getActualTypeData(typeSystem); | |
359 | |
360 if (targetType.equalsType(sourceType) || targetType.isGeneric()) { | |
361 return null; | |
362 } | |
363 | |
364 CodeTree condition = null; | |
365 if (field.isShortCircuit()) { | |
366 ActualParameter shortCircuit = target.getPreviousParameter(); | |
367 assert shortCircuit != null; | |
368 condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); | |
369 } | |
370 | |
371 CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), valueName(target)); | |
372 | |
373 return createLazyAssignment(parent, castValueName(field), target.getActualType(), condition, value); | |
374 } | |
375 | |
376 /** | |
377 * <pre> | |
378 * variant1 $condition != null | |
379 * | |
380 * $type $name = defaultValue($type); | |
381 * if ($condition) { | |
382 * $name = $value; | |
383 * } | |
384 * | |
385 * variant2 $condition != null | |
386 * $type $name = $value; | |
387 * </pre> | |
388 * | |
389 * . | |
390 */ | |
391 private static CodeTree createLazyAssignment(CodeTreeBuilder parent, String name, TypeMirror type, CodeTree condition, CodeTree value) { | |
392 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | |
393 if (condition == null) { | |
394 builder.declaration(type, name, value); | |
395 } else { | |
396 builder.declaration(type, name, new CodeTreeBuilder(parent).defaultValue(type).getRoot()); | |
397 | |
398 builder.startIf().tree(condition).end(); | |
399 builder.startBlock(); | |
400 builder.startStatement(); | |
401 builder.string(name); | |
402 builder.string(" = "); | |
403 builder.tree(value); | |
404 builder.end(); // statement | |
405 builder.end(); // block | |
406 } | |
407 return builder.getRoot(); | |
302 } | 408 } |
303 | 409 |
304 @Override | 410 @Override |
305 protected void createChildren(NodeData node) { | 411 protected void createChildren(NodeData node) { |
306 Map<NodeData, List<TypeElement>> childTypes = new LinkedHashMap<>(); | 412 Map<NodeData, List<TypeElement>> childTypes = new LinkedHashMap<>(); |
518 CodeTreeBuilder guarded = new CodeTreeBuilder(body); | 624 CodeTreeBuilder guarded = new CodeTreeBuilder(body); |
519 guarded.startReturn().startNew(nodeClassName(specialization)); | 625 guarded.startReturn().startNew(nodeClassName(specialization)); |
520 guarded.string(THIS_NODE_LOCAL_VAR_NAME); | 626 guarded.string(THIS_NODE_LOCAL_VAR_NAME); |
521 guarded.end().end(); | 627 guarded.end().end(); |
522 | 628 |
523 body.tree(createGuardAndCast(getContext(), body, "allowed", node.getGenericSpecialization(), specialization, true, guarded.getRoot(), null)); | 629 body.tree(createGuardAndCast(body, "allowed", node.getGenericSpecialization(), specialization, true, guarded.getRoot(), null)); |
524 } | 630 } |
525 body.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).end().end(); | 631 body.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).end().end(); |
526 | 632 |
527 return method; | 633 return method; |
528 } | 634 } |
567 CodeTreeBuilder invokeMethodBuilder = new CodeTreeBuilder(builder); | 673 CodeTreeBuilder invokeMethodBuilder = new CodeTreeBuilder(builder); |
568 emitInvokeDoMethod(invokeMethodBuilder, current, 0); | 674 emitInvokeDoMethod(invokeMethodBuilder, current, 0); |
569 CodeTree invokeMethod = invokeMethodBuilder.getRoot(); | 675 CodeTree invokeMethod = invokeMethodBuilder.getRoot(); |
570 | 676 |
571 if (next != null) { | 677 if (next != null) { |
572 invokeMethod = createGuardAndCast(getContext(), builder, "", current.getNode().getGenericSpecialization(), current, false, invokeMethod, null); | 678 invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, false, invokeMethod, null); |
573 } | 679 } |
574 | 680 |
575 builder.tree(invokeMethod); | 681 builder.tree(invokeMethod); |
576 | 682 |
577 if (next != null) { | 683 if (next != null) { |
589 builder.startTryBlock(); | 695 builder.startTryBlock(); |
590 } | 696 } |
591 | 697 |
592 builder.startReturn(); | 698 builder.startReturn(); |
593 startCallOperationMethod(builder, specialization); | 699 startCallOperationMethod(builder, specialization); |
594 addValueParameterNamesWithCasts(context, builder, specialization.getNode().getGenericSpecialization(), specialization); | 700 addValueParameterNamesWithCasts(builder, specialization.getNode().getGenericSpecialization(), specialization); |
595 builder.end().end(); // start call operation | 701 builder.end().end(); // start call operation |
596 builder.end(); // return | 702 builder.end(); // return |
597 | 703 |
598 if (specialization.getExceptions().length > 0) { | 704 if (specialization.getExceptions().length > 0) { |
599 for (SpecializationThrowsData exception : specialization.getExceptions()) { | 705 for (SpecializationThrowsData exception : specialization.getExceptions()) { |
696 builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); | 802 builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); |
697 if (returnVoid) { | 803 if (returnVoid) { |
698 builder.string("// ignore").newLine(); | 804 builder.string("// ignore").newLine(); |
699 } else { | 805 } else { |
700 builder.startReturn(); | 806 builder.startReturn(); |
701 builder.tree(castPrimaryExecute(node, castedType, CodeTreeBuilder.singleString("ex.getResult()"))); | 807 builder.tree(createExpectType(node, castedType, CodeTreeBuilder.singleString("ex.getResult()"))); |
702 builder.end(); | 808 builder.end(); |
703 } | 809 } |
704 builder.end(); | 810 builder.end(); |
705 | 811 |
706 if (!returnVoid) { | 812 if (!returnVoid) { |
707 builder.startReturn(); | 813 builder.startReturn(); |
708 builder.tree(castPrimaryExecute(node, castedType, CodeTreeBuilder.singleString("value"))); | 814 builder.tree(createExpectType(node, castedType, CodeTreeBuilder.singleString("value"))); |
709 builder.end(); | 815 builder.end(); |
710 } | 816 } |
711 } else { | 817 } else { |
712 if (returnVoid) { | 818 if (returnVoid) { |
713 builder.statement(primaryExecuteCall); | 819 builder.statement(primaryExecuteCall); |
714 } else { | 820 } else { |
715 builder.startReturn(); | 821 builder.startReturn(); |
716 builder.tree(castPrimaryExecute(node, castedType, primaryExecuteCall)); | 822 builder.tree(createExpectType(node, castedType, primaryExecuteCall)); |
717 builder.end(); | 823 builder.end(); |
718 } | 824 } |
719 } | 825 } |
720 } | 826 } |
721 | 827 |
722 private CodeTree castPrimaryExecute(NodeData node, ExecutableTypeData castedType, CodeTree value) { | 828 private CodeTree createExpectType(NodeData node, ExecutableTypeData castedType, CodeTree value) { |
723 if (castedType == null) { | 829 if (castedType == null) { |
724 return value; | 830 return value; |
725 } else if (castedType.getType().isVoid()) { | 831 } else if (castedType.getType().isVoid()) { |
726 return value; | 832 return value; |
727 } else if (castedType.getType().isGeneric()) { | 833 } else if (castedType.getType().isGeneric()) { |
728 return value; | 834 return value; |
729 } | 835 } |
730 | 836 |
731 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); | 837 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); |
838 String targetMethodName; | |
732 if (castedType.hasUnexpectedValue(getContext())) { | 839 if (castedType.hasUnexpectedValue(getContext())) { |
733 startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.expectTypeMethodName(castedType.getType())); | 840 targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(castedType.getType()); |
734 } else { | 841 } else { |
735 startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.asTypeMethodName(castedType.getType())); | 842 targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(castedType.getType()); |
736 } | 843 } |
844 startCallTypeSystemMethod(getContext(), builder, node, targetMethodName); | |
845 | |
737 builder.tree(value); | 846 builder.tree(value); |
738 builder.end().end(); | 847 builder.end().end(); |
739 return builder.getRoot(); | 848 return builder.getRoot(); |
740 } | 849 } |
741 | 850 |
755 SpecializationData next = specialization.findNextSpecialization(); | 864 SpecializationData next = specialization.findNextSpecialization(); |
756 CodeTree returnSpecialized = null; | 865 CodeTree returnSpecialized = null; |
757 if (next != null) { | 866 if (next != null) { |
758 returnSpecialized = createReturnSpecializeAndExecute(builder, next, null); | 867 returnSpecialized = createReturnSpecializeAndExecute(builder, next, null); |
759 } | 868 } |
760 builder.tree(createGuardAndCast(context, builder, "", specialization, specialization, false, executeNode, returnSpecialized)); | 869 builder.tree(createGuardAndCast(builder, null, specialization, specialization, false, executeNode, returnSpecialized)); |
761 } | 870 } |
762 | 871 |
763 private CodeTree createDeoptimize(CodeTreeBuilder parent) { | 872 private CodeTree createDeoptimize(CodeTreeBuilder parent) { |
764 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 873 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
765 builder.startStatement(); | 874 builder.startStatement(); |
861 if (!shortCircuit) { | 970 if (!shortCircuit) { |
862 builder.type(specialization.getNode().getTypeSystem().getGenericType()); | 971 builder.type(specialization.getNode().getTypeSystem().getGenericType()); |
863 builder.string(" "); | 972 builder.string(" "); |
864 } | 973 } |
865 | 974 |
866 builder.string(valueName(specialization, specParameter)); | 975 builder.string(valueName(specParameter)); |
867 builder.string(" = "); | 976 builder.string(" = "); |
868 ExecutableTypeData genericExecutableType = field.getNodeData().findGenericExecutableType(getContext(), specParameter.getActualTypeData(node.getTypeSystem())); | 977 ExecutableTypeData genericExecutableType = field.getNodeData().findGenericExecutableType(getContext(), specParameter.getActualTypeData(node.getTypeSystem())); |
869 if (genericExecutableType == null) { | 978 if (genericExecutableType == null) { |
870 throw new AssertionError("Must have generic executable type. Parser validation most likely failed. " + Arrays.toString(field.getNodeData().getExecutableTypes())); | 979 throw new AssertionError("Must have generic executable type. Parser validation most likely failed. " + Arrays.toString(field.getNodeData().getExecutableTypes())); |
871 } | 980 } |
897 private void buildSpecializedValueExecute(CodeTreeBuilder builder, SpecializationData specialization, NodeFieldData field) { | 1006 private void buildSpecializedValueExecute(CodeTreeBuilder builder, SpecializationData specialization, NodeFieldData field) { |
898 ActualParameter param = specialization.findParameter(field.getName()); | 1007 ActualParameter param = specialization.findParameter(field.getName()); |
899 boolean shortCircuit = startShortCircuit(builder, specialization, field, null); | 1008 boolean shortCircuit = startShortCircuit(builder, specialization, field, null); |
900 | 1009 |
901 if (!shortCircuit) { | 1010 if (!shortCircuit) { |
902 builder.startStatement().type(param.getActualType()).string(" ").string(valueName(specialization, param)).end(); | 1011 builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).end(); |
903 } | 1012 } |
904 | 1013 |
905 ExecutableTypeData execType = field.getNodeData().findExecutableType(param.getActualTypeData(field.getNodeData().getTypeSystem())); | 1014 ExecutableTypeData execType = field.getNodeData().findExecutableType(param.getActualTypeData(field.getNodeData().getTypeSystem())); |
906 | 1015 |
907 if (execType.hasUnexpectedValue(getContext())) { | 1016 if (execType.hasUnexpectedValue(getContext())) { |
949 } | 1058 } |
950 shortCircuitIndex++; | 1059 shortCircuitIndex++; |
951 } | 1060 } |
952 } | 1061 } |
953 | 1062 |
954 builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(specialization, shortCircuitParam)).string(" = "); | 1063 builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); |
955 ShortCircuitData shortCircuitData = specialization.getShortCircuits()[shortCircuitIndex]; | 1064 ShortCircuitData shortCircuitData = specialization.getShortCircuits()[shortCircuitIndex]; |
956 | 1065 |
957 startCallOperationMethod(builder, shortCircuitData); | 1066 startCallOperationMethod(builder, shortCircuitData); |
958 addValueParameterNames(builder, shortCircuitData, exceptionField != null ? exceptionField.getName() : null, false); | 1067 addValueParameterNames(builder, shortCircuitData, exceptionField != null ? exceptionField.getName() : null, false); |
959 builder.end().end(); // call operation | 1068 builder.end().end(); // call operation |
960 | 1069 |
961 builder.end(); // statement | 1070 builder.end(); // statement |
962 | 1071 |
963 builder.declaration(parameter.getActualType(), valueName(specialization, parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getActualType())); | 1072 builder.declaration(parameter.getActualType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getActualType())); |
964 builder.startIf().string(shortCircuitParam.getSpecification().getName()).end(); | 1073 builder.startIf().string(shortCircuitParam.getSpecification().getName()).end(); |
965 builder.startBlock(); | 1074 builder.startBlock(); |
966 | 1075 |
967 return true; | 1076 return true; |
968 } | 1077 } |
1021 genericExecute.startCall(factoryClassName(specialization.getNode()), generatedMethodName); | 1130 genericExecute.startCall(factoryClassName(specialization.getNode()), generatedMethodName); |
1022 genericExecute.string("this"); | 1131 genericExecute.string("this"); |
1023 addValueParameterNames(genericExecute, specialization.getNode().getGenericSpecialization(), null, true); | 1132 addValueParameterNames(genericExecute, specialization.getNode().getGenericSpecialization(), null, true); |
1024 genericExecute.end(); // call generated generic | 1133 genericExecute.end(); // call generated generic |
1025 | 1134 |
1026 CodeTree genericInvocation = castPrimaryExecute(node, returnExecutableType, genericExecute.getRoot()); | 1135 CodeTree genericInvocation = createExpectType(node, returnExecutableType, genericExecute.getRoot()); |
1027 | 1136 |
1028 if (generatedGeneric != null && Utils.isVoid(generatedGeneric.getReturnType())) { | 1137 if (generatedGeneric != null && Utils.isVoid(generatedGeneric.getReturnType())) { |
1029 builder.statement(genericInvocation); | 1138 builder.statement(genericInvocation); |
1030 | 1139 |
1031 if (!Utils.isVoid(builder.findMethod().asType())) { | 1140 if (!Utils.isVoid(builder.findMethod().asType())) { |