comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java @ 16755:bd28da642eea

Truffle-DSL: Several new features implemented: Implementation of a new code generation layout which shares code between generated nodes. Declaration order of specializations is now used as specialization order. Specializations do no longer perform fallthrough on respecialization, they now always respecialize from the first specialization. Implemented support for contains relations between specializations. Improved reachability error messages. Preliminary support for @Implies.
author Christian Humer <christian.humer@gmail.com>
date Mon, 11 Aug 2014 15:53:05 +0200
parents 4f397be8f424
children
comparison
equal deleted inserted replaced
16754:55fd5be68a52 16755:bd28da642eea
33 33
34 import com.oracle.truffle.api.dsl.*; 34 import com.oracle.truffle.api.dsl.*;
35 import com.oracle.truffle.api.nodes.*; 35 import com.oracle.truffle.api.nodes.*;
36 import com.oracle.truffle.dsl.processor.*; 36 import com.oracle.truffle.dsl.processor.*;
37 import com.oracle.truffle.dsl.processor.ast.*; 37 import com.oracle.truffle.dsl.processor.ast.*;
38 import com.oracle.truffle.dsl.processor.ast.CodeTypeMirror.ArrayCodeTypeMirror;
38 import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality; 39 import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality;
39 import com.oracle.truffle.dsl.processor.node.SpecializationGroup.TypeGuard; 40 import com.oracle.truffle.dsl.processor.node.SpecializationGroup.TypeGuard;
40 import com.oracle.truffle.dsl.processor.template.*; 41 import com.oracle.truffle.dsl.processor.template.*;
41 import com.oracle.truffle.dsl.processor.typesystem.*; 42 import com.oracle.truffle.dsl.processor.typesystem.*;
42 43
43 public class NodeCodeGenerator extends CompilationUnitFactory<NodeData> { 44 public class NodeCodeGenerator extends CompilationUnitFactory<NodeData> {
44 45
45 private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode"; 46 private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode";
46 47
47 private static final String EXECUTE_GENERIC_NAME = "executeGeneric0"; 48 private static final String EXECUTE_CHAINED = "executeChained0";
48 private static final String EXECUTE_SPECIALIZE_NAME = "executeAndSpecialize0"; 49 private static final String SPECIALIZE = "specialize0";
49 private static final String EXECUTE_POLYMORPHIC_NAME = "executePolymorphic0"; 50 private static final String DSLSHARE_REWRITE = "rewrite";
50 51 private static final String DSLSHARE_FIND_ROOT = "findRoot";
51 private static final String UPDATE_TYPES_NAME = "updateTypes"; 52 private static final String DSLSHARE_REWRITE_TO_POLYMORHPIC = "rewriteToPolymorphic";
52 private static final String COPY_WITH_CONSTRUCTOR_NAME = "copyWithConstructor"; 53 private static final String EXECUTE_UNINITIALIZED = "executeUninitialized0";
53 private static final String CREATE_SPECIALIZATION_NAME = "createSpecialization"; 54 private static final String REWRITE = "rewrite0";
54 55 private static final String CREATE_INFO = "createInfo0";
55 public NodeCodeGenerator(ProcessorContext context) { 56 private static final String CONTAINS_FALLBACK = "containsFallback";
56 super(context); 57
57 } 58 private static final String FACTORY_METHOD_NAME = "create0";
59 private static final String EMPTY_CLASS_ARRAY = "EMPTY_CLASS_ARRAY";
60
61 private static final String METADATA_FIELD_NAME = "METADATA";
58 62
59 private TypeMirror getUnexpectedValueException() { 63 private TypeMirror getUnexpectedValueException() {
60 return getContext().getTruffleTypes().getUnexpectedValueException(); 64 return getContext().getTruffleTypes().getUnexpectedValueException();
61 } 65 }
62 66
90 94
91 private static String implicitTypeName(ActualParameter param) { 95 private static String implicitTypeName(ActualParameter param) {
92 return param.getLocalName() + "ImplicitType"; 96 return param.getLocalName() + "ImplicitType";
93 } 97 }
94 98
95 private static String polymorphicTypeName(ActualParameter param) { 99 private static String polymorphicTypeName(NodeExecutionData param) {
96 return param.getLocalName() + "PolymorphicType"; 100 return param.getName() + "PolymorphicType";
97 } 101 }
98 102
99 private static String valueName(ActualParameter param) { 103 private static String valueName(ActualParameter param) {
100 return param.getLocalName(); 104 return param.getLocalName();
101 } 105 }
144 148
145 method.addParameter(new CodeVariableElement(parameter.getType(), name)); 149 method.addParameter(new CodeVariableElement(parameter.getType(), name));
146 } 150 }
147 } 151 }
148 152
149 private void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, 153 private static void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame,
150 Map<String, String> customNames) { 154 Map<String, String> customNames) {
151 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { 155 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
152 builder.string("frameValue"); 156 builder.string("frameValue");
153 } 157 }
154 for (ActualParameter parameter : specialization.getParameters()) { 158 for (ActualParameter parameter : specialization.getParameters()) {
173 builder.string(valueName(parameter)); 177 builder.string(valueName(parameter));
174 } 178 }
175 } 179 }
176 } 180 }
177 181
178 private String valueName(ActualParameter sourceParameter, ActualParameter targetParameter) { 182 private static String valueName(ActualParameter sourceParameter, ActualParameter targetParameter) {
179 if (!sourceParameter.getSpecification().isSignature()) { 183 if (!sourceParameter.getSpecification().isSignature()) {
180 return valueName(targetParameter); 184 return valueName(targetParameter);
181 } else if (sourceParameter.getTypeSystemType() != null && targetParameter.getTypeSystemType() != null) { 185 } else if (sourceParameter.getTypeSystemType() != null && targetParameter.getTypeSystemType() != null) {
182 if (sourceParameter.getTypeSystemType().needsCastTo(getContext(), targetParameter.getTypeSystemType())) { 186 if (sourceParameter.getTypeSystemType().needsCastTo(targetParameter.getTypeSystemType())) {
183 return castValueName(targetParameter); 187 return castValueName(targetParameter);
184 } 188 }
185 } 189 }
186 return valueName(targetParameter); 190 return valueName(targetParameter);
187 } 191 }
188 192
189 private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName, 193 private static CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName,
190 String... customSignatureValueNames) { 194 String... customSignatureValueNames) {
191 CodeTreeBuilder builder = parent.create(); 195 CodeTreeBuilder builder = parent.create();
192 196
193 boolean castedValues = sourceMethod != targetMethod; 197 boolean castedValues = sourceMethod != targetMethod;
194 198
199 } 203 }
200 TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement()); 204 TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement());
201 NodeData node = (NodeData) targetMethod.getTemplate(); 205 NodeData node = (NodeData) targetMethod.getTemplate();
202 206
203 if (target == null) { 207 if (target == null) {
204 boolean accessible = targetMethod.canBeAccessedByInstanceOf(getContext(), node.getNodeType()); 208 boolean accessible = targetMethod.canBeAccessedByInstanceOf(node.getNodeType());
205 if (accessible) { 209 if (accessible) {
206 if (builder.findMethod().getModifiers().contains(STATIC)) { 210 if (builder.findMethod().getModifiers().contains(STATIC)) {
207 if (method.getModifiers().contains(STATIC)) { 211 if (method.getModifiers().contains(STATIC)) {
208 builder.type(targetClass.asType()); 212 builder.type(targetClass.asType());
209 } else { 213 } else {
274 } 278 }
275 builder.string(targetParameter.getSpecification().getName()); 279 builder.string(targetParameter.getSpecification().getName());
276 builder.end(); 280 builder.end();
277 } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) { 281 } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) {
278 builder.cast(targetParameter.getType(), CodeTreeBuilder.singleString("ex.getResult()")); 282 builder.cast(targetParameter.getType(), CodeTreeBuilder.singleString("ex.getResult()"));
279 } else if (!Utils.needsCastTo(getContext(), valueType, targetType)) { 283 } else if (!Utils.needsCastTo(valueType, targetType)) {
280 builder.startGroup(); 284 builder.startGroup();
281 builder.string(valueName(targetParameter)); 285 builder.string(valueName(targetParameter));
282 builder.end(); 286 builder.end();
283 } else { 287 } else {
284 builder.string(castValueName(targetParameter)); 288 builder.string(castValueName(targetParameter));
295 String name = Utils.firstLetterUpperCase(nodeid); 299 String name = Utils.firstLetterUpperCase(nodeid);
296 name += "BaseNode"; 300 name += "BaseNode";
297 return name; 301 return name;
298 } 302 }
299 303
300 private static CodeTree createCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder parent, NodeData node, String methodName, CodeTree... args) { 304 private static CodeTree createCallTypeSystemMethod(CodeTreeBuilder parent, NodeData node, String methodName, CodeTree... args) {
301 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 305 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
302 startCallTypeSystemMethod(context, builder, node.getTypeSystem(), methodName); 306 startCallTypeSystemMethod(builder, node.getTypeSystem(), methodName);
303 for (CodeTree arg : args) { 307 for (CodeTree arg : args) {
304 builder.tree(arg); 308 builder.tree(arg);
305 } 309 }
306 builder.end().end(); 310 builder.end().end();
307 return builder.getRoot(); 311 return builder.getRoot();
308 } 312 }
309 313
310 private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body, TypeSystemData typeSystem, String methodName) { 314 private static void startCallTypeSystemMethod(CodeTreeBuilder body, TypeSystemData typeSystem, String methodName) {
311 VariableElement singleton = TypeSystemCodeGenerator.findSingleton(context, typeSystem); 315 GeneratedTypeMirror typeMirror = new GeneratedTypeMirror(Utils.getPackageName(typeSystem.getTemplateType()), TypeSystemCodeGenerator.typeName(typeSystem));
312 assert singleton != null;
313
314 body.startGroup(); 316 body.startGroup();
315 body.staticReference(singleton.getEnclosingElement().asType(), singleton.getSimpleName().toString()); 317 body.staticReference(typeMirror, TypeSystemCodeGenerator.singletonName(typeSystem));
316 body.string(".").startCall(methodName); 318 body.string(".").startCall(methodName);
317 } 319 }
318 320
319 /** 321 /**
320 * <pre> 322 * <pre>
361 if (executionData != null) { 363 if (executionData != null) {
362 if (executionData.isShortCircuit()) { 364 if (executionData.isShortCircuit()) {
363 nodes.nullLiteral(); 365 nodes.nullLiteral();
364 arguments.string(valueName(parameter.getPreviousParameter())); 366 arguments.string(valueName(parameter.getPreviousParameter()));
365 } 367 }
366 nodes.tree(createAccessChild(executionData, null)); 368 nodes.tree(createAccessChild(executionData, "rootNode"));
367 arguments.string(valueName(parameter)); 369 arguments.string(valueName(parameter));
368 empty = false; 370 empty = false;
369 } 371 }
370 } 372 }
371 nodes.end(); 373 nodes.end();
372 arguments.end(); 374 arguments.end();
373 375 builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end();
376
377 builder.declaration(baseClassName(getModel()), "rootNode", builder.create().startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_FIND_ROOT).string("this").end());
374 builder.startThrow().startNew(getContext().getType(UnsupportedSpecializationException.class)); 378 builder.startThrow().startNew(getContext().getType(UnsupportedSpecializationException.class));
375 builder.string("this"); 379 builder.string("rootNode");
376 builder.startNewArray(getContext().getTruffleTypes().getNodeArray(), null); 380 builder.startNewArray(getContext().getTruffleTypes().getNodeArray(), null);
377
378 builder.tree(nodes.getRoot()); 381 builder.tree(nodes.getRoot());
379 builder.end(); 382 builder.end();
380 if (!empty) { 383 if (!empty) {
381 builder.tree(arguments.getRoot()); 384 builder.tree(arguments.getRoot());
382 } 385 }
444 List<CodeTypeElement> casts = new ArrayList<>(getElement().getEnclosedElements()); 447 List<CodeTypeElement> casts = new ArrayList<>(getElement().getEnclosedElements());
445 getElement().getEnclosedElements().clear(); 448 getElement().getEnclosedElements().clear();
446 449
447 Map<NodeData, List<TypeElement>> childTypes = new LinkedHashMap<>(); 450 Map<NodeData, List<TypeElement>> childTypes = new LinkedHashMap<>();
448 for (NodeData nodeChild : node.getEnclosingNodes()) { 451 for (NodeData nodeChild : node.getEnclosingNodes()) {
449 NodeCodeGenerator generator = new NodeCodeGenerator(getContext()); 452 NodeCodeGenerator generator = new NodeCodeGenerator();
450 childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements()); 453 childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements());
451 } 454 }
452 455
453 if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) { 456 if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) {
454 NodeFactoryFactory factory = new NodeFactoryFactory(context, childTypes); 457 NodeFactoryFactory factory = new NodeFactoryFactory(childTypes);
455 add(factory, node); 458 add(factory, node);
456 factory.getElement().getEnclosedElements().addAll(casts); 459 factory.getElement().getEnclosedElements().addAll(casts);
457 } 460 }
458 } 461 }
459 462
460 protected CodeTree createCastType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) { 463 private static CodeTree createCastType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) {
461 if (targetType == null) { 464 if (targetType == null) {
462 return value; 465 return value;
463 } else if (sourceType != null && !sourceType.needsCastTo(getContext(), targetType)) { 466 } else if (sourceType != null && !sourceType.needsCastTo(targetType)) {
464 return value; 467 return value;
465 } 468 }
466 469
467 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); 470 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
468 String targetMethodName; 471 String targetMethodName;
469 if (expect) { 472 if (expect) {
470 targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType); 473 targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType);
471 } else { 474 } else {
472 targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType); 475 targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType);
473 } 476 }
474 startCallTypeSystemMethod(getContext(), builder, typeSystem, targetMethodName); 477 startCallTypeSystemMethod(builder, typeSystem, targetMethodName);
475 builder.tree(value); 478 builder.tree(value);
476 builder.end().end(); 479 builder.end().end();
477 return builder.getRoot(); 480 return builder.getRoot();
478 } 481 }
479 482
480 protected CodeTree createExpectType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, CodeTree expression) { 483 private static CodeTree createExpectType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, CodeTree expression) {
481 return createCastType(typeSystem, sourceType, targetType, true, expression); 484 return createCastType(typeSystem, sourceType, targetType, true, expression);
482 } 485 }
483 486
484 public CodeTree createDeoptimize(CodeTreeBuilder parent) { 487 private CodeTree createDeoptimize(CodeTreeBuilder parent) {
485 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 488 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
486 builder.startStatement(); 489 builder.startStatement();
487 builder.startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end(); 490 builder.startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end();
488 builder.end(); 491 builder.end();
489 return builder.getRoot(); 492 return builder.getRoot();
492 private class NodeFactoryFactory extends ClassElementFactory<NodeData> { 495 private class NodeFactoryFactory extends ClassElementFactory<NodeData> {
493 496
494 private final Map<NodeData, List<TypeElement>> childTypes; 497 private final Map<NodeData, List<TypeElement>> childTypes;
495 private CodeTypeElement generatedNode; 498 private CodeTypeElement generatedNode;
496 499
497 public NodeFactoryFactory(ProcessorContext context, Map<NodeData, List<TypeElement>> childElements) { 500 public NodeFactoryFactory(Map<NodeData, List<TypeElement>> childElements) {
498 super(context);
499 this.childTypes = childElements; 501 this.childTypes = childElements;
500 } 502 }
501 503
502 @Override 504 @Override
503 protected CodeTypeElement create(NodeData node) { 505 protected CodeTypeElement create(NodeData node) {
504 Modifier visibility = Utils.getVisibility(node.getTemplateType().getModifiers()); 506 Modifier visibility = Utils.getVisibility(node.getTemplateType().getModifiers());
507
505 CodeTypeElement clazz = createClass(node, modifiers(), factoryClassName(node), null, false); 508 CodeTypeElement clazz = createClass(node, modifiers(), factoryClassName(node), null, false);
506 if (visibility != null) { 509 if (visibility != null) {
507 clazz.getModifiers().add(visibility); 510 clazz.getModifiers().add(visibility);
508 } 511 }
509 clazz.getModifiers().add(Modifier.FINAL); 512 clazz.getModifiers().add(Modifier.FINAL);
510 clazz.add(createConstructorUsingFields(modifiers(PRIVATE), clazz));
511 return clazz; 513 return clazz;
512 } 514 }
513 515
514 @Override 516 @Override
515 protected void createChildren(NodeData node) { 517 protected void createChildren(NodeData node) {
516 CodeTypeElement clazz = getElement(); 518 CodeTypeElement clazz = getElement();
517 519
518 Modifier createVisibility = Utils.getVisibility(clazz.getModifiers()); 520 Modifier createVisibility = Utils.getVisibility(clazz.getModifiers());
519 521
520 CodeTypeElement polymorphicNode = null;
521 if (node.needsFactory()) { 522 if (node.needsFactory()) {
522 NodeBaseFactory factory = new NodeBaseFactory(context); 523 NodeBaseFactory factory = new NodeBaseFactory();
523 add(factory, node.getGenericSpecialization() == null ? node.getSpecializations().get(0) : node.getGenericSpecialization()); 524 add(factory, node.getGenericSpecialization() == null ? node.getSpecializations().get(0) : node.getGenericSpecialization());
524 generatedNode = factory.getElement(); 525 generatedNode = factory.getElement();
525 526
526 if (node.needsRewrites(context)) {
527 clazz.add(createCreateGenericMethod(node, createVisibility));
528 }
529
530 createFactoryMethods(node, clazz, createVisibility); 527 createFactoryMethods(node, clazz, createVisibility);
531 528
532 for (SpecializationData specialization : node.getSpecializations()) { 529 for (SpecializationData specialization : node.getSpecializations()) {
533 if (!specialization.isReachable()) { 530 if (!specialization.isReachable() || specialization.isGeneric()) {
534 continue; 531 continue;
535 } 532 }
536 533
537 if (specialization.isPolymorphic() && node.isPolymorphic()) { 534 if (specialization.isPolymorphic() && node.isPolymorphic(context)) {
538 PolymorphicNodeFactory polymorphicFactory = new PolymorphicNodeFactory(getContext(), generatedNode); 535 PolymorphicNodeFactory polymorphicFactory = new PolymorphicNodeFactory(generatedNode);
539 add(polymorphicFactory, specialization); 536 add(polymorphicFactory, specialization);
540 polymorphicNode = polymorphicFactory.getElement();
541 continue; 537 continue;
542 } 538 }
543 539
544 add(new SpecializedNodeFactory(context, generatedNode), specialization); 540 add(new SpecializedNodeFactory(generatedNode), specialization);
545 } 541 }
546 542
547 TypeMirror nodeFactory = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(NodeFactory.class)), node.getNodeType()); 543 TypeMirror nodeFactory = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getTruffleTypes().getNodeFactoryBase()), node.getNodeType());
548 clazz.getImplements().add(nodeFactory); 544 clazz.setSuperClass(nodeFactory);
545 clazz.add(createNodeFactoryConstructor(node));
549 clazz.add(createCreateNodeMethod(node)); 546 clazz.add(createCreateNodeMethod(node));
550 clazz.add(createGetNodeClassMethod(node)); 547 // clazz.add(createGetNodeClassMethod(node));
551 clazz.add(createGetNodeSignaturesMethod()); 548 // clazz.add(createGetNodeSignaturesMethod());
552 clazz.add(createGetChildrenSignatureMethod(node)); 549 // clazz.add(createGetChildrenSignatureMethod(node));
553 clazz.add(createGetInstanceMethod(node, createVisibility)); 550 clazz.add(createGetInstanceMethod(node, createVisibility));
554 clazz.add(createInstanceConstant(node, clazz.asType())); 551 clazz.add(createInstanceConstant(node, clazz.asType()));
555 }
556
557 if (polymorphicNode != null) {
558 patchParameterType(clazz, UPDATE_TYPES_NAME, generatedNode.asType(), polymorphicNode.asType());
559 } 552 }
560 553
561 for (NodeData childNode : childTypes.keySet()) { 554 for (NodeData childNode : childTypes.keySet()) {
562 if (childNode.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { 555 if (childNode.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) {
563 continue; 556 continue;
582 clazz.add(createGetFactories(node)); 575 clazz.add(createGetFactories(node));
583 } 576 }
584 577
585 } 578 }
586 579
587 private void patchParameterType(CodeTypeElement enclosingClass, String methodName, TypeMirror originalType, TypeMirror newType) { 580 private Element createNodeFactoryConstructor(NodeData node) {
588 for (TypeElement enclosedType : ElementFilter.typesIn(enclosingClass.getEnclosedElements())) { 581 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), null, factoryClassName(node));
589 CodeTypeElement type = (CodeTypeElement) enclosedType;
590 ExecutableElement method = type.getMethod(methodName);
591 for (VariableElement v : method.getParameters()) {
592 CodeVariableElement var = (CodeVariableElement) v;
593 if (Utils.typeEquals(var.getType(), originalType)) {
594 var.setType(newType);
595 }
596 }
597 }
598 }
599
600 private CodeExecutableElement createGetNodeClassMethod(NodeData node) {
601 TypeMirror returnType = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(Class.class)), node.getNodeType());
602 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeClass");
603 CodeTreeBuilder builder = method.createBuilder(); 582 CodeTreeBuilder builder = method.createBuilder();
604 builder.startReturn().typeLiteral(node.getNodeType()).end(); 583 builder.startStatement();
605 return method; 584 builder.startCall("super");
606 } 585
607 586 // node type
608 private CodeExecutableElement createGetNodeSignaturesMethod() { 587 builder.typeLiteral(node.getNodeType());
609 TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class)); 588
610 TypeMirror classType = getContext().getType(Class.class); 589 // execution signature
611 TypeMirror returnType = Utils.getDeclaredType(listType, Utils.getDeclaredType(listType, classType)); 590 builder.startGroup();
612 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeSignatures"); 591 if (node.getChildExecutions().isEmpty()) {
613 CodeTreeBuilder builder = method.createBuilder(); 592 builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY);
614 builder.startReturn(); 593 } else {
615 builder.startStaticCall(getContext().getType(Arrays.class), "asList"); 594 builder.startNewArray(new ArrayCodeTypeMirror(context.getType(Class.class)), null);
595 for (NodeExecutionData execution : node.getChildExecutions()) {
596 builder.typeLiteral(execution.getNodeType());
597 }
598 builder.end();
599 }
600 builder.end();
601
602 // node signatures
603 builder.startGroup();
604 builder.startNewArray(new ArrayCodeTypeMirror(new ArrayCodeTypeMirror(context.getType(Class.class))), null);
616 List<ExecutableElement> constructors = findUserConstructors(generatedNode.asType()); 605 List<ExecutableElement> constructors = findUserConstructors(generatedNode.asType());
617 for (ExecutableElement constructor : constructors) { 606 for (ExecutableElement constructor : constructors) {
618 builder.tree(createAsList(builder, Utils.asTypeMirrors(constructor.getParameters()), classType)); 607 builder.startGroup();
608 if (constructor.getParameters().isEmpty()) {
609 builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY);
610 } else {
611 builder.startNewArray(new ArrayCodeTypeMirror(context.getType(Class.class)), null);
612 for (VariableElement var : constructor.getParameters()) {
613 builder.typeLiteral(var.asType());
614 }
615 builder.end();
616 }
617 builder.end();
619 } 618 }
620 builder.end(); 619 builder.end();
621 builder.end(); 620 builder.end();
621
622 builder.end().end().end();
622 return method; 623 return method;
623 }
624
625 private CodeExecutableElement createGetChildrenSignatureMethod(NodeData node) {
626 Types types = getContext().getEnvironment().getTypeUtils();
627 TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class));
628 TypeMirror classType = getContext().getType(Class.class);
629 TypeMirror nodeType = getContext().getTruffleTypes().getNode();
630 TypeMirror wildcardNodeType = types.getWildcardType(nodeType, null);
631 classType = Utils.getDeclaredType(Utils.fromTypeMirror(classType), wildcardNodeType);
632 TypeMirror returnType = Utils.getDeclaredType(listType, classType);
633
634 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getExecutionSignature");
635 CodeTreeBuilder builder = method.createBuilder();
636
637 List<TypeMirror> signatureTypes = new ArrayList<>();
638 assert !node.getSpecializations().isEmpty();
639 SpecializationData data = node.getSpecializations().get(0);
640
641 for (ActualParameter parameter : data.getSignatureParameters()) {
642 signatureTypes.add(parameter.getSpecification().getExecution().getNodeType());
643 }
644
645 builder.startReturn().tree(createAsList(builder, signatureTypes, classType)).end();
646 return method;
647 }
648
649 private CodeTree createAsList(CodeTreeBuilder parent, List<TypeMirror> types, TypeMirror elementClass) {
650 CodeTreeBuilder builder = parent.create();
651 builder.startGroup();
652 builder.type(getContext().getType(Arrays.class));
653 builder.string(".<").type(elementClass).string(">");
654 builder.startCall("asList");
655 for (TypeMirror typeMirror : types) {
656 builder.typeLiteral(typeMirror);
657 }
658 builder.end().end();
659 return builder.getRoot();
660 } 624 }
661 625
662 private CodeExecutableElement createCreateNodeMethod(NodeData node) { 626 private CodeExecutableElement createCreateNodeMethod(NodeData node) {
663 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNode"); 627 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNode");
664 CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Object.class), "arguments"); 628 CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Object.class), "arguments");
834 CodeTreeBuilder body = method.createBuilder(); 798 CodeTreeBuilder body = method.createBuilder();
835 body.startReturn(); 799 body.startReturn();
836 if (node.getSpecializations().isEmpty()) { 800 if (node.getSpecializations().isEmpty()) {
837 body.nullLiteral(); 801 body.nullLiteral();
838 } else { 802 } else {
839 body.startCall(nodeSpecializationClassName(node.getSpecializations().get(0)), CREATE_SPECIALIZATION_NAME); 803 body.startCall(nodeSpecializationClassName(node.getSpecializations().get(0)), FACTORY_METHOD_NAME);
840 for (VariableElement var : method.getParameters()) { 804 for (VariableElement var : method.getParameters()) {
841 body.string(var.getSimpleName().toString()); 805 body.string(var.getSimpleName().toString());
842 } 806 }
843 body.end(); 807 body.end();
844 } 808 }
845 body.end(); 809 body.end();
846 return method; 810 return method;
847 } 811 }
848 812
849 private CodeExecutableElement createCreateGenericMethod(NodeData node, Modifier visibility) {
850 CodeExecutableElement method = new CodeExecutableElement(modifiers(), node.getNodeType(), "createGeneric");
851 if (visibility != null) {
852 method.getModifiers().add(visibility);
853 }
854 method.getModifiers().add(Modifier.STATIC);
855 method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME));
856
857 CodeTreeBuilder body = method.createBuilder();
858
859 SpecializationData found = null;
860 List<SpecializationData> specializations = node.getSpecializations();
861 for (int i = 0; i < specializations.size(); i++) {
862 if (specializations.get(i).isReachable()) {
863 found = specializations.get(i);
864 }
865 }
866
867 if (found == null) {
868 body.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end();
869 } else {
870 body.startReturn().startCall(nodeSpecializationClassName(found), CREATE_SPECIALIZATION_NAME).startGroup().string(THIS_NODE_LOCAL_VAR_NAME).end().end().end();
871 }
872 return method;
873 }
874 } 813 }
875 814
876 private class NodeBaseFactory extends ClassElementFactory<SpecializationData> { 815 private class NodeBaseFactory extends ClassElementFactory<SpecializationData> {
877
878 public NodeBaseFactory(ProcessorContext context) {
879 super(context);
880 }
881 816
882 @Override 817 @Override
883 protected CodeTypeElement create(SpecializationData specialization) { 818 protected CodeTypeElement create(SpecializationData specialization) {
884 NodeData node = specialization.getNode(); 819 NodeData node = specialization.getNode();
885 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, ABSTRACT, STATIC), baseClassName(node), node.getNodeType(), false); 820 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, ABSTRACT, STATIC), baseClassName(node), node.getNodeType(), false);
821 clazz.getImplements().add(context.getTruffleTypes().getDslNode());
886 822
887 for (NodeChildData child : node.getChildren()) { 823 for (NodeChildData child : node.getChildren()) {
888 clazz.add(createChildField(child)); 824 clazz.add(createChildField(child));
889 825
890 if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) { 826 if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) {
926 CodeTypeElement clazz = getElement(); 862 CodeTypeElement clazz = getElement();
927 863
928 SpecializationGroup rootGroup = createSpecializationGroups(node); 864 SpecializationGroup rootGroup = createSpecializationGroups(node);
929 865
930 if (node.needsRewrites(context)) { 866 if (node.needsRewrites(context)) {
931 if (node.isPolymorphic()) { 867 if (node.isPolymorphic(context)) {
932 868
933 CodeVariableElement var = new CodeVariableElement(modifiers(PROTECTED), clazz.asType(), "next0"); 869 CodeVariableElement var = new CodeVariableElement(modifiers(PROTECTED), clazz.asType(), "next0");
934 var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation())); 870 var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation()));
935 clazz.add(var); 871 clazz.add(var);
936 872
937 CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getPolymorphicSpecialization()); 873 CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getPolymorphicSpecialization());
938 clazz.add(genericCachedExecute); 874 clazz.add(genericCachedExecute);
939 875
940 getElement().add(createUpdateTypes(clazz.asType()));
941 } 876 }
942 877
943 for (CodeExecutableElement method : createImplicitChildrenAccessors()) { 878 for (CodeExecutableElement method : createImplicitChildrenAccessors()) {
944 clazz.add(method); 879 clazz.add(method);
945 } 880 }
946 clazz.add(createGenericExecuteAndSpecialize(node, rootGroup));
947 clazz.add(createInfoMessage(node)); 881 clazz.add(createInfoMessage(node));
948 } 882 clazz.add(createMonomorphicRewrite());
949 883 clazz.add(createCreateSpecializationMethod(node, rootGroup));
950 if (needsInvokeCopyConstructorMethod()) { 884 }
951 clazz.add(createCopy(clazz.asType(), null)); 885
952 } 886 clazz.add(createAdoptChildren0());
953 887 clazz.add(createGetMetadata0(true));
954 if (node.getGenericSpecialization() != null && node.getGenericSpecialization().isReachable()) { 888 clazz.add(createUpdateTypes0());
955 clazz.add(createGenericExecute(node, rootGroup)); 889 clazz.add(createGetNext());
956 } 890 }
957 } 891
958 892 private Element createGetNext() {
959 protected boolean needsInvokeCopyConstructorMethod() { 893 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), context.getType(Node.class), "getNext0");
960 return getModel().getNode().isPolymorphic(); 894 CodeTreeBuilder builder = method.createBuilder();
961 } 895 NodeData node = getModel().getNode();
962 896
963 protected CodeExecutableElement createCopy(TypeMirror baseType, SpecializationData specialization) { 897 if (node.isPolymorphic(context)) {
964 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), baseType, COPY_WITH_CONSTRUCTOR_NAME); 898 builder.startReturn().string("next0").end();
965 if (specialization == null) {
966 method.getModifiers().add(ABSTRACT);
967 } else { 899 } else {
900 builder.returnNull();
901 }
902
903 return method;
904 }
905
906 protected final CodeExecutableElement createUpdateTypes0() {
907 ArrayType classArray = new ArrayCodeTypeMirror(context.getType(Class.class));
908 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(void.class), "updateTypes0");
909 method.getParameters().add(new CodeVariableElement(classArray, "types"));
910
911 if (getModel().isPolymorphic()) {
968 CodeTreeBuilder builder = method.createBuilder(); 912 CodeTreeBuilder builder = method.createBuilder();
969 builder.startReturn(); 913
970 builder.startNew(getElement().asType()); 914 int index = 0;
971 builder.string("this"); 915 for (NodeExecutionData execution : getModel().getNode().getChildExecutions()) {
972 for (ActualParameter param : getImplicitTypeParameters(specialization)) { 916 String fieldName = polymorphicTypeName(execution);
973 builder.string(implicitTypeName(param)); 917
974 } 918 builder.startStatement();
975 builder.end().end(); 919 builder.string(fieldName).string(" = ").string("types[").string(String.valueOf(index)).string("]");
976 } 920 builder.end();
921 index++;
922 }
923 }
924
925 return method;
926 }
927
928 protected final CodeExecutableElement createGetMetadata0(boolean empty) {
929 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getTruffleTypes().getDslMetadata(), "getMetadata0");
930 if (empty) {
931 method.createBuilder().startReturn().staticReference(context.getTruffleTypes().getDslMetadata(), "NONE").end();
932 } else {
933 method.createBuilder().startReturn().string(METADATA_FIELD_NAME).end();
934 }
935 return method;
936 }
937
938 private CodeExecutableElement createAdoptChildren0() {
939 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), context.getType(void.class), "adoptChildren0");
940 method.getParameters().add(new CodeVariableElement(context.getTruffleTypes().getNode(), "other"));
941 method.getParameters().add(new CodeVariableElement(context.getTruffleTypes().getNode(), "newNext"));
942 NodeData node = getModel().getNode();
943 CodeTreeBuilder builder = method.createBuilder();
944 List<NodeExecutionData> executions = node.getChildExecutions();
945
946 if (executions.size() > 0) {
947 builder.startIf().string("other == null").end().startBlock();
948 for (NodeExecutionData execution : executions) {
949 builder.startStatement().tree(createAccessChild(execution, "this")).string(" = null").end();
950 }
951 builder.end().startElseBlock();
952
953 String access;
954 if (executions.size() > 1) {
955 builder.declaration(baseClassName(node), "otherCast", builder.create().cast(baseClassName(node)).string("other"));
956 access = "otherCast";
957 } else {
958 assert executions.size() == 1;
959 access = "((" + baseClassName(node) + ") other)";
960 }
961 for (NodeExecutionData execution : executions) {
962 builder.startStatement().tree(createAccessChild(execution, "this")).string(" = ").tree(createAccessChild(execution, access)).end();
963 }
964
965 builder.end();
966 }
967
968 if (getModel().getNode().isPolymorphic(context)) {
969 builder.startIf().string("newNext == null").end().startBlock();
970 builder.statement("this.next0 = null");
971 builder.end().startElseBlock();
972 builder.statement("this.next0 = (" + baseClassName(getModel().getNode()) + ") newNext");
973 builder.end();
974 }
975
977 return method; 976 return method;
978 } 977 }
979 978
980 private List<CodeExecutableElement> createImplicitChildrenAccessors() { 979 private List<CodeExecutableElement> createImplicitChildrenAccessors() {
981 NodeData node = getModel().getNode(); 980 NodeData node = getModel().getNode();
1033 builder.staticReference(getContext().getTruffleTypes().getTruffleOptions(), name); 1032 builder.staticReference(getContext().getTruffleTypes().getTruffleOptions(), name);
1034 return builder.getRoot(); 1033 return builder.getRoot();
1035 } 1034 }
1036 1035
1037 private Element createInfoMessage(NodeData node) { 1036 private Element createInfoMessage(NodeData node) {
1038 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), getContext().getType(String.class), "createInfo0"); 1037 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), getContext().getType(String.class), CREATE_INFO);
1039 method.addParameter(new CodeVariableElement(getContext().getType(String.class), "message")); 1038 method.addParameter(new CodeVariableElement(getContext().getType(String.class), "message"));
1040 addInternalValueParameters(method, node.getGenericSpecialization(), false, false); 1039 addInternalValueParameters(method, node.getGenericSpecialization(), false, false);
1041 1040
1042 CodeTreeBuilder builder = method.createBuilder(); 1041 CodeTreeBuilder builder = method.createBuilder();
1043 1042
1089 1088
1090 return method; 1089 return method;
1091 } 1090 }
1092 1091
1093 private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph) { 1092 private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph) {
1094 CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), EXECUTE_POLYMORPHIC_NAME); 1093 CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), EXECUTE_CHAINED);
1095 addInternalValueParameters(cachedExecute, polymorph, true, false); 1094 addInternalValueParameters(cachedExecute, polymorph, true, false);
1096 1095
1097 ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0); 1096 ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0);
1098 boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext()); 1097 boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext());
1099 if (sourceThrowsUnexpected && sourceExecutableType.getType().equals(node.getGenericSpecialization().getReturnType().getTypeSystemType())) { 1098 if (sourceThrowsUnexpected && sourceExecutableType.getType().equals(node.getGenericSpecialization().getReturnType().getTypeSystemType())) {
1118 sourceSectionConstructor = constructor; 1117 sourceSectionConstructor = constructor;
1119 } 1118 }
1120 } 1119 }
1121 } 1120 }
1122 if (node.needsRewrites(getContext())) { 1121 if (node.needsRewrites(getContext())) {
1123 clazz.add(createCopyConstructor(clazz, findCopyConstructor(node.getNodeType()), sourceSectionConstructor)); 1122 ExecutableElement copyConstructor = findCopyConstructor(node.getNodeType());
1123 clazz.add(createCopyConstructor(clazz, copyConstructor, sourceSectionConstructor));
1124 } 1124 }
1125 } 1125 }
1126 1126
1127 private CodeExecutableElement createUserConstructor(CodeTypeElement type, ExecutableElement superConstructor) { 1127 private CodeExecutableElement createUserConstructor(CodeTypeElement type, ExecutableElement superConstructor) {
1128 CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString()); 1128 CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
1143 } 1143 }
1144 builder.end().end(); 1144 builder.end().end();
1145 } 1145 }
1146 1146
1147 for (VariableElement var : type.getFields()) { 1147 for (VariableElement var : type.getFields()) {
1148 if (var.getModifiers().contains(STATIC)) {
1149 continue;
1150 }
1148 NodeChildData child = node.findChild(var.getSimpleName().toString()); 1151 NodeChildData child = node.findChild(var.getSimpleName().toString());
1149 1152
1150 if (child != null) { 1153 if (child != null) {
1151 method.getParameters().add(new CodeVariableElement(child.getOriginalType(), child.getName())); 1154 method.getParameters().add(new CodeVariableElement(child.getOriginalType(), child.getName()));
1152 } else { 1155 } else {
1185 } else if (sourceSectionConstructor != null) { 1188 } else if (sourceSectionConstructor != null) {
1186 builder.startStatement().startSuperCall().string("copy.getSourceSection()").end().end(); 1189 builder.startStatement().startSuperCall().string("copy.getSourceSection()").end().end();
1187 } 1190 }
1188 1191
1189 for (VariableElement var : type.getFields()) { 1192 for (VariableElement var : type.getFields()) {
1190 builder.startStatement(); 1193 if (var.getModifiers().contains(STATIC) || !var.getModifiers().contains(FINAL)) {
1194 continue;
1195 }
1191 final String varName = var.getSimpleName().toString(); 1196 final String varName = var.getSimpleName().toString();
1192 final TypeMirror varType = var.asType(); 1197 final TypeMirror varType = var.asType();
1193 1198 if (Utils.isAssignable(varType, getContext().getTruffleTypes().getNodeArray())) {
1194 String copyAccess = "copy." + varName; 1199 CodeTree size = builder.create().string("copy.", varName, ".length").getRoot();
1195 if (Utils.isAssignable(getContext(), varType, getContext().getTruffleTypes().getNodeArray())) { 1200 builder.startStatement().string("this.").string(varName).string(" = ").startNewArray((ArrayType) varType, size).end().end();
1196 copyAccess += ".clone()"; 1201 } else {
1197 } 1202 builder.startStatement().string("this.", varName, " = copy.", varName).end();
1198 CodeTree init = CodeTreeBuilder.singleString(copyAccess); 1203 }
1199 builder.startStatement().string("this.").string(varName).string(" = ").tree(init).end();
1200 } 1204 }
1201 1205
1202 return method; 1206 return method;
1203 } 1207 }
1204 1208
1223 1227
1224 var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType)); 1228 var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType));
1225 return var; 1229 return var;
1226 } 1230 }
1227 1231
1228 private CodeExecutableElement createGenericExecuteAndSpecialize(final NodeData node, SpecializationGroup rootGroup) {
1229 TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType();
1230 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), genericReturnType, EXECUTE_SPECIALIZE_NAME);
1231 method.addParameter(new CodeVariableElement(getContext().getType(int.class), "minimumState"));
1232 addInternalValueParameters(method, node.getGenericSpecialization(), true, false);
1233 method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason"));
1234
1235 CodeTreeBuilder builder = method.createBuilder();
1236 builder.startStatement();
1237 builder.startStaticCall(getContext().getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end();
1238 builder.end();
1239
1240 String currentNode = "this";
1241 for (SpecializationData specialization : node.getSpecializations()) {
1242 if (!specialization.getExceptions().isEmpty()) {
1243 currentNode = "current";
1244 builder.declaration(baseClassName(node), currentNode, "this");
1245 break;
1246 }
1247 }
1248
1249 builder.startStatement().string("String message = ").startCall("createInfo0").string("reason");
1250 addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, false, null);
1251 builder.end().end();
1252
1253 final String currentNodeVar = currentNode;
1254 builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), rootGroup, true, new CodeBlock<SpecializationData>() {
1255
1256 public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
1257 return createGenericInvokeAndSpecialize(b, node.getGenericSpecialization(), current, currentNodeVar);
1258 }
1259 }, null, false, true, false));
1260
1261 boolean firstUnreachable = true;
1262 for (SpecializationData current : node.getSpecializations()) {
1263 if (current.isReachable()) {
1264 continue;
1265 }
1266 if (firstUnreachable) {
1267 emitEncounteredSynthetic(builder, current);
1268 firstUnreachable = false;
1269 }
1270 }
1271 emitUnreachableSpecializations(builder, node);
1272
1273 return method;
1274 }
1275
1276 private SpecializationGroup createSpecializationGroups(final NodeData node) { 1232 private SpecializationGroup createSpecializationGroups(final NodeData node) {
1277 List<SpecializationData> specializations = node.getSpecializations(); 1233 List<SpecializationData> specializations = node.getSpecializations();
1278 List<SpecializationData> filteredSpecializations = new ArrayList<>(); 1234 List<SpecializationData> filteredSpecializations = new ArrayList<>();
1279 for (SpecializationData current : specializations) { 1235 for (SpecializationData current : specializations) {
1280 if (current.isUninitialized() || current.isPolymorphic() || !current.isReachable()) { 1236 if (current.isUninitialized() || current.isPolymorphic() || !current.isReachable()) {
1284 } 1240 }
1285 1241
1286 return SpecializationGroup.create(filteredSpecializations); 1242 return SpecializationGroup.create(filteredSpecializations);
1287 } 1243 }
1288 1244
1289 private CodeExecutableElement createGenericExecute(NodeData node, SpecializationGroup group) { 1245 protected final CodeExecutableElement createExecuteUninitialized() {
1290 TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType(); 1246 NodeData node = getModel().getNode();
1291 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), genericReturnType, EXECUTE_GENERIC_NAME); 1247 SpecializationData generic = node.getGenericSpecialization();
1292 1248 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), generic.getReturnType().getType(), EXECUTE_UNINITIALIZED);
1249 addInternalValueParameters(method, generic, true, false);
1250 CodeTreeBuilder builder = method.createBuilder();
1251
1252 CodeTreeBuilder createSpecializationCall = builder.create();
1253 createSpecializationCall.startCall(SPECIALIZE);
1254 addInternalValueParameterNames(createSpecializationCall, generic, generic, null, node.needsFrame(getContext()), null);
1255 createSpecializationCall.end();
1256 builder.declaration(baseClassName(node), "newNode", createSpecializationCall);
1257
1258 if (generic.isReachable()) {
1259 builder.startIf().string("newNode == null").end().startBlock();
1260
1261 builder.startIf().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "inInterpreter").end().end().startBlock();
1262 builder.statement("containsFallback = true");
1263 builder.end();
1264 builder.tree(createGenericInvoke(builder, generic, generic));
1265 builder.end();
1266 builder.startElseBlock();
1267 builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
1268 }
1269
1270 builder.startReturn();
1271 builder.startStaticCall(context.getTruffleTypes().getDslShare(), "rewriteUninitialized").string("this").string("newNode").end();
1272 builder.string(".").startCall(EXECUTE_CHAINED);
1273 addInternalValueParameterNames(builder, generic, generic, null, true, null);
1274 builder.end();
1275 builder.end();
1276
1277 if (generic.isReachable()) {
1278 builder.end();
1279 }
1280
1281 return method;
1282 }
1283
1284 private CodeTree createInfoCall(CodeTreeBuilder parent, SpecializationData specialization, String reason) {
1285 CodeTreeBuilder builder = parent.create();
1286 builder.startCall(CREATE_INFO).string(reason);
1287 addInternalValueParameterNames(builder, specialization, specialization, null, false, null);
1288 builder.end();
1289 return builder.getRoot();
1290 }
1291
1292 private CodeExecutableElement createMonomorphicRewrite() {
1293 NodeData node = getModel().getNode();
1294
1295 SpecializationData generic = node.getGenericSpecialization();
1296 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), generic.getReturnType().getType(), REWRITE);
1297 addInternalValueParameters(method, generic, true, false);
1298 method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason"));
1299
1300 CodeTreeBuilder builder = method.createBuilder();
1301
1302 builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end().end();
1303 String baseClassName = baseClassName(getModel().getNode());
1304 CodeTreeBuilder createSpecializationCall = builder.create();
1305 createSpecializationCall.startCall(SPECIALIZE);
1306 addInternalValueParameterNames(createSpecializationCall, generic, generic, null, node.needsFrame(getContext()), null);
1307 createSpecializationCall.end();
1308 builder.declaration(baseClassName, "newNode", createSpecializationCall);
1309
1310 builder.startIf().string("newNode == null").end().startBlock();
1311 builder.startStatement();
1312 String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization());
1313 builder.string("newNode = ").startNew(uninitializedName).string("this").end();
1314 builder.end();
1315 if (node.isFallbackReachable()) {
1316 builder.startStatement().string("((", uninitializedName, ") newNode).containsFallback = true").end();
1317 }
1318 builder.end();
1319
1320 builder.startStatement();
1321 builder.type(getContext().getType(String.class)).string(" message = ").tree(createInfoCall(builder, generic, "reason"));
1322 builder.end();
1323
1324 builder.declaration(baseClassName, "returnNode",
1325 builder.create().startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_REWRITE).string("this").string("newNode").string("message").end().getRoot());
1326 builder.startIf().string("returnNode == null").end().startBlock();
1327 builder.tree(createRewritePolymorphic(builder, node, "this"));
1328 builder.end();
1329
1330 builder.startReturn();
1331 builder.startCall("returnNode", EXECUTE_CHAINED);
1332 addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, null);
1333 builder.end();
1334 builder.end();
1335
1336 return method;
1337 }
1338
1339 private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node, String currentNode) {
1340 String polyClassName = nodePolymorphicClassName(node);
1341 CodeTreeBuilder builder = parent.create();
1342
1343 builder.startStatement().string("returnNode = ");
1344 builder.startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_REWRITE_TO_POLYMORHPIC);
1345 builder.string("this");
1346 builder.tree(builder.create().startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string(currentNode).end().getRoot());
1347 builder.tree(builder.create().startNew(polyClassName).string(currentNode).end().getRoot());
1348 builder.startGroup().cast(baseClassName(node)).startCall("copy").end().end();
1349 builder.string("newNode");
1350 builder.string("message");
1351 builder.end();
1352 builder.end();
1353
1354 return builder.getRoot();
1355 }
1356
1357 private CodeExecutableElement createCreateSpecializationMethod(NodeData node, SpecializationGroup group) {
1358 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), new GeneratedTypeMirror(Utils.getPackageName(node.getTemplateType()), baseClassName(node)),
1359 SPECIALIZE);
1293 if (!node.needsFrame(getContext())) { 1360 if (!node.needsFrame(getContext())) {
1294 method.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getSlowPath())); 1361 method.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getSlowPath()));
1295 } 1362 }
1363
1296 addInternalValueParameters(method, node.getGenericSpecialization(), node.needsFrame(getContext()), false); 1364 addInternalValueParameters(method, node.getGenericSpecialization(), node.needsFrame(getContext()), false);
1297 final CodeTreeBuilder builder = method.createBuilder(); 1365 final CodeTreeBuilder builder = method.createBuilder();
1298 1366 builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), group, new CodeBlock<SpecializationData>() {
1299 builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), group, false, new CodeBlock<SpecializationData>() {
1300 1367
1301 public CodeTree create(CodeTreeBuilder b, SpecializationData current) { 1368 public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
1302 return createGenericInvoke(builder, current.getNode().getGenericSpecialization(), current); 1369 return createCreateSpecializationMethodBody0(builder, current);
1303 } 1370 }
1304 }, null, false, true, false)); 1371 }, null, false, true, false, true));
1305 1372
1306 emitUnreachableSpecializations(builder, node); 1373 emitUnreachableSpecializations(builder, node);
1307 1374
1308 return method; 1375 return method;
1376 }
1377
1378 protected CodeTree createCreateSpecializationMethodBody0(CodeTreeBuilder parent, SpecializationData current) {
1379 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1380 if (current.isGeneric()) {
1381 builder.startReturn().nullLiteral().end();
1382 } else {
1383 String className = nodeSpecializationClassName(current);
1384 if (!current.getExcludedBy().isEmpty()) {
1385 builder.startIf().string("!").startStaticCall(context.getTruffleTypes().getDslShare(), "isExcluded");
1386 builder.string("this").string(nodeSpecializationClassName(current), ".", METADATA_FIELD_NAME).end().end();
1387 builder.startBlock();
1388 }
1389
1390 if (current.getNode().getGenericSpecialization().isReachable()) {
1391 builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
1392 }
1393 builder.startReturn();
1394 builder.cast(baseClassName(getModel().getNode()));
1395 builder.startGroup().startCall(className, FACTORY_METHOD_NAME).string("this");
1396 for (ActualParameter param : current.getSignatureParameters()) {
1397 NodeChildData child = param.getSpecification().getExecution().getChild();
1398 List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
1399 if (types.size() > 1) {
1400 builder.string(implicitTypeName(param));
1401 }
1402 }
1403 builder.end().end();
1404 builder.end();
1405
1406 if (!current.getExcludedBy().isEmpty()) {
1407 builder.end();
1408 }
1409 }
1410 return builder.getRoot();
1411
1309 } 1412 }
1310 1413
1311 private void emitUnreachableSpecializations(final CodeTreeBuilder builder, NodeData node) { 1414 private void emitUnreachableSpecializations(final CodeTreeBuilder builder, NodeData node) {
1312 for (SpecializationData current : node.getSpecializations()) { 1415 for (SpecializationData current : node.getSpecializations()) {
1313 if (current.isReachable()) { 1416 if (current.isReachable()) {
1315 } 1418 }
1316 builder.string("// unreachable ").string(current.getId()).newLine(); 1419 builder.string("// unreachable ").string(current.getId()).newLine();
1317 } 1420 }
1318 } 1421 }
1319 1422
1320 protected CodeTree createExecuteTree(CodeTreeBuilder outerParent, final SpecializationData source, final SpecializationGroup group, final boolean checkMinimumState, 1423 protected CodeTree createExecuteTree(CodeTreeBuilder outerParent, final SpecializationData source, final SpecializationGroup group, final CodeBlock<SpecializationData> guardedblock,
1321 final CodeBlock<SpecializationData> guardedblock, final CodeTree elseBlock, boolean forceElse, final boolean emitAssumptions, final boolean typedCasts) { 1424 final CodeTree elseBlock, boolean forceElse, final boolean emitAssumptions, final boolean typedCasts, final boolean castForGuardsOnly) {
1322 return guard(outerParent, source, group, checkMinimumState, new CodeBlock<Integer>() { 1425 return guard(outerParent, source, group, new CodeBlock<Integer>() {
1323 1426
1324 public CodeTree create(CodeTreeBuilder parent, Integer ifCount) { 1427 public CodeTree create(CodeTreeBuilder parent, Integer ifCount) {
1325 CodeTreeBuilder builder = parent.create(); 1428 CodeTreeBuilder builder = parent.create();
1326 1429
1327 if (group.getSpecialization() != null) { 1430 if (group.getSpecialization() != null) {
1329 1432
1330 assert group.getChildren().isEmpty() : "missed a specialization"; 1433 assert group.getChildren().isEmpty() : "missed a specialization";
1331 1434
1332 } else { 1435 } else {
1333 for (SpecializationGroup childGroup : group.getChildren()) { 1436 for (SpecializationGroup childGroup : group.getChildren()) {
1334 builder.tree(createExecuteTree(builder, source, childGroup, checkMinimumState, guardedblock, null, false, emitAssumptions, typedCasts)); 1437 builder.tree(createExecuteTree(builder, source, childGroup, guardedblock, null, false, emitAssumptions, typedCasts, castForGuardsOnly));
1335 } 1438 }
1336 } 1439 }
1337 1440
1338 return builder.getRoot(); 1441 return builder.getRoot();
1339 } 1442 }
1340 }, elseBlock, forceElse, emitAssumptions, typedCasts); 1443 }, elseBlock, forceElse, emitAssumptions, typedCasts, castForGuardsOnly);
1341 } 1444 }
1342 1445
1343 private CodeTree guard(CodeTreeBuilder parent, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, CodeBlock<Integer> bodyBlock, CodeTree elseBlock, 1446 private CodeTree guard(CodeTreeBuilder parent, SpecializationData source, SpecializationGroup group, CodeBlock<Integer> bodyBlock, CodeTree elseBlock, boolean forceElse,
1344 boolean forceElse, boolean emitAssumptions, boolean typedCasts) { 1447 boolean emitAssumptions, boolean typedCasts, boolean castForGuardsOnly) {
1345 CodeTreeBuilder builder = parent.create(); 1448 CodeTreeBuilder builder = parent.create();
1346 1449
1347 int ifCount = emitGuards(builder, source, group, checkMinimumState, emitAssumptions, typedCasts); 1450 int ifCount = emitGuards(builder, source, group, emitAssumptions, typedCasts, castForGuardsOnly);
1348 1451
1349 if (isReachableGroup(group, ifCount, checkMinimumState)) { 1452 if (isReachableGroup(group, ifCount)) {
1350 builder.tree(bodyBlock.create(builder, ifCount)); 1453 builder.tree(bodyBlock.create(builder, ifCount));
1351 } 1454 }
1352 1455
1353 builder.end(ifCount); 1456 builder.end(ifCount);
1354 1457
1359 } 1462 }
1360 1463
1361 return builder.getRoot(); 1464 return builder.getRoot();
1362 } 1465 }
1363 1466
1364 private boolean isReachableGroup(SpecializationGroup group, int ifCount, boolean checkMinimumState) { 1467 private boolean isReachableGroup(SpecializationGroup group, int ifCount) {
1365 if (ifCount != 0) { 1468 if (ifCount != 0) {
1366 return true; 1469 return true;
1367 } 1470 }
1368 SpecializationGroup previous = group.getPreviousGroup(); 1471 SpecializationGroup previous = group.getPreviousGroup();
1369 if (previous == null || previous.findElseConnectableGuards(checkMinimumState).isEmpty()) { 1472 if (previous == null || previous.findElseConnectableGuards().isEmpty()) {
1370 return true; 1473 return true;
1371 } 1474 }
1372 1475
1373 /* 1476 /*
1374 * Hacky else case. In this case the specialization is not reachable due to previous 1477 * Hacky else case. In this case the specialization is not reachable due to previous
1375 * else branch. This is only true if the minimum state is not checked. 1478 * else branch. This is only true if the minimum state is not checked.
1376 */ 1479 */
1377 if (previous.getGuards().size() == 1 && previous.getTypeGuards().isEmpty() && previous.getAssumptions().isEmpty() && !checkMinimumState && 1480 if (previous.getGuards().size() == 1 && previous.getTypeGuards().isEmpty() && previous.getAssumptions().isEmpty() &&
1378 (previous.getParent() == null || previous.getMaxSpecializationIndex() != previous.getParent().getMaxSpecializationIndex())) { 1481 (previous.getParent() == null || previous.getMaxSpecializationIndex() != previous.getParent().getMaxSpecializationIndex())) {
1379 return false; 1482 return false;
1380 } 1483 }
1381 1484
1382 return true; 1485 return true;
1383 } 1486 }
1384 1487
1385 private int emitGuards(CodeTreeBuilder builder, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, boolean emitAssumptions, boolean typedCasts) { 1488 private int emitGuards(CodeTreeBuilder builder, SpecializationData source, SpecializationGroup group, boolean emitAssumptions, boolean typedCasts, boolean castForGuardsOnly) {
1386 NodeData node = source.getNode(); 1489 NodeData node = source.getNode();
1387 1490
1388 CodeTreeBuilder guardsBuilder = builder.create(); 1491 CodeTreeBuilder guardsBuilder = builder.create();
1389 CodeTreeBuilder castBuilder = builder.create(); 1492 CodeTreeBuilder castBuilder = builder.create();
1390 CodeTreeBuilder guardsCastBuilder = builder.create(); 1493 CodeTreeBuilder guardsCastBuilder = builder.create();
1391 1494
1392 String guardsAnd = ""; 1495 String guardsAnd = "";
1393 String guardsCastAnd = ""; 1496 String guardsCastAnd = "";
1394
1395 boolean minimumState = checkMinimumState;
1396 if (minimumState) {
1397 int groupMaxIndex = group.getUncheckedSpecializationIndex();
1398
1399 if (groupMaxIndex > -1) {
1400 guardsBuilder.string(guardsAnd);
1401 guardsBuilder.string("minimumState < " + groupMaxIndex);
1402 guardsAnd = " && ";
1403 }
1404 }
1405 1497
1406 if (emitAssumptions) { 1498 if (emitAssumptions) {
1407 for (String assumption : group.getAssumptions()) { 1499 for (String assumption : group.getAssumptions()) {
1408 guardsBuilder.string(guardsAnd); 1500 guardsBuilder.string(guardsAnd);
1409 guardsBuilder.string("this"); 1501 guardsBuilder.string("this");
1434 guardsBuilder.string(guardsAnd); 1526 guardsBuilder.string(guardsAnd);
1435 guardsBuilder.tree(implicitGuard); 1527 guardsBuilder.tree(implicitGuard);
1436 guardsAnd = " && "; 1528 guardsAnd = " && ";
1437 } 1529 }
1438 1530
1439 CodeTree cast = createCast(castBuilder, execution, valueParam, typeGuard.getType(), checkMinimumState, typedCasts); 1531 CodeTree implicitGetType = null;
1440 if (cast != null) { 1532 if (castForGuardsOnly) {
1441 castBuilder.tree(cast); 1533 implicitGetType = createGetImplicitType(builder, execution, valueParam, typeGuard.getType());
1442 } 1534 }
1443 } 1535
1444 List<GuardData> elseGuards = group.findElseConnectableGuards(checkMinimumState); 1536 boolean performCast = true;
1445 1537 if (castForGuardsOnly) {
1446 for (GuardData guard : group.getGuards()) { 1538 // if cast for guards we just cast if the type guard is used inside a guard.
1539 performCast = group.isTypeGuardUsedInAnyGuardBelow(context, source, typeGuard);
1540 }
1541
1542 if (performCast) {
1543 CodeTree cast = createCast(castBuilder, execution, valueParam, typeGuard.getType(), typedCasts);
1544 if (cast != null) {
1545 castBuilder.tree(cast);
1546 }
1547 }
1548 if (implicitGetType != null) {
1549 castBuilder.tree(implicitGetType);
1550 }
1551 }
1552 List<GuardExpression> elseGuards = group.findElseConnectableGuards();
1553
1554 for (GuardExpression guard : group.getGuards()) {
1447 if (elseGuards.contains(guard)) { 1555 if (elseGuards.contains(guard)) {
1448 continue; 1556 continue;
1449 } 1557 }
1450 1558
1451 if (needsTypeGuard(source, group, guard)) { 1559 if (needsTypeGuard(source, group, guard)) {
1461 builder.tree(castBuilder.getRoot()); 1569 builder.tree(castBuilder.getRoot());
1462 ifCount = startGuardIf(builder, guardsCastBuilder, ifCount, elseGuards); 1570 ifCount = startGuardIf(builder, guardsCastBuilder, ifCount, elseGuards);
1463 return ifCount; 1571 return ifCount;
1464 } 1572 }
1465 1573
1466 private int startGuardIf(CodeTreeBuilder builder, CodeTreeBuilder conditionBuilder, int ifCount, List<GuardData> elseGuard) { 1574 private int startGuardIf(CodeTreeBuilder builder, CodeTreeBuilder conditionBuilder, int ifCount, List<GuardExpression> elseGuard) {
1467 int newIfCount = ifCount; 1575 int newIfCount = ifCount;
1468 1576
1469 if (!conditionBuilder.isEmpty()) { 1577 if (!conditionBuilder.isEmpty()) {
1470 if (ifCount == 0 && !elseGuard.isEmpty()) { 1578 if (ifCount == 0 && !elseGuard.isEmpty()) {
1471 builder.startElseIf(); 1579 builder.startElseIf();
1480 newIfCount++; 1588 newIfCount++;
1481 } 1589 }
1482 return newIfCount; 1590 return newIfCount;
1483 } 1591 }
1484 1592
1485 private boolean needsTypeGuard(SpecializationData source, SpecializationGroup group, GuardData guard) { 1593 private boolean needsTypeGuard(SpecializationData source, SpecializationGroup group, GuardExpression guard) {
1486 int signatureIndex = 0; 1594 int signatureIndex = 0;
1487 for (ActualParameter parameter : guard.getParameters()) { 1595 for (ActualParameter parameter : guard.getResolvedGuard().getParameters()) {
1488 if (!parameter.getSpecification().isSignature()) { 1596 if (!parameter.getSpecification().isSignature()) {
1489 continue; 1597 continue;
1490 } 1598 }
1491 1599
1492 TypeGuard typeGuard = group.findTypeGuard(signatureIndex); 1600 TypeGuard typeGuard = group.findTypeGuard(signatureIndex);
1496 ActualParameter sourceParameter = source.findParameter(parameter.getLocalName()); 1604 ActualParameter sourceParameter = source.findParameter(parameter.getLocalName());
1497 if (sourceParameter == null) { 1605 if (sourceParameter == null) {
1498 sourceParameter = source.getNode().getGenericSpecialization().findParameter(parameter.getLocalName()); 1606 sourceParameter = source.getNode().getGenericSpecialization().findParameter(parameter.getLocalName());
1499 } 1607 }
1500 1608
1501 if (Utils.needsCastTo(getContext(), sourceParameter.getType(), requiredType.getPrimitiveType())) { 1609 if (Utils.needsCastTo(sourceParameter.getType(), requiredType.getPrimitiveType())) {
1502 return true; 1610 return true;
1503 } 1611 }
1504 } 1612 }
1505 1613
1506 signatureIndex++; 1614 signatureIndex++;
1513 1621
1514 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 1622 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1515 1623
1516 TypeData sourceType = source.getTypeSystemType(); 1624 TypeData sourceType = source.getTypeSystemType();
1517 1625
1518 if (!sourceType.needsCastTo(getContext(), targetType)) { 1626 if (!sourceType.needsCastTo(targetType)) {
1519 return null; 1627 return null;
1520 } 1628 }
1521 1629
1522 builder.startGroup(); 1630 builder.startGroup();
1523 1631
1539 } 1647 }
1540 } else { 1648 } else {
1541 castMethodName = TypeSystemCodeGenerator.isTypeMethodName(targetType); 1649 castMethodName = TypeSystemCodeGenerator.isTypeMethodName(targetType);
1542 } 1650 }
1543 1651
1544 startCallTypeSystemMethod(getContext(), builder, node.getTypeSystem(), castMethodName); 1652 startCallTypeSystemMethod(builder, node.getTypeSystem(), castMethodName);
1545 builder.string(valueName(source)); 1653 builder.string(valueName(source));
1546 if (castTypeName != null) { 1654 if (castTypeName != null) {
1547 builder.string(castTypeName); 1655 builder.string(castTypeName);
1548 } 1656 }
1549 builder.end().end(); // call 1657 builder.end().end(); // call
1556 1664
1557 return builder.getRoot(); 1665 return builder.getRoot();
1558 } 1666 }
1559 1667
1560 // TODO merge redundancies with #createTypeGuard 1668 // TODO merge redundancies with #createTypeGuard
1561 private CodeTree createCast(CodeTreeBuilder parent, NodeExecutionData execution, ActualParameter source, TypeData targetType, boolean checkMinimumState, boolean typedCasts) { 1669 private CodeTree createCast(CodeTreeBuilder parent, NodeExecutionData execution, ActualParameter source, TypeData targetType, boolean typedCasts) {
1562 NodeData node = execution.getChild().getNodeData(); 1670 NodeData node = execution.getChild().getNodeData();
1563 TypeData sourceType = source.getTypeSystemType(); 1671 TypeData sourceType = source.getTypeSystemType();
1564 1672
1565 if (!sourceType.needsCastTo(getContext(), targetType)) { 1673 if (!sourceType.needsCastTo(targetType)) {
1566 return null; 1674 return null;
1567 } 1675 }
1568 1676
1569 CodeTree condition = null; 1677 CodeTree condition = null;
1570 if (execution.isShortCircuit()) { 1678 if (execution.isShortCircuit()) {
1589 args.add(CodeTreeBuilder.singleString(valueName(source))); 1697 args.add(CodeTreeBuilder.singleString(valueName(source)));
1590 if (castTypeName != null) { 1698 if (castTypeName != null) {
1591 args.add(CodeTreeBuilder.singleString(castTypeName)); 1699 args.add(CodeTreeBuilder.singleString(castTypeName));
1592 } 1700 }
1593 1701
1594 CodeTree value = createCallTypeSystemMethod(context, parent, node, castMethodName, args.toArray(new CodeTree[0])); 1702 CodeTree cast = createCallTypeSystemMethod(parent, node, castMethodName, args.toArray(new CodeTree[0]));
1595 1703
1596 CodeTreeBuilder builder = parent.create(); 1704 CodeTreeBuilder builder = parent.create();
1597 builder.tree(createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, value)); 1705 builder.tree(createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, cast));
1598 if (checkMinimumState && types.size() > 1) { 1706
1599 CodeTree castType = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.getImplicitClass(targetType), CodeTreeBuilder.singleString(valueName(source))); 1707 return builder.getRoot();
1708 }
1709
1710 private CodeTree createGetImplicitType(CodeTreeBuilder parent, NodeExecutionData execution, ActualParameter source, TypeData targetType) {
1711 CodeTree condition = null;
1712 if (execution.isShortCircuit()) {
1713 ActualParameter shortCircuit = source.getPreviousParameter();
1714 assert shortCircuit != null;
1715 condition = CodeTreeBuilder.singleString(valueName(shortCircuit));
1716 }
1717
1718 CodeTreeBuilder builder = parent.create();
1719 List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
1720 if (types.size() > 1) {
1721 CodeTree castType = createCallTypeSystemMethod(parent, execution.getChild().getNodeData(), TypeSystemCodeGenerator.getImplicitClass(targetType),
1722 CodeTreeBuilder.singleString(valueName(source)));
1600 builder.tree(createLazyAssignment(builder, implicitTypeName(source), getContext().getType(Class.class), condition, castType)); 1723 builder.tree(createLazyAssignment(builder, implicitTypeName(source), getContext().getType(Class.class), condition, castType));
1601 } 1724 }
1602
1603 return builder.getRoot(); 1725 return builder.getRoot();
1604 } 1726 }
1605 1727
1606 private CodeTree createMethodGuard(CodeTreeBuilder parent, String prefix, SpecializationData source, GuardData guard) { 1728 private CodeTree createMethodGuard(CodeTreeBuilder parent, String prefix, SpecializationData source, GuardExpression guard) {
1607 CodeTreeBuilder builder = parent.create(); 1729 CodeTreeBuilder builder = parent.create();
1608 builder.string(prefix); 1730 builder.string(prefix);
1609 if (guard.isNegated()) { 1731 if (guard.isNegated()) {
1610 builder.string("!"); 1732 builder.string("!");
1611 } 1733 }
1612 builder.tree(createTemplateMethodCall(builder, null, source, guard, null)); 1734 builder.tree(createTemplateMethodCall(builder, null, source, guard.getResolvedGuard(), null));
1613 return builder.getRoot(); 1735 return builder.getRoot();
1614 } 1736 }
1615 1737
1616 protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) { 1738 protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) {
1617 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 1739 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1623 } 1745 }
1624 1746
1625 return encloseThrowsWithFallThrough(current, builder.getRoot()); 1747 return encloseThrowsWithFallThrough(current, builder.getRoot());
1626 } 1748 }
1627 1749
1628 protected CodeTree createGenericInvokeAndSpecialize(CodeTreeBuilder parent, SpecializationData source, SpecializationData current, String currentNodeVar) {
1629 CodeTreeBuilder builder = parent.create();
1630 CodeTreeBuilder prefix = parent.create();
1631
1632 NodeData node = current.getNode();
1633
1634 if (current.isGeneric() && node.isPolymorphic()) {
1635 builder.startIf().string(currentNodeVar).string(".next0 == null && minimumState > 0").end().startBlock();
1636 builder.tree(createRewritePolymorphic(builder, node, currentNodeVar));
1637 builder.end();
1638 builder.startElseBlock();
1639 builder.tree(createRewriteGeneric(builder, source, current, currentNodeVar));
1640 builder.end();
1641 } else {
1642 if (current.getExceptions().isEmpty()) {
1643 builder.tree(createGenericInvoke(builder, source, current, createReplaceCall(builder, current, currentNodeVar, currentNodeVar, null), null));
1644 } else {
1645 builder.startStatement().string(currentNodeVar).string(" = ").tree(createReplaceCall(builder, current, currentNodeVar, currentNodeVar, null)).end();
1646 builder.tree(createGenericInvoke(builder, source, current, null, CodeTreeBuilder.singleString(currentNodeVar)));
1647 }
1648 }
1649 CodeTreeBuilder root = parent.create();
1650 root.tree(prefix.getRoot());
1651 root.tree(encloseThrowsWithFallThrough(current, builder.getRoot()));
1652 return root.getRoot();
1653 }
1654
1655 private CodeTree createRewriteGeneric(CodeTreeBuilder parent, SpecializationData source, SpecializationData current, String currentNode) {
1656 NodeData node = current.getNode();
1657
1658 CodeTreeBuilder builder = parent.create();
1659 builder.declaration(getContext().getTruffleTypes().getNode(), "root", currentNode);
1660 builder.startIf().string(currentNode).string(".next0 != null").end().startBlock();
1661 /*
1662 * Communicates to the caller of executeAndSpecialize that it was rewritten to generic.
1663 * Its important that this is used instead of the currentNode since the caller is this.
1664 * CurrentNode may not be this anymore at this place.
1665 */
1666 builder.statement("this.next0 = null");
1667 builder.tree(createFindRoot(builder, node, false));
1668 builder.end();
1669 builder.end();
1670 builder.tree(createGenericInvoke(builder, source, current, createReplaceCall(builder, current, "root", "(" + baseClassName(node) + ") root", null), null));
1671 return builder.getRoot();
1672 }
1673
1674 protected CodeTree createFindRoot(CodeTreeBuilder parent, NodeData node, boolean countDepth) {
1675 CodeTreeBuilder builder = parent.create();
1676 builder.startDoBlock();
1677 builder.startAssert().string("root != null").string(" : ").doubleQuote("No polymorphic parent node.").end();
1678 builder.startStatement().string("root = ").string("root.getParent()").end();
1679 if (countDepth) {
1680 builder.statement("depth++");
1681 }
1682 builder.end();
1683 builder.startDoWhile();
1684 builder.string("!").startParantheses().instanceOf("root", nodePolymorphicClassName(node)).end();
1685 builder.end();
1686 return builder.getRoot();
1687 }
1688
1689 private CodeTree encloseThrowsWithFallThrough(SpecializationData current, CodeTree tree) { 1750 private CodeTree encloseThrowsWithFallThrough(SpecializationData current, CodeTree tree) {
1690 if (current.getExceptions().isEmpty()) { 1751 if (current.getExceptions().isEmpty()) {
1691 return tree; 1752 return tree;
1692 } 1753 }
1693 CodeTreeBuilder builder = new CodeTreeBuilder(null); 1754 CodeTreeBuilder builder = new CodeTreeBuilder(null);
1694 1755
1695 builder.startTryBlock(); 1756 builder.startTryBlock();
1696 builder.tree(tree); 1757 builder.tree(tree);
1697 for (SpecializationThrowsData exception : current.getExceptions()) { 1758 for (SpecializationThrowsData exception : current.getExceptions()) {
1698 builder.end().startCatchBlock(exception.getJavaClass(), "rewriteEx"); 1759 builder.end().startCatchBlock(exception.getJavaClass(), "rewriteEx");
1699 builder.string("// fall through").newLine(); 1760 builder.tree(createDeoptimize(builder));
1700 } 1761 builder.tree(createCallRewriteMonomorphic(builder, false, current.getNode().getGenericSpecialization().getReturnType().getTypeSystemType(), current, null,
1701 builder.end(); 1762 "Thrown " + Utils.getSimpleName(exception.getJavaClass())));
1702 1763 }
1703 return builder.getRoot();
1704 }
1705
1706 protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current, CodeTree replaceCall, CodeTree replaceVar) {
1707 assert replaceCall == null || replaceVar == null;
1708 CodeTreeBuilder builder = parent.create();
1709 CodeTree replace = replaceVar;
1710 if (replace == null) {
1711 replace = replaceCall;
1712 }
1713 if (current.isGeneric()) {
1714 builder.startReturn().tree(replace).string(".").startCall(EXECUTE_GENERIC_NAME);
1715 addInternalValueParameterNames(builder, source, current, null, current.getNode().needsFrame(getContext()), null);
1716 builder.end().end();
1717 } else if (current.getMethod() == null) {
1718 if (replaceCall != null) {
1719 builder.statement(replaceCall);
1720 }
1721 emitEncounteredSynthetic(builder, current);
1722 } else if (!current.canBeAccessedByInstanceOf(getContext(), source.getNode().getNodeType())) {
1723 if (replaceCall != null) {
1724 builder.statement(replaceCall);
1725 }
1726 builder.startReturn().tree(createTemplateMethodCall(parent, null, source, current, null)).end();
1727 } else {
1728 replace.add(new CodeTree(CodeTreeKind.STRING, null, "."));
1729 builder.startReturn().tree(createTemplateMethodCall(parent, replace, source, current, null)).end();
1730 }
1731 return builder.getRoot();
1732 }
1733
1734 protected CodeTree createReplaceCall(CodeTreeBuilder builder, SpecializationData current, String target, String source, String message) {
1735 String className = nodeSpecializationClassName(current);
1736 CodeTreeBuilder replaceCall = builder.create();
1737 if (target != null) {
1738 replaceCall.startCall(target, "replace");
1739 } else {
1740 replaceCall.startCall("replace");
1741 }
1742 replaceCall.startGroup().cast(baseClassName(current.getNode())).startCall(className, CREATE_SPECIALIZATION_NAME).string(source);
1743 for (ActualParameter param : current.getSignatureParameters()) {
1744 NodeChildData child = param.getSpecification().getExecution().getChild();
1745 List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
1746 if (types.size() > 1) {
1747 replaceCall.string(implicitTypeName(param));
1748 }
1749 }
1750 replaceCall.end().end();
1751
1752 if (message == null) {
1753 replaceCall.string("message");
1754 } else {
1755 replaceCall.doubleQuote(message);
1756 }
1757 replaceCall.end();
1758 return replaceCall.getRoot();
1759 }
1760
1761 private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node, String currentNode) {
1762 String polyClassName = nodePolymorphicClassName(node);
1763 String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization());
1764 CodeTreeBuilder builder = parent.create();
1765
1766 builder.declaration(getElement().asType(), "currentCopy", currentNode + "." + COPY_WITH_CONSTRUCTOR_NAME + "()");
1767 for (ActualParameter param : getModel().getSignatureParameters()) {
1768 NodeExecutionData execution = param.getSpecification().getExecution();
1769 builder.startStatement().tree(createAccessChild(execution, "currentCopy")).string(" = ").nullLiteral().end();
1770 }
1771 builder.startStatement().string("currentCopy.next0 = ").startNew(uninitializedName).string("currentCopy").end().end();
1772
1773 builder.declaration(polyClassName, "polymorphic", builder.create().startNew(polyClassName).string(currentNode).end());
1774 builder.startStatement().string("polymorphic.next0 = ").string("currentCopy").end();
1775 builder.startStatement().startCall(currentNode, "replace").string("polymorphic").string("message").end().end();
1776
1777 builder.startReturn();
1778 builder.startCall("currentCopy.next0", EXECUTE_POLYMORPHIC_NAME);
1779 addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, null);
1780 builder.end();
1781 builder.end(); 1764 builder.end();
1782 1765
1783 return builder.getRoot(); 1766 return builder.getRoot();
1784 } 1767 }
1785 1768
1786 protected CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) { 1769 protected CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) {
1787 TypeData type = executable.getType(); 1770 TypeData type = executable.getType();
1788 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 1771 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1789 NodeData node = specialization.getNode(); 1772 NodeData node = specialization.getNode();
1790 1773
1791 ExecutableTypeData castedType = node.findExecutableType(type, 0);
1792 TypeData primaryType = castExecutable.getType(); 1774 TypeData primaryType = castExecutable.getType();
1793 1775
1794 boolean needsTry = castExecutable.hasUnexpectedValue(getContext()); 1776 boolean needsTry = castExecutable.hasUnexpectedValue(getContext());
1795 boolean returnVoid = type.isVoid(); 1777 boolean returnVoid = type.isVoid();
1796 1778
1807 for (int i = 0; i < executeParameterNames.length; i++) { 1789 for (int i = 0; i < executeParameterNames.length; i++) {
1808 executeParameterNames[i] = valueName(executeParameters.get(i)); 1790 executeParameterNames[i] = valueName(executeParameters.get(i));
1809 } 1791 }
1810 1792
1811 builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null)); 1793 builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null));
1794 boolean hasUnexpected = executable.hasUnexpectedValue(getContext());
1812 1795
1813 CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null, executeParameterNames); 1796 CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null, executeParameterNames);
1814 if (needsTry) { 1797 if (needsTry) {
1815 if (!returnVoid) { 1798 if (!returnVoid) {
1816 builder.declaration(primaryType.getPrimitiveType(), "value"); 1799 builder.declaration(primaryType.getPrimitiveType(), "value");
1829 builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); 1812 builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
1830 if (returnVoid) { 1813 if (returnVoid) {
1831 builder.string("// ignore").newLine(); 1814 builder.string("// ignore").newLine();
1832 } else { 1815 } else {
1833 builder.startReturn(); 1816 builder.startReturn();
1834 builder.tree(createExpectExecutableType(node, specialization.getNode().getTypeSystem().getGenericTypeData(), castedType, CodeTreeBuilder.singleString("ex.getResult()"))); 1817 builder.tree(createExpectExecutableType(node, specialization.getNode().getTypeSystem().getGenericTypeData(), hasUnexpected, executable.getType(),
1818 CodeTreeBuilder.singleString("ex.getResult()")));
1835 builder.end(); 1819 builder.end();
1836 } 1820 }
1837 builder.end(); 1821 builder.end();
1838 1822
1839 if (!returnVoid) { 1823 if (!returnVoid) {
1840 builder.startReturn(); 1824 builder.startReturn();
1841 builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), executable, CodeTreeBuilder.singleString("value"))); 1825 builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), hasUnexpected, executable.getType(), CodeTreeBuilder.singleString("value")));
1842 builder.end(); 1826 builder.end();
1843 } 1827 }
1844 } else { 1828 } else {
1845 if (returnVoid) { 1829 if (returnVoid) {
1846 builder.statement(primaryExecuteCall); 1830 builder.statement(primaryExecuteCall);
1847 } else { 1831 } else {
1848 builder.startReturn(); 1832 builder.startReturn();
1849 builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), executable, primaryExecuteCall)); 1833 builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), hasUnexpected, executable.getType(), primaryExecuteCall));
1850 builder.end(); 1834 builder.end();
1851 } 1835 }
1852 } 1836 }
1853 1837
1854 return builder.getRoot(); 1838 return builder.getRoot();
1855 } 1839 }
1856 1840
1857 protected CodeTree createExpectExecutableType(NodeData node, TypeData sourceType, ExecutableTypeData castedType, CodeTree value) { 1841 protected CodeTree createExpectExecutableType(NodeData node, TypeData sourceType, boolean hasUnexpected, TypeData exepctedType, CodeTree value) {
1858 boolean hasUnexpected = castedType.hasUnexpectedValue(getContext()); 1842 return createCastType(node.getTypeSystem(), sourceType, exepctedType, hasUnexpected, value);
1859 return createCastType(node.getTypeSystem(), sourceType, castedType.getType(), hasUnexpected, value);
1860 } 1843 }
1861 1844
1862 protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List<ActualParameter> targetParameters, 1845 protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List<ActualParameter> targetParameters,
1863 ActualParameter unexpectedParameter) { 1846 ActualParameter unexpectedParameter) {
1864 CodeTreeBuilder builder = parent.create(); 1847 CodeTreeBuilder builder = parent.create();
1909 } 1892 }
1910 elseIf = builder.startIf(elseIf); 1893 elseIf = builder.startIf(elseIf);
1911 1894
1912 ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName()); 1895 ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName());
1913 TypeData sourceType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null; 1896 TypeData sourceType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null;
1914 builder.string(polymorphicTypeName(targetParameter)).string(" == ").typeLiteral(possiblePolymoprhicType.getPrimitiveType()); 1897 builder.string(polymorphicTypeName(targetParameter.getSpecification().getExecution())).string(" == ").typeLiteral(possiblePolymoprhicType.getPrimitiveType());
1915 builder.end().startBlock(); 1898 builder.end().startBlock();
1916 builder.startStatement(); 1899 builder.startStatement();
1917 builder.tree(createExecuteChildExpression(parent, execution, sourceType, new ActualParameter(targetParameter, possiblePolymoprhicType), unexpectedParameter, null)); 1900 builder.tree(createExecuteChildExpression(parent, execution, sourceType, new ActualParameter(targetParameter, possiblePolymoprhicType), unexpectedParameter, null));
1918 builder.end(); 1901 builder.end();
1919 builder.end(); 1902 builder.end();
2119 private CodeTree createImplicitCast(CodeTreeBuilder parent, TypeSystemData typeSystem, ImplicitCastData cast, CodeTree expression) { 2102 private CodeTree createImplicitCast(CodeTreeBuilder parent, TypeSystemData typeSystem, ImplicitCastData cast, CodeTree expression) {
2120 if (cast == null) { 2103 if (cast == null) {
2121 return expression; 2104 return expression;
2122 } 2105 }
2123 CodeTreeBuilder builder = parent.create(); 2106 CodeTreeBuilder builder = parent.create();
2124 startCallTypeSystemMethod(getContext(), builder, typeSystem, cast.getMethodName()); 2107 startCallTypeSystemMethod(builder, typeSystem, cast.getMethodName());
2125 builder.tree(expression); 2108 builder.tree(expression);
2126 builder.end().end(); 2109 builder.end().end();
2127 return builder.getRoot(); 2110 return builder.getRoot();
2128 } 2111 }
2129 2112
2176 sourceType = targetExecutable.getType(); 2159 sourceType = targetExecutable.getType();
2177 } 2160 }
2178 2161
2179 ImplicitCastData cast = getModel().getNode().getTypeSystem().lookupCast(implicitSourceType, targetType); 2162 ImplicitCastData cast = getModel().getNode().getTypeSystem().lookupCast(implicitSourceType, targetType);
2180 if (cast != null) { 2163 if (cast != null) {
2181 if (cast.getSourceType().needsCastTo(getContext(), targetType)) { 2164 if (cast.getSourceType().needsCastTo(targetType)) {
2182 return true; 2165 return true;
2183 } 2166 }
2184 } 2167 }
2185 2168
2186 if (sourceType.needsCastTo(getContext(), targetType)) { 2169 if (sourceType.needsCastTo(targetType)) {
2187 return true; 2170 return true;
2188 } 2171 }
2189 } 2172 }
2190 return false; 2173 return false;
2191 } 2174 }
2217 List<ActualParameter> genericParameters = generic.getParametersAfter(genericParameter); 2200 List<ActualParameter> genericParameters = generic.getParametersAfter(genericParameter);
2218 builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter)); 2201 builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter));
2219 if (specialization.isPolymorphic()) { 2202 if (specialization.isPolymorphic()) {
2220 builder.tree(createReturnOptimizeTypes(builder, currentExecutable, specialization, param)); 2203 builder.tree(createReturnOptimizeTypes(builder, currentExecutable, specialization, param));
2221 } else { 2204 } else {
2222 builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization, param, 2205 builder.tree(createCallRewriteMonomorphic(builder, currentExecutable.hasUnexpectedValue(context), currentExecutable.getType(), specialization, param,
2223 "Expected " + param.getLocalName() + " instanceof " + Utils.getSimpleName(param.getType()))); 2206 "Expected " + param.getLocalName() + " instanceof " + Utils.getSimpleName(param.getType())));
2224 } 2207 }
2225 builder.end(); // catch block 2208 builder.end(); // catch block
2226 2209
2227 return builder.getRoot(); 2210 return builder.getRoot();
2230 private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, ActualParameter param) { 2213 private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, ActualParameter param) {
2231 NodeData node = specialization.getNode(); 2214 NodeData node = specialization.getNode();
2232 SpecializationData polymorphic = node.getPolymorphicSpecialization(); 2215 SpecializationData polymorphic = node.getPolymorphicSpecialization();
2233 2216
2234 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 2217 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
2235 builder.startStatement().string(polymorphicTypeName(param)).string(" = ").typeLiteral(getContext().getType(Object.class)).end(); 2218 builder.startStatement().string(polymorphicTypeName(param.getSpecification().getExecution())).string(" = ").typeLiteral(getContext().getType(Object.class)).end();
2236 2219
2237 builder.startReturn(); 2220 builder.startReturn();
2238 2221
2239 CodeTreeBuilder execute = new CodeTreeBuilder(builder); 2222 CodeTreeBuilder execute = new CodeTreeBuilder(builder);
2240 execute.startCall("next0", EXECUTE_POLYMORPHIC_NAME); 2223 execute.startCall("next0", EXECUTE_CHAINED);
2241 addInternalValueParameterNames(execute, specialization, polymorphic, param.getLocalName(), true, null); 2224 addInternalValueParameterNames(execute, specialization, polymorphic, param.getLocalName(), true, null);
2242 execute.end(); 2225 execute.end();
2243 2226
2244 TypeData sourceType = polymorphic.getReturnType().getTypeSystemType(); 2227 TypeData sourceType = polymorphic.getReturnType().getTypeSystemType();
2245 2228
2246 builder.tree(createExpectExecutableType(node, sourceType, currentExecutable, execute.getRoot())); 2229 builder.tree(createExpectExecutableType(node, sourceType, currentExecutable.hasUnexpectedValue(context), currentExecutable.getType(), execute.getRoot()));
2247 2230
2248 builder.end(); 2231 builder.end();
2249 return builder.getRoot(); 2232 return builder.getRoot();
2250 } 2233 }
2251 2234
2288 sourceType = getModel().getNode().getTypeSystem().getGenericTypeData(); 2271 sourceType = getModel().getNode().getTypeSystem().getGenericTypeData();
2289 } 2272 }
2290 2273
2291 CodeTree value = CodeTreeBuilder.singleString(localName); 2274 CodeTree value = CodeTreeBuilder.singleString(localName);
2292 2275
2293 if (sourceType.needsCastTo(getContext(), targetType)) { 2276 if (sourceType.needsCastTo(targetType)) {
2294 value = createCallTypeSystemMethod(getContext(), builder, getModel().getNode(), TypeSystemCodeGenerator.asTypeMethodName(targetType), value); 2277 value = createCallTypeSystemMethod(builder, getModel().getNode(), TypeSystemCodeGenerator.asTypeMethodName(targetType), value);
2295 } 2278 }
2296 builder.tree(value); 2279 builder.tree(value);
2297 } else { 2280 } else {
2298 builder.defaultValue(parameter.getType()); 2281 builder.defaultValue(parameter.getType());
2299 } 2282 }
2348 builder.end(); // statement 2331 builder.end(); // statement
2349 2332
2350 return builder.getRoot(); 2333 return builder.getRoot();
2351 } 2334 }
2352 2335
2353 protected CodeTree createReturnExecuteAndSpecialize(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData current, ActualParameter exceptionParam, String reason) { 2336 protected CodeTree createCallRewriteMonomorphic(CodeTreeBuilder parent, boolean hasUnexpected, TypeData returnType, SpecializationData current, ActualParameter exceptionParam, String reason) {
2354 NodeData node = current.getNode(); 2337 NodeData node = current.getNode();
2355 SpecializationData generic = node.getGenericSpecialization(); 2338 SpecializationData generic = node.getGenericSpecialization();
2356 CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); 2339 CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent);
2357 specializeCall.startCall(EXECUTE_SPECIALIZE_NAME); 2340 specializeCall.startCall(REWRITE);
2358 specializeCall.string(String.valueOf(node.getSpecializations().indexOf(current)));
2359 addInternalValueParameterNames(specializeCall, generic, node.getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, null); 2341 addInternalValueParameterNames(specializeCall, generic, node.getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, null);
2360 specializeCall.doubleQuote(reason); 2342 specializeCall.doubleQuote(reason);
2361 specializeCall.end().end(); 2343 specializeCall.end().end();
2362 2344
2363 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 2345 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
2364 2346
2365 builder.startReturn(); 2347 builder.startReturn();
2366 builder.tree(createExpectExecutableType(node, generic.getReturnType().getTypeSystemType(), executable, specializeCall.getRoot())); 2348 builder.tree(createExpectExecutableType(node, generic.getReturnType().getTypeSystemType(), hasUnexpected, returnType, specializeCall.getRoot()));
2367 builder.end(); 2349 builder.end();
2368 2350
2369 return builder.getRoot(); 2351 return builder.getRoot();
2370 } 2352 }
2371 2353
2372 protected final CodeExecutableElement createUpdateTypes(TypeMirror polymorphicType) {
2373 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), getContext().getType(void.class), UPDATE_TYPES_NAME);
2374 method.getParameters().add(new CodeVariableElement(polymorphicType, "polymorphic"));
2375 CodeTreeBuilder builder = method.createBuilder();
2376
2377 if (getModel().isPolymorphic()) {
2378 builder.startStatement();
2379 builder.startCall("next0", "updateTypes").string("polymorphic").end();
2380 builder.end();
2381 } else if (getModel().isSpecialized()) {
2382 for (ActualParameter parameter : getModel().getParameters()) {
2383 if (!parameter.getSpecification().isSignature()) {
2384 continue;
2385 }
2386 if (lookupPolymorphicTargetTypes(parameter).size() <= 1) {
2387 continue;
2388 }
2389 builder.startStatement();
2390 builder.startCall("polymorphic", createUpdateTypeName(parameter));
2391 builder.typeLiteral(parameter.getType());
2392 builder.end().end();
2393 }
2394
2395 builder.startStatement().startCall("super", UPDATE_TYPES_NAME).string("polymorphic").end().end();
2396 }
2397 return method;
2398 }
2399
2400 protected String createUpdateTypeName(ActualParameter parameter) {
2401 return "update" + Utils.firstLetterUpperCase(parameter.getLocalName()) + "Type";
2402 }
2403 } 2354 }
2404 2355
2405 private class PolymorphicNodeFactory extends SpecializedNodeFactory { 2356 private class PolymorphicNodeFactory extends SpecializedNodeFactory {
2406 2357
2407 public PolymorphicNodeFactory(ProcessorContext context, CodeTypeElement nodeGen) { 2358 public PolymorphicNodeFactory(CodeTypeElement nodeGen) {
2408 super(context, nodeGen); 2359 super(nodeGen);
2409 } 2360 }
2410 2361
2411 @Override 2362 @Override
2412 public CodeTypeElement create(SpecializationData polymorph) { 2363 public CodeTypeElement create(SpecializationData polymorph) {
2413 NodeData node = polymorph.getNode(); 2364 NodeData node = polymorph.getNode();
2430 } 2381 }
2431 ActualParameter parameter = specialization.findParameter(polymorphParameter.getLocalName()); 2382 ActualParameter parameter = specialization.findParameter(polymorphParameter.getLocalName());
2432 assert parameter != null; 2383 assert parameter != null;
2433 types.add(parameter.getTypeSystemType()); 2384 types.add(parameter.getTypeSystemType());
2434 } 2385 }
2435 CodeVariableElement var = new CodeVariableElement(modifiers(PRIVATE), getContext().getType(Class.class), polymorphicTypeName(polymorphParameter)); 2386
2387 }
2388
2389 for (NodeExecutionData execution : getModel().getNode().getChildExecutions()) {
2390 String fieldName = polymorphicTypeName(execution);
2391 CodeVariableElement var = new CodeVariableElement(modifiers(PRIVATE), getContext().getType(Class.class), fieldName);
2436 var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getCompilationFinal())); 2392 var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getCompilationFinal()));
2437 clazz.add(var); 2393 clazz.add(var);
2438 } 2394 }
2439 2395
2440 return clazz; 2396 return clazz;
2445 CodeTypeElement clazz = getElement(); 2401 CodeTypeElement clazz = getElement();
2446 2402
2447 createConstructors(clazz); 2403 createConstructors(clazz);
2448 createExecuteMethods(specialization); 2404 createExecuteMethods(specialization);
2449 2405
2450 getElement().add(createUpdateTypes(nodeGen.asType())); 2406 clazz.add(createUpdateTypes0());
2451
2452 for (ActualParameter parameter : specialization.getParameters()) {
2453 if (!parameter.getSpecification().isSignature()) {
2454 continue;
2455 }
2456 if (lookupPolymorphicTargetTypes(parameter).size() <= 1) {
2457 continue;
2458 }
2459 getElement().add(createUpdateType(parameter));
2460 }
2461
2462 if (needsInvokeCopyConstructorMethod()) {
2463 clazz.add(createCopy(nodeGen.asType(), specialization));
2464 }
2465
2466 createCachedExecuteMethods(specialization); 2407 createCachedExecuteMethods(specialization);
2467 } 2408 }
2468 2409
2469 private ExecutableElement createUpdateType(ActualParameter parameter) {
2470 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), getContext().getType(void.class), createUpdateTypeName(parameter));
2471 method.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), "type"));
2472 CodeTreeBuilder builder = method.createBuilder();
2473
2474 String fieldName = polymorphicTypeName(parameter);
2475 builder.startIf().string(fieldName).isNull().end().startBlock();
2476 builder.startStatement().string(fieldName).string(" = ").string("type").end();
2477 builder.end();
2478 builder.startElseIf().string(fieldName).string(" != ").string("type").end();
2479 builder.startBlock();
2480 builder.startStatement().string(fieldName).string(" = ").typeLiteral(getContext().getType(Object.class)).end();
2481 builder.end();
2482
2483 return method;
2484 }
2485
2486 } 2410 }
2487 2411
2488 private class SpecializedNodeFactory extends NodeBaseFactory { 2412 private class SpecializedNodeFactory extends NodeBaseFactory {
2489 2413
2490 protected final CodeTypeElement nodeGen; 2414 protected final CodeTypeElement nodeGen;
2491 2415
2492 public SpecializedNodeFactory(ProcessorContext context, CodeTypeElement nodeGen) { 2416 public SpecializedNodeFactory(CodeTypeElement nodeGen) {
2493 super(context);
2494 this.nodeGen = nodeGen; 2417 this.nodeGen = nodeGen;
2495 } 2418 }
2496 2419
2497 @Override 2420 @Override
2498 public CodeTypeElement create(SpecializationData specialization) { 2421 public CodeTypeElement create(SpecializationData specialization) {
2500 TypeMirror baseType = node.getNodeType(); 2423 TypeMirror baseType = node.getNodeType();
2501 if (nodeGen != null) { 2424 if (nodeGen != null) {
2502 baseType = nodeGen.asType(); 2425 baseType = nodeGen.asType();
2503 } 2426 }
2504 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false); 2427 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false);
2428
2429 if (specialization.isSpecialized() || specialization.isUninitialized()) {
2430 clazz.add(createGetMetadata0(false));
2431 clazz.add(createMetadataLiteral());
2432 }
2505 2433
2506 NodeCost cost; 2434 NodeCost cost;
2507 if (specialization.isGeneric()) { 2435 if (specialization.isGeneric()) {
2508 cost = NodeCost.MEGAMORPHIC; 2436 cost = NodeCost.MEGAMORPHIC;
2509 } else if (specialization.isUninitialized()) { 2437 } else if (specialization.isUninitialized()) {
2515 } else { 2443 } else {
2516 throw new AssertionError(); 2444 throw new AssertionError();
2517 } 2445 }
2518 clazz.getAnnotationMirrors().add(createNodeInfo(node, cost)); 2446 clazz.getAnnotationMirrors().add(createNodeInfo(node, cost));
2519 2447
2448 if (specialization.isUninitialized() && node.getGenericSpecialization().isReachable()) {
2449 clazz.add(createUninitializedGetCostOverride());
2450 }
2451
2520 return clazz; 2452 return clazz;
2453 }
2454
2455 private Element createUninitializedGetCostOverride() {
2456 TypeMirror returnType = context.getTruffleTypes().getNodeCost();
2457 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getCost");
2458 CodeTreeBuilder builder = method.createBuilder();
2459 builder.startIf().string(CONTAINS_FALLBACK).end().startBlock();
2460 builder.startReturn().staticReference(returnType, "MONOMORPHIC").end();
2461 builder.end();
2462 builder.startReturn().string("super.getCost()").end();
2463 return method;
2464 }
2465
2466 private CodeVariableElement createMetadataLiteral() {
2467 CodeVariableElement includes = new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), context.getTruffleTypes().getDslMetadata(), METADATA_FIELD_NAME);
2468
2469 CodeTreeBuilder builder = includes.createInitBuilder();
2470
2471 SpecializationData specialization = getModel();
2472 NodeData node = specialization.getNode();
2473
2474 Set<SpecializationData> contains = specialization.getContains();
2475 if (specialization.isUninitialized()) {
2476 contains = new HashSet<>();
2477
2478 SpecializationData polymorphic = node.getPolymorphicSpecialization();
2479 if (polymorphic != null) {
2480 contains.addAll(polymorphic.getContains());
2481 }
2482 SpecializationData generic = node.getGenericSpecialization();
2483 if (generic != null) {
2484 contains.addAll(generic.getContains());
2485 }
2486 }
2487
2488 builder.startNew(context.getTruffleTypes().getDslMetadata());
2489 builder.startGroup().string(nodeSpecializationClassName(getModel()), ".class").end();
2490 builder.tree(createSpecializationListLiteral(builder, contains));
2491 builder.tree(createSpecializationListLiteral(builder, getModel().getExcludedBy()));
2492 builder.tree(createSpecializationTypeLiteral(builder, SpecializationData.getSignatureTypes(getModel())));
2493 builder.string("0").string("0");
2494 builder.end();
2495 return includes;
2496 }
2497
2498 private CodeTree createSpecializationTypeLiteral(CodeTreeBuilder parent, List<TypeMirror> list) {
2499 ArrayType classArray = new ArrayCodeTypeMirror(context.getType(Class.class));
2500 CodeTreeBuilder builder = parent.create();
2501
2502 if (list.isEmpty()) {
2503 builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY);
2504 } else {
2505 builder.startNewArray(classArray, null);
2506 for (TypeMirror type : list) {
2507 builder.typeLiteral(type);
2508 }
2509 builder.end();
2510 }
2511
2512 return builder.getRoot();
2513 }
2514
2515 private CodeTree createSpecializationListLiteral(CodeTreeBuilder parent, Set<SpecializationData> list) {
2516 ArrayType classArray = new ArrayCodeTypeMirror(context.getType(Class.class));
2517 CodeTreeBuilder builder = parent.create();
2518
2519 if (list.isEmpty()) {
2520 builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY);
2521 } else {
2522 builder.startNewArray(classArray, null);
2523 for (SpecializationData specialization : list) {
2524 if (specialization.isGeneric() || specialization.isPolymorphic()) {
2525 specialization = getModel().getNode().getUninitializedSpecialization();
2526 }
2527 builder.startGroup().string(nodeSpecializationClassName(specialization)).string(".class").end();
2528 }
2529 builder.end();
2530 }
2531
2532 return builder.getRoot();
2521 } 2533 }
2522 2534
2523 protected CodeAnnotationMirror createNodeInfo(NodeData node, NodeCost cost) { 2535 protected CodeAnnotationMirror createNodeInfo(NodeData node, NodeCost cost) {
2524 String shortName = node.getShortName(); 2536 String shortName = node.getShortName();
2525 CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(getContext().getTruffleTypes().getNodeInfoAnnotation()); 2537 CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(getContext().getTruffleTypes().getNodeInfoAnnotation());
2539 CodeTypeElement clazz = getElement(); 2551 CodeTypeElement clazz = getElement();
2540 createConstructors(clazz); 2552 createConstructors(clazz);
2541 2553
2542 createExecuteMethods(specialization); 2554 createExecuteMethods(specialization);
2543 createCachedExecuteMethods(specialization); 2555 createCachedExecuteMethods(specialization);
2544 if (specialization.getNode().isPolymorphic()) { 2556
2545 getElement().add(createUpdateTypes(nodeGen.asType())); 2557 if (specialization.isUninitialized()) {
2546 } 2558 if (specialization.getNode().isFallbackReachable()) {
2547 if (needsInvokeCopyConstructorMethod()) { 2559 CodeVariableElement var = new CodeVariableElement(modifiers(Modifier.PRIVATE), context.getType(boolean.class), CONTAINS_FALLBACK);
2548 clazz.add(createCopy(nodeGen.asType(), specialization)); 2560 var.addAnnotationMirror(new CodeAnnotationMirror(context.getTruffleTypes().getCompilationFinal()));
2561 clazz.add(var);
2562 }
2563 clazz.add(createExecuteUninitialized());
2549 } 2564 }
2550 2565
2551 if (!specialization.isUninitialized() && specialization.getNode().needsRewrites(context)) { 2566 if (!specialization.isUninitialized() && specialization.getNode().needsRewrites(context)) {
2552 clazz.add(createCopyConstructorFactoryMethod(nodeGen.asType(), specialization)); 2567 clazz.add(createCopyConstructorFactoryMethod(nodeGen.asType(), specialization));
2553 } else { 2568 } else {
2566 SpecializationData specialization = getModel(); 2581 SpecializationData specialization = getModel();
2567 NodeData node = specialization.getNode(); 2582 NodeData node = specialization.getNode();
2568 for (ExecutableElement constructor : ElementFilter.constructorsIn(superTypeElement.getEnclosedElements())) { 2583 for (ExecutableElement constructor : ElementFilter.constructorsIn(superTypeElement.getEnclosedElements())) {
2569 if (specialization.isUninitialized()) { 2584 if (specialization.isUninitialized()) {
2570 // ignore copy constructors for uninitialized if not polymorphic 2585 // ignore copy constructors for uninitialized if not polymorphic
2571 if (isCopyConstructor(constructor) && !node.isPolymorphic()) { 2586 if (isCopyConstructor(constructor) && !node.isPolymorphic(context)) {
2572 continue; 2587 continue;
2573 } 2588 }
2574 } else if (node.getUninitializedSpecialization() != null) { 2589 } else if (node.getUninitializedSpecialization() != null) {
2575 // ignore others than copy constructors for specialized nodes 2590 // ignore others than copy constructors for specialized nodes
2576 if (!isCopyConstructor(constructor)) { 2591 if (!isCopyConstructor(constructor)) {
2584 } 2599 }
2585 CodeTree body = superConstructor.getBodyTree(); 2600 CodeTree body = superConstructor.getBodyTree();
2586 CodeTreeBuilder builder = superConstructor.createBuilder(); 2601 CodeTreeBuilder builder = superConstructor.createBuilder();
2587 builder.tree(body); 2602 builder.tree(body);
2588 2603
2589 if (node.isPolymorphic()) {
2590 if (specialization.isSpecialized() || specialization.isPolymorphic()) {
2591 builder.statement("this.next0 = copy.next0");
2592 }
2593 }
2594 if (superConstructor != null) { 2604 if (superConstructor != null) {
2595 for (ActualParameter param : getImplicitTypeParameters(getModel())) { 2605 for (ActualParameter param : getImplicitTypeParameters(getModel())) {
2596 clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), implicitTypeName(param))); 2606 clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), implicitTypeName(param)));
2597 superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param))); 2607 superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param)));
2598 2608
2626 } 2636 }
2627 } 2637 }
2628 2638
2629 protected void createCachedExecuteMethods(SpecializationData specialization) { 2639 protected void createCachedExecuteMethods(SpecializationData specialization) {
2630 NodeData node = specialization.getNode(); 2640 NodeData node = specialization.getNode();
2631 if (!node.isPolymorphic()) { 2641 if (!node.isPolymorphic(context)) {
2632 return; 2642 return;
2633 } 2643 }
2634 2644
2635 CodeTypeElement clazz = getElement(); 2645 CodeTypeElement clazz = getElement();
2636 2646
2637 final SpecializationData polymorphic = node.getPolymorphicSpecialization(); 2647 final SpecializationData polymorphic = node.getPolymorphicSpecialization();
2638 ExecutableElement executeCached = nodeGen.getMethod(EXECUTE_POLYMORPHIC_NAME); 2648 ExecutableElement executeCached = nodeGen.getMethod(EXECUTE_CHAINED);
2639 CodeExecutableElement executeMethod = CodeExecutableElement.clone(getContext().getEnvironment(), executeCached); 2649 CodeExecutableElement executeMethod = CodeExecutableElement.clone(getContext().getEnvironment(), executeCached);
2640 executeMethod.getModifiers().remove(Modifier.ABSTRACT); 2650 executeMethod.getModifiers().remove(Modifier.ABSTRACT);
2641 CodeTreeBuilder builder = executeMethod.createBuilder(); 2651 CodeTreeBuilder builder = executeMethod.createBuilder();
2642 2652
2643 if (specialization.isGeneric() || specialization.isPolymorphic()) { 2653 if (specialization.isPolymorphic()) {
2644 builder.startThrow().startNew(getContext().getType(AssertionError.class)); 2654 builder.startReturn().startCall("this.next0", EXECUTE_CHAINED);
2645 builder.doubleQuote("Should not be reached."); 2655 addInternalValueParameterNames(builder, polymorphic, polymorphic, null, true, null);
2646 builder.end().end(); 2656 builder.end().end();
2647 } else if (specialization.isUninitialized()) { 2657 } else if (specialization.isUninitialized()) {
2648 builder.tree(createAppendPolymorphic(builder, specialization)); 2658 if (node.getGenericSpecialization().isReachable()) {
2659 builder.startIf().string("!containsFallback").end().startBlock();
2660 builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
2661 builder.end();
2662 } else {
2663 builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
2664 }
2665 builder.startReturn().startCall("this", EXECUTE_UNINITIALIZED);
2666 addInternalValueParameterNames(builder, polymorphic, polymorphic, null, true, null);
2667 builder.end().end();
2649 } else { 2668 } else {
2650 CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder); 2669 CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder);
2651 elseBuilder.startReturn().startCall("this.next0", EXECUTE_POLYMORPHIC_NAME); 2670 elseBuilder.startReturn().startCall("this.next0", EXECUTE_CHAINED);
2652 addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, null); 2671 addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, null);
2653 elseBuilder.end().end(); 2672 elseBuilder.end().end();
2654 2673
2655 boolean forceElse = specialization.getExceptions().size() > 0; 2674 builder.tree(createExecuteTree(builder, polymorphic, SpecializationGroup.create(specialization), new CodeBlock<SpecializationData>() {
2656 builder.tree(createExecuteTree(builder, polymorphic, SpecializationGroup.create(specialization), false, new CodeBlock<SpecializationData>() {
2657 2675
2658 public CodeTree create(CodeTreeBuilder b, SpecializationData current) { 2676 public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
2659 return createGenericInvoke(b, polymorphic, current); 2677 return createGenericInvoke(b, polymorphic, current);
2660 } 2678 }
2661 }, elseBuilder.getRoot(), forceElse, true, true)); 2679 }, elseBuilder.getRoot(), false, true, true, false));
2662 } 2680 }
2663 clazz.add(executeMethod); 2681 clazz.add(executeMethod);
2664 }
2665
2666 private CodeTree createAppendPolymorphic(CodeTreeBuilder parent, SpecializationData specialization) {
2667 NodeData node = specialization.getNode();
2668
2669 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
2670 builder.tree(createDeoptimize(builder));
2671
2672 builder.declaration(getContext().getTruffleTypes().getNode(), "root", "this");
2673 builder.declaration(getContext().getType(int.class), "depth", "0");
2674 builder.tree(createFindRoot(builder, node, true));
2675 builder.newLine();
2676
2677 builder.startIf().string("depth > ").string(String.valueOf(node.getPolymorphicDepth())).end();
2678 builder.startBlock();
2679 String message = "Polymorphic limit reached (" + node.getPolymorphicDepth() + ")";
2680 String castRoot = "(" + baseClassName(node) + ") root";
2681 builder.tree(createGenericInvoke(builder, node.getPolymorphicSpecialization(), node.getGenericSpecialization(),
2682 createReplaceCall(builder, node.getGenericSpecialization(), "root", castRoot, message), null));
2683 builder.end();
2684
2685 builder.startElseBlock();
2686 builder.startStatement().string("next0 = ");
2687 builder.startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string("this").end();
2688 builder.end();
2689
2690 CodeTreeBuilder specializeCall = new CodeTreeBuilder(builder);
2691 specializeCall.startCall(EXECUTE_SPECIALIZE_NAME);
2692 specializeCall.string("0");
2693 addInternalValueParameterNames(specializeCall, specialization, node.getGenericSpecialization(), null, true, null);
2694 specializeCall.startGroup().doubleQuote("Uninitialized polymorphic (").string(" + depth + ").doubleQuote("/" + node.getPolymorphicDepth() + ")").end();
2695 specializeCall.end().end();
2696
2697 builder.declaration(node.getGenericSpecialization().getReturnType().getType(), "result", specializeCall.getRoot());
2698
2699 CodeTree root = builder.create().cast(nodePolymorphicClassName(node)).string("root").getRoot();
2700 builder.startIf().string("this.next0 != null").end().startBlock();
2701 builder.startStatement().string("(").tree(root).string(").").startCall(UPDATE_TYPES_NAME).tree(root).end().end();
2702 builder.end();
2703
2704 if (Utils.isVoid(builder.findMethod().getReturnType())) {
2705 builder.returnStatement();
2706 } else {
2707 builder.startReturn().string("result").end();
2708 }
2709
2710 builder.end();
2711
2712 return builder.getRoot();
2713 } 2682 }
2714 2683
2715 private CodeTree createExecuteBody(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData execType) { 2684 private CodeTree createExecuteBody(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData execType) {
2716 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 2685 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
2717 2686
2729 return builder.getRoot(); 2698 return builder.getRoot();
2730 } 2699 }
2731 2700
2732 private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType, boolean evaluated) { 2701 private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType, boolean evaluated) {
2733 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod()); 2702 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod());
2703
2704 method.getAnnotationMirrors().clear();
2705 for (VariableElement variable : method.getParameters()) {
2706 variable.getAnnotationMirrors().clear();
2707 }
2734 2708
2735 CodeTreeBuilder builder = method.createBuilder(); 2709 CodeTreeBuilder builder = method.createBuilder();
2736 int i = 0; 2710 int i = 0;
2737 int signatureIndex = -1; 2711 int signatureIndex = -1;
2738 for (VariableElement param : method.getParameters()) { 2712 for (VariableElement param : method.getParameters()) {
2838 CodeTree returnSpecialized = null; 2812 CodeTree returnSpecialized = null;
2839 2813
2840 if (specialization.findNextSpecialization() != null) { 2814 if (specialization.findNextSpecialization() != null) {
2841 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder); 2815 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder);
2842 returnBuilder.tree(createDeoptimize(builder)); 2816 returnBuilder.tree(createDeoptimize(builder));
2843 returnBuilder.tree(createReturnExecuteAndSpecialize(builder, executable, specialization, null, "One of guards " + specialization.getGuardDefinitions() + " failed")); 2817 returnBuilder.tree(createCallRewriteMonomorphic(builder, executable.hasUnexpectedValue(context), executable.getType(), specialization, null,
2818 "One of guards " + specialization.getGuards() + " failed"));
2844 returnSpecialized = returnBuilder.getRoot(); 2819 returnSpecialized = returnBuilder.getRoot();
2845 } 2820 }
2846 2821
2847 builder.tree(createExecuteTree(builder, specialization, SpecializationGroup.create(specialization), false, new CodeBlock<SpecializationData>() { 2822 builder.tree(createExecuteTree(builder, specialization, SpecializationGroup.create(specialization), new CodeBlock<SpecializationData>() {
2848 2823
2849 public CodeTree create(CodeTreeBuilder b, SpecializationData current) { 2824 public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
2850 return createExecute(b, executable, specialization); 2825 return createExecute(b, executable, specialization);
2851 } 2826 }
2852 }, returnSpecialized, false, false, false)); 2827 }, returnSpecialized, false, false, false, false));
2853 2828
2854 return builder.getRoot(); 2829 return builder.getRoot();
2855 } 2830 }
2856 2831
2857 private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) { 2832 private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) {
2867 builder.end(); 2842 builder.end();
2868 } 2843 }
2869 2844
2870 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent); 2845 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent);
2871 if (specialization.isPolymorphic()) { 2846 if (specialization.isPolymorphic()) {
2872 returnBuilder.startCall("next0", EXECUTE_POLYMORPHIC_NAME); 2847 returnBuilder.startCall("next0", EXECUTE_CHAINED);
2873 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, null); 2848 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, null);
2874 returnBuilder.end(); 2849 returnBuilder.end();
2875 } else if (specialization.isUninitialized()) { 2850 } else if (specialization.isUninitialized()) {
2876 returnBuilder.startCall("super", EXECUTE_SPECIALIZE_NAME); 2851 returnBuilder.startCall(EXECUTE_UNINITIALIZED);
2877 returnBuilder.string("0");
2878 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, null); 2852 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, null);
2879 returnBuilder.doubleQuote("Uninitialized monomorphic");
2880 returnBuilder.end(); 2853 returnBuilder.end();
2881 } else if (specialization.getMethod() == null && !node.needsRewrites(context)) { 2854 } else if (specialization.getMethod() == null && !node.needsRewrites(context)) {
2882 emitEncounteredSynthetic(builder, specialization); 2855 emitEncounteredSynthetic(builder, specialization);
2883 } else if (specialization.isGeneric()) {
2884 returnBuilder.startCall("super", EXECUTE_GENERIC_NAME);
2885 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, node.needsFrame(getContext()), null);
2886 returnBuilder.end();
2887 } else { 2856 } else {
2888 returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null)); 2857 returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null));
2889 } 2858 }
2890 2859
2891 if (!returnBuilder.isEmpty()) { 2860 if (!returnBuilder.isEmpty()) {
2893 TypeData sourceType = specialization.getReturnType().getTypeSystemType(); 2862 TypeData sourceType = specialization.getReturnType().getTypeSystemType();
2894 2863
2895 builder.startReturn(); 2864 builder.startReturn();
2896 if (targetType == null || sourceType == null) { 2865 if (targetType == null || sourceType == null) {
2897 builder.tree(returnBuilder.getRoot()); 2866 builder.tree(returnBuilder.getRoot());
2898 } else if (sourceType.needsCastTo(getContext(), targetType)) { 2867 } else if (sourceType.needsCastTo(targetType)) {
2899 String castMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType); 2868 String castMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType);
2900 if (!executable.hasUnexpectedValue(context)) { 2869 if (!executable.hasUnexpectedValue(context)) {
2901 castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType); 2870 castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType);
2902 } 2871 }
2903 builder.tree(createCallTypeSystemMethod(context, parent, node, castMethodName, returnBuilder.getRoot())); 2872 builder.tree(createCallTypeSystemMethod(parent, node, castMethodName, returnBuilder.getRoot()));
2904 } else { 2873 } else {
2905 builder.tree(returnBuilder.getRoot()); 2874 builder.tree(returnBuilder.getRoot());
2906 } 2875 }
2907 builder.end(); 2876 builder.end();
2908 } 2877 }
2909 2878
2910 if (!specialization.getExceptions().isEmpty()) { 2879 if (!specialization.getExceptions().isEmpty()) {
2911 for (SpecializationThrowsData exception : specialization.getExceptions()) { 2880 for (SpecializationThrowsData exception : specialization.getExceptions()) {
2912 builder.end().startCatchBlock(exception.getJavaClass(), "ex"); 2881 builder.end().startCatchBlock(exception.getJavaClass(), "ex");
2913 builder.tree(createDeoptimize(builder)); 2882 builder.tree(createDeoptimize(builder));
2914 builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization, null, "Thrown " + Utils.getSimpleName(exception.getJavaClass()))); 2883 builder.tree(createCallRewriteMonomorphic(parent, executable.hasUnexpectedValue(context), executable.getType(), specialization, null,
2884 "Thrown " + Utils.getSimpleName(exception.getJavaClass())));
2915 } 2885 }
2916 builder.end(); 2886 builder.end();
2917 } 2887 }
2918 if (!specialization.getAssumptions().isEmpty()) { 2888 if (!specialization.getAssumptions().isEmpty()) {
2919 builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex"); 2889 builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex");
2920 builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization, null, "Assumption failed")); 2890 builder.tree(createCallRewriteMonomorphic(parent, executable.hasUnexpectedValue(context), executable.getType(), specialization, null, "Assumption failed"));
2921 builder.end(); 2891 builder.end();
2922 } 2892 }
2923 2893
2924 return builder.getRoot(); 2894 return builder.getRoot();
2925 } 2895 }
2926 2896
2927 protected CodeExecutableElement createCopyConstructorFactoryMethod(TypeMirror baseType, SpecializationData specialization) { 2897 protected CodeExecutableElement createCopyConstructorFactoryMethod(TypeMirror baseType, SpecializationData specialization) {
2928 List<ActualParameter> implicitTypeParams = getImplicitTypeParameters(specialization); 2898 List<ActualParameter> implicitTypeParams = getImplicitTypeParameters(specialization);
2929 CodeVariableElement[] parameters = new CodeVariableElement[implicitTypeParams.size() + 1];
2930 int i = 0;
2931 String baseName = "current"; 2899 String baseName = "current";
2932 parameters[i++] = new CodeVariableElement(specialization.getNode().getNodeType(), baseName); 2900 CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), FACTORY_METHOD_NAME);
2901 method.addParameter(new CodeVariableElement(specialization.getNode().getNodeType(), baseName));
2933 for (ActualParameter implicitTypeParam : implicitTypeParams) { 2902 for (ActualParameter implicitTypeParam : implicitTypeParams) {
2934 parameters[i++] = new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(implicitTypeParam)); 2903 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(implicitTypeParam)));
2935 } 2904 }
2936 CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), CREATE_SPECIALIZATION_NAME, parameters);
2937 CodeTreeBuilder builder = method.createBuilder(); 2905 CodeTreeBuilder builder = method.createBuilder();
2938 builder.startReturn(); 2906 builder.startReturn();
2939 builder.startNew(getElement().asType()); 2907 builder.startNew(getElement().asType());
2940 builder.startGroup().cast(baseType, CodeTreeBuilder.singleString(baseName)).end(); 2908 builder.startGroup().cast(baseType, CodeTreeBuilder.singleString(baseName)).end();
2941 for (ActualParameter param : implicitTypeParams) { 2909 for (ActualParameter param : implicitTypeParams) {
2945 return method; 2913 return method;
2946 } 2914 }
2947 2915
2948 protected CodeExecutableElement createConstructorFactoryMethod(SpecializationData specialization, ExecutableElement constructor) { 2916 protected CodeExecutableElement createConstructorFactoryMethod(SpecializationData specialization, ExecutableElement constructor) {
2949 List<? extends VariableElement> parameters = constructor.getParameters(); 2917 List<? extends VariableElement> parameters = constructor.getParameters();
2950 CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), CREATE_SPECIALIZATION_NAME, 2918 CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), FACTORY_METHOD_NAME,
2951 parameters.toArray(new CodeVariableElement[parameters.size()])); 2919 parameters.toArray(new CodeVariableElement[parameters.size()]));
2952 CodeTreeBuilder builder = method.createBuilder(); 2920 CodeTreeBuilder builder = method.createBuilder();
2953 builder.startReturn(); 2921 builder.startReturn();
2954 builder.startNew(getElement().asType()); 2922 builder.startNew(getElement().asType());
2955 for (VariableElement param : parameters) { 2923 for (VariableElement param : parameters) {