comparison graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.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 3cc5fb59916e
children
comparison
equal deleted inserted replaced
10595:47233c73ca58 10596:f43eb2f1bbbc
34 import com.oracle.truffle.api.nodes.*; 34 import com.oracle.truffle.api.nodes.*;
35 import com.oracle.truffle.codegen.processor.*; 35 import com.oracle.truffle.codegen.processor.*;
36 import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; 36 import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality;
37 import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind; 37 import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind;
38 import com.oracle.truffle.codegen.processor.template.*; 38 import com.oracle.truffle.codegen.processor.template.*;
39 import com.oracle.truffle.codegen.processor.template.TemplateMethod.Signature;
39 import com.oracle.truffle.codegen.processor.typesystem.*; 40 import com.oracle.truffle.codegen.processor.typesystem.*;
40 41
41 public class NodeParser extends TemplateParser<NodeData> { 42 public class NodeParser extends TemplateParser<NodeData> {
42 43
43 public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, SpecializationListener.class, 44 public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, SpecializationListener.class,
150 if (nodeClass != null) { 151 if (nodeClass != null) {
151 nodeType = inheritType(nodeClass, "value", nodeType); 152 nodeType = inheritType(nodeClass, "value", nodeType);
152 } 153 }
153 154
154 if (nodeType == null) { 155 if (nodeType == null) {
155 if (nodeClass == null) { 156 return null;
156 // no node
157 return null;
158 } else {
159 // FIXME nodeType not specified error
160 return null;
161 }
162 } 157 }
163 158
164 Elements elementUtil = context.getEnvironment().getElementUtils(); 159 Elements elementUtil = context.getEnvironment().getElementUtils();
165 Set<Element> elementSet = new HashSet<>(elementUtil.getAllMembers(templateType)); 160 Set<Element> elementSet = new HashSet<>(elementUtil.getAllMembers(templateType));
166 if (!Utils.typeEquals(templateType.asType(), nodeType)) { 161 if (!Utils.typeEquals(templateType.asType(), nodeType)) {
204 } 199 }
205 200
206 for (NodeData splittedNode : nodes) { 201 for (NodeData splittedNode : nodes) {
207 finalizeSpecializations(elements, splittedNode); 202 finalizeSpecializations(elements, splittedNode);
208 verifyNode(splittedNode, elements); 203 verifyNode(splittedNode, elements);
204 splittedNode.setPolymorphicSpecializations(createPolymorphicSpecializations(splittedNode));
205 assignShortCircuitsToSpecializations(splittedNode);
209 } 206 }
210 207
211 if (node.isNodeContainer()) { 208 if (node.isNodeContainer()) {
212 node.setDeclaredNodes(nodes); 209 node.setDeclaredNodes(nodes);
213 node.setSpecializationListeners(new ArrayList<SpecializationListenerData>()); 210 node.setSpecializationListeners(new ArrayList<SpecializationListenerData>());
214 node.setSpecializations(new ArrayList<SpecializationData>()); 211 node.setSpecializations(new ArrayList<SpecializationData>());
215 return node; 212 }
216 } else { 213 return node;
217 return node; 214 }
218 } 215
216 private List<SpecializationData> createPolymorphicSpecializations(NodeData node) {
217 if (!node.needsRewrites(context) || node.getPolymorphicDepth() <= 1) {
218 return Collections.emptyList();
219 }
220
221 Signature genericSignature = node.getGenericSpecialization().getSignature();
222 Set<Signature> signatures = new HashSet<>();
223
224 for (SpecializationData specialization1 : node.getSpecializations()) {
225 Signature signature = specialization1.getSignature();
226
227 for (SpecializationData specialization2 : node.getSpecializations()) {
228 if (specialization1 == specialization2) {
229 continue;
230 }
231 signatures.add(signature.combine(genericSignature, specialization2.getSignature()));
232 }
233 }
234
235 while (true) {
236 List<Signature> newSignatures = new ArrayList<>();
237 for (Signature signature1 : signatures) {
238 for (Signature signature2 : signatures) {
239 if (signature1 == signature2) {
240 continue;
241 }
242 newSignatures.add(signature1.combine(genericSignature, signature2));
243 }
244 }
245 if (!signatures.addAll(newSignatures)) {
246 break;
247 }
248 }
249
250 List<Signature> sortedSignatures = new ArrayList<>(signatures);
251 Collections.sort(sortedSignatures);
252
253 List<SpecializationData> specializations = new ArrayList<>();
254 SpecializationData generic = node.getGenericSpecialization();
255 for (Signature signature : sortedSignatures) {
256 SpecializationData specialization = new SpecializationData(generic, false, false, true);
257 specialization.forceFrame(context.getTruffleTypes().getFrame());
258 specialization.setNode(node);
259 specialization.updateSignature(signature);
260
261 if (specialization.isGenericSpecialization(context)) {
262 specializations.add(0, specialization);
263 } else {
264 specializations.add(specialization);
265 }
266 }
267
268 return specializations;
219 } 269 }
220 270
221 private NodeData parseNodeData(TypeElement templateType, TypeMirror nodeType, List<? extends Element> elements, List<TypeElement> lookupTypes) { 271 private NodeData parseNodeData(TypeElement templateType, TypeMirror nodeType, List<? extends Element> elements, List<TypeElement> lookupTypes) {
222 NodeData nodeData = new NodeData(templateType, templateType.getSimpleName().toString()); 272 NodeData nodeData = new NodeData(templateType, templateType.getSimpleName().toString());
223 273
232 if (typeSystem == null) { 282 if (typeSystem == null) {
233 nodeData.addError("The used type system '%s' is invalid or not a Node.", Utils.getQualifiedName(typeSytemType)); 283 nodeData.addError("The used type system '%s' is invalid or not a Node.", Utils.getQualifiedName(typeSytemType));
234 return nodeData; 284 return nodeData;
235 } 285 }
236 286
287 AnnotationMirror polymorphicMirror = findFirstAnnotation(lookupTypes, PolymorphicLimit.class);
288 if (polymorphicMirror != null) {
289 AnnotationValue limitValue = Utils.getAnnotationValue(polymorphicMirror, "value");
290 int polymorphicLimit = Utils.getAnnotationValue(Integer.class, polymorphicMirror, "value");
291 if (polymorphicLimit < 1) {
292 nodeData.addError(limitValue, "Invalid polymorphic limit %s.", polymorphicLimit);
293 }
294 nodeData.setPolymorphicDepth(polymorphicLimit);
295 }
296
237 List<String> assumptionsList = new ArrayList<>(); 297 List<String> assumptionsList = new ArrayList<>();
238
239 for (int i = lookupTypes.size() - 1; i >= 0; i--) { 298 for (int i = lookupTypes.size() - 1; i >= 0; i--) {
240 TypeElement type = lookupTypes.get(i); 299 TypeElement type = lookupTypes.get(i);
241 AnnotationMirror assumptions = Utils.findAnnotationMirror(context.getEnvironment(), type, NodeAssumptions.class); 300 AnnotationMirror assumptions = Utils.findAnnotationMirror(context.getEnvironment(), type, NodeAssumptions.class);
242 if (assumptions != null) { 301 if (assumptions != null) {
243 List<String> assumptionStrings = Utils.getAnnotationValueList(String.class, assumptions, "value"); 302 List<String> assumptionStrings = Utils.getAnnotationValueList(String.class, assumptions, "value");
541 } else { 600 } else {
542 parameters.add(new ActualParameter(parameterSpec, specializationParameter.getType(), specializationParameter.getIndex(), specializationParameter.isImplicit())); 601 parameters.add(new ActualParameter(parameterSpec, specializationParameter.getType(), specializationParameter.getIndex(), specializationParameter.isImplicit()));
543 } 602 }
544 } 603 }
545 TemplateMethod genericMethod = new TemplateMethod("Generic", node, specification, null, null, returnType, parameters); 604 TemplateMethod genericMethod = new TemplateMethod("Generic", node, specification, null, null, returnType, parameters);
546 genericSpecialization = new SpecializationData(genericMethod, true, false); 605 genericSpecialization = new SpecializationData(genericMethod, true, false, false);
547 606
548 specializations.add(genericSpecialization); 607 specializations.add(genericSpecialization);
549 } 608 }
550 609
551 if (genericSpecialization != null) { 610 if (genericSpecialization != null) {
552 if (genericSpecialization.isUseSpecializationsForGeneric()) { 611 for (ActualParameter parameter : genericSpecialization.getReturnTypeAndParameters()) {
553 for (ActualParameter parameter : genericSpecialization.getReturnTypeAndParameters()) { 612 if (Utils.isObject(parameter.getType())) {
554 if (Utils.isObject(parameter.getType())) { 613 continue;
555 continue; 614 }
615 Set<String> types = new HashSet<>();
616 for (SpecializationData specialization : specializations) {
617 ActualParameter actualParameter = specialization.findParameter(parameter.getLocalName());
618 if (actualParameter != null) {
619 types.add(Utils.getQualifiedName(actualParameter.getType()));
556 } 620 }
557 Set<String> types = new HashSet<>(); 621 }
558 for (SpecializationData specialization : specializations) { 622 if (types.size() > 1) {
559 ActualParameter actualParameter = specialization.findParameter(parameter.getLocalName()); 623 genericSpecialization.replaceParameter(parameter.getLocalName(), new ActualParameter(parameter, node.getTypeSystem().getGenericTypeData()));
560 if (actualParameter != null) {
561 types.add(Utils.getQualifiedName(actualParameter.getType()));
562 }
563 }
564 if (types.size() > 1) {
565 genericSpecialization.replaceParameter(parameter.getLocalName(), new ActualParameter(parameter, node.getTypeSystem().getGenericTypeData()));
566 }
567 } 624 }
568 } 625 }
569 TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", node, genericSpecialization.getSpecification(), null, null, genericSpecialization.getReturnType(), 626 TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", node, genericSpecialization.getSpecification(), null, null, genericSpecialization.getReturnType(),
570 genericSpecialization.getParameters()); 627 genericSpecialization.getParameters());
571 // should not use messages from generic specialization 628 // should not use messages from generic specialization
572 uninializedMethod.getMessages().clear(); 629 uninializedMethod.getMessages().clear();
573 specializations.add(new SpecializationData(uninializedMethod, false, true)); 630 specializations.add(new SpecializationData(uninializedMethod, false, true, false));
574 } 631 }
575 632
576 Collections.sort(specializations); 633 Collections.sort(specializations);
577 634
578 node.setSpecializations(specializations); 635 node.setSpecializations(specializations);
593 List<String> ids = calculateSpecializationIds(needsId); 650 List<String> ids = calculateSpecializationIds(needsId);
594 for (int i = 0; i < ids.size(); i++) { 651 for (int i = 0; i < ids.size(); i++) {
595 needsId.get(i).setId(ids.get(i)); 652 needsId.get(i).setId(ids.get(i));
596 } 653 }
597 } 654 }
655
656 // calculate reachability
657 int specializationCount = 0;
658 boolean reachable = true;
659 for (SpecializationData specialization : specializations) {
660 if (specialization.isUninitialized()) {
661 specialization.setReachable(true);
662 continue;
663 }
664 if (!reachable && specialization.getMethod() != null) {
665 specialization.addError("%s is not reachable.", specialization.isGeneric() ? "Generic" : "Specialization");
666 }
667 specialization.setReachable(reachable);
668 if (!specialization.hasRewrite(context)) {
669 reachable = false;
670 }
671 if (!specialization.isGeneric()) {
672 specializationCount++;
673 }
674 }
675
676 if (node.getPolymorphicDepth() < 0) {
677 node.setPolymorphicDepth(specializationCount - 1);
678 }
679
680 // reduce polymorphicness if generic is not reachable
681 if (node.getGenericSpecialization() != null && !node.getGenericSpecialization().isReachable()) {
682 node.setPolymorphicDepth(1);
683 }
598 } 684 }
599 685
600 private void assignShortCircuitsToSpecializations(NodeData node) { 686 private void assignShortCircuitsToSpecializations(NodeData node) {
601 Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(node.getShortCircuits()); 687 Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(node.getShortCircuits());
602 688
651 if (!valid) { 737 if (!valid) {
652 return; 738 return;
653 } 739 }
654 740
655 NodeChildData[] fields = node.filterFields(ExecutionKind.SHORT_CIRCUIT); 741 NodeChildData[] fields = node.filterFields(ExecutionKind.SHORT_CIRCUIT);
656 for (SpecializationData specialization : node.getSpecializations()) { 742 List<SpecializationData> specializations = new ArrayList<>();
743 specializations.addAll(node.getSpecializations());
744 specializations.addAll(node.getPolymorphicSpecializations());
745
746 for (SpecializationData specialization : specializations) {
657 List<ShortCircuitData> assignedShortCuts = new ArrayList<>(fields.length); 747 List<ShortCircuitData> assignedShortCuts = new ArrayList<>(fields.length);
658 748
659 for (int i = 0; i < fields.length; i++) { 749 for (int i = 0; i < fields.length; i++) {
660 List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(fields[i].getName()); 750 List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(fields[i].getName());
661 751
818 private void verifyNode(NodeData nodeData, List<? extends Element> elements) { 908 private void verifyNode(NodeData nodeData, List<? extends Element> elements) {
819 // verify order is not ambiguous 909 // verify order is not ambiguous
820 verifySpecializationOrder(nodeData); 910 verifySpecializationOrder(nodeData);
821 911
822 verifyMissingAbstractMethods(nodeData, elements); 912 verifyMissingAbstractMethods(nodeData, elements);
823
824 assignShortCircuitsToSpecializations(nodeData);
825 913
826 verifyConstructors(nodeData); 914 verifyConstructors(nodeData);
827 915
828 verifyNamingConvention(nodeData.getShortCircuits(), "needs"); 916 verifyNamingConvention(nodeData.getShortCircuits(), "needs");
829 917