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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 | 105 |
106 // TODO(johnniwinther): Split this into more precise subsets. | 106 // TODO(johnniwinther): Split this into more precise subsets. |
107 Iterable<Element> get staticUses => const <Element>[]; | 107 Iterable<Element> get staticUses => const <Element>[]; |
108 | 108 |
109 // TODO(johnniwinther): Replace this by called constructors with type | 109 // TODO(johnniwinther): Replace this by called constructors with type |
110 // arguments. | 110 // arguments. |
111 Iterable<InterfaceType> get instantiatedTypes => const <InterfaceType>[]; | 111 Iterable<InterfaceType> get instantiatedTypes => const <InterfaceType>[]; |
112 | 112 |
113 // TODO(johnniwinther): Collect checked types for checked mode separately to | 113 // TODO(johnniwinther): Collect checked types for checked mode separately to |
114 // support serialization. | 114 // support serialization. |
115 Iterable<DartType> get isChecks => const <DartType>[]; | 115 Iterable<DartType> get checkedTypes => const <DartType>[]; |
116 | |
117 Iterable<DartType> get checkedModeChecks => const <DartType>[]; | |
118 | |
119 Iterable<DartType> get asCasts => const <DartType>[]; | |
120 | 116 |
121 Iterable<MethodElement> get closurizedFunctions => const <MethodElement>[]; | 117 Iterable<MethodElement> get closurizedFunctions => const <MethodElement>[]; |
122 | |
123 Iterable<LocalFunctionElement> get closures => const <LocalFunctionElement>[]; | |
124 } | 118 } |
125 | 119 |
126 abstract class Enqueuer { | 120 abstract class Enqueuer { |
127 final String name; | 121 final String name; |
128 final Compiler compiler; // TODO(ahe): Remove this dependency. | 122 final Compiler compiler; // TODO(ahe): Remove this dependency. |
129 final EnqueuerStrategy strategy; | 123 final EnqueuerStrategy strategy; |
130 final ItemCompilationContextCreator itemCompilationContextCreator; | 124 final ItemCompilationContextCreator itemCompilationContextCreator; |
131 final Map<String, Set<Element>> instanceMembersByName | 125 final Map<String, Set<Element>> instanceMembersByName |
132 = new Map<String, Set<Element>>(); | 126 = new Map<String, Set<Element>>(); |
133 final Map<String, Set<Element>> instanceFunctionsByName | 127 final Map<String, Set<Element>> instanceFunctionsByName |
(...skipping 26 matching lines...) Expand all Loading... |
160 /// Returns [:true:] if this enqueuer is the resolution enqueuer. | 154 /// Returns [:true:] if this enqueuer is the resolution enqueuer. |
161 bool get isResolutionQueue => false; | 155 bool get isResolutionQueue => false; |
162 | 156 |
163 QueueFilter get filter => compiler.enqueuerFilter; | 157 QueueFilter get filter => compiler.enqueuerFilter; |
164 | 158 |
165 DiagnosticReporter get reporter => compiler.reporter; | 159 DiagnosticReporter get reporter => compiler.reporter; |
166 | 160 |
167 /// Returns [:true:] if [member] has been processed by this enqueuer. | 161 /// Returns [:true:] if [member] has been processed by this enqueuer. |
168 bool isProcessed(Element member); | 162 bool isProcessed(Element member); |
169 | 163 |
170 bool isClassProcessed(ClassElement cls) => _processedClasses.contains(cls); | |
171 | |
172 Iterable<ClassElement> get processedClasses => _processedClasses; | |
173 | |
174 /** | 164 /** |
175 * Documentation wanted -- johnniwinther | 165 * Documentation wanted -- johnniwinther |
176 * | 166 * |
177 * Invariant: [element] must be a declaration element. | 167 * Invariant: [element] must be a declaration element. |
178 */ | 168 */ |
179 void addToWorkList(Element element) { | 169 void addToWorkList(Element element) { |
180 assert(invariant(element, element.isDeclaration)); | 170 assert(invariant(element, element.isDeclaration)); |
181 if (internalAddToWorkList(element) && compiler.dumpInfo) { | 171 if (internalAddToWorkList(element) && compiler.dumpInfo) { |
182 // TODO(sigmund): add other missing dependencies (internals, selectors | 172 // TODO(sigmund): add other missing dependencies (internals, selectors |
183 // enqueued after allocations), also enable only for the codegen enqueuer. | 173 // enqueued after allocations), also enable only for the codegen enqueuer. |
184 compiler.dumpInfoTask.registerDependency( | 174 compiler.dumpInfoTask.registerDependency( |
185 compiler.currentElement, element); | 175 compiler.currentElement, element); |
186 } | 176 } |
187 } | 177 } |
188 | 178 |
189 /** | 179 /** |
190 * Adds [element] to the work list if it has not already been processed. | 180 * Adds [element] to the work list if it has not already been processed. |
191 * | 181 * |
192 * Returns [true] if the element was actually added to the queue. | 182 * Returns [true] if the element was actually added to the queue. |
193 */ | 183 */ |
194 bool internalAddToWorkList(Element element); | 184 bool internalAddToWorkList(Element element); |
195 | 185 |
196 /// Apply the [worldImpact] of processing [element] to this enqueuer. | 186 /// Apply the [worldImpact] of processing [element] to this enqueuer. |
197 void applyImpact(Element element, WorldImpact worldImpact) { | 187 void applyImpact(Element element, WorldImpact worldImpact) { |
198 // TODO(johnniwinther): Optimize the application of the world impact. | 188 // TODO(johnniwinther): Optimize the application of the world impact. |
199 worldImpact.dynamicInvocations.forEach(registerDynamicInvocation); | 189 worldImpact.dynamicInvocations.forEach(registerDynamicInvocation); |
200 worldImpact.dynamicGetters.forEach(registerDynamicGetter); | 190 worldImpact.dynamicGetters.forEach(registerDynamicGetter); |
201 worldImpact.dynamicSetters.forEach(registerDynamicSetter); | 191 worldImpact.dynamicSetters.forEach(registerDynamicSetter); |
202 worldImpact.staticUses.forEach(registerStaticUse); | 192 worldImpact.staticUses.forEach(registerStaticUse); |
203 worldImpact.instantiatedTypes.forEach(registerInstantiatedType); | 193 // TODO(johnniwinther): Register [worldImpact.instantiatedTypes] when it |
204 worldImpact.isChecks.forEach(registerIsCheck); | 194 // doesn't require a [Registry]. |
205 worldImpact.asCasts.forEach(registerIsCheck); | 195 worldImpact.checkedTypes.forEach(registerIsCheck); |
206 if (compiler.enableTypeAssertions) { | |
207 worldImpact.checkedModeChecks.forEach(registerIsCheck); | |
208 } | |
209 worldImpact.closurizedFunctions.forEach(registerGetOfStaticFunction); | 196 worldImpact.closurizedFunctions.forEach(registerGetOfStaticFunction); |
210 worldImpact.closures.forEach(registerClosure); | |
211 } | 197 } |
212 | 198 |
213 // TODO(johnniwinther): Remove the need for passing the [registry]. | 199 // TODO(johnniwinther): Remove the need for passing the [registry]. |
214 void registerInstantiatedType(InterfaceType type, | 200 void registerInstantiatedType(InterfaceType type, |
215 {bool mirrorUsage: false}) { | 201 {bool mirrorUsage: false}) { |
216 task.measure(() { | 202 task.measure(() { |
217 ClassElement cls = type.element; | 203 ClassElement cls = type.element; |
218 cls.ensureResolved(resolution); | 204 cls.ensureResolved(resolution); |
219 universe.registerTypeInstantiation( | 205 universe.registerTypeInstantiation( |
220 type, | 206 type, |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 | 327 |
342 void processInstantiatedClass(ClassElement cls) { | 328 void processInstantiatedClass(ClassElement cls) { |
343 task.measure(() { | 329 task.measure(() { |
344 if (_processedClasses.contains(cls)) return; | 330 if (_processedClasses.contains(cls)) return; |
345 // The class must be resolved to compute the set of all | 331 // The class must be resolved to compute the set of all |
346 // supertypes. | 332 // supertypes. |
347 cls.ensureResolved(resolution); | 333 cls.ensureResolved(resolution); |
348 | 334 |
349 void processClass(ClassElement superclass) { | 335 void processClass(ClassElement superclass) { |
350 if (_processedClasses.contains(superclass)) return; | 336 if (_processedClasses.contains(superclass)) return; |
351 // TODO(johnniwinther): Re-insert this invariant when unittests don't | |
352 // fail. There is already a similar invariant on the members. | |
353 /*if (!isResolutionQueue) { | |
354 assert(invariant(superclass, | |
355 superclass.isClosure || | |
356 compiler.enqueuer.resolution.isClassProcessed(superclass), | |
357 message: "Class $superclass has not been " | |
358 "processed in resolution.")); | |
359 }*/ | |
360 | 337 |
361 _processedClasses.add(superclass); | 338 _processedClasses.add(superclass); |
362 recentClasses.add(superclass); | 339 recentClasses.add(superclass); |
363 superclass.ensureResolved(resolution); | 340 superclass.ensureResolved(resolution); |
364 superclass.implementation.forEachMember(processInstantiatedClassMember); | 341 superclass.implementation.forEachMember(processInstantiatedClassMember); |
365 if (isResolutionQueue && !superclass.isSynthesized) { | 342 if (isResolutionQueue && !superclass.isSynthesized) { |
366 compiler.resolver.checkClass(superclass); | 343 compiler.resolver.checkClass(superclass); |
367 } | 344 } |
368 // We only tell the backend once that [superclass] was instantiated, so | 345 // We only tell the backend once that [superclass] was instantiated, so |
369 // any additional dependencies must be treated as global | 346 // any additional dependencies must be treated as global |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 } | 760 } |
784 | 761 |
785 /// [Enqueuer] which is specific to resolution. | 762 /// [Enqueuer] which is specific to resolution. |
786 class ResolutionEnqueuer extends Enqueuer { | 763 class ResolutionEnqueuer extends Enqueuer { |
787 /** | 764 /** |
788 * Map from declaration elements to the [TreeElements] object holding the | 765 * Map from declaration elements to the [TreeElements] object holding the |
789 * resolution mapping for the element implementation. | 766 * resolution mapping for the element implementation. |
790 * | 767 * |
791 * Invariant: Key elements are declaration elements. | 768 * Invariant: Key elements are declaration elements. |
792 */ | 769 */ |
793 final Set<AstElement> processedElements; | 770 final Set<AstElement> resolvedElements; |
794 | 771 |
795 final Queue<ResolutionWorkItem> queue; | 772 final Queue<ResolutionWorkItem> queue; |
796 | 773 |
797 /** | 774 /** |
798 * A deferred task queue for the resolution phase which is processed | 775 * A deferred task queue for the resolution phase which is processed |
799 * when the resolution queue has been emptied. | 776 * when the resolution queue has been emptied. |
800 */ | 777 */ |
801 final Queue<DeferredTask> deferredTaskQueue; | 778 final Queue<DeferredTask> deferredTaskQueue; |
802 | 779 |
803 ResolutionEnqueuer(Compiler compiler, | 780 ResolutionEnqueuer(Compiler compiler, |
804 ItemCompilationContext itemCompilationContextCreator(), | 781 ItemCompilationContext itemCompilationContextCreator(), |
805 EnqueuerStrategy strategy) | 782 EnqueuerStrategy strategy) |
806 : super('resolution enqueuer', | 783 : super('resolution enqueuer', |
807 compiler, | 784 compiler, |
808 itemCompilationContextCreator, | 785 itemCompilationContextCreator, |
809 strategy), | 786 strategy), |
810 processedElements = new Set<AstElement>(), | 787 resolvedElements = new Set<AstElement>(), |
811 queue = new Queue<ResolutionWorkItem>(), | 788 queue = new Queue<ResolutionWorkItem>(), |
812 deferredTaskQueue = new Queue<DeferredTask>(); | 789 deferredTaskQueue = new Queue<DeferredTask>(); |
813 | 790 |
814 bool get isResolutionQueue => true; | 791 bool get isResolutionQueue => true; |
815 | 792 |
816 bool isProcessed(Element member) => processedElements.contains(member); | 793 bool isProcessed(Element member) => resolvedElements.contains(member); |
817 | 794 |
818 /// Returns `true` if [element] has been processed by the resolution enqueuer. | 795 /// Returns `true` if [element] has been processed by the resolution enqueuer. |
819 bool hasBeenProcessed(Element element) { | 796 bool hasBeenResolved(Element element) { |
820 return processedElements.contains(element.analyzableElement.declaration); | 797 return resolvedElements.contains(element.analyzableElement.declaration); |
821 } | 798 } |
822 | 799 |
823 /// Registers [element] as processed by the resolution enqueuer. | 800 /// Registers [element] as resolved for the resolution enqueuer. |
824 void registerProcessedElement(AstElement element) { | 801 void registerResolvedElement(AstElement element) { |
825 processedElements.add(element); | 802 resolvedElements.add(element); |
826 } | 803 } |
827 | 804 |
828 /** | 805 /** |
829 * Decides whether an element should be included to satisfy requirements | 806 * Decides whether an element should be included to satisfy requirements |
830 * of the mirror system. | 807 * of the mirror system. |
831 * | 808 * |
832 * During resolution, we have to resort to matching elements against the | 809 * During resolution, we have to resort to matching elements against the |
833 * [MirrorsUsed] pattern, as we do not have a complete picture of the world, | 810 * [MirrorsUsed] pattern, as we do not have a complete picture of the world, |
834 * yet. | 811 * yet. |
835 */ | 812 */ |
836 bool shouldIncludeElementDueToMirrors(Element element, | 813 bool shouldIncludeElementDueToMirrors(Element element, |
837 {bool includedEnclosing}) { | 814 {bool includedEnclosing}) { |
838 return includedEnclosing || compiler.backend.requiredByMirrorSystem(element)
; | 815 return includedEnclosing || compiler.backend.requiredByMirrorSystem(element)
; |
839 } | 816 } |
840 | 817 |
841 bool internalAddToWorkList(Element element) { | 818 bool internalAddToWorkList(Element element) { |
842 if (element.isErroneous) return false; | 819 if (element.isErroneous) return false; |
843 | 820 |
844 assert(invariant(element, element is AnalyzableElement, | 821 assert(invariant(element, element is AnalyzableElement, |
845 message: 'Element $element is not analyzable.')); | 822 message: 'Element $element is not analyzable.')); |
846 if (hasBeenProcessed(element)) return false; | 823 if (hasBeenResolved(element)) return false; |
847 if (queueIsClosed) { | 824 if (queueIsClosed) { |
848 throw new SpannableAssertionFailure(element, | 825 throw new SpannableAssertionFailure(element, |
849 "Resolution work list is closed. Trying to add $element."); | 826 "Resolution work list is closed. Trying to add $element."); |
850 } | 827 } |
851 | 828 |
852 compiler.world.registerUsedElement(element); | 829 compiler.world.registerUsedElement(element); |
853 | 830 |
854 ResolutionWorkItem workItem; | 831 ResolutionWorkItem workItem; |
855 if (compiler.serialization.isDeserialized(element)) { | 832 if (compiler.serialization.isDeserialized(element)) { |
856 workItem = compiler.serialization.createResolutionWorkItem( | 833 workItem = compiler.serialization.createResolutionWorkItem( |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
928 } | 905 } |
929 | 906 |
930 void emptyDeferredTaskQueue() { | 907 void emptyDeferredTaskQueue() { |
931 while (!deferredTaskQueue.isEmpty) { | 908 while (!deferredTaskQueue.isEmpty) { |
932 DeferredTask task = deferredTaskQueue.removeFirst(); | 909 DeferredTask task = deferredTaskQueue.removeFirst(); |
933 reporter.withCurrentElement(task.element, task.action); | 910 reporter.withCurrentElement(task.element, task.action); |
934 } | 911 } |
935 } | 912 } |
936 | 913 |
937 void _logSpecificSummary(log(message)) { | 914 void _logSpecificSummary(log(message)) { |
938 log('Resolved ${processedElements.length} elements.'); | 915 log('Resolved ${resolvedElements.length} elements.'); |
939 } | 916 } |
940 | 917 |
941 void forgetElement(Element element) { | 918 void forgetElement(Element element) { |
942 super.forgetElement(element); | 919 super.forgetElement(element); |
943 processedElements.remove(element); | 920 resolvedElements.remove(element); |
944 } | 921 } |
945 } | 922 } |
946 | 923 |
947 /// [Enqueuer] which is specific to code generation. | 924 /// [Enqueuer] which is specific to code generation. |
948 class CodegenEnqueuer extends Enqueuer { | 925 class CodegenEnqueuer extends Enqueuer { |
949 final Queue<CodegenWorkItem> queue; | 926 final Queue<CodegenWorkItem> queue; |
950 final Map<Element, js.Expression> generatedCode = | 927 final Map<Element, js.Expression> generatedCode = |
951 new Map<Element, js.Expression>(); | 928 new Map<Element, js.Expression>(); |
952 | 929 |
953 final Set<Element> newlyEnqueuedElements; | 930 final Set<Element> newlyEnqueuedElements; |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1092 @override | 1069 @override |
1093 void processStaticUse(Enqueuer enqueuer, Element element) { | 1070 void processStaticUse(Enqueuer enqueuer, Element element) { |
1094 enqueuer.registerStaticUseInternal(element); | 1071 enqueuer.registerStaticUseInternal(element); |
1095 } | 1072 } |
1096 | 1073 |
1097 @override | 1074 @override |
1098 void processSelector(Enqueuer enqueuer, UniverseSelector selector) { | 1075 void processSelector(Enqueuer enqueuer, UniverseSelector selector) { |
1099 enqueuer.handleUnseenSelectorInternal(selector); | 1076 enqueuer.handleUnseenSelectorInternal(selector); |
1100 } | 1077 } |
1101 } | 1078 } |
OLD | NEW |