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