| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dart2js.enqueue; | 5 library dart2js.enqueue; |
| 6 | 6 |
| 7 import 'dart:collection' show | 7 import 'dart:collection' show |
| 8 Queue; | 8 Queue; |
| 9 | 9 |
| 10 import 'common/names.dart' show | 10 import 'common/names.dart' show |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 typedef ItemCompilationContext ItemCompilationContextCreator(); | 61 typedef ItemCompilationContext ItemCompilationContextCreator(); |
| 62 | 62 |
| 63 class EnqueueTask extends CompilerTask { | 63 class EnqueueTask extends CompilerTask { |
| 64 final ResolutionEnqueuer resolution; | 64 final ResolutionEnqueuer resolution; |
| 65 final CodegenEnqueuer codegen; | 65 final CodegenEnqueuer codegen; |
| 66 | 66 |
| 67 String get name => 'Enqueue'; | 67 String get name => 'Enqueue'; |
| 68 | 68 |
| 69 EnqueueTask(Compiler compiler) | 69 EnqueueTask(Compiler compiler) |
| 70 : resolution = new ResolutionEnqueuer( | 70 : resolution = new ResolutionEnqueuer( |
| 71 compiler, compiler.backend.createItemCompilationContext), | 71 compiler, compiler.backend.createItemCompilationContext, |
| 72 compiler.analyzeOnly && compiler.analyzeMain |
| 73 ? const EnqueuerStrategy() : const TreeShakingEnqueuerStrategy()), |
| 72 codegen = new CodegenEnqueuer( | 74 codegen = new CodegenEnqueuer( |
| 73 compiler, compiler.backend.createItemCompilationContext), | 75 compiler, compiler.backend.createItemCompilationContext, |
| 76 const TreeShakingEnqueuerStrategy()), |
| 74 super(compiler) { | 77 super(compiler) { |
| 75 codegen.task = this; | 78 codegen.task = this; |
| 76 resolution.task = this; | 79 resolution.task = this; |
| 77 | 80 |
| 78 codegen.nativeEnqueuer = compiler.backend.nativeCodegenEnqueuer(codegen); | 81 codegen.nativeEnqueuer = compiler.backend.nativeCodegenEnqueuer(codegen); |
| 79 resolution.nativeEnqueuer = | 82 resolution.nativeEnqueuer = |
| 80 compiler.backend.nativeResolutionEnqueuer(resolution); | 83 compiler.backend.nativeResolutionEnqueuer(resolution); |
| 81 } | 84 } |
| 82 | 85 |
| 83 void forgetElement(Element element) { | 86 void forgetElement(Element element) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 104 // TODO(johnniwinther): Collect checked types for checked mode separately to | 107 // TODO(johnniwinther): Collect checked types for checked mode separately to |
| 105 // support serialization. | 108 // support serialization. |
| 106 Iterable<DartType> get checkedTypes => const <DartType>[]; | 109 Iterable<DartType> get checkedTypes => const <DartType>[]; |
| 107 | 110 |
| 108 Iterable<MethodElement> get closurizedFunctions => const <MethodElement>[]; | 111 Iterable<MethodElement> get closurizedFunctions => const <MethodElement>[]; |
| 109 } | 112 } |
| 110 | 113 |
| 111 abstract class Enqueuer { | 114 abstract class Enqueuer { |
| 112 final String name; | 115 final String name; |
| 113 final Compiler compiler; // TODO(ahe): Remove this dependency. | 116 final Compiler compiler; // TODO(ahe): Remove this dependency. |
| 117 final EnqueuerStrategy strategy; |
| 114 final ItemCompilationContextCreator itemCompilationContextCreator; | 118 final ItemCompilationContextCreator itemCompilationContextCreator; |
| 115 final Map<String, Set<Element>> instanceMembersByName | 119 final Map<String, Set<Element>> instanceMembersByName |
| 116 = new Map<String, Set<Element>>(); | 120 = new Map<String, Set<Element>>(); |
| 117 final Map<String, Set<Element>> instanceFunctionsByName | 121 final Map<String, Set<Element>> instanceFunctionsByName |
| 118 = new Map<String, Set<Element>>(); | 122 = new Map<String, Set<Element>>(); |
| 119 final Set<ClassElement> _processedClasses = new Set<ClassElement>(); | 123 final Set<ClassElement> _processedClasses = new Set<ClassElement>(); |
| 120 Set<ClassElement> recentClasses = new Setlet<ClassElement>(); | 124 Set<ClassElement> recentClasses = new Setlet<ClassElement>(); |
| 121 final Universe universe = new Universe(); | 125 final Universe universe = new Universe(); |
| 122 | 126 |
| 123 static final TRACE_MIRROR_ENQUEUING = | 127 static final TRACE_MIRROR_ENQUEUING = |
| 124 const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING"); | 128 const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING"); |
| 125 | 129 |
| 126 bool queueIsClosed = false; | 130 bool queueIsClosed = false; |
| 127 EnqueueTask task; | 131 EnqueueTask task; |
| 128 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask | 132 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask |
| 129 | 133 |
| 130 bool hasEnqueuedReflectiveElements = false; | 134 bool hasEnqueuedReflectiveElements = false; |
| 131 bool hasEnqueuedReflectiveStaticFields = false; | 135 bool hasEnqueuedReflectiveStaticFields = false; |
| 132 | 136 |
| 133 Enqueuer(this.name, this.compiler, this.itemCompilationContextCreator); | 137 Enqueuer(this.name, |
| 138 this.compiler, |
| 139 this.itemCompilationContextCreator, |
| 140 this.strategy); |
| 134 | 141 |
| 135 Queue<WorkItem> get queue; | 142 Queue<WorkItem> get queue; |
| 136 bool get queueIsEmpty => queue.isEmpty; | 143 bool get queueIsEmpty => queue.isEmpty; |
| 137 | 144 |
| 138 /// Returns [:true:] if this enqueuer is the resolution enqueuer. | 145 /// Returns [:true:] if this enqueuer is the resolution enqueuer. |
| 139 bool get isResolutionQueue => false; | 146 bool get isResolutionQueue => false; |
| 140 | 147 |
| 141 QueueFilter get filter => compiler.enqueuerFilter; | 148 QueueFilter get filter => compiler.enqueuerFilter; |
| 142 | 149 |
| 143 /// Returns [:true:] if [member] has been processed by this enqueuer. | 150 /// Returns [:true:] if [member] has been processed by this enqueuer. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 processInstantiatedClass(cls); | 196 processInstantiatedClass(cls); |
| 190 compiler.backend.registerInstantiatedType(type, registry); | 197 compiler.backend.registerInstantiatedType(type, registry); |
| 191 }); | 198 }); |
| 192 } | 199 } |
| 193 | 200 |
| 194 bool checkNoEnqueuedInvokedInstanceMethods() { | 201 bool checkNoEnqueuedInvokedInstanceMethods() { |
| 195 return filter.checkNoEnqueuedInvokedInstanceMethods(this); | 202 return filter.checkNoEnqueuedInvokedInstanceMethods(this); |
| 196 } | 203 } |
| 197 | 204 |
| 198 void processInstantiatedClassMembers(ClassElement cls) { | 205 void processInstantiatedClassMembers(ClassElement cls) { |
| 199 cls.implementation.forEachMember(processInstantiatedClassMember); | 206 strategy.processInstantiatedClass(this, cls); |
| 200 } | 207 } |
| 201 | 208 |
| 202 void processInstantiatedClassMember(ClassElement cls, Element member) { | 209 void processInstantiatedClassMember(ClassElement cls, Element member) { |
| 203 assert(invariant(member, member.isDeclaration)); | 210 assert(invariant(member, member.isDeclaration)); |
| 204 if (isProcessed(member)) return; | 211 if (isProcessed(member)) return; |
| 205 if (!member.isInstanceMember) return; | 212 if (!member.isInstanceMember) return; |
| 206 String memberName = member.name; | 213 String memberName = member.name; |
| 207 | 214 |
| 208 if (member.isField) { | 215 if (member.isField) { |
| 209 // The obvious thing to test here would be "member.isNative", | 216 // The obvious thing to test here would be "member.isNative", |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 | 556 |
| 550 processInstanceMembers(String n, bool f(Element e)) { | 557 processInstanceMembers(String n, bool f(Element e)) { |
| 551 processSet(instanceMembersByName, n, f); | 558 processSet(instanceMembersByName, n, f); |
| 552 } | 559 } |
| 553 | 560 |
| 554 processInstanceFunctions(String n, bool f(Element e)) { | 561 processInstanceFunctions(String n, bool f(Element e)) { |
| 555 processSet(instanceFunctionsByName, n, f); | 562 processSet(instanceFunctionsByName, n, f); |
| 556 } | 563 } |
| 557 | 564 |
| 558 void handleUnseenSelector(UniverseSelector universeSelector) { | 565 void handleUnseenSelector(UniverseSelector universeSelector) { |
| 566 strategy.processSelector(this, universeSelector); |
| 567 } |
| 568 |
| 569 void handleUnseenSelectorInternal(UniverseSelector universeSelector) { |
| 559 Selector selector = universeSelector.selector; | 570 Selector selector = universeSelector.selector; |
| 560 String methodName = selector.name; | 571 String methodName = selector.name; |
| 561 processInstanceMembers(methodName, (Element member) { | 572 processInstanceMembers(methodName, (Element member) { |
| 562 if (universeSelector.appliesUnnamed(member, compiler.world)) { | 573 if (universeSelector.appliesUnnamed(member, compiler.world)) { |
| 563 if (member.isFunction && selector.isGetter) { | 574 if (member.isFunction && selector.isGetter) { |
| 564 registerClosurizedMember(member, compiler.globalDependencies); | 575 registerClosurizedMember(member, compiler.globalDependencies); |
| 565 } | 576 } |
| 566 if (member.isField && member.enclosingClass.isNative) { | 577 if (member.isField && member.enclosingClass.isNative) { |
| 567 if (selector.isGetter || selector.isCall) { | 578 if (selector.isGetter || selector.isCall) { |
| 568 nativeEnqueuer.registerFieldLoad(member); | 579 nativeEnqueuer.registerFieldLoad(member); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 597 } | 608 } |
| 598 } | 609 } |
| 599 | 610 |
| 600 /** | 611 /** |
| 601 * Documentation wanted -- johnniwinther | 612 * Documentation wanted -- johnniwinther |
| 602 * | 613 * |
| 603 * Invariant: [element] must be a declaration element. | 614 * Invariant: [element] must be a declaration element. |
| 604 */ | 615 */ |
| 605 void registerStaticUse(Element element) { | 616 void registerStaticUse(Element element) { |
| 606 if (element == null) return; | 617 if (element == null) return; |
| 618 strategy.processStaticUse(this, element); |
| 619 } |
| 620 |
| 621 void registerStaticUseInternal(Element element) { |
| 607 assert(invariant(element, element.isDeclaration, | 622 assert(invariant(element, element.isDeclaration, |
| 608 message: "Element ${element} is not the declaration.")); | 623 message: "Element ${element} is not the declaration.")); |
| 609 if (Elements.isStaticOrTopLevel(element) && element.isField) { | 624 if (Elements.isStaticOrTopLevel(element) && element.isField) { |
| 610 universe.registerStaticFieldUse(element); | 625 universe.registerStaticFieldUse(element); |
| 611 } | 626 } |
| 612 addToWorkList(element); | 627 addToWorkList(element); |
| 613 compiler.backend.registerStaticUse(element, this); | 628 compiler.backend.registerStaticUse(element, this); |
| 614 } | 629 } |
| 615 | 630 |
| 616 void registerGetOfStaticFunction(FunctionElement element) { | 631 void registerGetOfStaticFunction(FunctionElement element) { |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 742 | 757 |
| 743 final Queue<ResolutionWorkItem> queue; | 758 final Queue<ResolutionWorkItem> queue; |
| 744 | 759 |
| 745 /** | 760 /** |
| 746 * A deferred task queue for the resolution phase which is processed | 761 * A deferred task queue for the resolution phase which is processed |
| 747 * when the resolution queue has been emptied. | 762 * when the resolution queue has been emptied. |
| 748 */ | 763 */ |
| 749 final Queue<DeferredTask> deferredTaskQueue; | 764 final Queue<DeferredTask> deferredTaskQueue; |
| 750 | 765 |
| 751 ResolutionEnqueuer(Compiler compiler, | 766 ResolutionEnqueuer(Compiler compiler, |
| 752 ItemCompilationContext itemCompilationContextCreator()) | 767 ItemCompilationContext itemCompilationContextCreator(), |
| 753 : super('resolution enqueuer', compiler, itemCompilationContextCreator), | 768 EnqueuerStrategy strategy) |
| 769 : super('resolution enqueuer', |
| 770 compiler, |
| 771 itemCompilationContextCreator, |
| 772 strategy), |
| 754 resolvedElements = new Set<AstElement>(), | 773 resolvedElements = new Set<AstElement>(), |
| 755 queue = new Queue<ResolutionWorkItem>(), | 774 queue = new Queue<ResolutionWorkItem>(), |
| 756 deferredTaskQueue = new Queue<DeferredTask>(); | 775 deferredTaskQueue = new Queue<DeferredTask>(); |
| 757 | 776 |
| 758 bool get isResolutionQueue => true; | 777 bool get isResolutionQueue => true; |
| 759 | 778 |
| 760 bool isProcessed(Element member) => resolvedElements.contains(member); | 779 bool isProcessed(Element member) => resolvedElements.contains(member); |
| 761 | 780 |
| 762 /// Returns `true` if [element] has been processed by the resolution enqueuer. | 781 /// Returns `true` if [element] has been processed by the resolution enqueuer. |
| 763 bool hasBeenResolved(Element element) { | 782 bool hasBeenResolved(Element element) { |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 906 final Map<Element, js.Expression> generatedCode = | 925 final Map<Element, js.Expression> generatedCode = |
| 907 new Map<Element, js.Expression>(); | 926 new Map<Element, js.Expression>(); |
| 908 | 927 |
| 909 final Set<Element> newlyEnqueuedElements; | 928 final Set<Element> newlyEnqueuedElements; |
| 910 | 929 |
| 911 final Set<UniverseSelector> newlySeenSelectors; | 930 final Set<UniverseSelector> newlySeenSelectors; |
| 912 | 931 |
| 913 bool enabledNoSuchMethod = false; | 932 bool enabledNoSuchMethod = false; |
| 914 | 933 |
| 915 CodegenEnqueuer(Compiler compiler, | 934 CodegenEnqueuer(Compiler compiler, |
| 916 ItemCompilationContext itemCompilationContextCreator()) | 935 ItemCompilationContext itemCompilationContextCreator(), |
| 936 EnqueuerStrategy strategy) |
| 917 : queue = new Queue<CodegenWorkItem>(), | 937 : queue = new Queue<CodegenWorkItem>(), |
| 918 newlyEnqueuedElements = compiler.cacheStrategy.newSet(), | 938 newlyEnqueuedElements = compiler.cacheStrategy.newSet(), |
| 919 newlySeenSelectors = compiler.cacheStrategy.newSet(), | 939 newlySeenSelectors = compiler.cacheStrategy.newSet(), |
| 920 super('codegen enqueuer', compiler, itemCompilationContextCreator); | 940 super('codegen enqueuer', compiler, itemCompilationContextCreator, |
| 941 strategy); |
| 921 | 942 |
| 922 bool isProcessed(Element member) => | 943 bool isProcessed(Element member) => |
| 923 member.isAbstract || generatedCode.containsKey(member); | 944 member.isAbstract || generatedCode.containsKey(member); |
| 924 | 945 |
| 925 /** | 946 /** |
| 926 * Decides whether an element should be included to satisfy requirements | 947 * Decides whether an element should be included to satisfy requirements |
| 927 * of the mirror system. | 948 * of the mirror system. |
| 928 * | 949 * |
| 929 * For code generation, we rely on the precomputed set of elements that takes | 950 * For code generation, we rely on the precomputed set of elements that takes |
| 930 * subtyping constraints into account. | 951 * subtyping constraints into account. |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1012 void processWorkItem(void f(WorkItem work), WorkItem work) { | 1033 void processWorkItem(void f(WorkItem work), WorkItem work) { |
| 1013 f(work); | 1034 f(work); |
| 1014 } | 1035 } |
| 1015 } | 1036 } |
| 1016 | 1037 |
| 1017 void removeFromSet(Map<String, Set<Element>> map, Element element) { | 1038 void removeFromSet(Map<String, Set<Element>> map, Element element) { |
| 1018 Set<Element> set = map[element.name]; | 1039 Set<Element> set = map[element.name]; |
| 1019 if (set == null) return; | 1040 if (set == null) return; |
| 1020 set.remove(element); | 1041 set.remove(element); |
| 1021 } | 1042 } |
| 1043 |
| 1044 /// Strategy used by the enqueuer to populate the world. |
| 1045 // TODO(johnniwinther): Merge this interface with [QueueFilter]. |
| 1046 class EnqueuerStrategy { |
| 1047 const EnqueuerStrategy(); |
| 1048 |
| 1049 /// Process a class instantiated in live code. |
| 1050 void processInstantiatedClass(Enqueuer enqueuer, ClassElement cls) {} |
| 1051 |
| 1052 /// Process an element statically accessed in live code. |
| 1053 void processStaticUse(Enqueuer enqueuer, Element element) {} |
| 1054 |
| 1055 /// Process a selector for a call site in live code. |
| 1056 void processSelector(Enqueuer enqueuer, UniverseSelector selector) {} |
| 1057 } |
| 1058 |
| 1059 class TreeShakingEnqueuerStrategy implements EnqueuerStrategy { |
| 1060 const TreeShakingEnqueuerStrategy(); |
| 1061 |
| 1062 @override |
| 1063 void processInstantiatedClass(Enqueuer enqueuer, ClassElement cls) { |
| 1064 cls.implementation.forEachMember(enqueuer.processInstantiatedClassMember); |
| 1065 } |
| 1066 |
| 1067 @override |
| 1068 void processStaticUse(Enqueuer enqueuer, Element element) { |
| 1069 enqueuer.registerStaticUseInternal(element); |
| 1070 } |
| 1071 |
| 1072 @override |
| 1073 void processSelector(Enqueuer enqueuer, UniverseSelector selector) { |
| 1074 enqueuer.handleUnseenSelectorInternal(selector); |
| 1075 } |
| 1076 } |
| OLD | NEW |