Mercurial > hg > graal-jvmci-8
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 |