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