comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java @ 10597:79041ab43660

Truffle-DSL: API-change: Renamed truffle.api.codegen to truffle.api.dsl for all projects and packages.
author Christian Humer <christian.humer@gmail.com>
date Mon, 01 Jul 2013 20:58:32 +0200
parents
children e93efe3ba5f4
comparison
equal deleted inserted replaced
10596:f43eb2f1bbbc 10597:79041ab43660
1 /*
2 * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package com.oracle.truffle.dsl.processor.node;
24
25 import static com.oracle.truffle.dsl.processor.Utils.*;
26 import static javax.lang.model.element.Modifier.*;
27
28 import java.util.*;
29
30 import javax.lang.model.element.*;
31 import javax.lang.model.type.*;
32 import javax.lang.model.util.*;
33
34 import com.oracle.truffle.api.dsl.*;
35 import com.oracle.truffle.api.nodes.NodeInfo.Kind;
36 import com.oracle.truffle.dsl.processor.*;
37 import com.oracle.truffle.dsl.processor.ast.*;
38 import com.oracle.truffle.dsl.processor.node.NodeChildData.*;
39 import com.oracle.truffle.dsl.processor.template.*;
40 import com.oracle.truffle.dsl.processor.typesystem.*;
41
42 public class NodeCodeGenerator extends CompilationUnitFactory<NodeData> {
43
44 private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode";
45
46 private static final String EXECUTE_GENERIC_NAME = "executeGeneric0";
47 private static final String EXECUTE_SPECIALIZE_NAME = "executeAndSpecialize0";
48
49 public NodeCodeGenerator(ProcessorContext context) {
50 super(context);
51 }
52
53 private TypeMirror getUnexpectedValueException() {
54 return getContext().getTruffleTypes().getUnexpectedValueException();
55 }
56
57 private static String factoryClassName(NodeData node) {
58 return node.getNodeId() + "Factory";
59 }
60
61 private static String nodeSpecializationClassName(SpecializationData specialization) {
62 String nodeid = specialization.getNode().getNodeId();
63 if (nodeid.endsWith("Node") && !nodeid.equals("Node")) {
64 nodeid = nodeid.substring(0, nodeid.length() - 4);
65 }
66
67 String name = Utils.firstLetterUpperCase(nodeid);
68 name += Utils.firstLetterUpperCase(specialization.getId());
69 name += "Node";
70 return name;
71 }
72
73 private static String nodePolymorphicClassName(NodeData node, SpecializationData specialization) {
74 String nodeid = node.getNodeId();
75 if (nodeid.endsWith("Node") && !nodeid.equals("Node")) {
76 nodeid = nodeid.substring(0, nodeid.length() - 4);
77 }
78
79 String name = Utils.firstLetterUpperCase(nodeid);
80 int index = specialization == null ? 0 : node.getPolymorphicSpecializations().indexOf(specialization);
81 if (index == 0) {
82 name += "PolymorphicNode";
83 } else {
84 name += "Polymorphic" + index + "Node";
85 }
86 return name;
87 }
88
89 private static String valueNameEvaluated(ActualParameter targetParameter) {
90 return valueName(targetParameter) + "Evaluated";
91 }
92
93 private static String valueName(ActualParameter param) {
94 return param.getLocalName();
95 }
96
97 private static String castValueName(ActualParameter parameter) {
98 return valueName(parameter) + "Cast";
99 }
100
101 private void addInternalValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame, boolean evaluated) {
102 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
103 method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue"));
104 }
105 for (ActualParameter parameter : specialization.getParameters()) {
106 ParameterSpec spec = parameter.getSpecification();
107 if (forceFrame && spec.getName().equals("frame")) {
108 continue;
109 }
110 if (spec.isLocal()) {
111 continue;
112 }
113
114 String name = valueName(parameter);
115 if (evaluated && spec.isSignature()) {
116 name = valueNameEvaluated(parameter);
117 }
118
119 method.addParameter(new CodeVariableElement(parameter.getType(), name));
120 }
121 }
122
123 private void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, boolean includeImplicit) {
124 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
125 builder.string("frameValue");
126 }
127 for (ActualParameter parameter : specialization.getParameters()) {
128 ParameterSpec spec = parameter.getSpecification();
129 if (forceFrame && spec.getName().equals("frame")) {
130 continue;
131 }
132
133 if (!includeImplicit && (parameter.isImplicit())) {
134 continue;
135 }
136 if (parameter.getSpecification().isLocal()) {
137 continue;
138 }
139
140 ActualParameter sourceParameter = source.findParameter(parameter.getLocalName());
141
142 if (unexpectedValueName != null && parameter.getLocalName().equals(unexpectedValueName)) {
143 builder.cast(parameter.getType(), CodeTreeBuilder.singleString("ex.getResult()"));
144 } else if (sourceParameter != null) {
145 builder.string(valueName(sourceParameter, parameter));
146 } else {
147 builder.string(valueName(parameter));
148 }
149 }
150 }
151
152 private String valueName(ActualParameter sourceParameter, ActualParameter targetParameter) {
153 if (sourceParameter != null) {
154 if (!sourceParameter.getSpecification().isSignature()) {
155 return valueName(targetParameter);
156 } else if (sourceParameter.getTypeSystemType() != null && targetParameter.getTypeSystemType() != null) {
157 if (sourceParameter.getTypeSystemType().needsCastTo(getContext(), targetParameter.getTypeSystemType())) {
158 return castValueName(targetParameter);
159 }
160 }
161 return valueName(targetParameter);
162 } else {
163 return valueName(targetParameter);
164 }
165 }
166
167 private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName,
168 String... customSignatureValueNames) {
169 CodeTreeBuilder builder = parent.create();
170
171 boolean castedValues = sourceMethod != targetMethod;
172
173 builder.startGroup();
174 ExecutableElement method = targetMethod.getMethod();
175 if (method == null) {
176 throw new UnsupportedOperationException();
177 }
178 TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement());
179 NodeData node = (NodeData) targetMethod.getTemplate();
180
181 if (target == null) {
182 boolean accessible = targetMethod.canBeAccessedByInstanceOf(getContext(), node.getNodeType());
183 if (accessible) {
184 if (builder.findMethod().getModifiers().contains(STATIC)) {
185 if (method.getModifiers().contains(STATIC)) {
186 builder.type(targetClass.asType());
187 } else {
188 builder.string(THIS_NODE_LOCAL_VAR_NAME);
189 }
190 } else {
191 if (targetMethod instanceof ExecutableTypeData) {
192 builder.string("this");
193 } else {
194 builder.string("super");
195 }
196 }
197 } else {
198 if (method.getModifiers().contains(STATIC)) {
199 builder.type(targetClass.asType());
200 } else {
201 ActualParameter parameter = null;
202 for (ActualParameter searchParameter : targetMethod.getParameters()) {
203 if (searchParameter.getSpecification().isSignature()) {
204 parameter = searchParameter;
205 break;
206 }
207 }
208 ActualParameter sourceParameter = sourceMethod.findParameter(parameter.getLocalName());
209 assert parameter != null;
210
211 if (castedValues && sourceParameter != null) {
212 builder.string(valueName(sourceParameter, parameter));
213 } else {
214 builder.string(valueName(parameter));
215 }
216 }
217 }
218 builder.string(".");
219 } else {
220 builder.tree(target);
221 }
222 builder.startCall(method.getSimpleName().toString());
223
224 int signatureIndex = 0;
225
226 for (ActualParameter targetParameter : targetMethod.getParameters()) {
227 ActualParameter valueParameter = null;
228 if (sourceMethod != null) {
229 valueParameter = sourceMethod.findParameter(targetParameter.getLocalName());
230 }
231 if (valueParameter == null) {
232 valueParameter = targetParameter;
233 }
234 TypeData targetType = targetParameter.getTypeSystemType();
235
236 if (targetParameter.isImplicit() || valueParameter.isImplicit()) {
237 continue;
238 }
239
240 TypeData valueType = null;
241 if (valueParameter != null) {
242 valueType = valueParameter.getTypeSystemType();
243 }
244
245 if (signatureIndex < customSignatureValueNames.length && targetParameter.getSpecification().isSignature()) {
246 builder.string(customSignatureValueNames[signatureIndex]);
247 signatureIndex++;
248 } else if (targetParameter.getSpecification().isLocal()) {
249 builder.startGroup();
250 if (builder.findMethod().getModifiers().contains(Modifier.STATIC)) {
251 builder.string(THIS_NODE_LOCAL_VAR_NAME).string(".");
252 } else {
253 builder.string("this.");
254 }
255 builder.string(targetParameter.getSpecification().getName());
256 builder.end();
257 } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) {
258 builder.string("ex.getResult()");
259 } else if (targetType == null || targetType.isGeneric() || (valueType != null && valueType.equalsType(targetType))) {
260 builder.startGroup();
261
262 if (valueType != null && sourceMethod.getMethodName().equals(targetMethod.getMethodName()) && !valueType.isGeneric() && targetType.isGeneric()) {
263 builder.string("(");
264 builder.type(targetType.getPrimitiveType());
265 builder.string(") ");
266 }
267 builder.string(valueName(targetParameter));
268 builder.end();
269 } else {
270 builder.string(castValueName(targetParameter));
271 }
272 }
273
274 builder.end().end();
275
276 return builder.getRoot();
277 }
278
279 private static String baseClassName(NodeData node) {
280 String nodeid = node.getNodeId();
281 if (nodeid.endsWith("Node") && !nodeid.equals("Node")) {
282 nodeid = nodeid.substring(0, nodeid.length() - 4);
283 }
284 String name = Utils.firstLetterUpperCase(nodeid);
285 name += "BaseNode";
286 return name;
287 }
288
289 private static CodeTree createCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder parent, NodeData node, String methodName, CodeTree value) {
290 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
291 startCallTypeSystemMethod(context, builder, node, methodName);
292 builder.tree(value);
293 builder.end().end();
294 return builder.getRoot();
295 }
296
297 private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body, NodeData node, String methodName) {
298 VariableElement singleton = TypeSystemCodeGenerator.findSingleton(context, node.getTypeSystem());
299 assert singleton != null;
300
301 body.startGroup();
302 body.staticReference(singleton.getEnclosingElement().asType(), singleton.getSimpleName().toString());
303 body.string(".").startCall(methodName);
304 }
305
306 private CodeTree createGuardAndCast(CodeTreeBuilder parent, String conditionPrefix, SpecializationData sourceSpecialization, SpecializationData targetSpecialization, boolean castValues,
307 CodeTree guardedStatements, CodeTree elseStatements, boolean emitAssumptions, boolean forceElse) {
308
309 NodeData node = targetSpecialization.getNode();
310 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
311 CodeTree implicitGuards = createImplicitGuards(parent, conditionPrefix, sourceSpecialization, targetSpecialization, emitAssumptions);
312 CodeTree explicitGuards = createExplicitGuards(parent, implicitGuards == null ? conditionPrefix : null, sourceSpecialization, targetSpecialization);
313
314 Set<String> valuesNeedsCast;
315 if (castValues) {
316 // cast all
317 valuesNeedsCast = null;
318 } else {
319 // find out which values needs a cast
320 valuesNeedsCast = new HashSet<>();
321 for (GuardData guard : targetSpecialization.getGuards()) {
322 for (ActualParameter targetParameter : guard.getParameters()) {
323 NodeChildData field = node.findChild(targetParameter.getSpecification().getName());
324 if (field == null) {
325 continue;
326 }
327 TypeData targetType = targetParameter.getTypeSystemType();
328 ActualParameter sourceParameter = sourceSpecialization.findParameter(targetParameter.getLocalName());
329 if (sourceParameter == null) {
330 sourceParameter = targetParameter;
331 }
332 TypeData sourceType = sourceParameter.getTypeSystemType();
333
334 if (sourceType.needsCastTo(getContext(), targetType)) {
335 valuesNeedsCast.add(targetParameter.getLocalName());
336 }
337 }
338 }
339 }
340
341 int ifCount = 0;
342
343 if (implicitGuards != null) {
344 builder.startIf();
345 builder.tree(implicitGuards);
346 builder.end();
347 builder.startBlock();
348 ifCount++;
349 }
350
351 builder.tree(createCasts(parent, valuesNeedsCast, sourceSpecialization, targetSpecialization));
352
353 if (explicitGuards != null) {
354 builder.startIf();
355 builder.tree(explicitGuards);
356 builder.end();
357 builder.startBlock();
358 ifCount++;
359 }
360
361 if (implicitGuards == null && explicitGuards == null && conditionPrefix != null && !conditionPrefix.isEmpty()) {
362 builder.startIf();
363 builder.string(conditionPrefix);
364 builder.end().startBlock();
365 ifCount++;
366 }
367
368 builder.tree(guardedStatements);
369
370 builder.end(ifCount);
371 if (elseStatements != null && (forceElse || ifCount > 0)) {
372 builder.tree(elseStatements);
373 }
374 return builder.getRoot();
375 }
376
377 private CodeTree createExplicitGuards(CodeTreeBuilder parent, String conditionPrefix, TemplateMethod valueSpecialization, SpecializationData guardedSpecialization) {
378 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
379 String andOperator = conditionPrefix != null ? conditionPrefix + " && " : "";
380 if (guardedSpecialization.getGuards().size() > 0) {
381 // Explicitly specified guards
382 for (GuardData guard : guardedSpecialization.getGuards()) {
383 builder.string(andOperator);
384 builder.tree(createTemplateMethodCall(parent, null, valueSpecialization, guard, null));
385 andOperator = " && ";
386 }
387 }
388
389 return builder.isEmpty() ? null : builder.getRoot();
390 }
391
392 private CodeTree createCasts(CodeTreeBuilder parent, Set<String> castWhiteList, TemplateMethod valueSpecialization, SpecializationData guardedSpecialization) {
393 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
394 // Implict guards based on method signature
395 for (ActualParameter guardedParam : guardedSpecialization.getParameters()) {
396 NodeChildData field = guardedSpecialization.getNode().findChild(guardedParam.getSpecification().getName());
397 if (field == null) {
398 continue;
399 }
400 ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName());
401
402 if (valueParam == null) {
403 /*
404 * If used inside a function execute method. The value param may not exist. In that
405 * case it assumes that the value is already converted.
406 */
407 valueParam = guardedParam;
408 }
409
410 if (castWhiteList != null && !castWhiteList.contains(guardedParam.getLocalName())) {
411 continue;
412 }
413
414 CodeTree cast = createCast(parent, field, valueParam, guardedParam);
415 if (cast == null) {
416 continue;
417 }
418 builder.tree(cast);
419 }
420
421 return builder.getRoot();
422 }
423
424 private CodeTree createImplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, boolean emitAssumptions) {
425 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
426 // Implict guards based on method signature
427 String andOperator = conditionPrefix != null ? conditionPrefix + " && " : "";
428
429 if (emitAssumptions) {
430 for (String assumption : guardedSpecialization.getAssumptions()) {
431 builder.string(andOperator);
432 builder.string("this");
433 builder.string(".").string(assumption).string(".isValid()");
434 andOperator = " && ";
435 }
436 }
437
438 for (ActualParameter guardedParam : guardedSpecialization.getParameters()) {
439 NodeChildData field = guardedSpecialization.getNode().findChild(guardedParam.getSpecification().getName());
440 if (field == null) {
441 continue;
442 }
443 ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName());
444
445 if (valueParam == null) {
446 /*
447 * If used inside a function execute method. The value param may not exist. In that
448 * case it assumes that the value is already converted.
449 */
450 valueParam = guardedParam;
451 }
452
453 CodeTree implicitGuard = createImplicitGuard(builder, field, valueParam, guardedParam);
454 if (implicitGuard == null) {
455 continue;
456 }
457
458 builder.string(andOperator);
459 builder.tree(implicitGuard);
460 andOperator = " && ";
461 }
462
463 return builder.isEmpty() ? null : builder.getRoot();
464 }
465
466 private CodeTree createImplicitGuard(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, ActualParameter target) {
467 NodeData node = field.getNodeData();
468 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
469
470 TypeData targetType = target.getTypeSystemType();
471 TypeData sourceType = source.getTypeSystemType();
472
473 if (!sourceType.needsCastTo(getContext(), targetType)) {
474 return null;
475 }
476
477 builder.startGroup();
478
479 if (field.isShortCircuit()) {
480 ActualParameter shortCircuit = target.getPreviousParameter();
481 assert shortCircuit != null;
482 builder.string("(");
483 builder.string("!").string(valueName(shortCircuit));
484 builder.string(" || ");
485 }
486
487 startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(target.getTypeSystemType()));
488 builder.string(valueName(source));
489 builder.end().end(); // call
490
491 if (field.isShortCircuit()) {
492 builder.string(")");
493 }
494
495 builder.end(); // group
496
497 return builder.getRoot();
498 }
499
500 private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, ActualParameter target) {
501 NodeData node = field.getNodeData();
502 TypeData sourceType = source.getTypeSystemType();
503 TypeData targetType = target.getTypeSystemType();
504
505 if (!sourceType.needsCastTo(getContext(), targetType)) {
506 return null;
507 }
508
509 CodeTree condition = null;
510 if (field.isShortCircuit()) {
511 ActualParameter shortCircuit = target.getPreviousParameter();
512 assert shortCircuit != null;
513 condition = CodeTreeBuilder.singleString(valueName(shortCircuit));
514 }
515
516 CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), CodeTreeBuilder.singleString(valueName(target)));
517
518 return createLazyAssignment(parent, castValueName(target), target.getType(), condition, value);
519 }
520
521 /**
522 * <pre>
523 * variant1 $condition != null
524 *
525 * $type $name = defaultValue($type);
526 * if ($condition) {
527 * $name = $value;
528 * }
529 *
530 * variant2 $condition != null
531 * $type $name = $value;
532 * </pre>
533 *
534 * .
535 */
536 private static CodeTree createLazyAssignment(CodeTreeBuilder parent, String name, TypeMirror type, CodeTree condition, CodeTree value) {
537 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
538 if (condition == null) {
539 builder.declaration(type, name, value);
540 } else {
541 builder.declaration(type, name, new CodeTreeBuilder(parent).defaultValue(type).getRoot());
542
543 builder.startIf().tree(condition).end();
544 builder.startBlock();
545 builder.startStatement();
546 builder.string(name);
547 builder.string(" = ");
548 builder.tree(value);
549 builder.end(); // statement
550 builder.end(); // block
551 }
552 return builder.getRoot();
553 }
554
555 protected void emitEncounteredSynthetic(CodeTreeBuilder builder, TemplateMethod current) {
556 builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class));
557 builder.startCall("createInfo0");
558 builder.doubleQuote("Unsupported values");
559 addInternalValueParameterNames(builder, current, current, null, false, true);
560 builder.end().end().end();
561 }
562
563 private static List<ExecutableElement> findUserConstructors(TypeMirror nodeType) {
564 List<ExecutableElement> constructors = new ArrayList<>();
565 for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(nodeType).getEnclosedElements())) {
566 if (constructor.getModifiers().contains(PRIVATE)) {
567 continue;
568 }
569 if (isCopyConstructor(constructor)) {
570 continue;
571 }
572 constructors.add(constructor);
573 }
574
575 if (constructors.isEmpty()) {
576 constructors.add(new CodeExecutableElement(null, Utils.getSimpleName(nodeType)));
577 }
578
579 return constructors;
580 }
581
582 private static ExecutableElement findCopyConstructor(TypeMirror type) {
583 for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(type).getEnclosedElements())) {
584 if (constructor.getModifiers().contains(PRIVATE)) {
585 continue;
586 }
587 if (isCopyConstructor(constructor)) {
588 return constructor;
589 }
590 }
591
592 return null;
593 }
594
595 private static boolean isCopyConstructor(ExecutableElement element) {
596 if (element.getParameters().size() != 1) {
597 return false;
598 }
599 VariableElement var = element.getParameters().get(0);
600 TypeElement type = Utils.findNearestEnclosingType(var);
601
602 if (!Utils.typeEquals(var.asType(), type.asType())) {
603 return false;
604 }
605 return true;
606 }
607
608 @Override
609 protected void createChildren(NodeData node) {
610 Map<NodeData, List<TypeElement>> childTypes = new LinkedHashMap<>();
611 if (node.getDeclaredNodes() != null && !node.getDeclaredNodes().isEmpty()) {
612 for (NodeData nodeChild : node.getDeclaredNodes()) {
613 NodeCodeGenerator generator = new NodeCodeGenerator(getContext());
614 childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements());
615 }
616 }
617
618 if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) {
619 add(new NodeFactoryFactory(context, childTypes), node);
620 }
621 }
622
623 private class NodeFactoryFactory extends ClassElementFactory<NodeData> {
624
625 private final Map<NodeData, List<TypeElement>> childTypes;
626
627 private CodeTypeElement generatedNode;
628
629 public NodeFactoryFactory(ProcessorContext context, Map<NodeData, List<TypeElement>> childElements) {
630 super(context);
631 this.childTypes = childElements;
632 }
633
634 @Override
635 protected CodeTypeElement create(NodeData node) {
636 Modifier visibility = Utils.getVisibility(node.getTemplateType().getModifiers());
637 CodeTypeElement clazz = createClass(node, modifiers(), factoryClassName(node), null, false);
638 if (visibility != null) {
639 clazz.getModifiers().add(visibility);
640 }
641 clazz.getModifiers().add(Modifier.FINAL);
642 clazz.add(createConstructorUsingFields(modifiers(PRIVATE), clazz));
643 return clazz;
644 }
645
646 @Override
647 protected void createChildren(NodeData node) {
648 CodeTypeElement clazz = getElement();
649
650 Modifier createVisibility = Utils.getVisibility(clazz.getModifiers());
651
652 if (node.needsFactory()) {
653 NodeBaseFactory factory = new NodeBaseFactory(context);
654 add(factory, node.getGenericSpecialization() == null ? node.getSpecializations().get(0) : node.getGenericSpecialization());
655 generatedNode = factory.getElement();
656
657 if (node.needsRewrites(context)) {
658 clazz.add(createCreateGenericMethod(node, createVisibility));
659 }
660
661 createFactoryMethods(node, clazz, createVisibility);
662
663 PolymorphicNodeFactory generic = null;
664 for (SpecializationData specialization : node.getPolymorphicSpecializations()) {
665 PolymorphicNodeFactory polymorphicFactory = new PolymorphicNodeFactory(context, generic == null ? generatedNode : generic.getElement(), generic == null);
666 add(polymorphicFactory, specialization);
667 if (generic == null) {
668 generic = polymorphicFactory;
669 }
670 }
671
672 for (SpecializationData specialization : node.getSpecializations()) {
673 if (!specialization.isReachable()) {
674 continue;
675 }
676 add(new SpecializedNodeFactory(context, generatedNode), specialization);
677 }
678
679 TypeMirror nodeFactory = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(NodeFactory.class)), node.getNodeType());
680 clazz.getImplements().add(nodeFactory);
681 clazz.add(createCreateNodeMethod(node));
682 clazz.add(createCreateNodeGenericMethod(node));
683 clazz.add(createGetNodeClassMethod(node));
684 clazz.add(createGetNodeSignaturesMethod());
685 clazz.add(createGetChildrenSignatureMethod(node));
686 clazz.add(createGetInstanceMethod(node, createVisibility));
687 clazz.add(createInstanceConstant(node, clazz.asType()));
688 }
689
690 for (NodeData childNode : childTypes.keySet()) {
691 if (childNode.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) {
692 continue;
693 }
694
695 for (TypeElement type : childTypes.get(childNode)) {
696 Set<Modifier> typeModifiers = ((CodeTypeElement) type).getModifiers();
697 Modifier visibility = Utils.getVisibility(type.getModifiers());
698 typeModifiers.clear();
699 if (visibility != null) {
700 typeModifiers.add(visibility);
701 }
702
703 typeModifiers.add(Modifier.STATIC);
704 typeModifiers.add(Modifier.FINAL);
705 clazz.add(type);
706 }
707 }
708
709 List<NodeData> children = node.getNodeDeclaringChildren();
710 if (node.getParent() == null && children.size() > 0) {
711 clazz.add(createGetFactories(node));
712 }
713
714 }
715
716 private CodeExecutableElement createGetNodeClassMethod(NodeData node) {
717 TypeMirror returnType = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(Class.class)), node.getNodeType());
718 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeClass");
719 CodeTreeBuilder builder = method.createBuilder();
720 builder.startReturn().typeLiteral(node.getNodeType()).end();
721 return method;
722 }
723
724 private CodeExecutableElement createGetNodeSignaturesMethod() {
725 TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class));
726 TypeMirror classType = getContext().getType(Class.class);
727 TypeMirror returnType = Utils.getDeclaredType(listType, Utils.getDeclaredType(listType, classType));
728 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeSignatures");
729 CodeTreeBuilder builder = method.createBuilder();
730 builder.startReturn();
731 builder.startStaticCall(getContext().getType(Arrays.class), "asList");
732 List<ExecutableElement> constructors = findUserConstructors(generatedNode.asType());
733 for (ExecutableElement constructor : constructors) {
734 builder.tree(createAsList(builder, Utils.asTypeMirrors(constructor.getParameters()), classType));
735 }
736 builder.end();
737 builder.end();
738 return method;
739 }
740
741 private CodeExecutableElement createGetChildrenSignatureMethod(NodeData node) {
742 Types types = getContext().getEnvironment().getTypeUtils();
743 TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class));
744 TypeMirror classType = getContext().getType(Class.class);
745 TypeMirror nodeType = getContext().getTruffleTypes().getNode();
746 TypeMirror wildcardNodeType = types.getWildcardType(nodeType, null);
747 classType = Utils.getDeclaredType(Utils.fromTypeMirror(classType), wildcardNodeType);
748 TypeMirror returnType = Utils.getDeclaredType(listType, classType);
749
750 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getExecutionSignature");
751 CodeTreeBuilder builder = method.createBuilder();
752
753 List<TypeMirror> signatureTypes = new ArrayList<>();
754 assert !node.getSpecializations().isEmpty();
755 SpecializationData data = node.getSpecializations().get(0);
756 for (ActualParameter parameter : data.getParameters()) {
757 ParameterSpec spec = parameter.getSpecification();
758 NodeChildData field = node.findChild(spec.getName());
759 if (field == null) {
760 continue;
761 }
762
763 TypeMirror type;
764 if (field.getCardinality() == Cardinality.MANY && field.getNodeType().getKind() == TypeKind.ARRAY) {
765 type = ((ArrayType) field.getNodeType()).getComponentType();
766 } else {
767 type = field.getNodeType();
768 }
769
770 signatureTypes.add(type);
771 }
772
773 builder.startReturn().tree(createAsList(builder, signatureTypes, classType)).end();
774 return method;
775 }
776
777 private CodeTree createAsList(CodeTreeBuilder parent, List<TypeMirror> types, TypeMirror elementClass) {
778 CodeTreeBuilder builder = parent.create();
779 builder.startGroup();
780 builder.type(getContext().getType(Arrays.class));
781 builder.string(".<").type(elementClass).string(">");
782 builder.startCall("asList");
783 for (TypeMirror typeMirror : types) {
784 builder.typeLiteral(typeMirror);
785 }
786 builder.end().end();
787 return builder.getRoot();
788 }
789
790 private CodeExecutableElement createCreateNodeMethod(NodeData node) {
791 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNode");
792 CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Object.class), "arguments");
793 method.setVarArgs(true);
794 method.addParameter(arguments);
795
796 CodeTreeBuilder builder = method.createBuilder();
797 List<ExecutableElement> signatures = findUserConstructors(generatedNode.asType());
798 boolean ifStarted = false;
799
800 for (ExecutableElement element : signatures) {
801 ifStarted = builder.startIf(ifStarted);
802 builder.string("arguments.length == " + element.getParameters().size());
803
804 int index = 0;
805 for (VariableElement param : element.getParameters()) {
806 builder.string(" && ");
807 if (!param.asType().getKind().isPrimitive()) {
808 builder.string("(arguments[" + index + "] == null || ");
809 }
810 builder.string("arguments[" + index + "] instanceof ");
811 builder.type(Utils.boxType(getContext(), param.asType()));
812 if (!param.asType().getKind().isPrimitive()) {
813 builder.string(")");
814 }
815 index++;
816 }
817 builder.end();
818 builder.startBlock();
819
820 builder.startReturn().startCall("create");
821 index = 0;
822 for (VariableElement param : element.getParameters()) {
823 builder.startGroup();
824 builder.string("(").type(param.asType()).string(") ");
825 builder.string("arguments[").string(String.valueOf(index)).string("]");
826 builder.end();
827 index++;
828 }
829 builder.end().end();
830
831 builder.end(); // block
832 }
833
834 builder.startElseBlock();
835 builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class));
836 builder.doubleQuote("Invalid create signature.");
837 builder.end().end();
838 builder.end(); // else block
839 return method;
840 }
841
842 private CodeExecutableElement createCreateNodeGenericMethod(NodeData node) {
843 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNodeGeneric");
844 CodeVariableElement nodeParam = new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME);
845 method.addParameter(nodeParam);
846
847 CodeTreeBuilder builder = method.createBuilder();
848 if (!node.needsRewrites(getContext())) {
849 builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).doubleQuote("No specialized version.").end().end();
850 } else {
851 builder.startReturn().startCall("createGeneric");
852 builder.string(THIS_NODE_LOCAL_VAR_NAME);
853 builder.end().end();
854 }
855 return method;
856 }
857
858 private ExecutableElement createGetInstanceMethod(NodeData node, Modifier visibility) {
859 TypeElement nodeFactoryType = Utils.fromTypeMirror(getContext().getType(NodeFactory.class));
860 TypeMirror returnType = Utils.getDeclaredType(nodeFactoryType, node.getNodeType());
861
862 CodeExecutableElement method = new CodeExecutableElement(modifiers(), returnType, "getInstance");
863 if (visibility != null) {
864 method.getModifiers().add(visibility);
865 }
866 method.getModifiers().add(Modifier.STATIC);
867
868 String varName = instanceVarName(node);
869
870 CodeTreeBuilder builder = method.createBuilder();
871 builder.startIf();
872 builder.string(varName).string(" == null");
873 builder.end().startBlock();
874
875 builder.startStatement();
876 builder.string(varName);
877 builder.string(" = ");
878 builder.startNew(factoryClassName(node)).end();
879 builder.end();
880
881 builder.end();
882 builder.startReturn().string(varName).end();
883 return method;
884 }
885
886 private String instanceVarName(NodeData node) {
887 if (node.getParent() != null) {
888 return Utils.firstLetterLowerCase(factoryClassName(node)) + "Instance";
889 } else {
890 return "instance";
891 }
892 }
893
894 private CodeVariableElement createInstanceConstant(NodeData node, TypeMirror factoryType) {
895 String varName = instanceVarName(node);
896 CodeVariableElement var = new CodeVariableElement(modifiers(), factoryType, varName);
897 var.getModifiers().add(Modifier.PRIVATE);
898 var.getModifiers().add(Modifier.STATIC);
899 return var;
900 }
901
902 private ExecutableElement createGetFactories(NodeData node) {
903 List<NodeData> children = node.getNodeDeclaringChildren();
904 if (node.needsFactory()) {
905 children.add(node);
906 }
907
908 List<TypeMirror> nodeTypesList = new ArrayList<>();
909 TypeMirror prev = null;
910 boolean allSame = true;
911 for (NodeData child : children) {
912 nodeTypesList.add(child.getNodeType());
913 if (prev != null && !Utils.typeEquals(child.getNodeType(), prev)) {
914 allSame = false;
915 }
916 prev = child.getNodeType();
917 }
918 TypeMirror commonNodeSuperType = Utils.getCommonSuperType(getContext(), nodeTypesList.toArray(new TypeMirror[nodeTypesList.size()]));
919
920 Types types = getContext().getEnvironment().getTypeUtils();
921 TypeMirror factoryType = getContext().getType(NodeFactory.class);
922 TypeMirror baseType;
923 if (allSame) {
924 baseType = Utils.getDeclaredType(Utils.fromTypeMirror(factoryType), commonNodeSuperType);
925 } else {
926 baseType = Utils.getDeclaredType(Utils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null));
927 }
928 TypeMirror listType = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(List.class)), baseType);
929
930 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), listType, "getFactories");
931
932 CodeTreeBuilder builder = method.createBuilder();
933 builder.startReturn();
934 builder.startStaticCall(getContext().getType(Arrays.class), "asList");
935
936 for (NodeData child : children) {
937 builder.startGroup();
938 NodeData childNode = child;
939 List<NodeData> factories = new ArrayList<>();
940 while (childNode.getParent() != null) {
941 factories.add(childNode);
942 childNode = childNode.getParent();
943 }
944 Collections.reverse(factories);
945 for (NodeData nodeData : factories) {
946 builder.string(factoryClassName(nodeData)).string(".");
947 }
948 builder.string("getInstance()");
949 builder.end();
950 }
951 builder.end();
952 builder.end();
953 return method;
954 }
955
956 private void createFactoryMethods(NodeData node, CodeTypeElement clazz, Modifier createVisibility) {
957 List<ExecutableElement> constructors = findUserConstructors(generatedNode.asType());
958 for (ExecutableElement constructor : constructors) {
959 clazz.add(createCreateMethod(node, createVisibility, constructor));
960 }
961 }
962
963 private CodeExecutableElement createCreateMethod(NodeData node, Modifier visibility, ExecutableElement constructor) {
964 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), constructor);
965 method.setSimpleName(CodeNames.of("create"));
966 method.getModifiers().clear();
967 if (visibility != null) {
968 method.getModifiers().add(visibility);
969 }
970 method.getModifiers().add(Modifier.STATIC);
971 method.setReturnType(node.getNodeType());
972
973 CodeTreeBuilder body = method.createBuilder();
974 body.startReturn();
975 if (node.getSpecializations().isEmpty()) {
976 body.nullLiteral();
977 } else {
978 body.startNew(nodeSpecializationClassName(node.getSpecializations().get(0)));
979 for (VariableElement var : method.getParameters()) {
980 body.string(var.getSimpleName().toString());
981 }
982 body.end();
983 }
984 body.end();
985 return method;
986 }
987
988 private CodeExecutableElement createCreateGenericMethod(NodeData node, Modifier visibility) {
989 CodeExecutableElement method = new CodeExecutableElement(modifiers(), node.getNodeType(), "createGeneric");
990 if (visibility != null) {
991 method.getModifiers().add(visibility);
992 }
993 method.getModifiers().add(Modifier.STATIC);
994 method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME));
995
996 CodeTreeBuilder body = method.createBuilder();
997
998 SpecializationData found = null;
999 List<SpecializationData> specializations = node.getSpecializations();
1000 for (int i = 0; i < specializations.size(); i++) {
1001 if (specializations.get(i).isReachable()) {
1002 found = specializations.get(i);
1003 }
1004 }
1005
1006 if (found == null) {
1007 body.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end();
1008 } else {
1009 body.startReturn().startNew(nodeSpecializationClassName(found)).startGroup().cast(baseClassName(node)).string(THIS_NODE_LOCAL_VAR_NAME).end().end().end();
1010 }
1011 return method;
1012 }
1013 }
1014
1015 private class NodeBaseFactory extends ClassElementFactory<SpecializationData> {
1016
1017 public NodeBaseFactory(ProcessorContext context) {
1018 super(context);
1019 }
1020
1021 @Override
1022 protected CodeTypeElement create(SpecializationData specialization) {
1023 NodeData node = specialization.getNode();
1024 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, ABSTRACT, STATIC), baseClassName(node), node.getNodeType(), false);
1025
1026 for (NodeChildData child : node.getChildren()) {
1027 clazz.add(createChildField(child));
1028
1029 if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) {
1030 ExecutableElement getter = (ExecutableElement) child.getAccessElement();
1031 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), getter);
1032 method.getModifiers().remove(Modifier.ABSTRACT);
1033 method.createBuilder().startReturn().string("this.").string(child.getName()).end();
1034 clazz.add(method);
1035 }
1036 }
1037
1038 for (String assumption : node.getAssumptions()) {
1039 clazz.add(createAssumptionField(assumption));
1040 }
1041
1042 createConstructors(node, clazz);
1043
1044 return clazz;
1045 }
1046
1047 protected String typeGetterName(ActualParameter parameter) {
1048 return "get" + Utils.firstLetterUpperCase(parameter.getLocalName()) + "Type";
1049 }
1050
1051 @Override
1052 protected void createChildren(SpecializationData specialization) {
1053 NodeData node = specialization.getNode();
1054 CodeTypeElement clazz = getElement();
1055
1056 if (node.needsRewrites(context)) {
1057
1058 if (node.getPolymorphicDepth() > 1) {
1059
1060 CodeVariableElement var = new CodeVariableElement(modifiers(PROTECTED), clazz.asType(), "next0");
1061 var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation()));
1062 clazz.add(var);
1063
1064 CodeExecutableElement setter = new CodeExecutableElement(modifiers(PROTECTED), context.getType(void.class), "setNext0");
1065 setter.getParameters().add(new CodeVariableElement(clazz.asType(), "next0"));
1066 CodeTreeBuilder builder = setter.createBuilder();
1067 builder.statement("this.next0 = adoptChild(next0)");
1068 clazz.add(setter);
1069
1070 createTypeGetters(clazz, node.getGenericSpecialization());
1071
1072 clazz.add(createCreateSpecialization(node));
1073
1074 CodeExecutableElement genericCachedExecute = null;
1075 for (SpecializationData polymorph : node.getPolymorphicSpecializations()) {
1076 CodeExecutableElement cachedExecute = createCachedExecute(node, polymorph, genericCachedExecute);
1077 clazz.add(cachedExecute);
1078 if (genericCachedExecute == null) {
1079 genericCachedExecute = cachedExecute;
1080 }
1081 }
1082 }
1083
1084 clazz.add(createGenericExecuteAndSpecialize(node));
1085 clazz.add(createInfoMessage(node));
1086 }
1087
1088 if (node.getGenericSpecialization() != null && node.getGenericSpecialization().isReachable()) {
1089 clazz.add(createGenericExecute(node));
1090 }
1091 }
1092
1093 private Element createInfoMessage(NodeData node) {
1094 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), getContext().getType(String.class), "createInfo0");
1095 method.addParameter(new CodeVariableElement(getContext().getType(String.class), "message"));
1096 addInternalValueParameters(method, node.getGenericSpecialization(), false, false);
1097
1098 CodeTreeBuilder builder = method.createBuilder();
1099 builder.startStatement().string("StringBuilder builder = new StringBuilder(message)").end();
1100 builder.startStatement().startCall("builder", "append").doubleQuote(" (").end().end();
1101
1102 String sep = null;
1103 for (ActualParameter parameter : node.getGenericSpecialization().getParameters()) {
1104 if (!parameter.getSpecification().isSignature()) {
1105 continue;
1106 }
1107
1108 builder.startStatement();
1109 builder.string("builder");
1110 if (sep != null) {
1111 builder.startCall(".append").doubleQuote(sep).end();
1112 }
1113 builder.startCall(".append").doubleQuote(parameter.getLocalName()).end();
1114 builder.startCall(".append").doubleQuote(" = ").end();
1115 builder.startCall(".append").string(parameter.getLocalName()).end();
1116 builder.end();
1117
1118 if (!Utils.isPrimitive(parameter.getType())) {
1119 builder.startIf().string(parameter.getLocalName() + " != null").end();
1120 builder.startBlock();
1121 }
1122 builder.startStatement();
1123 if (Utils.isPrimitive(parameter.getType())) {
1124 builder.startCall("builder.append").doubleQuote(" (" + Utils.getSimpleName(parameter.getType()) + ")").end();
1125 } else {
1126 builder.startCall("builder.append").doubleQuote(" (").end();
1127 builder.startCall(".append").string(parameter.getLocalName() + ".getClass().getSimpleName()").end();
1128 builder.startCall(".append").doubleQuote(")").end();
1129 }
1130 builder.end();
1131 if (!Utils.isPrimitive(parameter.getType())) {
1132 builder.end();
1133 }
1134
1135 sep = ", ";
1136 }
1137
1138 builder.startStatement().startCall("builder", "append").doubleQuote(")").end().end();
1139
1140 builder.startReturn().string("builder.toString()").end();
1141
1142 return method;
1143 }
1144
1145 protected void createTypeGetters(CodeTypeElement clazz, SpecializationData specialization) {
1146 for (ActualParameter parameter : specialization.getReturnTypeAndParameters()) {
1147 if (!parameter.getSpecification().isSignature()) {
1148 continue;
1149 }
1150 CodeExecutableElement typeGetter = new CodeExecutableElement(modifiers(PROTECTED), context.getType(Class.class), typeGetterName(parameter));
1151 CodeTreeBuilder builder = typeGetter.createBuilder();
1152 builder.startReturn().typeLiteral(parameter.getType()).end();
1153 clazz.add(typeGetter);
1154 }
1155 }
1156
1157 private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph, CodeExecutableElement genericPolymorphMethod) {
1158 int index = node.getPolymorphicSpecializations().indexOf(polymorph);
1159 assert index != -1;
1160 boolean generic = index == 0;
1161
1162 String name = "executeCached" + index;
1163 CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED), polymorph.getReturnType().getType(), name);
1164 addInternalValueParameters(cachedExecute, polymorph, true, true);
1165
1166 if (generic) {
1167 cachedExecute.getModifiers().add(ABSTRACT);
1168 } else {
1169 SpecializationData genericPolymorph = node.getPolymorphicSpecializations().get(0);
1170 CodeTreeBuilder builder = cachedExecute.createBuilder();
1171 ExecutableTypeData genericExecutable = new ExecutableTypeData(genericPolymorph, genericPolymorphMethod, node.getTypeSystem(), genericPolymorph.getReturnType().getTypeSystemType());
1172 ExecutableTypeData specificExecutable = new ExecutableTypeData(polymorph, cachedExecute, node.getTypeSystem(), polymorph.getReturnType().getTypeSystemType());
1173 builder.tree(createCastingExecute(builder, polymorph, specificExecutable, genericExecutable));
1174 }
1175
1176 return cachedExecute;
1177
1178 }
1179
1180 private CodeExecutableElement createCreateSpecialization(NodeData node) {
1181 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), getElement().asType(), "createSpezialization0");
1182 method.getParameters().add(new CodeVariableElement(context.getType(Class.class), "clazz"));
1183 CodeTreeBuilder builder = method.createBuilder();
1184
1185 builder.startStatement().type(getElement().asType()).string(" node").end();
1186
1187 boolean elseIf = false;
1188 for (SpecializationData specialization : node.getSpecializations()) {
1189 if (specialization.isGeneric() || specialization.isUninitialized()) {
1190 continue;
1191 }
1192
1193 elseIf = builder.startIf(elseIf);
1194 builder.startGroup().string("clazz == ").string(nodeSpecializationClassName(specialization)).string(".class").end();
1195 builder.end();
1196 builder.startBlock();
1197 builder.startStatement();
1198 builder.string("node = ");
1199 builder.startNew(nodeSpecializationClassName(specialization)).string("this").end();
1200 builder.end();
1201 builder.end();
1202 }
1203
1204 builder.startElseBlock();
1205 builder.startThrow().startNew(context.getType(AssertionError.class)).end().end();
1206 builder.end();
1207
1208 builder.startStatement().startCall("node", "setNext0");
1209 builder.startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string("this").end();
1210 builder.end().end();
1211
1212 builder.startReturn().string("node").end();
1213
1214 return method;
1215 }
1216
1217 private void createConstructors(NodeData node, CodeTypeElement clazz) {
1218 List<ExecutableElement> constructors = findUserConstructors(node.getNodeType());
1219 if (constructors.isEmpty()) {
1220 clazz.add(createUserConstructor(clazz, null));
1221 } else {
1222 for (ExecutableElement constructor : constructors) {
1223 clazz.add(createUserConstructor(clazz, constructor));
1224 }
1225 }
1226 if (node.needsRewrites(getContext())) {
1227 clazz.add(createCopyConstructor(clazz, findCopyConstructor(node.getNodeType())));
1228 }
1229 }
1230
1231 private CodeExecutableElement createUserConstructor(CodeTypeElement type, ExecutableElement superConstructor) {
1232 CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
1233 CodeTreeBuilder builder = method.createBuilder();
1234
1235 NodeData node = getModel().getNode();
1236
1237 if (superConstructor != null) {
1238 for (VariableElement param : superConstructor.getParameters()) {
1239 method.getParameters().add(CodeVariableElement.clone(param));
1240 }
1241 }
1242
1243 for (VariableElement var : type.getFields()) {
1244 NodeChildData child = node.findChild(var.getSimpleName().toString());
1245 if (child != null) {
1246 method.getParameters().add(new CodeVariableElement(child.getOriginalType(), child.getName()));
1247 } else {
1248 method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString()));
1249 }
1250 }
1251
1252 if (superConstructor != null) {
1253 builder.startStatement().startSuperCall();
1254 for (VariableElement param : superConstructor.getParameters()) {
1255 builder.string(param.getSimpleName().toString());
1256 }
1257 builder.end().end();
1258 }
1259
1260 for (VariableElement var : type.getFields()) {
1261 builder.startStatement();
1262 String fieldName = var.getSimpleName().toString();
1263
1264 CodeTree fieldInit = CodeTreeBuilder.singleString(var.getSimpleName().toString());
1265 builder.string("this.").string(var.getSimpleName().toString());
1266
1267 NodeChildData child = node.findChild(fieldName);
1268 if (child != null) {
1269 CreateCastData createCast = node.findCast(child.getName());
1270 if (createCast != null) {
1271 fieldInit = createTemplateMethodCall(builder, null, node.getGenericSpecialization(), createCast, null, child.getName());
1272 }
1273 }
1274
1275 if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNode())) {
1276 builder.string(" = adoptChild(").tree(fieldInit).string(")");
1277 } else if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) {
1278 builder.string(" = adoptChildren(").tree(fieldInit).string(")");
1279 } else {
1280 builder.string(" = ").tree(fieldInit);
1281 }
1282 builder.end();
1283 }
1284 return method;
1285 }
1286
1287 private CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor) {
1288 CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
1289 CodeTreeBuilder builder = method.createBuilder();
1290 if (!(superConstructor == null && type.getFields().isEmpty())) {
1291 method.getParameters().add(new CodeVariableElement(type.asType(), "copy"));
1292 }
1293
1294 if (superConstructor != null) {
1295 builder.startStatement().startSuperCall().string("copy").end().end();
1296 }
1297
1298 for (VariableElement var : type.getFields()) {
1299 builder.startStatement();
1300 String varName = var.getSimpleName().toString();
1301 builder.string("this.").string(varName);
1302 if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNode())) {
1303 builder.string(" = adoptChild(copy.").string(varName).string(")");
1304 } else if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) {
1305 builder.string(" = adoptChildren(copy.").string(varName).string(")");
1306 } else {
1307 builder.string(" = copy.").string(varName);
1308 }
1309 builder.end();
1310 }
1311 if (getModel().getNode().getPolymorphicDepth() > 1) {
1312 builder.statement("this.next0 = adoptChild(copy.next0)");
1313 }
1314
1315 return method;
1316 }
1317
1318 private CodeVariableElement createAssumptionField(String assumption) {
1319 CodeVariableElement var = new CodeVariableElement(getContext().getTruffleTypes().getAssumption(), assumption);
1320 var.getModifiers().add(Modifier.FINAL);
1321 return var;
1322 }
1323
1324 private CodeVariableElement createChildField(NodeChildData child) {
1325 CodeVariableElement var = new CodeVariableElement(child.getNodeType(), child.getName());
1326 var.getModifiers().add(Modifier.PROTECTED);
1327
1328 DeclaredType annotationType;
1329 if (child.getCardinality() == Cardinality.MANY) {
1330 annotationType = getContext().getTruffleTypes().getChildrenAnnotation();
1331 } else {
1332 annotationType = getContext().getTruffleTypes().getChildAnnotation();
1333 }
1334
1335 var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType));
1336 return var;
1337 }
1338
1339 private CodeExecutableElement createGenericExecuteAndSpecialize(NodeData node) {
1340
1341 TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType();
1342 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, EXECUTE_SPECIALIZE_NAME);
1343 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState"));
1344 addInternalValueParameters(method, node.getGenericSpecialization(), true, false);
1345 method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason"));
1346
1347 CodeTreeBuilder builder = method.createBuilder();
1348 builder.startStatement();
1349 builder.startStaticCall(getContext().getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end();
1350 builder.end();
1351
1352 emitSpecializationListeners(builder, node);
1353 builder.defaultDeclaration(node.getGenericSpecialization().getReturnType().getTypeSystemType().getPrimitiveType(), "result");
1354
1355 builder.defaultDeclaration(getContext().getType(Class.class), "resultClass");
1356
1357 builder.startStatement().string("boolean allowed = (minimumState == ").string(nodeSpecializationClassName(node.getSpecializations().get(0))).string(".class)").end();
1358
1359 builder.startStatement().string("String message = ").startCall("createInfo0").string("reason");
1360 addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, false, true);
1361 builder.end().end();
1362
1363 String prefix = null;
1364
1365 List<SpecializationData> specializations = node.getSpecializations();
1366
1367 for (SpecializationData current : specializations) {
1368 if (current.isUninitialized() || !current.isReachable()) {
1369 continue;
1370 }
1371 CodeTreeBuilder execute = new CodeTreeBuilder(builder);
1372
1373 execute.tree(createGenericInvokeAndSpecialize(builder, node.getGenericSpecialization(), current));
1374
1375 if (!current.isGeneric()) {
1376 builder.startStatement().string("allowed = allowed || (minimumState == ").string(nodeSpecializationClassName(current)).string(".class)").end();
1377 }
1378
1379 builder.tree(createGuardAndCast(builder, prefix, current.getNode().getGenericSpecialization(), current, true, execute.getRoot(), null, true, false));
1380 }
1381
1382 for (SpecializationData current : specializations) {
1383 if (current.isUninitialized() || current.isReachable()) {
1384 continue;
1385 }
1386 builder.string("// unreachable ").string(current.getId()).newLine();
1387 }
1388
1389 return method;
1390 }
1391
1392 private CodeExecutableElement createGenericExecute(NodeData node) {
1393 TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType();
1394 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, EXECUTE_GENERIC_NAME);
1395 addInternalValueParameters(method, node.getGenericSpecialization(), true, false);
1396 CodeTreeBuilder builder = method.createBuilder();
1397
1398 String prefix = null;
1399 List<SpecializationData> specializations = node.getSpecializations();
1400
1401 for (SpecializationData current : specializations) {
1402 if (current.isUninitialized() || !current.isReachable()) {
1403 continue;
1404 }
1405 CodeTreeBuilder execute = new CodeTreeBuilder(builder);
1406 execute.tree(createGenericInvoke(builder, node.getGenericSpecialization(), current));
1407 builder.tree(createGuardAndCast(builder, prefix, current.getNode().getGenericSpecialization(), current, true, execute.getRoot(), null, true, false));
1408 }
1409
1410 for (SpecializationData current : specializations) {
1411 if (current.isUninitialized() || current.isReachable()) {
1412 continue;
1413 }
1414 builder.string("// unreachable ").string(current.getId()).newLine();
1415 }
1416
1417 return method;
1418 }
1419
1420 protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) {
1421 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1422
1423 if (current.getMethod() == null) {
1424 emitEncounteredSynthetic(builder, current);
1425 } else {
1426 builder.startReturn().tree(createTemplateMethodCall(builder, null, source, current, null)).end();
1427 }
1428
1429 return encloseThrowsWithFallThrough(current, builder.getRoot());
1430 }
1431
1432 protected CodeTree createGenericInvokeAndSpecialize(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) {
1433 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1434
1435 NodeData node = current.getNode();
1436
1437 builder.startIf().string("resultClass == null").end().startBlock();
1438 if (current.getMethod() != null) {
1439 CodeTree executeCall = createTemplateMethodCall(builder, null, source, current, null);
1440 if (current.getReturnType().getTypeSystemType().isVoid()) {
1441 builder.statement(executeCall);
1442 } else {
1443 builder.startStatement().string("result = ").tree(executeCall).end();
1444 }
1445 builder.startStatement();
1446 builder.string("resultClass = ").string(nodeSpecializationClassName(current)).string(".class");
1447 builder.end();
1448 } else {
1449 emitEncounteredSynthetic(builder, current);
1450 }
1451 builder.end();
1452
1453 boolean ifAllowed = current.hasRewrite(getContext());
1454 if (ifAllowed) {
1455 builder.startIf().string("allowed").end().startBlock();
1456 }
1457
1458 if (!current.isGeneric() || node.getPolymorphicDepth() <= 1) {
1459 // generic rewrite
1460 builder.tree(createRewriteGeneric(builder, current));
1461 } else {
1462 boolean rewriteableToGeneric = node.getGenericSpecialization().getMethod() != null && node.getGenericSpecialization().isReachable();
1463 if (rewriteableToGeneric) {
1464 builder.startIf().string("resultClass == ").string(nodeSpecializationClassName(node.getGenericSpecialization())).string(".class").end();
1465 builder.startBlock();
1466
1467 boolean maybePolymorphic = node.getPolymorphicDepth() > 1;
1468 if (maybePolymorphic) {
1469 builder.startIf().string("next0 == null").end();
1470 builder.startBlock();
1471 }
1472 builder.tree(createRewriteGeneric(builder, current));
1473 if (maybePolymorphic) {
1474 builder.end().startElseBlock();
1475 builder.statement("Node searchNode = super.getParent()");
1476 builder.startWhile().string("searchNode != null").end();
1477 builder.startBlock();
1478 builder.statement("searchNode = searchNode.getParent()");
1479 builder.startIf().instanceOf("searchNode", nodePolymorphicClassName(node, node.getPolymorphicSpecializations().get(0))).end();
1480 builder.startBlock().breakStatement().end();
1481 builder.end();
1482 builder.startStatement().startCall("searchNode", "replace");
1483 builder.startGroup().startNew(nodeSpecializationClassName(current)).startGroup().cast(baseClassName(node)).string("searchNode").end().end().end();
1484 builder.string("message");
1485 builder.end().end().end();
1486 }
1487
1488 builder.end().startElseBlock();
1489 }
1490
1491 // polymorphic rewrite
1492 builder.tree(createRewritePolymorphic(builder, node));
1493
1494 if (rewriteableToGeneric) {
1495 builder.end();
1496 }
1497 }
1498
1499 if (current.getReturnType().getTypeSystemType().isVoid()) {
1500 builder.returnStatement();
1501 } else {
1502 builder.startReturn().string("result").end();
1503 }
1504 if (ifAllowed) {
1505 builder.end();
1506 }
1507
1508 return encloseThrowsWithFallThrough(current, builder.getRoot());
1509 }
1510
1511 private CodeTree encloseThrowsWithFallThrough(SpecializationData current, CodeTree tree) {
1512 if (current.getExceptions().isEmpty()) {
1513 return tree;
1514 }
1515 CodeTreeBuilder builder = new CodeTreeBuilder(null);
1516
1517 builder.startTryBlock();
1518 builder.tree(tree);
1519 for (SpecializationThrowsData exception : current.getExceptions()) {
1520 builder.end().startCatchBlock(exception.getJavaClass(), "rewriteEx");
1521 builder.string("// fall through").newLine();
1522 }
1523 builder.end();
1524
1525 return builder.getRoot();
1526 }
1527
1528 private CodeTree createRewriteGeneric(CodeTreeBuilder parent, SpecializationData current) {
1529 CodeTreeBuilder builder = parent.create();
1530 builder.startStatement().startCall("super", "replace");
1531 builder.startGroup().startNew(nodeSpecializationClassName(current)).string("this").end().end();
1532 builder.string("message");
1533 builder.end().end();
1534 return builder.getRoot();
1535 }
1536
1537 private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node) {
1538 CodeTreeBuilder builder = parent.create();
1539 builder.startStatement();
1540 builder.string(nodePolymorphicClassName(node, null));
1541 builder.string(" polymorphic = ");
1542 builder.startNew(nodePolymorphicClassName(node, null)).string("this").end();
1543 builder.end();
1544 for (NodeChildData child : node.getChildren()) {
1545 builder.startStatement().string("this.").string(child.getName()).string(" = null").end();
1546 }
1547 builder.startStatement().startCall("super", "replace");
1548 builder.string("polymorphic");
1549 builder.string("message");
1550 builder.end().end();
1551
1552 builder.statement("polymorphic.setNext0(this)");
1553 builder.statement("setNext0(createSpezialization0(resultClass))");
1554
1555 builder.statement("polymorphic.optimizeTypes()");
1556 return builder.getRoot();
1557 }
1558
1559 private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) {
1560 for (TemplateMethod listener : node.getSpecializationListeners()) {
1561 builder.startStatement();
1562 builder.tree(createTemplateMethodCall(builder, null, listener, listener, null));
1563 builder.end(); // statement
1564 }
1565 }
1566
1567 protected CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) {
1568 TypeData type = executable.getType();
1569 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1570 NodeData node = specialization.getNode();
1571
1572 ExecutableTypeData castedType = node.findExecutableType(type, 0);
1573 TypeData primaryType = castExecutable.getType();
1574
1575 boolean needsTry = castExecutable.hasUnexpectedValue(getContext());
1576 boolean returnVoid = type.isVoid();
1577
1578 List<ActualParameter> executeParameters = new ArrayList<>();
1579 for (ActualParameter sourceParameter : executable.getParameters()) {
1580 if (!sourceParameter.getSpecification().isSignature()) {
1581 continue;
1582 }
1583
1584 ActualParameter targetParameter = castExecutable.findParameter(sourceParameter.getLocalName());
1585 if (targetParameter != null) {
1586 executeParameters.add(targetParameter);
1587 }
1588 }
1589
1590 builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null, true));
1591
1592 CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null);
1593 if (needsTry) {
1594 if (!returnVoid) {
1595 builder.declaration(primaryType.getPrimitiveType(), "value");
1596 }
1597 builder.startTryBlock();
1598
1599 if (returnVoid) {
1600 builder.statement(primaryExecuteCall);
1601 } else {
1602 builder.startStatement();
1603 builder.string("value = ");
1604 builder.tree(primaryExecuteCall);
1605 builder.end();
1606 }
1607
1608 builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
1609 if (returnVoid) {
1610 builder.string("// ignore").newLine();
1611 } else {
1612 builder.startReturn();
1613 builder.tree(createExpectExecutableType(node, specialization.getNode().getTypeSystem().getGenericTypeData(), castedType, CodeTreeBuilder.singleString("ex.getResult()")));
1614 builder.end();
1615 }
1616 builder.end();
1617
1618 if (!returnVoid) {
1619 builder.startReturn();
1620 builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), executable, CodeTreeBuilder.singleString("value")));
1621 builder.end();
1622 }
1623 } else {
1624 if (returnVoid) {
1625 builder.statement(primaryExecuteCall);
1626 } else {
1627 builder.startReturn();
1628 builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), executable, primaryExecuteCall));
1629 builder.end();
1630 }
1631 }
1632
1633 return builder.getRoot();
1634 }
1635
1636 protected CodeTree createExpectExecutableType(NodeData node, TypeData sourceType, ExecutableTypeData castedType, CodeTree value) {
1637 boolean hasUnexpected = castedType.hasUnexpectedValue(getContext());
1638 return createCastType(node, sourceType, castedType.getType(), hasUnexpected, value);
1639 }
1640
1641 protected CodeTree createCastType(NodeData node, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) {
1642 if (targetType == null) {
1643 return value;
1644 } else if (!sourceType.needsCastTo(getContext(), targetType)) {
1645 return value;
1646 }
1647
1648 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
1649 String targetMethodName;
1650 if (expect) {
1651 targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType);
1652 } else {
1653 targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType);
1654 }
1655 startCallTypeSystemMethod(getContext(), builder, node, targetMethodName);
1656
1657 builder.tree(value);
1658 builder.end().end();
1659 return builder.getRoot();
1660 }
1661
1662 protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List<ActualParameter> targetParameters,
1663 ActualParameter unexpectedParameter, boolean cast) {
1664 NodeData sourceNode = specialization.getNode();
1665
1666 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1667
1668 for (ActualParameter targetParameter : targetParameters) {
1669 NodeChildData field = sourceNode.findChild(targetParameter.getSpecification().getName());
1670 if (!targetParameter.getSpecification().isSignature()) {
1671 continue;
1672 }
1673
1674 TypeData targetType = targetParameter.getTypeSystemType();
1675 ExecutableTypeData targetExecutable = null;
1676 if (field != null) {
1677 targetExecutable = field.findExecutableType(getContext(), targetType);
1678 }
1679
1680 ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName());
1681
1682 String targetVariableName = valueName(targetParameter);
1683 CodeTree executionExpression = null;
1684 if ((sourceParameter != null && cast) || sourceParameter != null) {
1685 TypeData sourceType = sourceParameter.getTypeSystemType();
1686 if (targetExecutable == null || !sourceType.needsCastTo(getContext(), targetType)) {
1687 if (field != null && field.isShortCircuit() && sourceParameter != null) {
1688 builder.tree(createShortCircuitValue(builder, specialization, field, targetParameter.getPreviousParameter(), unexpectedParameter));
1689 }
1690 builder.startStatement();
1691 builder.type(targetParameter.getType()).string(" ");
1692 builder.string(valueName(targetParameter)).string(" = ");
1693 builder.tree(CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter)));
1694 builder.end();
1695 continue;
1696 } else {
1697 CodeTree valueTree = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter));
1698 executionExpression = createExpectExecutableType(sourceNode, sourceType, targetExecutable, valueTree);
1699 }
1700 } else if (sourceParameter == null) {
1701 executionExpression = createExecuteChildExpression(builder, field, targetParameter, unexpectedParameter);
1702 }
1703
1704 if (executionExpression != null) {
1705 CodeTreeVariable executionVar = new CodeTreeVariable();
1706 CodeTree shortCircuitTree = createShortCircuitTree(builder, executionVar, targetVariableName, specialization, targetParameter, unexpectedParameter);
1707 CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpression, targetVariableName, specialization, sourceExecutable, targetExecutable, targetParameter,
1708 shortCircuitTree != executionVar);
1709
1710 executionVar.set(unexpectedTree);
1711 builder.tree(shortCircuitTree);
1712 }
1713 }
1714 return builder.getRoot();
1715 }
1716
1717 private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, SpecializationData specialization, ExecutableTypeData currentExecutable,
1718 ExecutableTypeData targetExecutable, ActualParameter param, boolean shortCircuit) {
1719 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1720 boolean unexpected = targetExecutable.hasUnexpectedValue(getContext());
1721 boolean cast = false;
1722 if (targetExecutable.getType().needsCastTo(getContext(), param.getTypeSystemType())) {
1723 unexpected = true;
1724 cast = true;
1725 }
1726
1727 if (specialization.isGeneric() && unexpected) {
1728 throw new AssertionError("Generic has unexpected parameters. " + specialization.toString());
1729 }
1730
1731 builder.startStatement();
1732
1733 if (!shortCircuit) {
1734 builder.type(param.getType()).string(" ").string(targetVariableName);
1735 }
1736
1737 if (unexpected) {
1738 if (!shortCircuit) {
1739 builder.end();
1740 }
1741 builder.startTryBlock();
1742 builder.startStatement();
1743 builder.string(targetVariableName);
1744 } else if (shortCircuit) {
1745 builder.startStatement();
1746 builder.string(targetVariableName);
1747 }
1748 builder.string(" = ");
1749 if (cast) {
1750 builder.tree(createCastType(specialization.getNode(), targetExecutable.getType(), param.getTypeSystemType(), true, body));
1751 } else {
1752 builder.tree(body);
1753 }
1754 builder.end();
1755
1756 if (unexpected) {
1757 builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
1758 SpecializationData generic = specialization.getNode().getGenericSpecialization();
1759 ActualParameter genericParameter = generic.findParameter(param.getLocalName());
1760
1761 List<ActualParameter> genericParameters = generic.getParametersAfter(genericParameter);
1762 builder.tree(createDeoptimize(builder));
1763 builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter, false));
1764 if (specialization.isPolymorphic()) {
1765 builder.tree(createReturnOptimizeTypes(builder, specialization, param));
1766 } else {
1767 builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization.findNextSpecialization(), param, "Expected " + param.getLocalName() + " instanceof " +
1768 Utils.getSimpleName(param.getType())));
1769 }
1770 builder.end(); // catch block
1771 }
1772
1773 return builder.getRoot();
1774 }
1775
1776 private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, SpecializationData specialization, ActualParameter param) {
1777 NodeData node = specialization.getNode();
1778 assert !node.getPolymorphicSpecializations().isEmpty();
1779 SpecializationData generic = node.getPolymorphicSpecializations().get(0);
1780
1781 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1782 builder.startReturn();
1783
1784 CodeTreeBuilder execute = new CodeTreeBuilder(builder);
1785 execute.startCall("next0", "executeCached0");
1786 addInternalValueParameterNames(execute, specialization, generic, param.getLocalName(), true, true);
1787 execute.end();
1788
1789 TypeData sourceType = generic.getReturnType().getTypeSystemType();
1790 TypeData targetType = specialization.getReturnType().getTypeSystemType();
1791
1792 builder.tree(createCastType(node, sourceType, targetType, true, execute.getRoot()));
1793
1794 builder.end();
1795 return builder.getRoot();
1796 }
1797
1798 private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData targetField, ActualParameter sourceParameter, ActualParameter unexpectedParameter) {
1799 TypeData type = sourceParameter.getTypeSystemType();
1800 ExecutableTypeData execType = targetField.findExecutableType(getContext(), type);
1801
1802 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1803 if (targetField != null) {
1804 Element accessElement = targetField.getAccessElement();
1805 if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) {
1806 builder.string("this.").string(targetField.getName());
1807 } else if (accessElement.getKind() == ElementKind.FIELD) {
1808 builder.string("this.").string(accessElement.getSimpleName().toString());
1809 } else {
1810 throw new AssertionError();
1811 }
1812 if (sourceParameter.getSpecification().isIndexed()) {
1813 builder.string("[" + sourceParameter.getIndex() + "]");
1814 }
1815 builder.string(".");
1816 }
1817
1818 builder.startCall(execType.getMethodName());
1819
1820 int index = 0;
1821 for (ActualParameter parameter : execType.getParameters()) {
1822
1823 if (!parameter.getSpecification().isSignature()) {
1824 builder.string(parameter.getLocalName());
1825 } else {
1826 if (index < targetField.getExecuteWith().size()) {
1827 NodeChildData child = targetField.getExecuteWith().get(index);
1828
1829 ParameterSpec spec = getModel().getSpecification().findParameterSpec(child.getName());
1830 List<ActualParameter> specializationParams = getModel().findParameters(spec);
1831
1832 if (specializationParams.isEmpty()) {
1833 builder.defaultValue(parameter.getType());
1834 continue;
1835 }
1836
1837 ActualParameter specializationParam = specializationParams.get(0);
1838
1839 TypeData targetType = parameter.getTypeSystemType();
1840 TypeData sourceType = specializationParam.getTypeSystemType();
1841 String localName = specializationParam.getLocalName();
1842
1843 if (unexpectedParameter != null && unexpectedParameter.getLocalName().equals(specializationParam.getLocalName())) {
1844 localName = "ex.getResult()";
1845 sourceType = getModel().getNode().getTypeSystem().getGenericTypeData();
1846 }
1847
1848 CodeTree value = CodeTreeBuilder.singleString(localName);
1849
1850 if (sourceType.needsCastTo(getContext(), targetType)) {
1851 value = createCallTypeSystemMethod(getContext(), builder, getModel().getNode(), TypeSystemCodeGenerator.asTypeMethodName(targetType), value);
1852 }
1853 builder.tree(value);
1854 } else {
1855 builder.defaultValue(parameter.getType());
1856 }
1857 index++;
1858 }
1859 }
1860
1861 builder.end();
1862
1863 return builder.getRoot();
1864 }
1865
1866 private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, SpecializationData specialization, ActualParameter parameter,
1867 ActualParameter exceptionParam) {
1868 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1869
1870 NodeChildData forField = specialization.getNode().findChild(parameter.getSpecification().getName());
1871 if (forField == null) {
1872 return body;
1873 }
1874
1875 if (forField.getExecutionKind() != ExecutionKind.SHORT_CIRCUIT) {
1876 return body;
1877 }
1878
1879 ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter);
1880
1881 builder.tree(createShortCircuitValue(builder, specialization, forField, shortCircuitParam, exceptionParam));
1882
1883 builder.declaration(parameter.getType(), targetVariableName, CodeTreeBuilder.createBuilder().defaultValue(parameter.getType()));
1884 builder.startIf().string(shortCircuitParam.getLocalName()).end();
1885 builder.startBlock();
1886 builder.tree(body);
1887 builder.end();
1888
1889 return builder.getRoot();
1890 }
1891
1892 private CodeTree createShortCircuitValue(CodeTreeBuilder parent, SpecializationData specialization, NodeChildData forField, ActualParameter shortCircuitParam, ActualParameter exceptionParam) {
1893 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1894 int shortCircuitIndex = 0;
1895 for (NodeChildData field : specialization.getNode().getChildren()) {
1896 if (field.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) {
1897 if (field == forField) {
1898 break;
1899 }
1900 shortCircuitIndex++;
1901 }
1902 }
1903
1904 builder.startStatement().type(shortCircuitParam.getType()).string(" ").string(valueName(shortCircuitParam)).string(" = ");
1905 ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex);
1906 builder.tree(createTemplateMethodCall(builder, null, specialization, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null));
1907 builder.end(); // statement
1908
1909 return builder.getRoot();
1910 }
1911
1912 protected CodeTree createDeoptimize(CodeTreeBuilder parent) {
1913 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1914 builder.startStatement();
1915 builder.startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end();
1916 builder.end();
1917 return builder.getRoot();
1918 }
1919
1920 protected CodeTree createReturnExecuteAndSpecialize(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData nextSpecialization, ActualParameter exceptionParam, String reason) {
1921 SpecializationData generic = getModel().getNode().getGenericSpecialization();
1922 CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent);
1923 specializeCall.startCall(EXECUTE_SPECIALIZE_NAME);
1924 specializeCall.string(nodeSpecializationClassName(nextSpecialization) + ".class");
1925 addInternalValueParameterNames(specializeCall, generic, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, true);
1926 specializeCall.doubleQuote(reason);
1927 specializeCall.end().end();
1928
1929 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1930
1931 builder.startReturn();
1932 builder.tree(createExpectExecutableType(nextSpecialization.getNode(), generic.getReturnType().getTypeSystemType(), executable, specializeCall.getRoot()));
1933 builder.end();
1934
1935 return builder.getRoot();
1936 }
1937 }
1938
1939 private class PolymorphicNodeFactory extends SpecializedNodeFactory {
1940
1941 private final boolean generic;
1942
1943 public PolymorphicNodeFactory(ProcessorContext context, CodeTypeElement nodeGen, boolean generic) {
1944 super(context, nodeGen);
1945 this.generic = generic;
1946 }
1947
1948 @Override
1949 public CodeTypeElement create(SpecializationData specialization) {
1950 NodeData node = specialization.getNode();
1951 TypeMirror baseType = node.getNodeType();
1952 if (nodeGen != null) {
1953 baseType = nodeGen.asType();
1954 }
1955 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC), nodePolymorphicClassName(node, specialization), baseType, false);
1956
1957 if (!generic) {
1958 clazz.getModifiers().add(Modifier.FINAL);
1959 }
1960
1961 clazz.getAnnotationMirrors().add(createNodeInfo(node, Kind.POLYMORPHIC));
1962
1963 return clazz;
1964 }
1965
1966 @Override
1967 protected void createChildren(SpecializationData specialization) {
1968 // super.createChildren(specialization);
1969 CodeTypeElement clazz = getElement();
1970
1971 createConstructors(clazz);
1972 createExecuteMethods(specialization);
1973
1974 if (generic) {
1975 getElement().add(createOptimizeTypes());
1976 createCachedExecuteMethods(specialization);
1977 }
1978 }
1979
1980 private CodeExecutableElement createOptimizeTypes() {
1981 NodeData node = getModel().getNode();
1982 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), getContext().getType(void.class), "optimizeTypes");
1983 CodeTreeBuilder builder = method.createBuilder();
1984 builder.startStatement().string(baseClassName(node)).string(" node = this.next0").end();
1985 TypeMirror classType = getContext().getType(Class.class);
1986
1987 SpecializationData genericSpecialization = node.getGenericSpecialization();
1988
1989 CodeTreeBuilder whileBodyBuilder = builder.create();
1990 for (ActualParameter parameter : node.getGenericSpecialization().getReturnTypeAndParameters()) {
1991 if (!parameter.getSpecification().isSignature()) {
1992 continue;
1993 }
1994
1995 ActualParameter genericParameter = genericSpecialization.findParameter(parameter.getLocalName());
1996
1997 String name = parameter.getLocalName() + "Type";
1998
1999 builder.declaration(classType, name, builder.create().startCall("node", typeGetterName(parameter)).end().getRoot());
2000
2001 whileBodyBuilder.startIf().string(name).string(" != ").startCall("node", typeGetterName(parameter)).end().end();
2002 whileBodyBuilder.startBlock();
2003 whileBodyBuilder.startStatement().string(name).string(" = ").typeLiteral(genericParameter.getType()).end();
2004 whileBodyBuilder.end();
2005 }
2006
2007 builder.startWhile().string("node != null && !(").instanceOf("node", nodeSpecializationClassName(node.getUninitializedSpecialization())).string(")").end();
2008 builder.startBlock();
2009 builder.tree(whileBodyBuilder.getRoot());
2010 builder.statement("node = node.next0");
2011 builder.end();
2012
2013 boolean elseIf = false;
2014 for (SpecializationData polymorph : node.getPolymorphicSpecializations()) {
2015 elseIf = builder.startIf(elseIf);
2016 String and = "";
2017 StringBuilder reason = new StringBuilder("Optimized polymorphic types for (");
2018 for (ActualParameter parameter : polymorph.getReturnTypeAndParameters()) {
2019 if (!parameter.getSpecification().isSignature()) {
2020 continue;
2021 }
2022 String name = parameter.getLocalName() + "Type";
2023 builder.string(and).string(name).string(" == ").typeLiteral(parameter.getType());
2024
2025 if (!and.isEmpty()) {
2026 reason.append(", ");
2027 }
2028 reason.append(Utils.getSimpleName(parameter.getType()));
2029 and = " && ";
2030 }
2031 reason.append(")");
2032 builder.end();
2033 builder.startBlock();
2034
2035 String className = nodePolymorphicClassName(node, polymorph);
2036 builder.startIf().string("getClass() != ").string(className).string(".class").end();
2037 builder.startBlock();
2038 builder.startStatement().startCall("super", "replace");
2039 builder.startNew(className).string("this").end();
2040 builder.doubleQuote(reason.toString());
2041 builder.end().end(); // call
2042 builder.end(); // block
2043 builder.end();
2044 }
2045 return method;
2046 }
2047 }
2048
2049 private class SpecializedNodeFactory extends NodeBaseFactory {
2050
2051 protected final CodeTypeElement nodeGen;
2052
2053 public SpecializedNodeFactory(ProcessorContext context, CodeTypeElement nodeGen) {
2054 super(context);
2055 this.nodeGen = nodeGen;
2056 }
2057
2058 @Override
2059 public CodeTypeElement create(SpecializationData specialization) {
2060 NodeData node = specialization.getNode();
2061 TypeMirror baseType = node.getNodeType();
2062 if (nodeGen != null) {
2063 baseType = nodeGen.asType();
2064 }
2065 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false);
2066
2067 Kind kind;
2068 if (specialization.isGeneric()) {
2069 kind = Kind.GENERIC;
2070 } else if (specialization.isUninitialized()) {
2071 kind = Kind.UNINITIALIZED;
2072 } else {
2073 kind = Kind.SPECIALIZED;
2074 }
2075 clazz.getAnnotationMirrors().add(createNodeInfo(node, kind));
2076
2077 return clazz;
2078 }
2079
2080 protected CodeAnnotationMirror createNodeInfo(NodeData node, Kind kind) {
2081 String shortName = node.getShortName();
2082 CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(getContext().getTruffleTypes().getNodeInfoAnnotation());
2083 if (shortName != null) {
2084 nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("shortName"), new CodeAnnotationValue(shortName));
2085 }
2086
2087 DeclaredType nodeinfoKind = getContext().getTruffleTypes().getNodeInfoKind();
2088 VariableElement varKind = Utils.findVariableElement(nodeinfoKind, kind.name());
2089
2090 nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("kind"), new CodeAnnotationValue(varKind));
2091 return nodeInfoMirror;
2092 }
2093
2094 @Override
2095 protected void createChildren(SpecializationData specialization) {
2096 CodeTypeElement clazz = getElement();
2097 createConstructors(clazz);
2098
2099 NodeData node = specialization.getNode();
2100
2101 if (!specialization.isGeneric() && !specialization.isUninitialized() && !specialization.isPolymorphic() && node.needsRewrites(getContext()) && node.getPolymorphicDepth() > 1) {
2102
2103 createTypeGetters(clazz, specialization);
2104 }
2105
2106 createExecuteMethods(specialization);
2107 createCachedExecuteMethods(specialization);
2108 }
2109
2110 protected void createConstructors(CodeTypeElement clazz) {
2111 TypeElement superTypeElement = Utils.fromTypeMirror(clazz.getSuperclass());
2112 for (ExecutableElement constructor : ElementFilter.constructorsIn(superTypeElement.getEnclosedElements())) {
2113 if (getModel().getNode().getUninitializedSpecialization() != null && !getModel().isUninitialized() &&
2114 (constructor.getParameters().size() != 1 || constructor.getParameters().get(0).getSimpleName().toString().equals(baseClassName(getModel().getNode())))) {
2115 continue;
2116 }
2117
2118 CodeExecutableElement superConstructor = createSuperConstructor(clazz, constructor);
2119 if (superConstructor != null) {
2120 if (getModel().isGeneric() && getModel().getNode().getPolymorphicDepth() > 1) {
2121 CodeTree body = superConstructor.getBodyTree();
2122 CodeTreeBuilder builder = superConstructor.createBuilder();
2123 builder.tree(body);
2124 builder.statement("this.next0 = null");
2125 }
2126
2127 clazz.add(superConstructor);
2128 }
2129 }
2130 }
2131
2132 protected void createExecuteMethods(SpecializationData specialization) {
2133 NodeData node = specialization.getNode();
2134 CodeTypeElement clazz = getElement();
2135
2136 for (ExecutableTypeData execType : node.getExecutableTypes()) {
2137 if (execType.isFinal()) {
2138 continue;
2139 }
2140 CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, true);
2141 clazz.add(executeMethod);
2142 CodeTreeBuilder builder = executeMethod.createBuilder();
2143 CodeTree result = createExecuteBody(builder, specialization, execType);
2144 if (result != null) {
2145 builder.tree(result);
2146 } else {
2147 clazz.remove(executeMethod);
2148 }
2149 }
2150 }
2151
2152 protected void createCachedExecuteMethods(SpecializationData specialization) {
2153 NodeData node = specialization.getNode();
2154 CodeTypeElement clazz = getElement();
2155 int index = 0;
2156 for (SpecializationData polymorphic : node.getPolymorphicSpecializations()) {
2157 boolean matchFound = false;
2158 if (!specialization.isGeneric() && !specialization.isUninitialized() && !specialization.isPolymorphic()) {
2159 matchFound = polymorphic.getSignature().hasAnyParameterMatch(specialization.getSignature());
2160 }
2161
2162 if (matchFound || index == 0) {
2163 ExecutableElement executeCached = nodeGen.getMethod("executeCached" + index);
2164 ExecutableTypeData execType = new ExecutableTypeData(polymorphic, executeCached, node.getTypeSystem(), polymorphic.getReturnType().getTypeSystemType());
2165
2166 CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, false);
2167 CodeTreeBuilder builder = executeMethod.createBuilder();
2168
2169 if (specialization.isGeneric() || specialization.isPolymorphic()) {
2170 builder.startThrow().startNew(getContext().getType(AssertionError.class));
2171 builder.doubleQuote("Should not be reached.");
2172 builder.end().end();
2173 } else if (specialization.isUninitialized()) {
2174 builder.tree(createAppendPolymorphic(builder, specialization));
2175 } else {
2176 CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder);
2177 elseBuilder.startReturn().startCall("this.next0", "executeCached" + index);
2178 addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, true);
2179 elseBuilder.end().end();
2180 CodeTreeBuilder execute = new CodeTreeBuilder(builder);
2181 execute.tree(createGenericInvoke(builder, polymorphic, specialization));
2182 boolean forceElse = !specialization.getExceptions().isEmpty();
2183 builder.tree(createGuardAndCast(builder, null, polymorphic, specialization, true, execute.getRoot(), elseBuilder.getRoot(), true, forceElse));
2184 }
2185 clazz.add(executeMethod);
2186 }
2187 index++;
2188 }
2189 }
2190
2191 private CodeTree createAppendPolymorphic(CodeTreeBuilder parent, SpecializationData specialization) {
2192 NodeData node = specialization.getNode();
2193 String genericClassName = nodePolymorphicClassName(node, null);
2194
2195 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
2196 builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end();
2197
2198 builder.declaration(getContext().getTruffleTypes().getNode(), "searchNode", "super.getParent()");
2199 builder.declaration(getContext().getType(int.class), "depth", "0");
2200 builder.startWhile().string("searchNode != null").end();
2201 builder.startBlock();
2202 builder.statement("depth++");
2203 builder.statement("searchNode = searchNode.getParent()");
2204
2205 builder.startIf().instanceOf("searchNode", genericClassName).end();
2206 builder.startBlock().breakStatement().end();
2207 builder.end(); // if
2208 builder.end(); // while
2209
2210 builder.startAssert().instanceOf("searchNode", genericClassName).end();
2211
2212 builder.startStatement();
2213 builder.string(genericClassName).string(" ").string("polymorphic = ").string("(").string(genericClassName).string(") searchNode");
2214 builder.end();
2215
2216 builder.startIf().string("depth >= ").string(String.valueOf(node.getPolymorphicDepth())).end();
2217 builder.startBlock();
2218 builder.startStatement();
2219 builder.startCall("searchNode", "replace");
2220 builder.startNew(nodeSpecializationClassName(node.getGenericSpecialization())).string("this").end();
2221 builder.doubleQuote("Polymorphic limit reached (" + node.getPolymorphicDepth() + ")");
2222 builder.end();
2223 builder.end();
2224
2225 builder.startReturn().startCall("super", EXECUTE_GENERIC_NAME);
2226 addInternalValueParameterNames(builder, specialization, node.getGenericSpecialization(), null, true, true);
2227 builder.end().end();
2228
2229 builder.end().startElseBlock();
2230 builder.startStatement().startCall("super", "setNext0");
2231 builder.startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string("this").end();
2232 builder.end().end();
2233
2234 CodeTreeBuilder specializeCall = new CodeTreeBuilder(builder);
2235 specializeCall.startCall(EXECUTE_SPECIALIZE_NAME);
2236 specializeCall.string(nodeSpecializationClassName(node.getUninitializedSpecialization()) + ".class");
2237 addInternalValueParameterNames(specializeCall, specialization, node.getGenericSpecialization(), null, true, true);
2238 specializeCall.startGroup().doubleQuote("Uninitialized polymorphic (").string(" + depth + ").doubleQuote("/" + node.getPolymorphicDepth() + ")").end();
2239 specializeCall.end().end();
2240
2241 builder.declaration(node.getGenericSpecialization().getReturnType().getType(), "result", specializeCall.getRoot());
2242
2243 builder.statement("polymorphic.optimizeTypes()");
2244
2245 if (Utils.isVoid(builder.findMethod().getReturnType())) {
2246 builder.returnStatement();
2247 } else {
2248 builder.startReturn().string("result").end();
2249 }
2250
2251 builder.end();
2252
2253 return builder.getRoot();
2254 }
2255
2256 private CodeTree createExecuteBody(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData execType) {
2257 TypeData primaryType = specialization.getReturnType().getTypeSystemType();
2258
2259 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
2260
2261 List<ExecutableTypeData> primaryExecutes = findFunctionalExecutableType(specialization, execType.getEvaluatedCount());
2262
2263 if (primaryExecutes.contains(execType) || primaryExecutes.isEmpty()) {
2264 builder.tree(createFunctionalExecute(builder, specialization, execType));
2265 } else if (needsCastingExecuteMethod(execType, primaryType)) {
2266 assert !primaryExecutes.isEmpty();
2267 builder.tree(createCastingExecute(builder, specialization, execType, primaryExecutes.get(0)));
2268 } else {
2269 return null;
2270 }
2271
2272 return builder.getRoot();
2273 }
2274
2275 private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType, boolean evaluated) {
2276 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod());
2277
2278 int i = 0;
2279 for (VariableElement param : method.getParameters()) {
2280 CodeVariableElement var = CodeVariableElement.clone(param);
2281 ActualParameter actualParameter = execType.getParameters().get(i);
2282 if (evaluated && actualParameter.getSpecification().isSignature()) {
2283 var.setName(valueNameEvaluated(actualParameter));
2284 } else {
2285 var.setName(valueName(actualParameter));
2286 }
2287 method.getParameters().set(i, var);
2288 i++;
2289 }
2290
2291 method.getAnnotationMirrors().clear();
2292 method.getModifiers().remove(Modifier.ABSTRACT);
2293 return method;
2294 }
2295
2296 private boolean needsCastingExecuteMethod(ExecutableTypeData execType, TypeData primaryType) {
2297 if (execType.isAbstract()) {
2298 return true;
2299 }
2300 if (Utils.isPrimitiveOrVoid(primaryType.getPrimitiveType()) && Utils.isPrimitiveOrVoid(execType.getType().getPrimitiveType())) {
2301 return true;
2302 }
2303 if (execType.getType().isGeneric()) {
2304 return true;
2305 }
2306 return false;
2307 }
2308
2309 private List<ExecutableTypeData> findFunctionalExecutableType(SpecializationData specialization, int evaluatedCount) {
2310 TypeData primaryType = specialization.getReturnType().getTypeSystemType();
2311 List<ExecutableTypeData> otherTypes = specialization.getNode().getExecutableTypes(evaluatedCount);
2312
2313 List<ExecutableTypeData> filteredTypes = new ArrayList<>();
2314 for (ExecutableTypeData compareType : otherTypes) {
2315 if (!Utils.typeEquals(compareType.getType().getPrimitiveType(), primaryType.getPrimitiveType())) {
2316 continue;
2317 }
2318 filteredTypes.add(compareType);
2319 }
2320
2321 // no direct matches found use generic where the type is Object
2322 if (filteredTypes.isEmpty()) {
2323 for (ExecutableTypeData compareType : otherTypes) {
2324 if (compareType.getType().isGeneric() && !compareType.hasUnexpectedValue(getContext())) {
2325 filteredTypes.add(compareType);
2326 }
2327 }
2328 }
2329
2330 if (filteredTypes.isEmpty()) {
2331 for (ExecutableTypeData compareType : otherTypes) {
2332 if (compareType.getType().isGeneric()) {
2333 filteredTypes.add(compareType);
2334 }
2335 }
2336 }
2337
2338 return filteredTypes;
2339 }
2340
2341 private CodeTree createFunctionalExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable) {
2342 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
2343 if (specialization.isUninitialized()) {
2344 builder.tree(createDeoptimize(builder));
2345 }
2346
2347 builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null, false));
2348
2349 CodeTree executeNode = createExecute(builder, executable, specialization);
2350
2351 SpecializationData next = specialization.findNextSpecialization();
2352 CodeTree returnSpecialized = null;
2353 if (next != null) {
2354 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder);
2355 returnBuilder.tree(createDeoptimize(builder));
2356 returnBuilder.tree(createReturnExecuteAndSpecialize(builder, executable, next, null, "One of guards " + specialization.getGuards() + " failed"));
2357 returnSpecialized = returnBuilder.getRoot();
2358 }
2359 builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized, false, false));
2360
2361 return builder.getRoot();
2362 }
2363
2364 private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) {
2365 NodeData node = specialization.getNode();
2366 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
2367 if (!specialization.getExceptions().isEmpty() || !specialization.getAssumptions().isEmpty()) {
2368 builder.startTryBlock();
2369 }
2370
2371 for (String assumption : specialization.getAssumptions()) {
2372 builder.startStatement();
2373 builder.string("this.").string(assumption).string(".check()");
2374 builder.end();
2375 }
2376
2377 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent);
2378 if (specialization.isPolymorphic()) {
2379 int index = 0;
2380 if (executable.hasUnexpectedValue(getContext())) {
2381 index = specialization.getNode().getPolymorphicSpecializations().indexOf(specialization);
2382 }
2383 returnBuilder.startCall("next0", "executeCached" + index);
2384 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true);
2385 returnBuilder.end();
2386 } else if (specialization.isUninitialized()) {
2387 returnBuilder.startCall("super", EXECUTE_SPECIALIZE_NAME);
2388 returnBuilder.startGroup().string(nodeSpecializationClassName(specialization)).string(".class").end();
2389 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true);
2390 returnBuilder.doubleQuote("Uninitialized monomorphic");
2391 returnBuilder.end();
2392 } else if (specialization.getMethod() == null && !node.needsRewrites(context)) {
2393 emitEncounteredSynthetic(builder, specialization);
2394 } else if (specialization.isGeneric()) {
2395 returnBuilder.startCall("super", EXECUTE_GENERIC_NAME);
2396 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true);
2397 returnBuilder.end();
2398 } else {
2399 returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null));
2400 }
2401
2402 if (!returnBuilder.isEmpty()) {
2403 builder.startReturn();
2404
2405 TypeData targetType = node.getTypeSystem().findTypeData(builder.findMethod().getReturnType());
2406 TypeData sourceType = specialization.getReturnType().getTypeSystemType();
2407
2408 if (targetType == null || sourceType == null) {
2409 builder.tree(returnBuilder.getRoot());
2410 } else if (sourceType.needsCastTo(getContext(), targetType)) {
2411 builder.tree(createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.expectTypeMethodName(targetType), returnBuilder.getRoot()));
2412 } else {
2413 builder.tree(returnBuilder.getRoot());
2414 }
2415 builder.end();
2416 }
2417
2418 if (!specialization.getExceptions().isEmpty()) {
2419 for (SpecializationThrowsData exception : specialization.getExceptions()) {
2420 builder.end().startCatchBlock(exception.getJavaClass(), "ex");
2421 builder.tree(createDeoptimize(builder));
2422 builder.tree(createReturnExecuteAndSpecialize(parent, executable, exception.getTransitionTo(), null, "Thrown " + Utils.getSimpleName(exception.getJavaClass())));
2423 }
2424 builder.end();
2425 }
2426 if (!specialization.getAssumptions().isEmpty()) {
2427 builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex");
2428 builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization.findNextSpecialization(), null, "Assumption failed"));
2429 builder.end();
2430 }
2431
2432 return builder.getRoot();
2433 }
2434
2435 }
2436
2437 }