Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(225)

Side by Side Diff: pkg/compiler/lib/src/enqueue.dart

Issue 1376863004: Avoid eager enqueueing from resolution (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Update minimal_resolution_test. Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698