comparison graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java @ 10596:f43eb2f1bbbc

Truffle-DSL: code-generation of polymorphic caching
author Christian Humer <christian.humer@gmail.com>
date Mon, 01 Jul 2013 20:32:20 +0200
parents 00b70a864d3b
children
comparison
equal deleted inserted replaced
10595:47233c73ca58 10596:f43eb2f1bbbc
30 import javax.lang.model.element.*; 30 import javax.lang.model.element.*;
31 import javax.lang.model.type.*; 31 import javax.lang.model.type.*;
32 import javax.lang.model.util.*; 32 import javax.lang.model.util.*;
33 33
34 import com.oracle.truffle.api.codegen.*; 34 import com.oracle.truffle.api.codegen.*;
35 import com.oracle.truffle.api.nodes.NodeInfo.Kind;
35 import com.oracle.truffle.codegen.processor.*; 36 import com.oracle.truffle.codegen.processor.*;
36 import com.oracle.truffle.codegen.processor.ast.*; 37 import com.oracle.truffle.codegen.processor.ast.*;
37 import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; 38 import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality;
38 import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind; 39 import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind;
39 import com.oracle.truffle.codegen.processor.template.*; 40 import com.oracle.truffle.codegen.processor.template.*;
68 name += Utils.firstLetterUpperCase(specialization.getId()); 69 name += Utils.firstLetterUpperCase(specialization.getId());
69 name += "Node"; 70 name += "Node";
70 return name; 71 return name;
71 } 72 }
72 73
74 private static String nodePolymorphicClassName(NodeData node, SpecializationData specialization) {
75 String nodeid = node.getNodeId();
76 if (nodeid.endsWith("Node") && !nodeid.equals("Node")) {
77 nodeid = nodeid.substring(0, nodeid.length() - 4);
78 }
79
80 String name = Utils.firstLetterUpperCase(nodeid);
81 int index = specialization == null ? 0 : node.getPolymorphicSpecializations().indexOf(specialization);
82 if (index == 0) {
83 name += "PolymorphicNode";
84 } else {
85 name += "Polymorphic" + index + "Node";
86 }
87 return name;
88 }
89
73 private static String valueNameEvaluated(ActualParameter targetParameter) { 90 private static String valueNameEvaluated(ActualParameter targetParameter) {
74 return valueName(targetParameter) + "Evaluated"; 91 return valueName(targetParameter) + "Evaluated";
75 } 92 }
76 93
77 private static String valueName(ActualParameter param) { 94 private static String valueName(ActualParameter param) {
80 97
81 private static String castValueName(ActualParameter parameter) { 98 private static String castValueName(ActualParameter parameter) {
82 return valueName(parameter) + "Cast"; 99 return valueName(parameter) + "Cast";
83 } 100 }
84 101
85 private void addInternalValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame) { 102 private void addInternalValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame, boolean evaluated) {
86 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { 103 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
87 method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue")); 104 method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue"));
88 } 105 }
89 for (ActualParameter parameter : specialization.getParameters()) { 106 for (ActualParameter parameter : specialization.getParameters()) {
90 ParameterSpec spec = parameter.getSpecification(); 107 ParameterSpec spec = parameter.getSpecification();
93 } 110 }
94 if (spec.isLocal()) { 111 if (spec.isLocal()) {
95 continue; 112 continue;
96 } 113 }
97 114
98 method.addParameter(new CodeVariableElement(parameter.getType(), valueName(parameter))); 115 String name = valueName(parameter);
116 if (evaluated && spec.isSignature()) {
117 name = valueNameEvaluated(parameter);
118 }
119
120 method.addParameter(new CodeVariableElement(parameter.getType(), name));
99 } 121 }
100 } 122 }
101 123
102 private void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, boolean includeImplicit) { 124 private void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, boolean includeImplicit) {
103 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { 125 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
150 boolean castedValues = sourceMethod != targetMethod; 172 boolean castedValues = sourceMethod != targetMethod;
151 173
152 builder.startGroup(); 174 builder.startGroup();
153 ExecutableElement method = targetMethod.getMethod(); 175 ExecutableElement method = targetMethod.getMethod();
154 if (method == null) { 176 if (method == null) {
155 throw new IllegalStateException("Cannot call synthetic operation methods."); 177 throw new UnsupportedOperationException();
156 } 178 }
157 TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement()); 179 TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement());
158 NodeData node = (NodeData) targetMethod.getTemplate(); 180 NodeData node = (NodeData) targetMethod.getTemplate();
159 181
160 if (target == null) { 182 if (target == null) {
281 body.staticReference(singleton.getEnclosingElement().asType(), singleton.getSimpleName().toString()); 303 body.staticReference(singleton.getEnclosingElement().asType(), singleton.getSimpleName().toString());
282 body.string(".").startCall(methodName); 304 body.string(".").startCall(methodName);
283 } 305 }
284 306
285 private CodeTree createGuardAndCast(CodeTreeBuilder parent, String conditionPrefix, SpecializationData sourceSpecialization, SpecializationData targetSpecialization, boolean castValues, 307 private CodeTree createGuardAndCast(CodeTreeBuilder parent, String conditionPrefix, SpecializationData sourceSpecialization, SpecializationData targetSpecialization, boolean castValues,
286 CodeTree guardedStatements, CodeTree elseStatements, boolean emitAssumptions) { 308 CodeTree guardedStatements, CodeTree elseStatements, boolean emitAssumptions, boolean forceElse) {
287 309
288 NodeData node = targetSpecialization.getNode(); 310 NodeData node = targetSpecialization.getNode();
289 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 311 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
290 CodeTree implicitGuards = createImplicitGuards(parent, conditionPrefix, sourceSpecialization, targetSpecialization, emitAssumptions); 312 CodeTree implicitGuards = createImplicitGuards(parent, conditionPrefix, sourceSpecialization, targetSpecialization, emitAssumptions);
291 CodeTree explicitGuards = createExplicitGuards(parent, implicitGuards == null ? conditionPrefix : null, sourceSpecialization, targetSpecialization); 313 CodeTree explicitGuards = createExplicitGuards(parent, implicitGuards == null ? conditionPrefix : null, sourceSpecialization, targetSpecialization);
345 } 367 }
346 368
347 builder.tree(guardedStatements); 369 builder.tree(guardedStatements);
348 370
349 builder.end(ifCount); 371 builder.end(ifCount);
350 if (elseStatements != null && ifCount > 0) { 372 if (elseStatements != null && (forceElse || ifCount > 0)) {
351 builder.tree(elseStatements); 373 builder.tree(elseStatements);
352 } 374 }
353 return builder.getRoot(); 375 return builder.getRoot();
354 } 376 }
355 377
529 builder.end(); // block 551 builder.end(); // block
530 } 552 }
531 return builder.getRoot(); 553 return builder.getRoot();
532 } 554 }
533 555
534 private void emitEncounteredSynthetic(CodeTreeBuilder builder, SpecializationData current) { 556 protected void emitEncounteredSynthetic(CodeTreeBuilder builder, TemplateMethod current) {
535 builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)); 557 builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class));
536 builder.startGroup(); 558 builder.startCall("createInfo0");
537 String sep = null; 559 builder.doubleQuote("Unsupported values");
538 for (ActualParameter parameters : current.getParameters()) { 560 addInternalValueParameterNames(builder, current, current, null, false, true);
539 if (parameters.getSpecification().isSignature()) { 561 builder.end().end().end();
540 if (sep == null) {
541 builder.doubleQuote("Unsupported values: " + parameters.getLocalName() + " = ");
542 sep = ", ";
543 } else {
544 builder.string(" + ");
545 builder.doubleQuote(sep + parameters.getLocalName() + " = ");
546 }
547 builder.string(" + ");
548 builder.string(parameters.getLocalName());
549 }
550 }
551 builder.end();
552 builder.end().end();
553 } 562 }
554 563
555 private static List<ExecutableElement> findUserConstructors(TypeMirror nodeType) { 564 private static List<ExecutableElement> findUserConstructors(TypeMirror nodeType) {
556 List<ExecutableElement> constructors = new ArrayList<>(); 565 List<ExecutableElement> constructors = new ArrayList<>();
557 for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(nodeType).getEnclosedElements())) { 566 for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(nodeType).getEnclosedElements())) {
593 602
594 if (!Utils.typeEquals(var.asType(), type.asType())) { 603 if (!Utils.typeEquals(var.asType(), type.asType())) {
595 return false; 604 return false;
596 } 605 }
597 return true; 606 return true;
598 }
599
600 private static CodeTree createReturnNewSpecialization(CodeTreeBuilder parent, SpecializationData specialization, String thisLocalVariableName, boolean hasCopyConstructor) {
601 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
602 builder.startReturn().startNew(nodeSpecializationClassName(specialization));
603 if (hasCopyConstructor) {
604 builder.string(thisLocalVariableName);
605 }
606 builder.end().end();
607 return builder.getRoot();
608 } 607 }
609 608
610 @Override 609 @Override
611 protected void createChildren(NodeData node) { 610 protected void createChildren(NodeData node) {
612 Map<NodeData, List<TypeElement>> childTypes = new LinkedHashMap<>(); 611 Map<NodeData, List<TypeElement>> childTypes = new LinkedHashMap<>();
620 if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) { 619 if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) {
621 add(new NodeFactoryFactory(context, childTypes), node); 620 add(new NodeFactoryFactory(context, childTypes), node);
622 } 621 }
623 } 622 }
624 623
625 private class NodeBaseFactory extends ClassElementFactory<NodeData> {
626
627 public NodeBaseFactory(ProcessorContext context) {
628 super(context);
629 }
630
631 @Override
632 protected CodeTypeElement create(NodeData node) {
633 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, ABSTRACT, STATIC), baseClassName(node), node.getNodeType(), false);
634
635 for (NodeChildData child : node.getChildren()) {
636 clazz.add(createChildField(child));
637
638 if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) {
639 ExecutableElement getter = (ExecutableElement) child.getAccessElement();
640 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), getter);
641 method.getModifiers().remove(Modifier.ABSTRACT);
642 method.createBuilder().startReturn().string("this.").string(child.getName()).end();
643 clazz.add(method);
644 }
645 }
646
647 for (String assumption : node.getAssumptions()) {
648 clazz.add(createAssumptionField(assumption));
649 }
650
651 createConstructors(node, clazz);
652
653 if (node.getExtensionElements() != null) {
654 clazz.getEnclosedElements().addAll(node.getExtensionElements());
655 }
656
657 return clazz;
658 }
659
660 @Override
661 protected void createChildren(NodeData node) {
662 CodeTypeElement clazz = getElement();
663
664 if (node.needsRewrites(context)) {
665 clazz.add(createGenericExecute(node, EXECUTE_SPECIALIZE_NAME, true));
666 }
667
668 if (node.getGenericSpecialization() != null) {
669 clazz.add(createGenericExecute(node, EXECUTE_GENERIC_NAME, false));
670 }
671 }
672
673 private void createConstructors(NodeData node, CodeTypeElement clazz) {
674 List<ExecutableElement> constructors = findUserConstructors(node.getNodeType());
675 if (constructors.isEmpty()) {
676 clazz.add(createUserConstructor(clazz, null));
677 } else {
678 for (ExecutableElement constructor : constructors) {
679 clazz.add(createUserConstructor(clazz, constructor));
680 }
681 }
682 if (node.needsRewrites(getContext())) {
683 clazz.add(createCopyConstructor(clazz, findCopyConstructor(node.getNodeType())));
684 }
685 }
686
687 private CodeExecutableElement createUserConstructor(CodeTypeElement type, ExecutableElement superConstructor) {
688 CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
689 CodeTreeBuilder builder = method.createBuilder();
690
691 if (superConstructor != null) {
692 for (VariableElement param : superConstructor.getParameters()) {
693 method.getParameters().add(CodeVariableElement.clone(param));
694 }
695 }
696
697 for (VariableElement var : type.getFields()) {
698 NodeChildData child = getModel().findChild(var.getSimpleName().toString());
699 if (child != null) {
700 method.getParameters().add(new CodeVariableElement(child.getOriginalType(), child.getName()));
701 } else {
702 method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString()));
703 }
704 }
705
706 if (superConstructor != null) {
707 builder.startStatement().startSuperCall();
708 for (VariableElement param : superConstructor.getParameters()) {
709 builder.string(param.getSimpleName().toString());
710 }
711 builder.end().end();
712 }
713
714 for (VariableElement var : type.getFields()) {
715 builder.startStatement();
716 String fieldName = var.getSimpleName().toString();
717
718 CodeTree fieldInit = CodeTreeBuilder.singleString(var.getSimpleName().toString());
719 builder.string("this.").string(var.getSimpleName().toString());
720
721 NodeChildData child = getModel().findChild(fieldName);
722 if (child != null) {
723 CreateCastData createCast = getModel().findCast(child.getName());
724 if (createCast != null) {
725 fieldInit = createTemplateMethodCall(builder, null, getModel().getGenericSpecialization(), createCast, null, child.getName());
726 }
727 }
728
729 if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNode())) {
730 builder.string(" = adoptChild(").tree(fieldInit).string(")");
731 } else if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) {
732 builder.string(" = adoptChildren(").tree(fieldInit).string(")");
733 } else {
734 builder.string(" = ").tree(fieldInit);
735 }
736 builder.end();
737 }
738 return method;
739 }
740
741 private CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor) {
742 CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
743 CodeTreeBuilder builder = method.createBuilder();
744 if (!(superConstructor == null && type.getFields().isEmpty())) {
745 method.getParameters().add(new CodeVariableElement(type.asType(), "copy"));
746 }
747
748 if (superConstructor != null) {
749 builder.startStatement().startSuperCall().string("copy").end().end();
750 }
751
752 for (VariableElement var : type.getFields()) {
753 builder.startStatement();
754 String varName = var.getSimpleName().toString();
755 builder.string("this.").string(varName);
756 if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNode())) {
757 builder.string(" = adoptChild(copy.").string(varName).string(")");
758 } else if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) {
759 builder.string(" = adoptChildren(copy.").string(varName).string(")");
760 } else {
761 builder.string(" = copy.").string(varName);
762 }
763 builder.end();
764 }
765 return method;
766 }
767
768 private CodeVariableElement createAssumptionField(String assumption) {
769 CodeVariableElement var = new CodeVariableElement(getContext().getTruffleTypes().getAssumption(), assumption);
770 var.getModifiers().add(Modifier.FINAL);
771 return var;
772 }
773
774 private CodeVariableElement createChildField(NodeChildData child) {
775 CodeVariableElement var = new CodeVariableElement(child.getNodeType(), child.getName());
776 var.getModifiers().add(Modifier.PROTECTED);
777
778 DeclaredType annotationType;
779 if (child.getCardinality() == Cardinality.MANY) {
780 var.getModifiers().add(Modifier.FINAL);
781 annotationType = getContext().getTruffleTypes().getChildrenAnnotation();
782 } else {
783 annotationType = getContext().getTruffleTypes().getChildAnnotation();
784 }
785
786 var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType));
787 return var;
788 }
789
790 private CodeExecutableElement createGenericExecute(NodeData node, String name, boolean specialize) {
791 TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType();
792
793 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, name);
794 CodeTreeBuilder builder = method.createBuilder();
795
796 String prefix = null;
797 if (specialize) {
798 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState"));
799
800 builder.startStatement();
801 builder.startStaticCall(getContext().getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end();
802 builder.end();
803
804 emitSpecializationListeners(builder, node);
805 builder.defaultDeclaration(node.getGenericSpecialization().getReturnSignature().getPrimitiveType(), "result");
806 if (node.getGenericSpecialization().isUseSpecializationsForGeneric()) {
807 builder.defaultDeclaration(getContext().getType(boolean.class), "resultIsSet");
808 }
809 builder.startStatement().string("boolean allowed = (minimumState == ").string(nodeSpecializationClassName(node.getSpecializations().get(0))).string(".class)").end();
810 prefix = null;
811
812 builder.startStatement().string("StringBuilder message = new StringBuilder(reason)").end();
813 builder.startStatement().startCall("message", "append").doubleQuote(" (").end().end();
814
815 String sep = null;
816 for (ActualParameter parameter : node.getGenericSpecialization().getParameters()) {
817 if (!parameter.getSpecification().isSignature()) {
818 continue;
819 }
820
821 builder.startStatement();
822 builder.string("message");
823 if (sep != null) {
824 builder.startCall(".append").doubleQuote(sep).end();
825 }
826 builder.startCall(".append").doubleQuote(parameter.getLocalName()).end();
827 builder.startCall(".append").doubleQuote(" = ").end();
828 builder.startCall(".append").string(parameter.getLocalName()).end();
829 builder.end();
830
831 if (!Utils.isPrimitive(parameter.getType())) {
832 builder.startIf().string(parameter.getLocalName() + " != null").end();
833 builder.startBlock();
834 }
835 builder.startStatement();
836 if (Utils.isPrimitive(parameter.getType())) {
837 builder.startCall("message.append").doubleQuote(" (" + Utils.getSimpleName(parameter.getType()) + ")").end();
838 } else {
839 builder.startCall("message.append").doubleQuote(" (").end();
840 builder.startCall(".append").string(parameter.getLocalName() + ".getClass().getSimpleName()").end();
841 builder.startCall(".append").doubleQuote(")").end();
842 }
843 builder.end();
844 if (!Utils.isPrimitive(parameter.getType())) {
845 builder.end();
846 }
847
848 sep = ", ";
849 }
850
851 builder.startStatement().startCall("message", "append").doubleQuote(")").end().end();
852 }
853
854 addInternalValueParameters(method, node.getGenericSpecialization(), true);
855
856 if (specialize) {
857 method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason"));
858 }
859
860 List<SpecializationData> specializations = node.getSpecializations();
861 if (!specialize && !node.getGenericSpecialization().isUseSpecializationsForGeneric()) {
862 specializations = Arrays.asList(node.getGenericSpecialization());
863 }
864
865 // group specializations for reachabiltiy
866 List<SpecializationData> unreachableSpecializations = new ArrayList<>();
867 List<SpecializationData> filteredSpecializations = new ArrayList<>();
868 if (!specialize) {
869 unreachableSpecializations = new ArrayList<>();
870 filteredSpecializations = new ArrayList<>();
871 boolean unreachable = false;
872 for (SpecializationData specialization : specializations) {
873 if (unreachable) {
874 unreachableSpecializations.add(specialization);
875 } else {
876 filteredSpecializations.add(specialization);
877 if (!specialization.isUninitialized() && specialization.isGenericSpecialization(getContext())) {
878 unreachable = true;
879 }
880 }
881 }
882 } else {
883 unreachableSpecializations = Collections.emptyList();
884 filteredSpecializations = specializations;
885 }
886
887 for (SpecializationData current : filteredSpecializations) {
888 if (current.isUninitialized()) {
889 continue;
890 }
891 CodeTreeBuilder execute = new CodeTreeBuilder(builder);
892
893 execute.tree(createGenericInvoke(builder, current, specialize));
894
895 if (specialize && !current.isGeneric()) {
896 builder.startStatement().string("allowed = allowed || (minimumState == ").string(nodeSpecializationClassName(current)).string(".class)").end();
897 }
898
899 builder.tree(createGuardAndCast(builder, prefix, current.getNode().getGenericSpecialization(), current, true, execute.getRoot(), null, true));
900 }
901
902 for (SpecializationData specializationData : unreachableSpecializations) {
903 builder.string("// unreachable ").string(specializationData.getId()).newLine();
904 }
905
906 return method;
907 }
908
909 private CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData current, boolean specialize) {
910 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
911
912 if (!current.getExceptions().isEmpty()) {
913 builder.startTryBlock();
914 }
915
916 CodeTree executeCall = null;
917 if (current.getMethod() != null) {
918 executeCall = createTemplateMethodCall(builder, null, current.getNode().getGenericSpecialization(), current, null);
919 }
920
921 if (specialize && executeCall == null && !current.getNode().getGenericSpecialization().isUseSpecializationsForGeneric()) {
922 emitEncounteredSynthetic(builder, current);
923 } else if (specialize) {
924
925 if (current.getNode().getGenericSpecialization().isUseSpecializationsForGeneric()) {
926 builder.startIf().string("!resultIsSet").end().startBlock();
927 if (executeCall != null) {
928 if (current.getReturnSignature().isVoid()) {
929 builder.statement(executeCall);
930 } else {
931 builder.startStatement().string("result = ").tree(executeCall).end();
932 }
933 builder.statement("resultIsSet = true");
934 } else {
935 emitEncounteredSynthetic(builder, current);
936 }
937 builder.end();
938 }
939
940 if (!current.isGeneric()) {
941 builder.startIf().string("allowed").end().startBlock();
942 }
943
944 if (!current.getNode().getGenericSpecialization().isUseSpecializationsForGeneric()) {
945 if (current.getReturnSignature().isVoid()) {
946 builder.statement(executeCall);
947 } else {
948 builder.startStatement().string("result = ").tree(executeCall).end();
949 }
950 }
951
952 builder.startStatement().startCall("super", "replace");
953 builder.startGroup().startNew(nodeSpecializationClassName(current)).string("this").end().end();
954 builder.string("message.toString()");
955 builder.end().end();
956
957 if (current.getReturnSignature().isVoid()) {
958 builder.returnStatement();
959 } else {
960 builder.startReturn().string("result").end();
961 }
962 if (!current.isGeneric()) {
963 builder.end();
964 }
965 } else {
966 if (executeCall == null) {
967 emitEncounteredSynthetic(builder, current);
968 } else {
969 builder.startReturn().tree(executeCall).end();
970 }
971 }
972
973 if (!current.getExceptions().isEmpty()) {
974 for (SpecializationThrowsData exception : current.getExceptions()) {
975 builder.end().startCatchBlock(exception.getJavaClass(), "rewriteEx");
976 builder.string("// fall through").newLine();
977 }
978 builder.end();
979 }
980
981 return builder.getRoot();
982 }
983
984 private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) {
985 for (TemplateMethod listener : node.getSpecializationListeners()) {
986 builder.startStatement();
987 builder.tree(createTemplateMethodCall(builder, null, listener, listener, null));
988 builder.end(); // statement
989 }
990 }
991 }
992
993 private class NodeFactoryFactory extends ClassElementFactory<NodeData> { 624 private class NodeFactoryFactory extends ClassElementFactory<NodeData> {
994 625
995 private final Map<NodeData, List<TypeElement>> childTypes; 626 private final Map<NodeData, List<TypeElement>> childTypes;
996 627
997 private CodeTypeElement generatedNode; 628 private CodeTypeElement generatedNode;
1019 650
1020 Modifier createVisibility = Utils.getVisibility(clazz.getModifiers()); 651 Modifier createVisibility = Utils.getVisibility(clazz.getModifiers());
1021 652
1022 if (node.needsFactory()) { 653 if (node.needsFactory()) {
1023 NodeBaseFactory factory = new NodeBaseFactory(context); 654 NodeBaseFactory factory = new NodeBaseFactory(context);
1024 add(factory, node); 655 add(factory, node.getGenericSpecialization() == null ? node.getSpecializations().get(0) : node.getGenericSpecialization());
1025 generatedNode = factory.getElement(); 656 generatedNode = factory.getElement();
1026 657
1027 if (node.needsRewrites(context)) { 658 if (node.needsRewrites(context)) {
1028 clazz.add(createCreateSpecializedMethod(node, createVisibility)); 659 clazz.add(createCreateGenericMethod(node, createVisibility));
1029 } 660 }
1030 661
1031 createFactoryMethods(node, clazz, createVisibility); 662 createFactoryMethods(node, clazz, createVisibility);
1032 663
664 PolymorphicNodeFactory generic = null;
665 for (SpecializationData specialization : node.getPolymorphicSpecializations()) {
666 PolymorphicNodeFactory polymorphicFactory = new PolymorphicNodeFactory(context, generic == null ? generatedNode : generic.getElement(), generic == null);
667 add(polymorphicFactory, specialization);
668 if (generic == null) {
669 generic = polymorphicFactory;
670 }
671 }
672
1033 for (SpecializationData specialization : node.getSpecializations()) { 673 for (SpecializationData specialization : node.getSpecializations()) {
674 if (!specialization.isReachable()) {
675 continue;
676 }
1034 add(new SpecializedNodeFactory(context, generatedNode), specialization); 677 add(new SpecializedNodeFactory(context, generatedNode), specialization);
1035 } 678 }
1036 679
1037 TypeMirror nodeFactory = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(NodeFactory.class)), node.getNodeType()); 680 TypeMirror nodeFactory = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(NodeFactory.class)), node.getNodeType());
1038 clazz.getImplements().add(nodeFactory); 681 clazz.getImplements().add(nodeFactory);
1039 clazz.add(createCreateNodeMethod(node)); 682 clazz.add(createCreateNodeMethod(node));
1040 clazz.add(createCreateNodeSpecializedMethod(node)); 683 clazz.add(createCreateNodeGenericMethod(node));
1041 clazz.add(createGetNodeClassMethod(node)); 684 clazz.add(createGetNodeClassMethod(node));
1042 clazz.add(createGetNodeSignaturesMethod()); 685 clazz.add(createGetNodeSignaturesMethod());
1043 clazz.add(createGetChildrenSignatureMethod(node)); 686 clazz.add(createGetChildrenSignatureMethod(node));
1044 clazz.add(createGetInstanceMethod(node, createVisibility)); 687 clazz.add(createGetInstanceMethod(node, createVisibility));
1045 clazz.add(createInstanceConstant(node, clazz.asType())); 688 clazz.add(createInstanceConstant(node, clazz.asType()));
1195 builder.end().end(); 838 builder.end().end();
1196 builder.end(); // else block 839 builder.end(); // else block
1197 return method; 840 return method;
1198 } 841 }
1199 842
1200 private CodeExecutableElement createCreateNodeSpecializedMethod(NodeData node) { 843 private CodeExecutableElement createCreateNodeGenericMethod(NodeData node) {
1201 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNodeSpecialized"); 844 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNodeGeneric");
1202 CodeVariableElement nodeParam = new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME); 845 CodeVariableElement nodeParam = new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME);
1203 CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Class.class), "types");
1204 method.addParameter(nodeParam); 846 method.addParameter(nodeParam);
1205 method.addParameter(arguments);
1206 method.setVarArgs(true);
1207 847
1208 CodeTreeBuilder builder = method.createBuilder(); 848 CodeTreeBuilder builder = method.createBuilder();
1209 if (!node.needsRewrites(getContext())) { 849 if (!node.needsRewrites(getContext())) {
1210 builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).doubleQuote("No specialized version.").end().end(); 850 builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).doubleQuote("No specialized version.").end().end();
1211 } else { 851 } else {
1212 builder.startIf(); 852 builder.startReturn().startCall("createGeneric");
1213 builder.string("types.length == 1");
1214 builder.end();
1215 builder.startBlock();
1216
1217 builder.startReturn().startCall("createSpecialized");
1218 builder.startGroup();
1219 builder.string(THIS_NODE_LOCAL_VAR_NAME); 853 builder.string(THIS_NODE_LOCAL_VAR_NAME);
1220 builder.end();
1221 builder.string("types[0]");
1222 builder.end().end(); 854 builder.end().end();
1223 855 }
1224 builder.end();
1225 builder.startElseBlock();
1226 builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class));
1227 builder.doubleQuote("Invalid createSpecialized signature.");
1228 builder.end().end();
1229 builder.end();
1230 }
1231
1232 return method; 856 return method;
1233 } 857 }
1234 858
1235 private ExecutableElement createGetInstanceMethod(NodeData node, Modifier visibility) { 859 private ExecutableElement createGetInstanceMethod(NodeData node, Modifier visibility) {
1236 TypeElement nodeFactoryType = Utils.fromTypeMirror(getContext().getType(NodeFactory.class)); 860 TypeElement nodeFactoryType = Utils.fromTypeMirror(getContext().getType(NodeFactory.class));
1360 } 984 }
1361 body.end(); 985 body.end();
1362 return method; 986 return method;
1363 } 987 }
1364 988
1365 private CodeExecutableElement createCreateSpecializedMethod(NodeData node, Modifier visibility) { 989 private CodeExecutableElement createCreateGenericMethod(NodeData node, Modifier visibility) {
1366 CodeExecutableElement method = new CodeExecutableElement(modifiers(), node.getNodeType(), "createSpecialized"); 990 CodeExecutableElement method = new CodeExecutableElement(modifiers(), node.getNodeType(), "createGeneric");
1367 if (visibility != null) { 991 if (visibility != null) {
1368 method.getModifiers().add(visibility); 992 method.getModifiers().add(visibility);
1369 } 993 }
1370 method.getModifiers().add(Modifier.STATIC); 994 method.getModifiers().add(Modifier.STATIC);
1371
1372 method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); 995 method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME));
1373 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "specializationClass"));
1374 996
1375 CodeTreeBuilder body = method.createBuilder(); 997 CodeTreeBuilder body = method.createBuilder();
1376 998
1377 boolean hasCopyConstructor = findCopyConstructor(generatedNode.asType()) != null; 999 SpecializationData found = null;
1378 1000 List<SpecializationData> specializations = node.getSpecializations();
1379 final String thisLocalVariableName = THIS_NODE_LOCAL_VAR_NAME + "Cast"; 1001 for (int i = 0; i < specializations.size(); i++) {
1380 1002 if (specializations.get(i).isReachable()) {
1381 if (hasCopyConstructor) { 1003 found = specializations.get(i);
1382 body.startStatement(); 1004 }
1383 body.type(generatedNode.asType()).string(" ").string(thisLocalVariableName); 1005 }
1384 body.string(" = ").string("(").type(generatedNode.asType()).string(") ").string(THIS_NODE_LOCAL_VAR_NAME); 1006
1385 body.end(); 1007 if (found == null) {
1386 } 1008 body.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end();
1387 1009 } else {
1388 boolean first = true; 1010 body.startReturn().startNew(nodeSpecializationClassName(found)).startGroup().cast(baseClassName(node)).string(THIS_NODE_LOCAL_VAR_NAME).end().end().end();
1389 for (TypeData type : node.getTypeSystem().getTypes()) { 1011 }
1390 SpecializationData specialization = node.findUniqueSpecialization(type);
1391 if (specialization != null && !type.isGeneric()) {
1392 if (first) {
1393 body.startIf();
1394 first = false;
1395 } else {
1396 body.startElseIf();
1397 }
1398 body.string("specializationClass == ").type(type.getBoxedType()).string(".class").end().startBlock();
1399 body.tree(createReturnNewSpecialization(body, specialization, thisLocalVariableName, hasCopyConstructor));
1400
1401 body.end(); // if
1402 }
1403 }
1404 body.tree(createReturnNewSpecialization(body, node.getGenericSpecialization(), thisLocalVariableName, hasCopyConstructor));
1405 return method; 1012 return method;
1406 } 1013 }
1407 1014 }
1408 } 1015
1409 1016 private class NodeBaseFactory extends ClassElementFactory<SpecializationData> {
1410 private class SpecializedNodeFactory extends ClassElementFactory<SpecializationData> { 1017
1411 1018 public NodeBaseFactory(ProcessorContext context) {
1412 private final CodeTypeElement nodeGen;
1413
1414 public SpecializedNodeFactory(ProcessorContext context, CodeTypeElement nodeGen) {
1415 super(context); 1019 super(context);
1416 this.nodeGen = nodeGen;
1417 } 1020 }
1418 1021
1419 @Override 1022 @Override
1420 public CodeTypeElement create(SpecializationData specialization) { 1023 protected CodeTypeElement create(SpecializationData specialization) {
1421 NodeData node = specialization.getNode(); 1024 NodeData node = specialization.getNode();
1422 TypeMirror baseType = node.getNodeType(); 1025 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, ABSTRACT, STATIC), baseClassName(node), node.getNodeType(), false);
1423 if (nodeGen != null) { 1026
1424 baseType = nodeGen.asType(); 1027 for (NodeChildData child : node.getChildren()) {
1425 } 1028 clazz.add(createChildField(child));
1426 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false); 1029
1427 1030 if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) {
1428 String shortName = specialization.getNode().getShortName(); 1031 ExecutableElement getter = (ExecutableElement) child.getAccessElement();
1429 CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(getContext().getTruffleTypes().getNodeInfoAnnotation()); 1032 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), getter);
1430 if (shortName != null) { 1033 method.getModifiers().remove(Modifier.ABSTRACT);
1431 nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("shortName"), new CodeAnnotationValue(shortName)); 1034 method.createBuilder().startReturn().string("this.").string(child.getName()).end();
1432 } 1035 clazz.add(method);
1433 1036 }
1434 DeclaredType nodeinfoKind = getContext().getTruffleTypes().getNodeInfoKind(); 1037 }
1435 VariableElement kind; 1038
1436 if (specialization.isGeneric()) { 1039 for (String assumption : node.getAssumptions()) {
1437 kind = Utils.findVariableElement(nodeinfoKind, "GENERIC"); 1040 clazz.add(createAssumptionField(assumption));
1438 } else if (specialization.isUninitialized()) { 1041 }
1439 kind = Utils.findVariableElement(nodeinfoKind, "UNINITIALIZED"); 1042
1440 } else { 1043 createConstructors(node, clazz);
1441 kind = Utils.findVariableElement(nodeinfoKind, "SPECIALIZED");
1442 }
1443
1444 nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("kind"), new CodeAnnotationValue(kind));
1445
1446 clazz.getAnnotationMirrors().add(nodeInfoMirror);
1447 1044
1448 return clazz; 1045 return clazz;
1046 }
1047
1048 protected String typeGetterName(ActualParameter parameter) {
1049 return "get" + Utils.firstLetterUpperCase(parameter.getLocalName()) + "Type";
1449 } 1050 }
1450 1051
1451 @Override 1052 @Override
1452 protected void createChildren(SpecializationData specialization) { 1053 protected void createChildren(SpecializationData specialization) {
1054 NodeData node = specialization.getNode();
1453 CodeTypeElement clazz = getElement(); 1055 CodeTypeElement clazz = getElement();
1454 NodeData node = specialization.getNode(); 1056
1455 1057 if (node.needsRewrites(context)) {
1456 TypeElement superTypeElement = Utils.fromTypeMirror(clazz.getSuperclass()); 1058
1457 for (ExecutableElement constructor : ElementFilter.constructorsIn(superTypeElement.getEnclosedElements())) { 1059 if (node.getPolymorphicDepth() > 1) {
1458 ExecutableElement superConstructor = createSuperConstructor(clazz, constructor); 1060
1459 if (superConstructor != null) { 1061 CodeVariableElement var = new CodeVariableElement(modifiers(PROTECTED), clazz.asType(), "next0");
1460 clazz.add(superConstructor); 1062 var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation()));
1461 } 1063 clazz.add(var);
1462 } 1064
1463 1065 CodeExecutableElement setter = new CodeExecutableElement(modifiers(PROTECTED), context.getType(void.class), "setNext0");
1464 for (ExecutableTypeData execType : node.getExecutableTypes()) { 1066 setter.getParameters().add(new CodeVariableElement(clazz.asType(), "next0"));
1465 if (execType.isFinal()) { 1067 CodeTreeBuilder builder = setter.createBuilder();
1068 builder.statement("this.next0 = adoptChild(next0)");
1069 clazz.add(setter);
1070
1071 createTypeGetters(clazz, node.getGenericSpecialization());
1072
1073 clazz.add(createCreateSpecialization(node));
1074
1075 CodeExecutableElement genericCachedExecute = null;
1076 for (SpecializationData polymorph : node.getPolymorphicSpecializations()) {
1077 CodeExecutableElement cachedExecute = createCachedExecute(node, polymorph, genericCachedExecute);
1078 clazz.add(cachedExecute);
1079 if (genericCachedExecute == null) {
1080 genericCachedExecute = cachedExecute;
1081 }
1082 }
1083 }
1084
1085 clazz.add(createGenericExecuteAndSpecialize(node));
1086 clazz.add(createInfoMessage(node));
1087 }
1088
1089 if (node.getGenericSpecialization() != null && node.getGenericSpecialization().isReachable()) {
1090 clazz.add(createGenericExecute(node));
1091 }
1092 }
1093
1094 private Element createInfoMessage(NodeData node) {
1095 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), getContext().getType(String.class), "createInfo0");
1096 method.addParameter(new CodeVariableElement(getContext().getType(String.class), "message"));
1097 addInternalValueParameters(method, node.getGenericSpecialization(), false, false);
1098
1099 CodeTreeBuilder builder = method.createBuilder();
1100 builder.startStatement().string("StringBuilder builder = new StringBuilder(message)").end();
1101 builder.startStatement().startCall("builder", "append").doubleQuote(" (").end().end();
1102
1103 String sep = null;
1104 for (ActualParameter parameter : node.getGenericSpecialization().getParameters()) {
1105 if (!parameter.getSpecification().isSignature()) {
1466 continue; 1106 continue;
1467 } 1107 }
1468 CodeExecutableElement executeMethod = createExecutableTypeOverride(execType); 1108
1469 clazz.add(executeMethod); 1109 builder.startStatement();
1470 CodeTreeBuilder builder = executeMethod.createBuilder(); 1110 builder.string("builder");
1471 CodeTree result = createExecuteBody(builder, specialization, execType); 1111 if (sep != null) {
1472 if (result != null) { 1112 builder.startCall(".append").doubleQuote(sep).end();
1473 builder.tree(result); 1113 }
1114 builder.startCall(".append").doubleQuote(parameter.getLocalName()).end();
1115 builder.startCall(".append").doubleQuote(" = ").end();
1116 builder.startCall(".append").string(parameter.getLocalName()).end();
1117 builder.end();
1118
1119 if (!Utils.isPrimitive(parameter.getType())) {
1120 builder.startIf().string(parameter.getLocalName() + " != null").end();
1121 builder.startBlock();
1122 }
1123 builder.startStatement();
1124 if (Utils.isPrimitive(parameter.getType())) {
1125 builder.startCall("builder.append").doubleQuote(" (" + Utils.getSimpleName(parameter.getType()) + ")").end();
1474 } else { 1126 } else {
1475 clazz.remove(executeMethod); 1127 builder.startCall("builder.append").doubleQuote(" (").end();
1476 } 1128 builder.startCall(".append").string(parameter.getLocalName() + ".getClass().getSimpleName()").end();
1477 } 1129 builder.startCall(".append").doubleQuote(")").end();
1478 } 1130 }
1479 1131 builder.end();
1480 private CodeTree createExecuteBody(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData execType) { 1132 if (!Utils.isPrimitive(parameter.getType())) {
1481 TypeData primaryType = specialization.getReturnType().getTypeSystemType(); 1133 builder.end();
1482 1134 }
1135
1136 sep = ", ";
1137 }
1138
1139 builder.startStatement().startCall("builder", "append").doubleQuote(")").end().end();
1140
1141 builder.startReturn().string("builder.toString()").end();
1142
1143 return method;
1144 }
1145
1146 protected void createTypeGetters(CodeTypeElement clazz, SpecializationData specialization) {
1147 for (ActualParameter parameter : specialization.getReturnTypeAndParameters()) {
1148 if (!parameter.getSpecification().isSignature()) {
1149 continue;
1150 }
1151 CodeExecutableElement typeGetter = new CodeExecutableElement(modifiers(PROTECTED), context.getType(Class.class), typeGetterName(parameter));
1152 CodeTreeBuilder builder = typeGetter.createBuilder();
1153 builder.startReturn().typeLiteral(parameter.getType()).end();
1154 clazz.add(typeGetter);
1155 }
1156 }
1157
1158 private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph, CodeExecutableElement genericPolymorphMethod) {
1159 int index = node.getPolymorphicSpecializations().indexOf(polymorph);
1160 assert index != -1;
1161 boolean generic = index == 0;
1162
1163 String name = "executeCached" + index;
1164 CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED), polymorph.getReturnType().getType(), name);
1165 addInternalValueParameters(cachedExecute, polymorph, true, true);
1166
1167 if (generic) {
1168 cachedExecute.getModifiers().add(ABSTRACT);
1169 } else {
1170 SpecializationData genericPolymorph = node.getPolymorphicSpecializations().get(0);
1171 CodeTreeBuilder builder = cachedExecute.createBuilder();
1172 ExecutableTypeData genericExecutable = new ExecutableTypeData(genericPolymorph, genericPolymorphMethod, node.getTypeSystem(), genericPolymorph.getReturnType().getTypeSystemType());
1173 ExecutableTypeData specificExecutable = new ExecutableTypeData(polymorph, cachedExecute, node.getTypeSystem(), polymorph.getReturnType().getTypeSystemType());
1174 builder.tree(createCastingExecute(builder, polymorph, specificExecutable, genericExecutable));
1175 }
1176
1177 return cachedExecute;
1178
1179 }
1180
1181 private CodeExecutableElement createCreateSpecialization(NodeData node) {
1182 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), getElement().asType(), "createSpezialization0");
1183 method.getParameters().add(new CodeVariableElement(context.getType(Class.class), "clazz"));
1184 CodeTreeBuilder builder = method.createBuilder();
1185
1186 builder.startStatement().type(getElement().asType()).string(" node").end();
1187
1188 boolean elseIf = false;
1189 for (SpecializationData specialization : node.getSpecializations()) {
1190 if (specialization.isGeneric() || specialization.isUninitialized()) {
1191 continue;
1192 }
1193
1194 elseIf = builder.startIf(elseIf);
1195 builder.startGroup().string("clazz == ").string(nodeSpecializationClassName(specialization)).string(".class").end();
1196 builder.end();
1197 builder.startBlock();
1198 builder.startStatement();
1199 builder.string("node = ");
1200 builder.startNew(nodeSpecializationClassName(specialization)).string("this").end();
1201 builder.end();
1202 builder.end();
1203 }
1204
1205 builder.startElseBlock();
1206 builder.startThrow().startNew(context.getType(AssertionError.class)).end().end();
1207 builder.end();
1208
1209 builder.startStatement().startCall("node", "setNext0");
1210 builder.startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string("this").end();
1211 builder.end().end();
1212
1213 builder.startReturn().string("node").end();
1214
1215 return method;
1216 }
1217
1218 private void createConstructors(NodeData node, CodeTypeElement clazz) {
1219 List<ExecutableElement> constructors = findUserConstructors(node.getNodeType());
1220 if (constructors.isEmpty()) {
1221 clazz.add(createUserConstructor(clazz, null));
1222 } else {
1223 for (ExecutableElement constructor : constructors) {
1224 clazz.add(createUserConstructor(clazz, constructor));
1225 }
1226 }
1227 if (node.needsRewrites(getContext())) {
1228 clazz.add(createCopyConstructor(clazz, findCopyConstructor(node.getNodeType())));
1229 }
1230 }
1231
1232 private CodeExecutableElement createUserConstructor(CodeTypeElement type, ExecutableElement superConstructor) {
1233 CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
1234 CodeTreeBuilder builder = method.createBuilder();
1235
1236 NodeData node = getModel().getNode();
1237
1238 if (superConstructor != null) {
1239 for (VariableElement param : superConstructor.getParameters()) {
1240 method.getParameters().add(CodeVariableElement.clone(param));
1241 }
1242 }
1243
1244 for (VariableElement var : type.getFields()) {
1245 NodeChildData child = node.findChild(var.getSimpleName().toString());
1246 if (child != null) {
1247 method.getParameters().add(new CodeVariableElement(child.getOriginalType(), child.getName()));
1248 } else {
1249 method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString()));
1250 }
1251 }
1252
1253 if (superConstructor != null) {
1254 builder.startStatement().startSuperCall();
1255 for (VariableElement param : superConstructor.getParameters()) {
1256 builder.string(param.getSimpleName().toString());
1257 }
1258 builder.end().end();
1259 }
1260
1261 for (VariableElement var : type.getFields()) {
1262 builder.startStatement();
1263 String fieldName = var.getSimpleName().toString();
1264
1265 CodeTree fieldInit = CodeTreeBuilder.singleString(var.getSimpleName().toString());
1266 builder.string("this.").string(var.getSimpleName().toString());
1267
1268 NodeChildData child = node.findChild(fieldName);
1269 if (child != null) {
1270 CreateCastData createCast = node.findCast(child.getName());
1271 if (createCast != null) {
1272 fieldInit = createTemplateMethodCall(builder, null, node.getGenericSpecialization(), createCast, null, child.getName());
1273 }
1274 }
1275
1276 if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNode())) {
1277 builder.string(" = adoptChild(").tree(fieldInit).string(")");
1278 } else if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) {
1279 builder.string(" = adoptChildren(").tree(fieldInit).string(")");
1280 } else {
1281 builder.string(" = ").tree(fieldInit);
1282 }
1283 builder.end();
1284 }
1285 return method;
1286 }
1287
1288 private CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor) {
1289 CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
1290 CodeTreeBuilder builder = method.createBuilder();
1291 if (!(superConstructor == null && type.getFields().isEmpty())) {
1292 method.getParameters().add(new CodeVariableElement(type.asType(), "copy"));
1293 }
1294
1295 if (superConstructor != null) {
1296 builder.startStatement().startSuperCall().string("copy").end().end();
1297 }
1298
1299 for (VariableElement var : type.getFields()) {
1300 builder.startStatement();
1301 String varName = var.getSimpleName().toString();
1302 builder.string("this.").string(varName);
1303 if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNode())) {
1304 builder.string(" = adoptChild(copy.").string(varName).string(")");
1305 } else if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) {
1306 builder.string(" = adoptChildren(copy.").string(varName).string(")");
1307 } else {
1308 builder.string(" = copy.").string(varName);
1309 }
1310 builder.end();
1311 }
1312 if (getModel().getNode().getPolymorphicDepth() > 1) {
1313 builder.statement("this.next0 = adoptChild(copy.next0)");
1314 }
1315
1316 return method;
1317 }
1318
1319 private CodeVariableElement createAssumptionField(String assumption) {
1320 CodeVariableElement var = new CodeVariableElement(getContext().getTruffleTypes().getAssumption(), assumption);
1321 var.getModifiers().add(Modifier.FINAL);
1322 return var;
1323 }
1324
1325 private CodeVariableElement createChildField(NodeChildData child) {
1326 CodeVariableElement var = new CodeVariableElement(child.getNodeType(), child.getName());
1327 var.getModifiers().add(Modifier.PROTECTED);
1328
1329 DeclaredType annotationType;
1330 if (child.getCardinality() == Cardinality.MANY) {
1331 annotationType = getContext().getTruffleTypes().getChildrenAnnotation();
1332 } else {
1333 annotationType = getContext().getTruffleTypes().getChildAnnotation();
1334 }
1335
1336 var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType));
1337 return var;
1338 }
1339
1340 private CodeExecutableElement createGenericExecuteAndSpecialize(NodeData node) {
1341
1342 TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType();
1343 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, EXECUTE_SPECIALIZE_NAME);
1344 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState"));
1345 addInternalValueParameters(method, node.getGenericSpecialization(), true, false);
1346 method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason"));
1347
1348 CodeTreeBuilder builder = method.createBuilder();
1349 builder.startStatement();
1350 builder.startStaticCall(getContext().getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end();
1351 builder.end();
1352
1353 emitSpecializationListeners(builder, node);
1354 builder.defaultDeclaration(node.getGenericSpecialization().getReturnType().getTypeSystemType().getPrimitiveType(), "result");
1355
1356 builder.defaultDeclaration(getContext().getType(Class.class), "resultClass");
1357
1358 builder.startStatement().string("boolean allowed = (minimumState == ").string(nodeSpecializationClassName(node.getSpecializations().get(0))).string(".class)").end();
1359
1360 builder.startStatement().string("String message = ").startCall("createInfo0").string("reason");
1361 addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, false, true);
1362 builder.end().end();
1363
1364 String prefix = null;
1365
1366 List<SpecializationData> specializations = node.getSpecializations();
1367
1368 for (SpecializationData current : specializations) {
1369 if (current.isUninitialized() || !current.isReachable()) {
1370 continue;
1371 }
1372 CodeTreeBuilder execute = new CodeTreeBuilder(builder);
1373
1374 execute.tree(createGenericInvokeAndSpecialize(builder, node.getGenericSpecialization(), current));
1375
1376 if (!current.isGeneric()) {
1377 builder.startStatement().string("allowed = allowed || (minimumState == ").string(nodeSpecializationClassName(current)).string(".class)").end();
1378 }
1379
1380 builder.tree(createGuardAndCast(builder, prefix, current.getNode().getGenericSpecialization(), current, true, execute.getRoot(), null, true, false));
1381 }
1382
1383 for (SpecializationData current : specializations) {
1384 if (current.isUninitialized() || current.isReachable()) {
1385 continue;
1386 }
1387 builder.string("// unreachable ").string(current.getId()).newLine();
1388 }
1389
1390 return method;
1391 }
1392
1393 private CodeExecutableElement createGenericExecute(NodeData node) {
1394 TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType();
1395 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, EXECUTE_GENERIC_NAME);
1396 addInternalValueParameters(method, node.getGenericSpecialization(), true, false);
1397 CodeTreeBuilder builder = method.createBuilder();
1398
1399 String prefix = null;
1400 List<SpecializationData> specializations = node.getSpecializations();
1401
1402 for (SpecializationData current : specializations) {
1403 if (current.isUninitialized() || !current.isReachable()) {
1404 continue;
1405 }
1406 CodeTreeBuilder execute = new CodeTreeBuilder(builder);
1407 execute.tree(createGenericInvoke(builder, node.getGenericSpecialization(), current));
1408 builder.tree(createGuardAndCast(builder, prefix, current.getNode().getGenericSpecialization(), current, true, execute.getRoot(), null, true, false));
1409 }
1410
1411 for (SpecializationData current : specializations) {
1412 if (current.isUninitialized() || current.isReachable()) {
1413 continue;
1414 }
1415 builder.string("// unreachable ").string(current.getId()).newLine();
1416 }
1417
1418 return method;
1419 }
1420
1421 protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) {
1483 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 1422 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1484 1423
1485 List<ExecutableTypeData> primaryExecutes = findFunctionalExecutableType(specialization, execType.getEvaluatedCount()); 1424 if (current.getMethod() == null) {
1486 1425 emitEncounteredSynthetic(builder, current);
1487 if (primaryExecutes.contains(execType) || primaryExecutes.isEmpty()) {
1488 builder.tree(createFunctionalExecute(builder, specialization, execType));
1489 } else if (needsCastingExecuteMethod(execType, primaryType)) {
1490 assert !primaryExecutes.isEmpty();
1491 builder.tree(createCastingExecute(builder, specialization, execType, primaryExecutes.get(0)));
1492 } else { 1426 } else {
1493 return null; 1427 builder.startReturn().tree(createTemplateMethodCall(builder, null, source, current, null)).end();
1494 } 1428 }
1429
1430 return encloseThrowsWithFallThrough(current, builder.getRoot());
1431 }
1432
1433 protected CodeTree createGenericInvokeAndSpecialize(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) {
1434 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1435
1436 NodeData node = current.getNode();
1437
1438 builder.startIf().string("resultClass == null").end().startBlock();
1439 if (current.getMethod() != null) {
1440 CodeTree executeCall = createTemplateMethodCall(builder, null, source, current, null);
1441 if (current.getReturnType().getTypeSystemType().isVoid()) {
1442 builder.statement(executeCall);
1443 } else {
1444 builder.startStatement().string("result = ").tree(executeCall).end();
1445 }
1446 builder.startStatement();
1447 builder.string("resultClass = ").string(nodeSpecializationClassName(current)).string(".class");
1448 builder.end();
1449 } else {
1450 emitEncounteredSynthetic(builder, current);
1451 }
1452 builder.end();
1453
1454 boolean ifAllowed = current.hasRewrite(getContext());
1455 if (ifAllowed) {
1456 builder.startIf().string("allowed").end().startBlock();
1457 }
1458
1459 if (!current.isGeneric() || node.getPolymorphicDepth() <= 1) {
1460 // generic rewrite
1461 builder.tree(createRewriteGeneric(builder, current));
1462 } else {
1463 boolean rewriteableToGeneric = node.getGenericSpecialization().getMethod() != null && node.getGenericSpecialization().isReachable();
1464 if (rewriteableToGeneric) {
1465 builder.startIf().string("resultClass == ").string(nodeSpecializationClassName(node.getGenericSpecialization())).string(".class").end();
1466 builder.startBlock();
1467
1468 boolean maybePolymorphic = node.getPolymorphicDepth() > 1;
1469 if (maybePolymorphic) {
1470 builder.startIf().string("next0 == null").end();
1471 builder.startBlock();
1472 }
1473 builder.tree(createRewriteGeneric(builder, current));
1474 if (maybePolymorphic) {
1475 builder.end().startElseBlock();
1476 builder.statement("Node searchNode = super.getParent()");
1477 builder.startWhile().string("searchNode != null").end();
1478 builder.startBlock();
1479 builder.statement("searchNode = searchNode.getParent()");
1480 builder.startIf().instanceOf("searchNode", nodePolymorphicClassName(node, node.getPolymorphicSpecializations().get(0))).end();
1481 builder.startBlock().breakStatement().end();
1482 builder.end();
1483 builder.startStatement().startCall("searchNode", "replace");
1484 builder.startGroup().startNew(nodeSpecializationClassName(current)).startGroup().cast(baseClassName(node)).string("searchNode").end().end().end();
1485 builder.string("message");
1486 builder.end().end().end();
1487 }
1488
1489 builder.end().startElseBlock();
1490 }
1491
1492 // polymorphic rewrite
1493 builder.tree(createRewritePolymorphic(builder, node));
1494
1495 if (rewriteableToGeneric) {
1496 builder.end();
1497 }
1498 }
1499
1500 if (current.getReturnType().getTypeSystemType().isVoid()) {
1501 builder.returnStatement();
1502 } else {
1503 builder.startReturn().string("result").end();
1504 }
1505 if (ifAllowed) {
1506 builder.end();
1507 }
1508
1509 return encloseThrowsWithFallThrough(current, builder.getRoot());
1510 }
1511
1512 private CodeTree encloseThrowsWithFallThrough(SpecializationData current, CodeTree tree) {
1513 if (current.getExceptions().isEmpty()) {
1514 return tree;
1515 }
1516 CodeTreeBuilder builder = new CodeTreeBuilder(null);
1517
1518 builder.startTryBlock();
1519 builder.tree(tree);
1520 for (SpecializationThrowsData exception : current.getExceptions()) {
1521 builder.end().startCatchBlock(exception.getJavaClass(), "rewriteEx");
1522 builder.string("// fall through").newLine();
1523 }
1524 builder.end();
1495 1525
1496 return builder.getRoot(); 1526 return builder.getRoot();
1497 } 1527 }
1498 1528
1499 private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType) { 1529 private CodeTree createRewriteGeneric(CodeTreeBuilder parent, SpecializationData current) {
1500 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod()); 1530 CodeTreeBuilder builder = parent.create();
1501 1531 builder.startStatement().startCall("super", "replace");
1502 int i = 0; 1532 builder.startGroup().startNew(nodeSpecializationClassName(current)).string("this").end().end();
1503 for (VariableElement param : method.getParameters()) { 1533 builder.string("message");
1504 CodeVariableElement var = CodeVariableElement.clone(param); 1534 builder.end().end();
1505 ActualParameter actualParameter = execType.getParameters().get(i); 1535 return builder.getRoot();
1506 if (actualParameter.getSpecification().isSignature()) { 1536 }
1507 var.setName(valueNameEvaluated(actualParameter)); 1537
1508 } else { 1538 private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node) {
1509 var.setName(valueName(actualParameter)); 1539 CodeTreeBuilder builder = parent.create();
1510 } 1540 builder.startStatement();
1511 method.getParameters().set(i, var); 1541 builder.string(nodePolymorphicClassName(node, null));
1512 i++; 1542 builder.string(" polymorphic = ");
1513 } 1543 builder.startNew(nodePolymorphicClassName(node, null)).string("this").end();
1514 1544 builder.end();
1515 method.getAnnotationMirrors().clear(); 1545 for (NodeChildData child : node.getChildren()) {
1516 method.getModifiers().remove(Modifier.ABSTRACT); 1546 builder.startStatement().string("this.").string(child.getName()).string(" = null").end();
1517 return method; 1547 }
1518 } 1548 builder.startStatement().startCall("super", "replace");
1519 1549 builder.string("polymorphic");
1520 private boolean needsCastingExecuteMethod(ExecutableTypeData execType, TypeData primaryType) { 1550 builder.string("message");
1521 if (execType.isAbstract()) { 1551 builder.end().end();
1522 return true; 1552
1523 } 1553 builder.statement("polymorphic.setNext0(this)");
1524 if (Utils.isPrimitiveOrVoid(primaryType.getPrimitiveType()) && Utils.isPrimitiveOrVoid(execType.getType().getPrimitiveType())) { 1554 builder.statement("setNext0(createSpezialization0(resultClass))");
1525 return true; 1555
1526 } 1556 builder.statement("polymorphic.optimizeTypes()");
1527 if (execType.getType().isGeneric()) { 1557 return builder.getRoot();
1528 return true; 1558 }
1529 } 1559
1530 return false; 1560 private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) {
1531 } 1561 for (TemplateMethod listener : node.getSpecializationListeners()) {
1532 1562 builder.startStatement();
1533 private List<ExecutableTypeData> findFunctionalExecutableType(SpecializationData specialization, int evaluatedCount) { 1563 builder.tree(createTemplateMethodCall(builder, null, listener, listener, null));
1534 TypeData primaryType = specialization.getReturnType().getTypeSystemType(); 1564 builder.end(); // statement
1535 List<ExecutableTypeData> otherTypes = specialization.getNode().getExecutableTypes(evaluatedCount); 1565 }
1536 1566 }
1537 List<ExecutableTypeData> filteredTypes = new ArrayList<>(); 1567
1538 for (ExecutableTypeData compareType : otherTypes) { 1568 protected CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) {
1539 if (!Utils.typeEquals(compareType.getType().getPrimitiveType(), primaryType.getPrimitiveType())) {
1540 continue;
1541 }
1542 filteredTypes.add(compareType);
1543 }
1544
1545 // no direct matches found use generic where the type is Object
1546 if (filteredTypes.isEmpty()) {
1547 for (ExecutableTypeData compareType : otherTypes) {
1548 if (compareType.getType().isGeneric() && !compareType.hasUnexpectedValue(getContext())) {
1549 filteredTypes.add(compareType);
1550 }
1551 }
1552 }
1553
1554 if (filteredTypes.isEmpty()) {
1555 for (ExecutableTypeData compareType : otherTypes) {
1556 if (compareType.getType().isGeneric()) {
1557 filteredTypes.add(compareType);
1558 }
1559 }
1560 }
1561
1562 return filteredTypes;
1563 }
1564
1565 private CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) {
1566 TypeData type = executable.getType(); 1569 TypeData type = executable.getType();
1567 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 1570 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1568 NodeData node = specialization.getNode(); 1571 NodeData node = specialization.getNode();
1569 1572
1570 ExecutableTypeData castedType = node.findExecutableType(type, 0); 1573 ExecutableTypeData castedType = node.findExecutableType(type, 0);
1613 } 1616 }
1614 builder.end(); 1617 builder.end();
1615 1618
1616 if (!returnVoid) { 1619 if (!returnVoid) {
1617 builder.startReturn(); 1620 builder.startReturn();
1618 builder.tree(createExpectExecutableType(node, castExecutable.getReturnSignature(), executable, CodeTreeBuilder.singleString("value"))); 1621 builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), executable, CodeTreeBuilder.singleString("value")));
1619 builder.end(); 1622 builder.end();
1620 } 1623 }
1621 } else { 1624 } else {
1622 if (returnVoid) { 1625 if (returnVoid) {
1623 builder.statement(primaryExecuteCall); 1626 builder.statement(primaryExecuteCall);
1624 } else { 1627 } else {
1625 builder.startReturn(); 1628 builder.startReturn();
1626 builder.tree(createExpectExecutableType(node, castExecutable.getReturnSignature(), executable, primaryExecuteCall)); 1629 builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), executable, primaryExecuteCall));
1627 builder.end(); 1630 builder.end();
1628 } 1631 }
1629 } 1632 }
1630 1633
1631 return builder.getRoot(); 1634 return builder.getRoot();
1632 } 1635 }
1633 1636
1634 private CodeTree createExpectExecutableType(NodeData node, TypeData sourceType, ExecutableTypeData castedType, CodeTree value) { 1637 protected CodeTree createExpectExecutableType(NodeData node, TypeData sourceType, ExecutableTypeData castedType, CodeTree value) {
1635 boolean hasUnexpected = castedType.hasUnexpectedValue(getContext()); 1638 boolean hasUnexpected = castedType.hasUnexpectedValue(getContext());
1636 return createCastType(node, sourceType, castedType.getType(), hasUnexpected, value); 1639 return createCastType(node, sourceType, castedType.getType(), hasUnexpected, value);
1637 } 1640 }
1638 1641
1639 private CodeTree createCastType(NodeData node, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) { 1642 protected CodeTree createCastType(NodeData node, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) {
1640 if (targetType == null) { 1643 if (targetType == null) {
1641 return value; 1644 return value;
1642 } else if (!sourceType.needsCastTo(getContext(), targetType)) { 1645 } else if (!sourceType.needsCastTo(getContext(), targetType)) {
1643 return value; 1646 return value;
1644 } 1647 }
1655 builder.tree(value); 1658 builder.tree(value);
1656 builder.end().end(); 1659 builder.end().end();
1657 return builder.getRoot(); 1660 return builder.getRoot();
1658 } 1661 }
1659 1662
1660 private CodeTree createFunctionalExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable) { 1663 protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List<ActualParameter> targetParameters,
1661 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1662 if (specialization.isUninitialized()) {
1663 builder.tree(createDeoptimize(builder));
1664 }
1665
1666 builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null, false));
1667
1668 CodeTree executeNode;
1669 executeNode = createExecute(builder, executable, specialization);
1670
1671 SpecializationData next = specialization.findNextSpecialization();
1672 CodeTree returnSpecialized = null;
1673 if (next != null) {
1674 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder);
1675 returnBuilder.tree(createDeoptimize(builder));
1676 returnBuilder.tree(createReturnExecuteAndSpecialize(builder, executable, next, null, "One of guards " + specialization.getGuards() + " failed"));
1677 returnSpecialized = returnBuilder.getRoot();
1678 }
1679 builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized, false));
1680
1681 return builder.getRoot();
1682 }
1683
1684 private CodeTree createDeoptimize(CodeTreeBuilder parent) {
1685 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1686 builder.startStatement();
1687 builder.startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end();
1688 builder.end();
1689 return builder.getRoot();
1690 }
1691
1692 private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) {
1693 NodeData node = specialization.getNode();
1694 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1695 if (!specialization.getExceptions().isEmpty() || !specialization.getAssumptions().isEmpty()) {
1696 builder.startTryBlock();
1697 }
1698
1699 for (String assumption : specialization.getAssumptions()) {
1700 builder.startStatement();
1701 builder.string("this.").string(assumption).string(".check()");
1702 builder.end();
1703 }
1704
1705 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent);
1706 if (specialization.isUninitialized()) {
1707 returnBuilder.startCall("super", EXECUTE_SPECIALIZE_NAME);
1708 returnBuilder.startGroup().string(nodeSpecializationClassName(specialization)).string(".class").end();
1709 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true);
1710 returnBuilder.doubleQuote("Uninitialized");
1711 returnBuilder.end();
1712 } else if (specialization.getMethod() == null && !node.needsRewrites(context)) {
1713 emitEncounteredSynthetic(builder, specialization);
1714 } else if (specialization.isGeneric()) {
1715 returnBuilder.startCall("super", EXECUTE_GENERIC_NAME);
1716 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true);
1717 returnBuilder.end();
1718 } else {
1719 returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null));
1720 }
1721
1722 if (!returnBuilder.isEmpty()) {
1723 builder.startReturn();
1724
1725 TypeData targetType = node.getTypeSystem().findTypeData(builder.findMethod().getReturnType());
1726 TypeData sourceType = specialization.getReturnType().getTypeSystemType();
1727
1728 if (targetType == null || sourceType == null) {
1729 builder.tree(returnBuilder.getRoot());
1730 } else if (sourceType.needsCastTo(getContext(), targetType)) {
1731 builder.tree(createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.expectTypeMethodName(targetType), returnBuilder.getRoot()));
1732 } else {
1733 builder.tree(returnBuilder.getRoot());
1734 }
1735 builder.end();
1736 }
1737
1738 if (!specialization.getExceptions().isEmpty()) {
1739 for (SpecializationThrowsData exception : specialization.getExceptions()) {
1740 builder.end().startCatchBlock(exception.getJavaClass(), "ex");
1741 builder.tree(createDeoptimize(builder));
1742 builder.tree(createReturnExecuteAndSpecialize(parent, executable, exception.getTransitionTo(), null, "Thrown " + Utils.getSimpleName(exception.getJavaClass())));
1743 }
1744 builder.end();
1745 }
1746 if (!specialization.getAssumptions().isEmpty()) {
1747 builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex");
1748 builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization.findNextSpecialization(), null, "Assumption failed"));
1749 builder.end();
1750 }
1751
1752 return builder.getRoot();
1753 }
1754
1755 private CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List<ActualParameter> targetParameters,
1756 ActualParameter unexpectedParameter, boolean cast) { 1664 ActualParameter unexpectedParameter, boolean cast) {
1757 NodeData sourceNode = specialization.getNode(); 1665 NodeData sourceNode = specialization.getNode();
1758 1666
1759 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 1667 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1760 1668
1815 if (targetExecutable.getType().needsCastTo(getContext(), param.getTypeSystemType())) { 1723 if (targetExecutable.getType().needsCastTo(getContext(), param.getTypeSystemType())) {
1816 unexpected = true; 1724 unexpected = true;
1817 cast = true; 1725 cast = true;
1818 } 1726 }
1819 1727
1728 if (specialization.isGeneric() && unexpected) {
1729 throw new AssertionError("Generic has unexpected parameters. " + specialization.toString());
1730 }
1731
1820 builder.startStatement(); 1732 builder.startStatement();
1821 1733
1822 if (!shortCircuit) { 1734 if (!shortCircuit) {
1823 builder.type(param.getType()).string(" ").string(targetVariableName); 1735 builder.type(param.getType()).string(" ").string(targetVariableName);
1824 } 1736 }
1848 ActualParameter genericParameter = generic.findParameter(param.getLocalName()); 1760 ActualParameter genericParameter = generic.findParameter(param.getLocalName());
1849 1761
1850 List<ActualParameter> genericParameters = generic.getParametersAfter(genericParameter); 1762 List<ActualParameter> genericParameters = generic.getParametersAfter(genericParameter);
1851 builder.tree(createDeoptimize(builder)); 1763 builder.tree(createDeoptimize(builder));
1852 builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter, false)); 1764 builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter, false));
1853 builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization.findNextSpecialization(), param, 1765 if (specialization.isPolymorphic()) {
1854 "Expected " + param.getLocalName() + " instanceof " + Utils.getSimpleName(param.getType()))); 1766 builder.tree(createReturnOptimizeTypes(builder, specialization, param));
1767 } else {
1768 builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization.findNextSpecialization(), param, "Expected " + param.getLocalName() + " instanceof " +
1769 Utils.getSimpleName(param.getType())));
1770 }
1855 builder.end(); // catch block 1771 builder.end(); // catch block
1856 } 1772 }
1857 1773
1774 return builder.getRoot();
1775 }
1776
1777 private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, SpecializationData specialization, ActualParameter param) {
1778 NodeData node = specialization.getNode();
1779 assert !node.getPolymorphicSpecializations().isEmpty();
1780 SpecializationData generic = node.getPolymorphicSpecializations().get(0);
1781
1782 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1783 builder.startReturn();
1784
1785 CodeTreeBuilder execute = new CodeTreeBuilder(builder);
1786 execute.startCall("next0", "executeCached0");
1787 addInternalValueParameterNames(execute, specialization, generic, param.getLocalName(), true, true);
1788 execute.end();
1789
1790 TypeData sourceType = generic.getReturnType().getTypeSystemType();
1791 TypeData targetType = specialization.getReturnType().getTypeSystemType();
1792
1793 builder.tree(createCastType(node, sourceType, targetType, true, execute.getRoot()));
1794
1795 builder.end();
1858 return builder.getRoot(); 1796 return builder.getRoot();
1859 } 1797 }
1860 1798
1861 private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData targetField, ActualParameter sourceParameter, ActualParameter unexpectedParameter) { 1799 private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData targetField, ActualParameter sourceParameter, ActualParameter unexpectedParameter) {
1862 TypeData type = sourceParameter.getTypeSystemType(); 1800 TypeData type = sourceParameter.getTypeSystemType();
1863 ExecutableTypeData execType = targetField.findExecutableType(getContext(), type); 1801 ExecutableTypeData execType = targetField.findExecutableType(getContext(), type);
1864 1802
1865 /*
1866 * FIXME Temporary deactivated due to partial evaluation failure else if
1867 * (accessElement.getKind() == ElementKind.METHOD) {
1868 * builder.startCall(accessElement.getSimpleName().toString()).end(); }
1869 */
1870 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 1803 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1871 if (targetField != null) { 1804 if (targetField != null) {
1872 Element accessElement = targetField.getAccessElement(); 1805 Element accessElement = targetField.getAccessElement();
1873 if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) { 1806 if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) {
1874 builder.string("this.").string(targetField.getName()); 1807 builder.string("this.").string(targetField.getName());
1975 builder.end(); // statement 1908 builder.end(); // statement
1976 1909
1977 return builder.getRoot(); 1910 return builder.getRoot();
1978 } 1911 }
1979 1912
1980 private CodeTree createReturnExecuteAndSpecialize(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData nextSpecialization, ActualParameter exceptionParam, String reason) { 1913 protected CodeTree createDeoptimize(CodeTreeBuilder parent) {
1981 1914 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1982 SpecializationData generic = nextSpecialization.getNode().getGenericSpecialization(); 1915 builder.startStatement();
1916 builder.startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end();
1917 builder.end();
1918 return builder.getRoot();
1919 }
1920
1921 protected CodeTree createReturnExecuteAndSpecialize(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData nextSpecialization, ActualParameter exceptionParam, String reason) {
1922 SpecializationData generic = getModel().getNode().getGenericSpecialization();
1983 CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); 1923 CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent);
1984 specializeCall.startCall(EXECUTE_SPECIALIZE_NAME); 1924 specializeCall.startCall(EXECUTE_SPECIALIZE_NAME);
1985 specializeCall.string(nodeSpecializationClassName(nextSpecialization) + ".class"); 1925 specializeCall.string(nodeSpecializationClassName(nextSpecialization) + ".class");
1986 addInternalValueParameterNames(specializeCall, generic, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, true); 1926 addInternalValueParameterNames(specializeCall, generic, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, true);
1987 specializeCall.doubleQuote(reason); 1927 specializeCall.doubleQuote(reason);
1988 specializeCall.end().end(); 1928 specializeCall.end().end();
1989 1929
1990 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 1930 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1991 1931
1992 builder.startReturn(); 1932 builder.startReturn();
1993 builder.tree(createExpectExecutableType(nextSpecialization.getNode(), generic.getReturnSignature(), executable, specializeCall.getRoot())); 1933 builder.tree(createExpectExecutableType(nextSpecialization.getNode(), generic.getReturnType().getTypeSystemType(), executable, specializeCall.getRoot()));
1994 builder.end(); 1934 builder.end();
1995 1935
1996 return builder.getRoot(); 1936 return builder.getRoot();
1997 } 1937 }
1938 }
1939
1940 private class PolymorphicNodeFactory extends SpecializedNodeFactory {
1941
1942 private final boolean generic;
1943
1944 public PolymorphicNodeFactory(ProcessorContext context, CodeTypeElement nodeGen, boolean generic) {
1945 super(context, nodeGen);
1946 this.generic = generic;
1947 }
1948
1949 @Override
1950 public CodeTypeElement create(SpecializationData specialization) {
1951 NodeData node = specialization.getNode();
1952 TypeMirror baseType = node.getNodeType();
1953 if (nodeGen != null) {
1954 baseType = nodeGen.asType();
1955 }
1956 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC), nodePolymorphicClassName(node, specialization), baseType, false);
1957
1958 if (!generic) {
1959 clazz.getModifiers().add(Modifier.FINAL);
1960 }
1961
1962 clazz.getAnnotationMirrors().add(createNodeInfo(node, Kind.POLYMORPHIC));
1963
1964 return clazz;
1965 }
1966
1967 @Override
1968 protected void createChildren(SpecializationData specialization) {
1969 // super.createChildren(specialization);
1970 CodeTypeElement clazz = getElement();
1971
1972 createConstructors(clazz);
1973 createExecuteMethods(specialization);
1974
1975 if (generic) {
1976 getElement().add(createOptimizeTypes());
1977 createCachedExecuteMethods(specialization);
1978 }
1979 }
1980
1981 private CodeExecutableElement createOptimizeTypes() {
1982 NodeData node = getModel().getNode();
1983 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), getContext().getType(void.class), "optimizeTypes");
1984 CodeTreeBuilder builder = method.createBuilder();
1985 builder.startStatement().string(baseClassName(node)).string(" node = this.next0").end();
1986 TypeMirror classType = getContext().getType(Class.class);
1987
1988 SpecializationData genericSpecialization = node.getGenericSpecialization();
1989
1990 CodeTreeBuilder whileBodyBuilder = builder.create();
1991 for (ActualParameter parameter : node.getGenericSpecialization().getReturnTypeAndParameters()) {
1992 if (!parameter.getSpecification().isSignature()) {
1993 continue;
1994 }
1995
1996 ActualParameter genericParameter = genericSpecialization.findParameter(parameter.getLocalName());
1997
1998 String name = parameter.getLocalName() + "Type";
1999
2000 builder.declaration(classType, name, builder.create().startCall("node", typeGetterName(parameter)).end().getRoot());
2001
2002 whileBodyBuilder.startIf().string(name).string(" != ").startCall("node", typeGetterName(parameter)).end().end();
2003 whileBodyBuilder.startBlock();
2004 whileBodyBuilder.startStatement().string(name).string(" = ").typeLiteral(genericParameter.getType()).end();
2005 whileBodyBuilder.end();
2006 }
2007
2008 builder.startWhile().string("node != null && !(").instanceOf("node", nodeSpecializationClassName(node.getUninitializedSpecialization())).string(")").end();
2009 builder.startBlock();
2010 builder.tree(whileBodyBuilder.getRoot());
2011 builder.statement("node = node.next0");
2012 builder.end();
2013
2014 boolean elseIf = false;
2015 for (SpecializationData polymorph : node.getPolymorphicSpecializations()) {
2016 elseIf = builder.startIf(elseIf);
2017 String and = "";
2018 StringBuilder reason = new StringBuilder("Optimized polymorphic types for (");
2019 for (ActualParameter parameter : polymorph.getReturnTypeAndParameters()) {
2020 if (!parameter.getSpecification().isSignature()) {
2021 continue;
2022 }
2023 String name = parameter.getLocalName() + "Type";
2024 builder.string(and).string(name).string(" == ").typeLiteral(parameter.getType());
2025
2026 if (!and.isEmpty()) {
2027 reason.append(", ");
2028 }
2029 reason.append(Utils.getSimpleName(parameter.getType()));
2030 and = " && ";
2031 }
2032 reason.append(")");
2033 builder.end();
2034 builder.startBlock();
2035
2036 String className = nodePolymorphicClassName(node, polymorph);
2037 builder.startIf().string("getClass() != ").string(className).string(".class").end();
2038 builder.startBlock();
2039 builder.startStatement().startCall("super", "replace");
2040 builder.startNew(className).string("this").end();
2041 builder.doubleQuote(reason.toString());
2042 builder.end().end(); // call
2043 builder.end(); // block
2044 builder.end();
2045 }
2046 return method;
2047 }
2048 }
2049
2050 private class SpecializedNodeFactory extends NodeBaseFactory {
2051
2052 protected final CodeTypeElement nodeGen;
2053
2054 public SpecializedNodeFactory(ProcessorContext context, CodeTypeElement nodeGen) {
2055 super(context);
2056 this.nodeGen = nodeGen;
2057 }
2058
2059 @Override
2060 public CodeTypeElement create(SpecializationData specialization) {
2061 NodeData node = specialization.getNode();
2062 TypeMirror baseType = node.getNodeType();
2063 if (nodeGen != null) {
2064 baseType = nodeGen.asType();
2065 }
2066 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false);
2067
2068 Kind kind;
2069 if (specialization.isGeneric()) {
2070 kind = Kind.GENERIC;
2071 } else if (specialization.isUninitialized()) {
2072 kind = Kind.UNINITIALIZED;
2073 } else {
2074 kind = Kind.SPECIALIZED;
2075 }
2076 clazz.getAnnotationMirrors().add(createNodeInfo(node, kind));
2077
2078 return clazz;
2079 }
2080
2081 protected CodeAnnotationMirror createNodeInfo(NodeData node, Kind kind) {
2082 String shortName = node.getShortName();
2083 CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(getContext().getTruffleTypes().getNodeInfoAnnotation());
2084 if (shortName != null) {
2085 nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("shortName"), new CodeAnnotationValue(shortName));
2086 }
2087
2088 DeclaredType nodeinfoKind = getContext().getTruffleTypes().getNodeInfoKind();
2089 VariableElement varKind = Utils.findVariableElement(nodeinfoKind, kind.name());
2090
2091 nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("kind"), new CodeAnnotationValue(varKind));
2092 return nodeInfoMirror;
2093 }
2094
2095 @Override
2096 protected void createChildren(SpecializationData specialization) {
2097 CodeTypeElement clazz = getElement();
2098 createConstructors(clazz);
2099
2100 NodeData node = specialization.getNode();
2101
2102 if (!specialization.isGeneric() && !specialization.isUninitialized() && !specialization.isPolymorphic() && node.needsRewrites(getContext()) && node.getPolymorphicDepth() > 1) {
2103
2104 createTypeGetters(clazz, specialization);
2105 }
2106
2107 createExecuteMethods(specialization);
2108 createCachedExecuteMethods(specialization);
2109 }
2110
2111 protected void createConstructors(CodeTypeElement clazz) {
2112 TypeElement superTypeElement = Utils.fromTypeMirror(clazz.getSuperclass());
2113 for (ExecutableElement constructor : ElementFilter.constructorsIn(superTypeElement.getEnclosedElements())) {
2114 if (getModel().getNode().getUninitializedSpecialization() != null && !getModel().isUninitialized() && constructor.getParameters().size() != 1 ||
2115 constructor.getParameters().get(0).getSimpleName().toString().equals(baseClassName(getModel().getNode()))) {
2116 continue;
2117 }
2118
2119 CodeExecutableElement superConstructor = createSuperConstructor(clazz, constructor);
2120 if (superConstructor != null) {
2121 if (getModel().isGeneric() && getModel().getNode().getPolymorphicDepth() > 1) {
2122 CodeTree body = superConstructor.getBodyTree();
2123 CodeTreeBuilder builder = superConstructor.createBuilder();
2124 builder.tree(body);
2125 builder.statement("this.next0 = null");
2126 }
2127
2128 clazz.add(superConstructor);
2129 }
2130 }
2131 }
2132
2133 protected void createExecuteMethods(SpecializationData specialization) {
2134 NodeData node = specialization.getNode();
2135 CodeTypeElement clazz = getElement();
2136
2137 for (ExecutableTypeData execType : node.getExecutableTypes()) {
2138 if (execType.isFinal()) {
2139 continue;
2140 }
2141 CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, true);
2142 clazz.add(executeMethod);
2143 CodeTreeBuilder builder = executeMethod.createBuilder();
2144 CodeTree result = createExecuteBody(builder, specialization, execType);
2145 if (result != null) {
2146 builder.tree(result);
2147 } else {
2148 clazz.remove(executeMethod);
2149 }
2150 }
2151 }
2152
2153 protected void createCachedExecuteMethods(SpecializationData specialization) {
2154 NodeData node = specialization.getNode();
2155 CodeTypeElement clazz = getElement();
2156 int index = 0;
2157 for (SpecializationData polymorphic : node.getPolymorphicSpecializations()) {
2158 boolean matchFound = false;
2159 if (!specialization.isGeneric() && !specialization.isUninitialized() && !specialization.isPolymorphic()) {
2160 matchFound = polymorphic.getSignature().hasAnyParameterMatch(specialization.getSignature());
2161 }
2162
2163 if (matchFound || index == 0) {
2164 ExecutableElement executeCached = nodeGen.getMethod("executeCached" + index);
2165 ExecutableTypeData execType = new ExecutableTypeData(polymorphic, executeCached, node.getTypeSystem(), polymorphic.getReturnType().getTypeSystemType());
2166
2167 CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, false);
2168 CodeTreeBuilder builder = executeMethod.createBuilder();
2169
2170 if (specialization.isGeneric() || specialization.isPolymorphic()) {
2171 builder.startThrow().startNew(getContext().getType(AssertionError.class));
2172 builder.doubleQuote("Should not be reached.");
2173 builder.end().end();
2174 } else if (specialization.isUninitialized()) {
2175 builder.tree(createAppendPolymorphic(builder, specialization));
2176 } else {
2177 CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder);
2178 elseBuilder.startReturn().startCall("this.next0", "executeCached" + index);
2179 addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, true);
2180 elseBuilder.end().end();
2181 CodeTreeBuilder execute = new CodeTreeBuilder(builder);
2182 execute.tree(createGenericInvoke(builder, polymorphic, specialization));
2183 boolean forceElse = !specialization.getExceptions().isEmpty();
2184 builder.tree(createGuardAndCast(builder, null, polymorphic, specialization, true, execute.getRoot(), elseBuilder.getRoot(), true, forceElse));
2185 }
2186 clazz.add(executeMethod);
2187 }
2188 index++;
2189 }
2190 }
2191
2192 private CodeTree createAppendPolymorphic(CodeTreeBuilder parent, SpecializationData specialization) {
2193 NodeData node = specialization.getNode();
2194 String genericClassName = nodePolymorphicClassName(node, null);
2195
2196 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
2197 builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end();
2198
2199 builder.declaration(getContext().getTruffleTypes().getNode(), "searchNode", "super.getParent()");
2200 builder.declaration(getContext().getType(int.class), "depth", "0");
2201 builder.startWhile().string("searchNode != null").end();
2202 builder.startBlock();
2203 builder.statement("depth++");
2204 builder.statement("searchNode = searchNode.getParent()");
2205
2206 builder.startIf().instanceOf("searchNode", genericClassName).end();
2207 builder.startBlock().breakStatement().end();
2208 builder.end(); // if
2209 builder.end(); // while
2210
2211 builder.startAssert().instanceOf("searchNode", genericClassName).end();
2212
2213 builder.startStatement();
2214 builder.string(genericClassName).string(" ").string("polymorphic = ").string("(").string(genericClassName).string(") searchNode");
2215 builder.end();
2216
2217 builder.startIf().string("depth >= ").string(String.valueOf(node.getPolymorphicDepth())).end();
2218 builder.startBlock();
2219 builder.startStatement();
2220 builder.startCall("searchNode", "replace");
2221 builder.startNew(nodeSpecializationClassName(node.getGenericSpecialization())).string("this").end();
2222 builder.doubleQuote("Polymorphic limit reached (" + node.getPolymorphicDepth() + ")");
2223 builder.end();
2224 builder.end();
2225
2226 builder.startReturn().startCall("super", EXECUTE_GENERIC_NAME);
2227 addInternalValueParameterNames(builder, specialization, node.getGenericSpecialization(), null, true, true);
2228 builder.end().end();
2229
2230 builder.end().startElseBlock();
2231 builder.startStatement().startCall("super", "setNext0");
2232 builder.startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string("this").end();
2233 builder.end().end();
2234
2235 CodeTreeBuilder specializeCall = new CodeTreeBuilder(builder);
2236 specializeCall.startCall(EXECUTE_SPECIALIZE_NAME);
2237 specializeCall.string(nodeSpecializationClassName(node.getUninitializedSpecialization()) + ".class");
2238 addInternalValueParameterNames(specializeCall, specialization, node.getGenericSpecialization(), null, true, true);
2239 specializeCall.startGroup().doubleQuote("Uninitialized polymorphic (").string(" + depth + ").doubleQuote("/" + node.getPolymorphicDepth() + ")").end();
2240 specializeCall.end().end();
2241
2242 builder.declaration(node.getGenericSpecialization().getReturnType().getType(), "result", specializeCall.getRoot());
2243
2244 builder.statement("polymorphic.optimizeTypes()");
2245
2246 if (Utils.isVoid(builder.findMethod().getReturnType())) {
2247 builder.returnStatement();
2248 } else {
2249 builder.startReturn().string("result").end();
2250 }
2251
2252 builder.end();
2253
2254 return builder.getRoot();
2255 }
2256
2257 private CodeTree createExecuteBody(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData execType) {
2258 TypeData primaryType = specialization.getReturnType().getTypeSystemType();
2259
2260 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
2261
2262 List<ExecutableTypeData> primaryExecutes = findFunctionalExecutableType(specialization, execType.getEvaluatedCount());
2263
2264 if (primaryExecutes.contains(execType) || primaryExecutes.isEmpty()) {
2265 builder.tree(createFunctionalExecute(builder, specialization, execType));
2266 } else if (needsCastingExecuteMethod(execType, primaryType)) {
2267 assert !primaryExecutes.isEmpty();
2268 builder.tree(createCastingExecute(builder, specialization, execType, primaryExecutes.get(0)));
2269 } else {
2270 return null;
2271 }
2272
2273 return builder.getRoot();
2274 }
2275
2276 private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType, boolean evaluated) {
2277 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod());
2278
2279 int i = 0;
2280 for (VariableElement param : method.getParameters()) {
2281 CodeVariableElement var = CodeVariableElement.clone(param);
2282 ActualParameter actualParameter = execType.getParameters().get(i);
2283 if (evaluated && actualParameter.getSpecification().isSignature()) {
2284 var.setName(valueNameEvaluated(actualParameter));
2285 } else {
2286 var.setName(valueName(actualParameter));
2287 }
2288 method.getParameters().set(i, var);
2289 i++;
2290 }
2291
2292 method.getAnnotationMirrors().clear();
2293 method.getModifiers().remove(Modifier.ABSTRACT);
2294 return method;
2295 }
2296
2297 private boolean needsCastingExecuteMethod(ExecutableTypeData execType, TypeData primaryType) {
2298 if (execType.isAbstract()) {
2299 return true;
2300 }
2301 if (Utils.isPrimitiveOrVoid(primaryType.getPrimitiveType()) && Utils.isPrimitiveOrVoid(execType.getType().getPrimitiveType())) {
2302 return true;
2303 }
2304 if (execType.getType().isGeneric()) {
2305 return true;
2306 }
2307 return false;
2308 }
2309
2310 private List<ExecutableTypeData> findFunctionalExecutableType(SpecializationData specialization, int evaluatedCount) {
2311 TypeData primaryType = specialization.getReturnType().getTypeSystemType();
2312 List<ExecutableTypeData> otherTypes = specialization.getNode().getExecutableTypes(evaluatedCount);
2313
2314 List<ExecutableTypeData> filteredTypes = new ArrayList<>();
2315 for (ExecutableTypeData compareType : otherTypes) {
2316 if (!Utils.typeEquals(compareType.getType().getPrimitiveType(), primaryType.getPrimitiveType())) {
2317 continue;
2318 }
2319 filteredTypes.add(compareType);
2320 }
2321
2322 // no direct matches found use generic where the type is Object
2323 if (filteredTypes.isEmpty()) {
2324 for (ExecutableTypeData compareType : otherTypes) {
2325 if (compareType.getType().isGeneric() && !compareType.hasUnexpectedValue(getContext())) {
2326 filteredTypes.add(compareType);
2327 }
2328 }
2329 }
2330
2331 if (filteredTypes.isEmpty()) {
2332 for (ExecutableTypeData compareType : otherTypes) {
2333 if (compareType.getType().isGeneric()) {
2334 filteredTypes.add(compareType);
2335 }
2336 }
2337 }
2338
2339 return filteredTypes;
2340 }
2341
2342 private CodeTree createFunctionalExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable) {
2343 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
2344 if (specialization.isUninitialized()) {
2345 builder.tree(createDeoptimize(builder));
2346 }
2347
2348 builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null, false));
2349
2350 CodeTree executeNode = createExecute(builder, executable, specialization);
2351
2352 SpecializationData next = specialization.findNextSpecialization();
2353 CodeTree returnSpecialized = null;
2354 if (next != null) {
2355 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder);
2356 returnBuilder.tree(createDeoptimize(builder));
2357 returnBuilder.tree(createReturnExecuteAndSpecialize(builder, executable, next, null, "One of guards " + specialization.getGuards() + " failed"));
2358 returnSpecialized = returnBuilder.getRoot();
2359 }
2360 builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized, false, false));
2361
2362 return builder.getRoot();
2363 }
2364
2365 private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) {
2366 NodeData node = specialization.getNode();
2367 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
2368 if (!specialization.getExceptions().isEmpty() || !specialization.getAssumptions().isEmpty()) {
2369 builder.startTryBlock();
2370 }
2371
2372 for (String assumption : specialization.getAssumptions()) {
2373 builder.startStatement();
2374 builder.string("this.").string(assumption).string(".check()");
2375 builder.end();
2376 }
2377
2378 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent);
2379 if (specialization.isPolymorphic()) {
2380 int index = 0;
2381 if (executable.hasUnexpectedValue(getContext())) {
2382 index = specialization.getNode().getPolymorphicSpecializations().indexOf(specialization);
2383 }
2384 returnBuilder.startCall("next0", "executeCached" + index);
2385 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true);
2386 returnBuilder.end();
2387 } else if (specialization.isUninitialized()) {
2388 returnBuilder.startCall("super", EXECUTE_SPECIALIZE_NAME);
2389 returnBuilder.startGroup().string(nodeSpecializationClassName(specialization)).string(".class").end();
2390 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true);
2391 returnBuilder.doubleQuote("Uninitialized monomorphic");
2392 returnBuilder.end();
2393 } else if (specialization.getMethod() == null && !node.needsRewrites(context)) {
2394 emitEncounteredSynthetic(builder, specialization);
2395 } else if (specialization.isGeneric()) {
2396 returnBuilder.startCall("super", EXECUTE_GENERIC_NAME);
2397 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true);
2398 returnBuilder.end();
2399 } else {
2400 returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null));
2401 }
2402
2403 if (!returnBuilder.isEmpty()) {
2404 builder.startReturn();
2405
2406 TypeData targetType = node.getTypeSystem().findTypeData(builder.findMethod().getReturnType());
2407 TypeData sourceType = specialization.getReturnType().getTypeSystemType();
2408
2409 if (targetType == null || sourceType == null) {
2410 builder.tree(returnBuilder.getRoot());
2411 } else if (sourceType.needsCastTo(getContext(), targetType)) {
2412 builder.tree(createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.expectTypeMethodName(targetType), returnBuilder.getRoot()));
2413 } else {
2414 builder.tree(returnBuilder.getRoot());
2415 }
2416 builder.end();
2417 }
2418
2419 if (!specialization.getExceptions().isEmpty()) {
2420 for (SpecializationThrowsData exception : specialization.getExceptions()) {
2421 builder.end().startCatchBlock(exception.getJavaClass(), "ex");
2422 builder.tree(createDeoptimize(builder));
2423 builder.tree(createReturnExecuteAndSpecialize(parent, executable, exception.getTransitionTo(), null, "Thrown " + Utils.getSimpleName(exception.getJavaClass())));
2424 }
2425 builder.end();
2426 }
2427 if (!specialization.getAssumptions().isEmpty()) {
2428 builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex");
2429 builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization.findNextSpecialization(), null, "Assumption failed"));
2430 builder.end();
2431 }
2432
2433 return builder.getRoot();
2434 }
1998 2435
1999 } 2436 }
2000 2437
2001 } 2438 }