Mercurial > hg > graal-compiler
comparison graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java @ 8245:703c09f8640c
Implemented support for @NodeClass annotation to support builtins.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Wed, 06 Mar 2013 18:32:33 +0100 |
parents | d81ff782fa1a |
children | c4c3f50fa9c2 |
comparison
equal
deleted
inserted
replaced
8244:10d37f893471 | 8245:703c09f8640c |
---|---|
49 private TypeMirror getUnexpectedValueException() { | 49 private TypeMirror getUnexpectedValueException() { |
50 return getContext().getTruffleTypes().getUnexpectedValueException(); | 50 return getContext().getTruffleTypes().getUnexpectedValueException(); |
51 } | 51 } |
52 | 52 |
53 private static String factoryClassName(NodeData node) { | 53 private static String factoryClassName(NodeData node) { |
54 return nodeClassName(node) + "Factory"; | 54 return node.getNodeId() + "Factory"; |
55 } | 55 } |
56 | 56 |
57 private static String nodeClassName(NodeData node) { | 57 private static String nodeSpecializationClassName(SpecializationData specialization) { |
58 return Utils.getSimpleName(node.getTemplateType().asType()); | 58 String nodeid = specialization.getNode().getNodeId(); |
59 } | 59 if (nodeid.endsWith("Node") && !nodeid.equals("Node")) { |
60 | 60 nodeid = nodeid.substring(0, nodeid.length() - 4); |
61 private static String nodeClassName(SpecializationData specialization) { | 61 } |
62 String name = specializationId(specialization); | 62 |
63 name += nodeClassName(specialization.getNode()); | 63 String name = Utils.firstLetterUpperCase(nodeid); |
64 if (name.equals(Utils.getSimpleName(specialization.getNode().getNodeType())) || name.equals(Utils.getSimpleName(specialization.getNode().getTemplateType()))) { | 64 name += Utils.firstLetterUpperCase(specialization.getId()); |
65 name = name + "Impl"; | 65 name += "Node"; |
66 } | |
67 | |
68 return name; | |
69 } | |
70 | |
71 private static String specializationId(SpecializationData specialization) { | |
72 String name = ""; | |
73 NodeData node = specialization.getNode(); | |
74 if (node.getSpecializations().size() > 1) { | |
75 name = specialization.getMethodName(); | |
76 if (name.startsWith("do")) { | |
77 name = name.substring(2); | |
78 } | |
79 } | |
80 return name; | 66 return name; |
81 } | 67 } |
82 | 68 |
83 private static String valueName(ActualParameter param) { | 69 private static String valueName(ActualParameter param) { |
84 return param.getName(); | 70 return param.getName(); |
86 | 72 |
87 private static String castValueName(ActualParameter parameter) { | 73 private static String castValueName(ActualParameter parameter) { |
88 return valueName(parameter) + "Cast"; | 74 return valueName(parameter) + "Cast"; |
89 } | 75 } |
90 | 76 |
91 private void addValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame) { | 77 private void addValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame, boolean includeHidden) { |
92 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { | 78 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { |
93 method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue")); | 79 method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue")); |
94 } | 80 } |
95 for (ActualParameter parameter : specialization.getParameters()) { | 81 for (ActualParameter parameter : specialization.getParameters()) { |
96 ParameterSpec spec = parameter.getSpecification(); | 82 ParameterSpec spec = parameter.getSpecification(); |
97 if (forceFrame && spec.getName().equals("frame")) { | 83 if (forceFrame && spec.getName().equals("frame")) { |
98 continue; | 84 continue; |
99 } | 85 } |
86 if (!includeHidden && parameter.isHidden()) { | |
87 continue; | |
88 } | |
89 | |
100 method.addParameter(new CodeVariableElement(parameter.getActualType(), valueName(parameter))); | 90 method.addParameter(new CodeVariableElement(parameter.getActualType(), valueName(parameter))); |
101 } | 91 } |
102 } | 92 } |
103 | 93 |
104 private static void addValueParameterNames(CodeTreeBuilder builder, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame) { | 94 private static void addValueParameterNames(CodeTreeBuilder builder, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, boolean includeHidden) { |
105 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { | 95 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { |
106 builder.string("frameValue"); | 96 builder.string("frameValue"); |
107 } | 97 } |
108 for (ActualParameter parameter : specialization.getParameters()) { | 98 for (ActualParameter parameter : specialization.getParameters()) { |
109 ParameterSpec spec = parameter.getSpecification(); | 99 ParameterSpec spec = parameter.getSpecification(); |
110 if (forceFrame && spec.getName().equals("frame")) { | 100 if (forceFrame && spec.getName().equals("frame")) { |
111 continue; | 101 continue; |
112 } | 102 } |
113 | 103 |
104 if (!includeHidden && parameter.isHidden()) { | |
105 continue; | |
106 } | |
107 | |
114 if (unexpectedValueName != null && parameter.getName().equals(unexpectedValueName)) { | 108 if (unexpectedValueName != null && parameter.getName().equals(unexpectedValueName)) { |
115 builder.string("ex.getResult()"); | 109 builder.string("ex.getResult()"); |
116 } else { | 110 } else { |
117 builder.string(valueName(parameter)); | 111 builder.string(valueName(parameter)); |
118 } | 112 } |
119 } | 113 } |
120 } | 114 } |
121 | 115 |
122 private static void addValueParameterNamesWithCasts(CodeTreeBuilder body, SpecializationData valueSpecialization, SpecializationData targetSpecialization) { | 116 private static void addValueParameterNamesWithCasts(CodeTreeBuilder body, SpecializationData valueSpecialization, SpecializationData targetSpecialization, boolean includeHidden) { |
123 NodeData node = targetSpecialization.getNode(); | 117 NodeData node = targetSpecialization.getNode(); |
124 TypeSystemData typeSystem = node.getTypeSystem(); | 118 TypeSystemData typeSystem = node.getTypeSystem(); |
125 | 119 |
126 for (ActualParameter targetParameter : targetSpecialization.getParameters()) { | 120 for (ActualParameter targetParameter : targetSpecialization.getParameters()) { |
127 ActualParameter valueParameter = valueSpecialization.findParameter(targetParameter.getName()); | 121 ActualParameter valueParameter = valueSpecialization.findParameter(targetParameter.getName()); |
128 TypeData targetType = targetParameter.getActualTypeData(typeSystem); | 122 TypeData targetType = targetParameter.getActualTypeData(typeSystem); |
129 | 123 |
124 if (!includeHidden && (targetParameter.isHidden() || valueParameter.isHidden())) { | |
125 continue; | |
126 } | |
127 | |
130 TypeData valueType = null; | 128 TypeData valueType = null; |
131 if (valueParameter != null) { | 129 if (valueParameter != null) { |
132 valueType = valueParameter.getActualTypeData(typeSystem); | 130 valueType = valueParameter.getActualTypeData(typeSystem); |
133 } | 131 } |
134 | 132 |
142 | 140 |
143 private static String genClassName(Template operation) { | 141 private static String genClassName(Template operation) { |
144 return getSimpleName(operation.getTemplateType()) + "Gen"; | 142 return getSimpleName(operation.getTemplateType()) + "Gen"; |
145 } | 143 } |
146 | 144 |
147 private static void startCallOperationMethod(CodeTreeBuilder body, TemplateMethod method) { | 145 private static void startCallOperationMethod(CodeTreeBuilder body, TemplateMethod templateMethod, boolean castedValues) { |
148 body.startGroup(); | 146 body.startGroup(); |
149 if (body.findMethod().getModifiers().contains(STATIC)) { | 147 ExecutableElement method = templateMethod.getMethod(); |
150 body.string(THIS_NODE_LOCAL_VAR_NAME); | 148 |
149 TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement()); | |
150 NodeData node = (NodeData) templateMethod.getTemplate(); | |
151 | |
152 boolean accessible = templateMethod.canBeAccessedByInstanceOf(node.getNodeType()); | |
153 if (accessible) { | |
154 if (body.findMethod().getModifiers().contains(STATIC)) { | |
155 body.string(THIS_NODE_LOCAL_VAR_NAME); | |
156 } else { | |
157 body.string("super"); | |
158 } | |
151 } else { | 159 } else { |
152 body.string("super"); | 160 if (method.getModifiers().contains(STATIC)) { |
161 body.type(targetClass.asType()); | |
162 } else { | |
163 ActualParameter parameter = templateMethod.getParameters().get(0); | |
164 if (castedValues) { | |
165 body.string(castValueName(parameter)); | |
166 } else { | |
167 body.string(valueName(parameter)); | |
168 } | |
169 } | |
153 } | 170 } |
154 body.string("."); | 171 body.string("."); |
155 body.startCall(method.getMethodName()); | 172 body.startCall(method.getSimpleName().toString()); |
156 } | 173 } |
157 | 174 |
158 private static String generatedGenericMethodName(SpecializationData specialization) { | 175 private static String generatedGenericMethodName(SpecializationData specialization) { |
159 final String prefix = "generic"; | 176 final String prefix = "generic"; |
160 | 177 |
166 for (SpecializationData current : specialization.getNode().getSpecializations()) { | 183 for (SpecializationData current : specialization.getNode().getSpecializations()) { |
167 if (specialization == current) { | 184 if (specialization == current) { |
168 if (prev == null || prev.isUninitialized()) { | 185 if (prev == null || prev.isUninitialized()) { |
169 return prefix; | 186 return prefix; |
170 } else { | 187 } else { |
171 return prefix + specializationId(current); | 188 return prefix + current.getId(); |
172 } | 189 } |
173 } | 190 } |
174 prev = current; | 191 prev = current; |
175 } | 192 } |
176 return prefix; | 193 return prefix; |
247 // Explicitly specified guards | 264 // Explicitly specified guards |
248 for (SpecializationGuardData guard : guardedSpecialization.getGuards()) { | 265 for (SpecializationGuardData guard : guardedSpecialization.getGuards()) { |
249 if ((guard.isOnSpecialization() && onSpecialization) || (guard.isOnExecution() && !onSpecialization)) { | 266 if ((guard.isOnSpecialization() && onSpecialization) || (guard.isOnExecution() && !onSpecialization)) { |
250 builder.string(andOperator); | 267 builder.string(andOperator); |
251 | 268 |
252 startCallOperationMethod(builder, guard.getGuardDeclaration()); | 269 startCallOperationMethod(builder, guard.getGuardDeclaration(), true); |
253 addValueParameterNamesWithCasts(builder, valueSpecialization, guardedSpecialization); | 270 addValueParameterNamesWithCasts(builder, valueSpecialization, guardedSpecialization, false); |
254 | 271 |
255 builder.end().end(); // call | 272 builder.end().end(); // call |
256 andOperator = " && "; | 273 andOperator = " && "; |
257 } | 274 } |
258 } | 275 } |
703 if (node.needsFactory()) { | 720 if (node.needsFactory()) { |
704 children.add(node); | 721 children.add(node); |
705 } | 722 } |
706 | 723 |
707 List<TypeMirror> nodeTypesList = new ArrayList<>(); | 724 List<TypeMirror> nodeTypesList = new ArrayList<>(); |
725 TypeMirror prev = null; | |
726 boolean allSame = true; | |
708 for (NodeData child : children) { | 727 for (NodeData child : children) { |
709 nodeTypesList.add(child.getTemplateType().asType()); | 728 nodeTypesList.add(child.getNodeType()); |
729 if (prev != null && !Utils.typeEquals(child.getNodeType(), prev)) { | |
730 allSame = false; | |
731 } | |
732 prev = child.getNodeType(); | |
710 } | 733 } |
711 TypeMirror commonNodeSuperType = Utils.getCommonSuperType(getContext(), nodeTypesList.toArray(new TypeMirror[nodeTypesList.size()])); | 734 TypeMirror commonNodeSuperType = Utils.getCommonSuperType(getContext(), nodeTypesList.toArray(new TypeMirror[nodeTypesList.size()])); |
712 | 735 |
713 Types types = getContext().getEnvironment().getTypeUtils(); | 736 Types types = getContext().getEnvironment().getTypeUtils(); |
714 TypeMirror factoryType = getContext().getType(NodeFactory.class); | 737 TypeMirror factoryType = getContext().getType(NodeFactory.class); |
715 TypeMirror baseType; | 738 TypeMirror baseType; |
716 if (children.size() == 1) { | 739 if (allSame) { |
717 baseType = types.getDeclaredType(Utils.fromTypeMirror(factoryType), commonNodeSuperType); | 740 baseType = types.getDeclaredType(Utils.fromTypeMirror(factoryType), commonNodeSuperType); |
718 } else { | 741 } else { |
719 baseType = types.getDeclaredType(Utils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null)); | 742 baseType = types.getDeclaredType(Utils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null)); |
720 } | 743 } |
721 TypeMirror listType = types.getDeclaredType(Utils.fromTypeMirror(getContext().getType(List.class)), baseType); | 744 TypeMirror listType = types.getDeclaredType(Utils.fromTypeMirror(getContext().getType(List.class)), baseType); |
782 CodeTreeBuilder body = method.createBuilder(); | 805 CodeTreeBuilder body = method.createBuilder(); |
783 body.startReturn(); | 806 body.startReturn(); |
784 if (node.getSpecializations().isEmpty()) { | 807 if (node.getSpecializations().isEmpty()) { |
785 body.null_(); | 808 body.null_(); |
786 } else { | 809 } else { |
787 body.startNew(nodeClassName(node.getSpecializations().get(0))); | 810 body.startNew(nodeSpecializationClassName(node.getSpecializations().get(0))); |
788 for (VariableElement var : method.getParameters()) { | 811 for (VariableElement var : method.getParameters()) { |
789 body.string(var.getSimpleName().toString()); | 812 body.string(var.getSimpleName().toString()); |
790 } | 813 } |
791 body.end(); | 814 body.end(); |
792 } | 815 } |
814 first = false; | 837 first = false; |
815 } else { | 838 } else { |
816 body.startElseIf(); | 839 body.startElseIf(); |
817 } | 840 } |
818 body.string("specializationClass == ").type(type.getBoxedType()).string(".class").end().startBlock(); | 841 body.string("specializationClass == ").type(type.getBoxedType()).string(".class").end().startBlock(); |
819 body.startReturn().startNew(nodeClassName(specialization)); | 842 body.startReturn().startNew(nodeSpecializationClassName(specialization)); |
820 body.string(THIS_NODE_LOCAL_VAR_NAME); | 843 body.string(THIS_NODE_LOCAL_VAR_NAME); |
821 body.end().end(); // new, return | 844 body.end().end(); // new, return |
822 | 845 |
823 body.end(); // if | 846 body.end(); // if |
824 } | 847 } |
825 } | 848 } |
826 body.startReturn().startNew(nodeClassName(node.getGenericSpecialization())); | 849 body.startReturn().startNew(nodeSpecializationClassName(node.getGenericSpecialization())); |
827 body.string(THIS_NODE_LOCAL_VAR_NAME); | 850 body.string(THIS_NODE_LOCAL_VAR_NAME); |
828 body.end().end(); | 851 body.end().end(); |
829 return method; | 852 return method; |
830 } | 853 } |
831 | 854 |
832 private CodeExecutableElement createSpecializeMethod(NodeData node) { | 855 private CodeExecutableElement createSpecializeMethod(NodeData node) { |
833 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), node.getNodeType(), "specialize"); | 856 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), node.getNodeType(), "specialize"); |
834 method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); | 857 method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); |
835 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); | 858 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); |
836 addValueParameters(method, node.getGenericSpecialization(), false); | 859 addValueParameters(method, node.getGenericSpecialization(), false, true); |
837 | 860 |
838 CodeTreeBuilder body = method.createBuilder(); | 861 CodeTreeBuilder body = method.createBuilder(); |
839 body.startStatement().string("boolean allowed = (minimumState == ").string(nodeClassName(node.getSpecializations().get(0))).string(".class)").end(); | 862 body.startStatement().string("boolean allowed = (minimumState == ").string(nodeSpecializationClassName(node.getSpecializations().get(0))).string(".class)").end(); |
840 | 863 |
841 for (int i = 1; i < node.getSpecializations().size(); i++) { | 864 for (int i = 1; i < node.getSpecializations().size(); i++) { |
842 SpecializationData specialization = node.getSpecializations().get(i); | 865 SpecializationData specialization = node.getSpecializations().get(i); |
843 body.startStatement().string("allowed = allowed || (minimumState == ").string(nodeClassName(specialization)).string(".class)").end(); | 866 body.startStatement().string("allowed = allowed || (minimumState == ").string(nodeSpecializationClassName(specialization)).string(".class)").end(); |
844 | 867 |
845 CodeTreeBuilder guarded = new CodeTreeBuilder(body); | 868 CodeTreeBuilder guarded = new CodeTreeBuilder(body); |
846 guarded.startReturn().startNew(nodeClassName(specialization)); | 869 guarded.startReturn().startNew(nodeSpecializationClassName(specialization)); |
847 guarded.string(THIS_NODE_LOCAL_VAR_NAME); | 870 guarded.string(THIS_NODE_LOCAL_VAR_NAME); |
848 guarded.end().end(); | 871 guarded.end().end(); |
849 | 872 |
850 body.tree(createGuardAndCast(body, "allowed", node.getGenericSpecialization(), specialization, true, guarded.getRoot(), null)); | 873 body.tree(createGuardAndCast(body, "allowed", node.getGenericSpecialization(), specialization, true, guarded.getRoot(), null)); |
851 } | 874 } |
869 continue; | 892 continue; |
870 } else { | 893 } else { |
871 String methodName = generatedGenericMethodName(current); | 894 String methodName = generatedGenericMethodName(current); |
872 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), genericReturnType, methodName); | 895 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), genericReturnType, methodName); |
873 method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); | 896 method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); |
874 addValueParameters(method, node.getGenericSpecialization(), true); | 897 addValueParameters(method, node.getGenericSpecialization(), true, true); |
875 | 898 |
876 emitGeneratedGenericSpecialization(method.createBuilder(), current, next); | 899 emitGeneratedGenericSpecialization(method.createBuilder(), current, next); |
877 | 900 |
878 methods.add(method); | 901 methods.add(method); |
879 } | 902 } |
882 | 905 |
883 return methods; | 906 return methods; |
884 } else { | 907 } else { |
885 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), genericReturnType, generatedGenericMethodName(null)); | 908 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), genericReturnType, generatedGenericMethodName(null)); |
886 method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); | 909 method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); |
887 addValueParameters(method, node.getGenericSpecialization(), true); | 910 addValueParameters(method, node.getGenericSpecialization(), true, true); |
888 emitInvokeDoMethod(method.createBuilder(), node.getGenericSpecialization(), 0); | 911 emitInvokeDoMethod(method.createBuilder(), node.getGenericSpecialization(), 0); |
889 return Arrays.asList(method); | 912 return Arrays.asList(method); |
890 } | 913 } |
891 } | 914 } |
892 | 915 |
904 if (next != null) { | 927 if (next != null) { |
905 builder.end(); | 928 builder.end(); |
906 | 929 |
907 builder.startReturn().startCall(generatedGenericMethodName(next)); | 930 builder.startReturn().startCall(generatedGenericMethodName(next)); |
908 builder.string(THIS_NODE_LOCAL_VAR_NAME); | 931 builder.string(THIS_NODE_LOCAL_VAR_NAME); |
909 addValueParameterNames(builder, next, null, true); | 932 addValueParameterNames(builder, next, null, true, true); |
910 builder.end().end(); | 933 builder.end().end(); |
911 } | 934 } |
912 } | 935 } |
913 | 936 |
914 private void emitInvokeDoMethod(CodeTreeBuilder builder, SpecializationData specialization, int level) { | 937 private void emitInvokeDoMethod(CodeTreeBuilder builder, SpecializationData specialization, int level) { |
915 if (!specialization.getExceptions().isEmpty()) { | 938 if (!specialization.getExceptions().isEmpty()) { |
916 builder.startTryBlock(); | 939 builder.startTryBlock(); |
917 } | 940 } |
918 | 941 |
919 builder.startReturn(); | 942 builder.startReturn(); |
920 startCallOperationMethod(builder, specialization); | 943 startCallOperationMethod(builder, specialization, true); |
921 addValueParameterNamesWithCasts(builder, specialization.getNode().getGenericSpecialization(), specialization); | 944 addValueParameterNamesWithCasts(builder, specialization.getNode().getGenericSpecialization(), specialization, false); |
922 builder.end().end(); // start call operation | 945 builder.end().end(); // start call operation |
923 builder.end(); // return | 946 builder.end(); // return |
924 | 947 |
925 if (!specialization.getExceptions().isEmpty()) { | 948 if (!specialization.getExceptions().isEmpty()) { |
926 for (SpecializationThrowsData exception : specialization.getExceptions()) { | 949 for (SpecializationThrowsData exception : specialization.getExceptions()) { |
927 builder.end().startCatchBlock(exception.getJavaClass(), "ex" + level); | 950 builder.end().startCatchBlock(exception.getJavaClass(), "ex" + level); |
928 | 951 |
929 builder.startReturn().startCall(generatedGenericMethodName(exception.getTransitionTo())); | 952 builder.startReturn().startCall(generatedGenericMethodName(exception.getTransitionTo())); |
930 builder.string(THIS_NODE_LOCAL_VAR_NAME); | 953 builder.string(THIS_NODE_LOCAL_VAR_NAME); |
931 addValueParameterNames(builder, exception.getTransitionTo(), null, true); | 954 addValueParameterNames(builder, exception.getTransitionTo(), null, true, true); |
932 builder.end().end(); | 955 builder.end().end(); |
933 } | 956 } |
934 builder.end(); | 957 builder.end(); |
935 } | 958 } |
936 } | 959 } |
943 } | 966 } |
944 | 967 |
945 @Override | 968 @Override |
946 public CodeTypeElement create(SpecializationData specialization) { | 969 public CodeTypeElement create(SpecializationData specialization) { |
947 NodeData node = specialization.getNode(); | 970 NodeData node = specialization.getNode(); |
948 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeClassName(specialization), node.getNodeType(), false); | 971 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), node.getNodeType(), false); |
949 return clazz; | 972 return clazz; |
950 } | 973 } |
951 | 974 |
952 @Override | 975 @Override |
953 protected void createChildren(SpecializationData specialization) { | 976 protected void createChildren(SpecializationData specialization) { |
1108 builder.startCall("replace"); | 1131 builder.startCall("replace"); |
1109 if (node.needsRewrites(getContext())) { | 1132 if (node.needsRewrites(getContext())) { |
1110 builder.startCall(factoryClassName(node), "specialize"); | 1133 builder.startCall(factoryClassName(node), "specialize"); |
1111 builder.string("this"); | 1134 builder.string("this"); |
1112 builder.typeLiteral(builder.findMethod().getEnclosingElement().asType()); | 1135 builder.typeLiteral(builder.findMethod().getEnclosingElement().asType()); |
1113 addValueParameterNames(builder, specialization, null, false); | 1136 addValueParameterNames(builder, specialization, null, false, true); |
1114 builder.end(); // call replace, call specialize | 1137 builder.end(); // call replace, call specialize |
1115 } else { | 1138 } else { |
1116 builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end(); | 1139 builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end(); |
1117 } | 1140 } |
1118 builder.end().end(); | 1141 builder.end().end(); |
1127 } | 1150 } |
1128 | 1151 |
1129 if ((specialization.isUninitialized() || specialization.isGeneric()) && node.needsRewrites(getContext())) { | 1152 if ((specialization.isUninitialized() || specialization.isGeneric()) && node.needsRewrites(getContext())) { |
1130 builder.startReturn().startCall(factoryClassName(node), generatedGenericMethodName(null)); | 1153 builder.startReturn().startCall(factoryClassName(node), generatedGenericMethodName(null)); |
1131 builder.string("this"); | 1154 builder.string("this"); |
1132 addValueParameterNames(builder, specialization, null, true); | 1155 addValueParameterNames(builder, specialization, null, true, true); |
1133 builder.end().end(); | 1156 builder.end().end(); |
1134 } else { | 1157 } else { |
1135 builder.startReturn(); | 1158 builder.startReturn(); |
1136 | 1159 |
1137 if (specialization.isUninitialized()) { | 1160 if (specialization.isUninitialized()) { |
1138 startCallOperationMethod(builder, specialization.getNode().getGenericSpecialization()); | 1161 startCallOperationMethod(builder, specialization.getNode().getGenericSpecialization(), false); |
1139 } else { | 1162 } else { |
1140 startCallOperationMethod(builder, specialization); | 1163 startCallOperationMethod(builder, specialization, false); |
1141 } | 1164 } |
1142 addValueParameterNames(builder, specialization, null, false); | 1165 addValueParameterNames(builder, specialization, null, false, false); |
1143 builder.end().end(); // operation call | 1166 builder.end().end(); // operation call |
1144 builder.end(); // return | 1167 builder.end(); // return |
1145 } | 1168 } |
1146 | 1169 |
1147 if (!specialization.getExceptions().isEmpty()) { | 1170 if (!specialization.getExceptions().isEmpty()) { |
1154 return builder.getRoot(); | 1177 return builder.getRoot(); |
1155 } | 1178 } |
1156 | 1179 |
1157 private CodeTree createExecuteChildren(CodeTreeBuilder parent, SpecializationData specialization) { | 1180 private CodeTree createExecuteChildren(CodeTreeBuilder parent, SpecializationData specialization) { |
1158 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 1181 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
1182 | |
1159 for (ActualParameter parameter : specialization.getParameters()) { | 1183 for (ActualParameter parameter : specialization.getParameters()) { |
1160 NodeFieldData field = specialization.getNode().findField(parameter.getSpecification().getName()); | 1184 NodeFieldData field = specialization.getNode().findField(parameter.getSpecification().getName()); |
1161 if (field == null) { | 1185 if (field == null) { |
1162 continue; | 1186 continue; |
1163 } | 1187 } |
1164 | 1188 |
1165 if (parameter.getActualTypeData(specialization.getNode().getTypeSystem()).isGeneric()) { | 1189 buildFieldExecute(builder, specialization, parameter, field, null); |
1166 buildGenericValueExecute(builder, specialization, parameter, field, null); | |
1167 } else { | |
1168 buildSpecializedValueExecute(builder, specialization, parameter, field); | |
1169 } | |
1170 } | 1190 } |
1171 return builder.getRoot(); | 1191 return builder.getRoot(); |
1172 } | 1192 } |
1173 | 1193 |
1174 private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) { | 1194 private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) { |
1175 for (TemplateMethod listener : node.getSpecializationListeners()) { | 1195 for (TemplateMethod listener : node.getSpecializationListeners()) { |
1176 builder.startStatement(); | 1196 builder.startStatement(); |
1177 startCallOperationMethod(builder, listener); | 1197 startCallOperationMethod(builder, listener, false); |
1178 addValueParameterNames(builder, listener, null, false); | 1198 addValueParameterNames(builder, listener, null, false, false); |
1179 builder.end().end(); | 1199 builder.end().end(); |
1180 builder.end(); // statement | 1200 builder.end(); // statement |
1181 } | 1201 } |
1182 } | 1202 } |
1183 | 1203 |
1184 private void buildGenericValueExecute(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter param, NodeFieldData field, ActualParameter exceptionParam) { | 1204 private void buildFieldExecute(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter param, NodeFieldData field, ActualParameter exceptionParam) { |
1185 NodeData node = specialization.getNode(); | |
1186 boolean shortCircuit = startShortCircuit(builder, specialization, param, exceptionParam); | 1205 boolean shortCircuit = startShortCircuit(builder, specialization, param, exceptionParam); |
1187 | 1206 ExecutableTypeData execType = field.getNodeData().findExecutableType(param.getActualTypeData(field.getNodeData().getTypeSystem())); |
1188 builder.startStatement(); | 1207 boolean unexpected = execType.hasUnexpectedValue(getContext()); |
1189 if (!shortCircuit) { | 1208 |
1190 builder.type(specialization.getNode().getTypeSystem().getGenericType()); | 1209 if (!shortCircuit && unexpected) { |
1191 builder.string(" "); | 1210 builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).end(); |
1192 } | 1211 } |
1193 | 1212 |
1194 builder.string(valueName(param)); | 1213 if (unexpected) { |
1195 builder.string(" = "); | 1214 builder.startTryBlock(); |
1196 ExecutableTypeData genericExecutableType = field.getNodeData().findGenericExecutableType(getContext(), param.getActualTypeData(node.getTypeSystem())); | 1215 } |
1197 if (genericExecutableType == null) { | 1216 |
1198 throw new AssertionError("Must have generic executable type. Parser validation most likely failed. " + (field.getNodeData().getExecutableTypes())); | 1217 if (!shortCircuit && !unexpected) { |
1199 } | 1218 builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).string(" = "); |
1200 buildExecute(builder, param, field, genericExecutableType); | 1219 } else { |
1220 builder.startStatement().string(valueName(param)).string(" = "); | |
1221 } | |
1222 buildExecute(builder, param, field, execType); | |
1201 builder.end(); | 1223 builder.end(); |
1202 | 1224 |
1225 if (unexpected) { | |
1226 builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); | |
1227 SpecializationData generic = specialization.getNode().getGenericSpecialization(); | |
1228 boolean execute = false; | |
1229 for (ActualParameter exParam : generic.getParameters()) { | |
1230 NodeFieldData exField = generic.getNode().findField(exParam.getSpecification().getName()); | |
1231 if (exField == null) { | |
1232 continue; | |
1233 } | |
1234 if (execute) { | |
1235 buildFieldExecute(builder, specialization.getNode().getGenericSpecialization(), exParam, exField, param); | |
1236 } else if (exParam.getName().equals(param.getName())) { | |
1237 execute = true; | |
1238 } | |
1239 } | |
1240 builder.tree(createReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), param)); | |
1241 builder.end(); // catch block | |
1242 } | |
1243 | |
1203 endShortCircuit(builder, shortCircuit); | 1244 endShortCircuit(builder, shortCircuit); |
1245 builder.newLine(); | |
1204 } | 1246 } |
1205 | 1247 |
1206 private void buildExecute(CodeTreeBuilder builder, ActualParameter parameter, NodeFieldData field, ExecutableTypeData execType) { | 1248 private void buildExecute(CodeTreeBuilder builder, ActualParameter parameter, NodeFieldData field, ExecutableTypeData execType) { |
1207 if (field != null) { | 1249 if (field != null) { |
1208 Element accessElement = field.getAccessElement(); | 1250 Element accessElement = field.getAccessElement(); |
1217 builder.string("[" + parameter.getIndex() + "]"); | 1259 builder.string("[" + parameter.getIndex() + "]"); |
1218 } | 1260 } |
1219 builder.string("."); | 1261 builder.string("."); |
1220 } | 1262 } |
1221 builder.startCall(execType.getMethodName()); | 1263 builder.startCall(execType.getMethodName()); |
1222 if (execType.getParameters().length == 1) { | 1264 if (execType.getParameters().size() == 1) { |
1223 builder.string("frameValue"); | 1265 builder.string("frameValue"); |
1224 } | 1266 } |
1225 builder.end(); | 1267 builder.end(); |
1226 } | |
1227 | |
1228 private void buildSpecializedValueExecute(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter param, NodeFieldData field) { | |
1229 boolean shortCircuit = startShortCircuit(builder, specialization, param, null); | |
1230 | |
1231 if (!shortCircuit) { | |
1232 builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).end(); | |
1233 } | |
1234 | |
1235 ExecutableTypeData execType = field.getNodeData().findExecutableType(param.getActualTypeData(field.getNodeData().getTypeSystem())); | |
1236 | |
1237 if (execType.hasUnexpectedValue(getContext())) { | |
1238 builder.startTryBlock(); | |
1239 } | |
1240 | |
1241 builder.startStatement().string(valueName(param)).string(" = "); | |
1242 buildExecute(builder, param, field, execType); | |
1243 builder.end(); | |
1244 | |
1245 if (execType.hasUnexpectedValue(getContext())) { | |
1246 builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); | |
1247 SpecializationData generic = specialization.getNode().getGenericSpecialization(); | |
1248 boolean execute = false; | |
1249 for (ActualParameter exParam : generic.getParameters()) { | |
1250 NodeFieldData exField = generic.getNode().findField(exParam.getSpecification().getName()); | |
1251 if (exField == null) { | |
1252 continue; | |
1253 } | |
1254 if (execute) { | |
1255 buildGenericValueExecute(builder, specialization.getNode().getGenericSpecialization(), exParam, exField, param); | |
1256 } else if (exParam.getName().equals(param.getName())) { | |
1257 execute = true; | |
1258 } | |
1259 } | |
1260 builder.tree(createReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), param)); | |
1261 builder.end(); // catch block | |
1262 } | |
1263 | |
1264 endShortCircuit(builder, shortCircuit); | |
1265 builder.newLine(); | |
1266 } | 1268 } |
1267 | 1269 |
1268 private boolean startShortCircuit(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter parameter, ActualParameter exceptionParam) { | 1270 private boolean startShortCircuit(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter parameter, ActualParameter exceptionParam) { |
1269 NodeFieldData forField = specialization.getNode().findField(parameter.getSpecification().getName()); | 1271 NodeFieldData forField = specialization.getNode().findField(parameter.getSpecification().getName()); |
1270 if (forField == null) { | 1272 if (forField == null) { |
1288 } | 1290 } |
1289 | 1291 |
1290 builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); | 1292 builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); |
1291 ShortCircuitData shortCircuitData = specialization.getShortCircuits()[shortCircuitIndex]; | 1293 ShortCircuitData shortCircuitData = specialization.getShortCircuits()[shortCircuitIndex]; |
1292 | 1294 |
1293 startCallOperationMethod(builder, shortCircuitData); | 1295 startCallOperationMethod(builder, shortCircuitData, false); |
1294 addValueParameterNames(builder, shortCircuitData, exceptionParam != null ? exceptionParam.getName() : null, false); | 1296 addValueParameterNames(builder, shortCircuitData, exceptionParam != null ? exceptionParam.getName() : null, false, false); |
1295 builder.end().end(); // call operation | 1297 builder.end().end(); // call operation |
1296 | 1298 |
1297 builder.end(); // statement | 1299 builder.end(); // statement |
1298 | 1300 |
1299 builder.declaration(parameter.getActualType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getActualType())); | 1301 builder.declaration(parameter.getActualType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getActualType())); |
1310 } | 1312 } |
1311 | 1313 |
1312 private CodeTree createReturnSpecializeAndExecute(CodeTreeBuilder parent, SpecializationData nextSpecialization, ActualParameter exceptionParam) { | 1314 private CodeTree createReturnSpecializeAndExecute(CodeTreeBuilder parent, SpecializationData nextSpecialization, ActualParameter exceptionParam) { |
1313 CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); | 1315 CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); |
1314 specializeCall.startCall("specializeAndExecute"); | 1316 specializeCall.startCall("specializeAndExecute"); |
1315 specializeCall.string(nodeClassName(nextSpecialization) + ".class"); | 1317 specializeCall.string(nodeSpecializationClassName(nextSpecialization) + ".class"); |
1316 addValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getName() : null, true); | 1318 addValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getName() : null, true, true); |
1317 specializeCall.end().end(); | 1319 specializeCall.end().end(); |
1318 | 1320 |
1319 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 1321 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
1320 builder.startReturn(); | 1322 builder.startReturn(); |
1321 builder.tree(specializeCall.getRoot()); | 1323 builder.tree(specializeCall.getRoot()); |
1332 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), returnType.getPrimitiveType(), "specializeAndExecute"); | 1334 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), returnType.getPrimitiveType(), "specializeAndExecute"); |
1333 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); | 1335 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); |
1334 if (canThrowUnexpected) { | 1336 if (canThrowUnexpected) { |
1335 method.addThrownType(getUnexpectedValueException()); | 1337 method.addThrownType(getUnexpectedValueException()); |
1336 } | 1338 } |
1337 addValueParameters(method, specialization.getNode().getGenericSpecialization(), true); | 1339 addValueParameters(method, specialization.getNode().getGenericSpecialization(), true, true); |
1338 clazz.add(method); | 1340 clazz.add(method); |
1339 | 1341 |
1340 CodeTreeBuilder builder = method.createBuilder(); | 1342 CodeTreeBuilder builder = method.createBuilder(); |
1341 | 1343 |
1342 builder.tree(createDeoptimize(builder)); | 1344 builder.tree(createDeoptimize(builder)); |
1343 emitSpecializationListeners(builder, specialization.getNode()); | 1345 emitSpecializationListeners(builder, specialization.getNode()); |
1344 | 1346 |
1345 builder.startStatement(); | 1347 builder.startStatement(); |
1346 builder.startCall("replace"); | 1348 builder.startCall("replace"); |
1347 builder.startCall(factoryClassName(specialization.getNode()), "specialize").string("this").string("minimumState"); | 1349 builder.startCall(factoryClassName(specialization.getNode()), "specialize").string("this").string("minimumState"); |
1348 addValueParameterNames(builder, specialization.getNode().getGenericSpecialization(), null, false); | 1350 addValueParameterNames(builder, specialization.getNode().getGenericSpecialization(), null, false, true); |
1349 builder.end(); | 1351 builder.end(); |
1350 builder.end(); // call replace | 1352 builder.end(); // call replace |
1351 builder.end(); // statement | 1353 builder.end(); // statement |
1352 | 1354 |
1353 String generatedMethodName = generatedGenericMethodName(specialization.findNextSpecialization()); | 1355 String generatedMethodName = generatedGenericMethodName(specialization.findNextSpecialization()); |
1354 ExecutableElement generatedGeneric = clazz.getEnclosingClass().getMethod(generatedMethodName); | 1356 ExecutableElement generatedGeneric = clazz.getEnclosingClass().getMethod(generatedMethodName); |
1355 | 1357 |
1356 CodeTreeBuilder genericExecute = CodeTreeBuilder.createBuilder(); | 1358 CodeTreeBuilder genericExecute = CodeTreeBuilder.createBuilder(); |
1357 genericExecute.startCall(factoryClassName(specialization.getNode()), generatedMethodName); | 1359 genericExecute.startCall(factoryClassName(specialization.getNode()), generatedMethodName); |
1358 genericExecute.string("this"); | 1360 genericExecute.string("this"); |
1359 addValueParameterNames(genericExecute, specialization.getNode().getGenericSpecialization(), null, true); | 1361 addValueParameterNames(genericExecute, specialization.getNode().getGenericSpecialization(), null, true, true); |
1360 genericExecute.end(); // call generated generic | 1362 genericExecute.end(); // call generated generic |
1361 | 1363 |
1362 CodeTree genericInvocation = createExpectType(node, returnExecutableType, genericExecute.getRoot()); | 1364 CodeTree genericInvocation = createExpectType(node, returnExecutableType, genericExecute.getRoot()); |
1363 | 1365 |
1364 if (generatedGeneric != null && Utils.isVoid(generatedGeneric.getReturnType())) { | 1366 if (generatedGeneric != null && Utils.isVoid(generatedGeneric.getReturnType())) { |