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 Queue; | 7 import 'dart:collection' show Queue; |
8 | 8 |
9 import 'common/codegen.dart' show CodegenWorkItem; | |
10 import 'common/names.dart' show Identifiers; | 9 import 'common/names.dart' show Identifiers; |
11 import 'common/resolution.dart' show Resolution; | 10 import 'common/resolution.dart' show Resolution; |
12 import 'common/resolution.dart' show ResolutionWorkItem; | 11 import 'common/resolution.dart' show ResolutionWorkItem; |
13 import 'common/tasks.dart' show CompilerTask; | 12 import 'common/tasks.dart' show CompilerTask; |
14 import 'common/work.dart' show ItemCompilationContext, WorkItem; | 13 import 'common/work.dart' show ItemCompilationContext, WorkItem; |
15 import 'common.dart'; | 14 import 'common.dart'; |
16 import 'compiler.dart' show Compiler; | 15 import 'compiler.dart' show Compiler; |
17 import 'dart_types.dart' show DartType, InterfaceType; | 16 import 'dart_types.dart' show DartType, InterfaceType; |
18 import 'elements/elements.dart' | 17 import 'elements/elements.dart' |
19 show | 18 show |
20 AnalyzableElement, | 19 AnalyzableElement, |
21 AstElement, | 20 AstElement, |
22 ClassElement, | 21 ClassElement, |
23 ConstructorElement, | 22 ConstructorElement, |
24 Element, | 23 Element, |
25 Elements, | 24 Elements, |
| 25 Entity, |
26 FunctionElement, | 26 FunctionElement, |
27 LibraryElement, | 27 LibraryElement, |
28 Member, | 28 Member, |
29 MemberElement, | |
30 Name, | 29 Name, |
31 TypedElement, | 30 TypedElement, |
32 TypedefElement; | 31 TypedefElement; |
33 import 'js/js.dart' as js; | |
34 import 'native/native.dart' as native; | 32 import 'native/native.dart' as native; |
35 import 'types/types.dart' show TypeMaskStrategy; | 33 import 'types/types.dart' show TypeMaskStrategy; |
36 import 'universe/selector.dart' show Selector; | 34 import 'universe/selector.dart' show Selector; |
37 import 'universe/universe.dart'; | 35 import 'universe/universe.dart'; |
38 import 'universe/use.dart' | 36 import 'universe/use.dart' |
39 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; | 37 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; |
40 import 'universe/world_impact.dart' | 38 import 'universe/world_impact.dart' |
41 show ImpactUseCase, WorldImpact, WorldImpactVisitor; | 39 show ImpactUseCase, WorldImpact, WorldImpactVisitor; |
42 import 'util/util.dart' show Setlet; | 40 import 'util/util.dart' show Setlet; |
43 | 41 |
44 typedef ItemCompilationContext ItemCompilationContextCreator(); | 42 typedef ItemCompilationContext ItemCompilationContextCreator(); |
45 | 43 |
46 class EnqueueTask extends CompilerTask { | 44 class EnqueueTask extends CompilerTask { |
47 final ResolutionEnqueuer resolution; | 45 final ResolutionEnqueuer resolution; |
48 final CodegenEnqueuer codegen; | 46 final Enqueuer codegen; |
49 final Compiler compiler; | 47 final Compiler compiler; |
50 | 48 |
51 String get name => 'Enqueue'; | 49 String get name => 'Enqueue'; |
52 | 50 |
53 EnqueueTask(Compiler compiler) | 51 EnqueueTask(Compiler compiler) |
54 : compiler = compiler, | 52 : compiler = compiler, |
55 resolution = new ResolutionEnqueuer( | 53 resolution = new ResolutionEnqueuer( |
56 compiler, | 54 compiler, |
57 compiler.backend.createItemCompilationContext, | 55 compiler.backend.createItemCompilationContext, |
58 compiler.options.analyzeOnly && compiler.options.analyzeMain | 56 compiler.options.analyzeOnly && compiler.options.analyzeMain |
59 ? const EnqueuerStrategy() | 57 ? const EnqueuerStrategy() |
60 : const TreeShakingEnqueuerStrategy()), | 58 : const TreeShakingEnqueuerStrategy()), |
61 codegen = compiler.backend.createCodegenEnqueuer(compiler), | 59 codegen = compiler.backend.createCodegenEnqueuer(compiler), |
62 super(compiler.measurer) { | 60 super(compiler.measurer) { |
63 codegen.task = this; | 61 codegen.task = this; |
64 resolution.task = this; | 62 resolution.task = this; |
65 | 63 |
66 codegen.nativeEnqueuer = compiler.backend.nativeCodegenEnqueuer(codegen); | 64 codegen.nativeEnqueuer = compiler.backend.nativeCodegenEnqueuer(codegen); |
67 resolution.nativeEnqueuer = | 65 resolution.nativeEnqueuer = |
68 compiler.backend.nativeResolutionEnqueuer(resolution); | 66 compiler.backend.nativeResolutionEnqueuer(resolution); |
69 } | 67 } |
70 | 68 |
71 void forgetElement(Element element) { | 69 void forgetElement(Element element) { |
72 resolution.forgetElement(element); | 70 resolution.forgetElement(element); |
73 codegen.forgetElement(element); | 71 codegen.forgetElement(element); |
74 } | 72 } |
75 } | 73 } |
76 | 74 |
77 abstract class Enqueuer { | 75 abstract class Enqueuer { |
| 76 EnqueueTask task; |
| 77 Universe get universe; |
| 78 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask |
| 79 void forgetElement(Element element); |
| 80 void processInstantiatedClassMembers(ClassElement cls); |
| 81 void processInstantiatedClassMember(ClassElement cls, Element member); |
| 82 void handleUnseenSelectorInternal(DynamicUse dynamicUse); |
| 83 void registerStaticUse(StaticUse staticUse); |
| 84 void registerStaticUseInternal(StaticUse staticUse); |
| 85 void registerDynamicUse(DynamicUse dynamicUse); |
| 86 void registerTypeUse(TypeUse typeUse); |
| 87 |
| 88 /// Returns [:true:] if this enqueuer is the resolution enqueuer. |
| 89 bool get isResolutionQueue; |
| 90 |
| 91 bool queueIsClosed; |
| 92 |
| 93 bool get queueIsEmpty; |
| 94 |
| 95 ImpactUseCase get impactUse; |
| 96 |
| 97 /** |
| 98 * Documentation wanted -- johnniwinther |
| 99 * |
| 100 * Invariant: [element] must be a declaration element. |
| 101 */ |
| 102 void addToWorkList(Element element); |
| 103 |
| 104 void enableIsolateSupport(); |
| 105 |
| 106 /// Enqueue the static fields that have been marked as used by reflective |
| 107 /// usage through `MirrorsUsed`. |
| 108 void enqueueReflectiveStaticFields(Iterable<Element> elements); |
| 109 |
| 110 /// Enqueue all elements that are matched by the mirrors used |
| 111 /// annotation or, in lack thereof, all elements. |
| 112 void enqueueReflectiveElements(Iterable<ClassElement> recents); |
| 113 |
| 114 void registerInstantiatedType(InterfaceType type, {bool mirrorUsage: false}); |
| 115 void forEach(void f(WorkItem work)); |
| 116 void applyImpact(Element element, WorldImpact worldImpact); |
| 117 bool checkNoEnqueuedInvokedInstanceMethods(); |
| 118 void logSummary(log(message)); |
| 119 |
| 120 /// Returns [:true:] if [member] has been processed by this enqueuer. |
| 121 bool isProcessed(Element member); |
| 122 |
| 123 Iterable<Entity> get processedEntities; |
| 124 } |
| 125 |
| 126 /// [Enqueuer] which is specific to resolution. |
| 127 class ResolutionEnqueuer extends Enqueuer { |
78 final String name; | 128 final String name; |
79 final Compiler compiler; // TODO(ahe): Remove this dependency. | 129 final Compiler compiler; // TODO(ahe): Remove this dependency. |
80 final EnqueuerStrategy strategy; | 130 final EnqueuerStrategy strategy; |
81 final ItemCompilationContextCreator itemCompilationContextCreator; | 131 final ItemCompilationContextCreator itemCompilationContextCreator; |
82 final Map<String, Set<Element>> instanceMembersByName = | 132 final Map<String, Set<Element>> instanceMembersByName = |
83 new Map<String, Set<Element>>(); | 133 new Map<String, Set<Element>>(); |
84 final Map<String, Set<Element>> instanceFunctionsByName = | 134 final Map<String, Set<Element>> instanceFunctionsByName = |
85 new Map<String, Set<Element>>(); | 135 new Map<String, Set<Element>>(); |
86 final Set<ClassElement> _processedClasses = new Set<ClassElement>(); | 136 final Set<ClassElement> _processedClasses = new Set<ClassElement>(); |
87 Set<ClassElement> recentClasses = new Setlet<ClassElement>(); | 137 Set<ClassElement> recentClasses = new Setlet<ClassElement>(); |
88 final Universe universe = new Universe(const TypeMaskStrategy()); | 138 final Universe universe = new Universe(const TypeMaskStrategy()); |
89 | 139 |
90 static final TRACE_MIRROR_ENQUEUING = | 140 static final TRACE_MIRROR_ENQUEUING = |
91 const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING"); | 141 const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING"); |
92 | 142 |
93 bool queueIsClosed = false; | 143 bool queueIsClosed = false; |
94 EnqueueTask task; | |
95 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask | |
96 | 144 |
97 bool hasEnqueuedReflectiveElements = false; | 145 bool hasEnqueuedReflectiveElements = false; |
98 bool hasEnqueuedReflectiveStaticFields = false; | 146 bool hasEnqueuedReflectiveStaticFields = false; |
99 | 147 |
100 WorldImpactVisitor impactVisitor; | 148 WorldImpactVisitor impactVisitor; |
101 | 149 |
102 Enqueuer(this.name, this.compiler, this.itemCompilationContextCreator, | 150 ResolutionEnqueuer( |
103 this.strategy) { | 151 Compiler compiler, this.itemCompilationContextCreator, this.strategy) |
| 152 : this.name = 'resolution enqueuer', |
| 153 this.compiler = compiler, |
| 154 processedElements = new Set<AstElement>(), |
| 155 queue = new Queue<ResolutionWorkItem>(), |
| 156 deferredQueue = new Queue<_DeferredAction>() { |
104 impactVisitor = new _EnqueuerImpactVisitor(this); | 157 impactVisitor = new _EnqueuerImpactVisitor(this); |
105 } | 158 } |
106 | 159 |
107 // TODO(johnniwinther): Move this to [ResolutionEnqueuer]. | 160 // TODO(johnniwinther): Move this to [ResolutionEnqueuer]. |
108 Resolution get resolution => compiler.resolution; | 161 Resolution get resolution => compiler.resolution; |
109 | 162 |
110 Queue<WorkItem> get queue; | |
111 bool get queueIsEmpty => queue.isEmpty; | 163 bool get queueIsEmpty => queue.isEmpty; |
112 | 164 |
113 /// Returns [:true:] if this enqueuer is the resolution enqueuer. | |
114 bool get isResolutionQueue => false; | |
115 | |
116 QueueFilter get filter => compiler.enqueuerFilter; | 165 QueueFilter get filter => compiler.enqueuerFilter; |
117 | 166 |
118 DiagnosticReporter get reporter => compiler.reporter; | 167 DiagnosticReporter get reporter => compiler.reporter; |
119 | 168 |
120 /// Returns [:true:] if [member] has been processed by this enqueuer. | |
121 bool isProcessed(Element member); | |
122 | |
123 bool isClassProcessed(ClassElement cls) => _processedClasses.contains(cls); | 169 bool isClassProcessed(ClassElement cls) => _processedClasses.contains(cls); |
124 | 170 |
125 Iterable<ClassElement> get processedClasses => _processedClasses; | 171 Iterable<ClassElement> get processedClasses => _processedClasses; |
126 | 172 |
127 ImpactUseCase get impactUse; | |
128 | |
129 /** | 173 /** |
130 * Documentation wanted -- johnniwinther | 174 * Documentation wanted -- johnniwinther |
131 * | 175 * |
132 * Invariant: [element] must be a declaration element. | 176 * Invariant: [element] must be a declaration element. |
133 */ | 177 */ |
134 void addToWorkList(Element element) { | 178 void addToWorkList(Element element) { |
135 assert(invariant(element, element.isDeclaration)); | 179 assert(invariant(element, element.isDeclaration)); |
136 if (internalAddToWorkList(element) && compiler.options.dumpInfo) { | 180 if (internalAddToWorkList(element) && compiler.options.dumpInfo) { |
137 // TODO(sigmund): add other missing dependencies (internals, selectors | 181 // TODO(sigmund): add other missing dependencies (internals, selectors |
138 // enqueued after allocations), also enable only for the codegen enqueuer. | 182 // enqueued after allocations), also enable only for the codegen enqueuer. |
139 compiler.dumpInfoTask | 183 compiler.dumpInfoTask |
140 .registerDependency(compiler.currentElement, element); | 184 .registerDependency(compiler.currentElement, element); |
141 } | 185 } |
142 } | 186 } |
143 | 187 |
144 /** | |
145 * Adds [element] to the work list if it has not already been processed. | |
146 * | |
147 * Returns [true] if the element was actually added to the queue. | |
148 */ | |
149 bool internalAddToWorkList(Element element); | |
150 | |
151 /// Apply the [worldImpact] of processing [element] to this enqueuer. | 188 /// Apply the [worldImpact] of processing [element] to this enqueuer. |
152 void applyImpact(Element element, WorldImpact worldImpact) { | 189 void applyImpact(Element element, WorldImpact worldImpact) { |
153 compiler.impactStrategy | 190 compiler.impactStrategy |
154 .visitImpact(element, worldImpact, impactVisitor, impactUse); | 191 .visitImpact(element, worldImpact, impactVisitor, impactUse); |
155 } | 192 } |
156 | 193 |
157 void registerInstantiatedType(InterfaceType type, {bool mirrorUsage: false}) { | 194 void registerInstantiatedType(InterfaceType type, {bool mirrorUsage: false}) { |
158 task.measure(() { | 195 task.measure(() { |
159 ClassElement cls = type.element; | 196 ClassElement cls = type.element; |
160 cls.ensureResolved(resolution); | 197 cls.ensureResolved(resolution); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
261 } | 298 } |
262 } | 299 } |
263 | 300 |
264 // The element is not yet used. Add it to the list of instance | 301 // The element is not yet used. Add it to the list of instance |
265 // members to still be processed. | 302 // members to still be processed. |
266 instanceMembersByName | 303 instanceMembersByName |
267 .putIfAbsent(memberName, () => new Set<Element>()) | 304 .putIfAbsent(memberName, () => new Set<Element>()) |
268 .add(member); | 305 .add(member); |
269 } | 306 } |
270 | 307 |
271 void registerNoSuchMethod(Element noSuchMethod); | |
272 | |
273 void enableIsolateSupport() {} | |
274 | |
275 void processInstantiatedClass(ClassElement cls) { | 308 void processInstantiatedClass(ClassElement cls) { |
276 task.measure(() { | 309 task.measure(() { |
277 if (_processedClasses.contains(cls)) return; | 310 if (_processedClasses.contains(cls)) return; |
278 // The class must be resolved to compute the set of all | 311 // The class must be resolved to compute the set of all |
279 // supertypes. | 312 // supertypes. |
280 cls.ensureResolved(resolution); | 313 cls.ensureResolved(resolution); |
281 | 314 |
282 void processClass(ClassElement superclass) { | 315 void processClass(ClassElement superclass) { |
283 if (_processedClasses.contains(superclass)) return; | 316 if (_processedClasses.contains(superclass)) return; |
284 // TODO(johnniwinther): Re-insert this invariant when unittests don't | 317 // TODO(johnniwinther): Re-insert this invariant when unittests don't |
(...skipping 30 matching lines...) Expand all Loading... |
315 } | 348 } |
316 | 349 |
317 void registerDynamicUse(DynamicUse dynamicUse) { | 350 void registerDynamicUse(DynamicUse dynamicUse) { |
318 task.measure(() { | 351 task.measure(() { |
319 if (universe.registerDynamicUse(dynamicUse)) { | 352 if (universe.registerDynamicUse(dynamicUse)) { |
320 handleUnseenSelector(dynamicUse); | 353 handleUnseenSelector(dynamicUse); |
321 } | 354 } |
322 }); | 355 }); |
323 } | 356 } |
324 | 357 |
325 /** | |
326 * Decides whether an element should be included to satisfy requirements | |
327 * of the mirror system. [includedEnclosing] provides a hint whether the | |
328 * enclosing element was included. | |
329 * | |
330 * The actual implementation depends on the current compiler phase. | |
331 */ | |
332 bool shouldIncludeElementDueToMirrors(Element element, | |
333 {bool includedEnclosing}); | |
334 | |
335 void logEnqueueReflectiveAction(action, [msg = ""]) { | 358 void logEnqueueReflectiveAction(action, [msg = ""]) { |
336 if (TRACE_MIRROR_ENQUEUING) { | 359 if (TRACE_MIRROR_ENQUEUING) { |
337 print("MIRROR_ENQUEUE (${isResolutionQueue ? "R" : "C"}): $action $msg"); | 360 print("MIRROR_ENQUEUE (${isResolutionQueue ? "R" : "C"}): $action $msg"); |
338 } | 361 } |
339 } | 362 } |
340 | 363 |
341 /// Enqeue the constructor [ctor] if it is required for reflection. | 364 /// Enqeue the constructor [ctor] if it is required for reflection. |
342 /// | 365 /// |
343 /// [enclosingWasIncluded] provides a hint whether the enclosing element was | 366 /// [enclosingWasIncluded] provides a hint whether the enclosing element was |
344 /// needed for reflection. | 367 /// needed for reflection. |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
640 while (queue.isNotEmpty) { | 663 while (queue.isNotEmpty) { |
641 // TODO(johnniwinther): Find an optimal process order. | 664 // TODO(johnniwinther): Find an optimal process order. |
642 filter.processWorkItem(f, queue.removeLast()); | 665 filter.processWorkItem(f, queue.removeLast()); |
643 } | 666 } |
644 List recents = recentClasses.toList(growable: false); | 667 List recents = recentClasses.toList(growable: false); |
645 recentClasses.clear(); | 668 recentClasses.clear(); |
646 if (!onQueueEmpty(recents)) recentClasses.addAll(recents); | 669 if (!onQueueEmpty(recents)) recentClasses.addAll(recents); |
647 } while (queue.isNotEmpty || recentClasses.isNotEmpty); | 670 } while (queue.isNotEmpty || recentClasses.isNotEmpty); |
648 } | 671 } |
649 | 672 |
650 /// [onQueueEmpty] is called whenever the queue is drained. [recentClasses] | |
651 /// contains the set of all classes seen for the first time since | |
652 /// [onQueueEmpty] was called last. A return value of [true] indicates that | |
653 /// the [recentClasses] have been processed and may be cleared. If [false] is | |
654 /// returned, [onQueueEmpty] will be called once the queue is empty again (or | |
655 /// still empty) and [recentClasses] will be a superset of the current value. | |
656 bool onQueueEmpty(Iterable<ClassElement> recentClasses) { | |
657 return compiler.backend.onQueueEmpty(this, recentClasses); | |
658 } | |
659 | |
660 void logSummary(log(message)) { | 673 void logSummary(log(message)) { |
661 _logSpecificSummary(log); | 674 log('Resolved ${processedElements.length} elements.'); |
662 nativeEnqueuer.logSummary(log); | 675 nativeEnqueuer.logSummary(log); |
663 } | 676 } |
664 | 677 |
665 /// Log summary specific to the concrete enqueuer. | |
666 void _logSpecificSummary(log(message)); | |
667 | |
668 String toString() => 'Enqueuer($name)'; | 678 String toString() => 'Enqueuer($name)'; |
669 | 679 |
670 void forgetElement(Element element) { | |
671 universe.forgetElement(element, compiler); | |
672 _processedClasses.remove(element); | |
673 instanceMembersByName[element.name]?.remove(element); | |
674 instanceFunctionsByName[element.name]?.remove(element); | |
675 } | |
676 } | |
677 | |
678 /// [Enqueuer] which is specific to resolution. | |
679 class ResolutionEnqueuer extends Enqueuer { | |
680 /// All declaration elements that have been processed by the resolver. | 680 /// All declaration elements that have been processed by the resolver. |
681 final Set<AstElement> processedElements; | 681 final Set<AstElement> processedElements; |
682 | 682 |
| 683 Iterable<Entity> get processedEntities => processedElements; |
| 684 |
683 final Queue<ResolutionWorkItem> queue; | 685 final Queue<ResolutionWorkItem> queue; |
684 | 686 |
685 /// Queue of deferred resolution actions to execute when the resolution queue | 687 /// Queue of deferred resolution actions to execute when the resolution queue |
686 /// has been emptied. | 688 /// has been emptied. |
687 final Queue<_DeferredAction> deferredQueue; | 689 final Queue<_DeferredAction> deferredQueue; |
688 | 690 |
689 static const ImpactUseCase IMPACT_USE = | 691 static const ImpactUseCase IMPACT_USE = |
690 const ImpactUseCase('ResolutionEnqueuer'); | 692 const ImpactUseCase('ResolutionEnqueuer'); |
691 | 693 |
692 ImpactUseCase get impactUse => IMPACT_USE; | 694 ImpactUseCase get impactUse => IMPACT_USE; |
693 | 695 |
694 ResolutionEnqueuer( | |
695 Compiler compiler, | |
696 ItemCompilationContext itemCompilationContextCreator(), | |
697 EnqueuerStrategy strategy) | |
698 : super('resolution enqueuer', compiler, itemCompilationContextCreator, | |
699 strategy), | |
700 processedElements = new Set<AstElement>(), | |
701 queue = new Queue<ResolutionWorkItem>(), | |
702 deferredQueue = new Queue<_DeferredAction>(); | |
703 | |
704 bool get isResolutionQueue => true; | 696 bool get isResolutionQueue => true; |
705 | 697 |
706 bool isProcessed(Element member) => processedElements.contains(member); | 698 bool isProcessed(Element member) => processedElements.contains(member); |
707 | 699 |
708 /// Returns `true` if [element] has been processed by the resolution enqueuer. | 700 /// Returns `true` if [element] has been processed by the resolution enqueuer. |
709 bool hasBeenProcessed(Element element) { | 701 bool hasBeenProcessed(Element element) { |
710 return processedElements.contains(element.analyzableElement.declaration); | 702 return processedElements.contains(element.analyzableElement.declaration); |
711 } | 703 } |
712 | 704 |
713 /// Registers [element] as processed by the resolution enqueuer. | 705 /// Registers [element] as processed by the resolution enqueuer. |
714 void registerProcessedElement(AstElement element) { | 706 void registerProcessedElement(AstElement element) { |
715 processedElements.add(element); | 707 processedElements.add(element); |
716 compiler.backend.onElementResolved(element); | 708 compiler.backend.onElementResolved(element); |
717 } | 709 } |
718 | 710 |
719 /** | 711 /** |
720 * Decides whether an element should be included to satisfy requirements | 712 * Decides whether an element should be included to satisfy requirements |
721 * of the mirror system. | 713 * of the mirror system. |
722 * | 714 * |
723 * During resolution, we have to resort to matching elements against the | 715 * During resolution, we have to resort to matching elements against the |
724 * [MirrorsUsed] pattern, as we do not have a complete picture of the world, | 716 * [MirrorsUsed] pattern, as we do not have a complete picture of the world, |
725 * yet. | 717 * yet. |
726 */ | 718 */ |
727 bool shouldIncludeElementDueToMirrors(Element element, | 719 bool shouldIncludeElementDueToMirrors(Element element, |
728 {bool includedEnclosing}) { | 720 {bool includedEnclosing}) { |
729 return includedEnclosing || | 721 return includedEnclosing || |
730 compiler.backend.requiredByMirrorSystem(element); | 722 compiler.backend.requiredByMirrorSystem(element); |
731 } | 723 } |
732 | 724 |
| 725 /** |
| 726 * Adds [element] to the work list if it has not already been processed. |
| 727 * |
| 728 * Returns [true] if the element was actually added to the queue. |
| 729 */ |
733 bool internalAddToWorkList(Element element) { | 730 bool internalAddToWorkList(Element element) { |
734 if (element.isMalformed) return false; | 731 if (element.isMalformed) return false; |
735 | 732 |
736 assert(invariant(element, element is AnalyzableElement, | 733 assert(invariant(element, element is AnalyzableElement, |
737 message: 'Element $element is not analyzable.')); | 734 message: 'Element $element is not analyzable.')); |
738 if (hasBeenProcessed(element)) return false; | 735 if (hasBeenProcessed(element)) return false; |
739 if (queueIsClosed) { | 736 if (queueIsClosed) { |
740 throw new SpannableAssertionFailure( | 737 throw new SpannableAssertionFailure( |
741 element, "Resolution work list is closed. Trying to add $element."); | 738 element, "Resolution work list is closed. Trying to add $element."); |
742 } | 739 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
800 void addDeferredAction(Element element, void action()) { | 797 void addDeferredAction(Element element, void action()) { |
801 if (queueIsClosed) { | 798 if (queueIsClosed) { |
802 throw new SpannableAssertionFailure( | 799 throw new SpannableAssertionFailure( |
803 element, | 800 element, |
804 "Resolution work list is closed. " | 801 "Resolution work list is closed. " |
805 "Trying to add deferred action for $element"); | 802 "Trying to add deferred action for $element"); |
806 } | 803 } |
807 deferredQueue.add(new _DeferredAction(element, action)); | 804 deferredQueue.add(new _DeferredAction(element, action)); |
808 } | 805 } |
809 | 806 |
| 807 /// [onQueueEmpty] is called whenever the queue is drained. [recentClasses] |
| 808 /// contains the set of all classes seen for the first time since |
| 809 /// [onQueueEmpty] was called last. A return value of [true] indicates that |
| 810 /// the [recentClasses] have been processed and may be cleared. If [false] is |
| 811 /// returned, [onQueueEmpty] will be called once the queue is empty again (or |
| 812 /// still empty) and [recentClasses] will be a superset of the current value. |
810 bool onQueueEmpty(Iterable<ClassElement> recentClasses) { | 813 bool onQueueEmpty(Iterable<ClassElement> recentClasses) { |
811 _emptyDeferredQueue(); | 814 _emptyDeferredQueue(); |
812 return super.onQueueEmpty(recentClasses); | 815 |
| 816 return compiler.backend.onQueueEmpty(this, recentClasses); |
813 } | 817 } |
814 | 818 |
815 void emptyDeferredQueueForTesting() => _emptyDeferredQueue(); | 819 void emptyDeferredQueueForTesting() => _emptyDeferredQueue(); |
816 | 820 |
817 void _emptyDeferredQueue() { | 821 void _emptyDeferredQueue() { |
818 while (!deferredQueue.isEmpty) { | 822 while (!deferredQueue.isEmpty) { |
819 _DeferredAction task = deferredQueue.removeFirst(); | 823 _DeferredAction task = deferredQueue.removeFirst(); |
820 reporter.withCurrentElement(task.element, task.action); | 824 reporter.withCurrentElement(task.element, task.action); |
821 } | 825 } |
822 } | 826 } |
823 | 827 |
824 void _logSpecificSummary(log(message)) { | |
825 log('Resolved ${processedElements.length} elements.'); | |
826 } | |
827 | |
828 void forgetElement(Element element) { | 828 void forgetElement(Element element) { |
829 super.forgetElement(element); | 829 universe.forgetElement(element, compiler); |
| 830 _processedClasses.remove(element); |
| 831 instanceMembersByName[element.name]?.remove(element); |
| 832 instanceFunctionsByName[element.name]?.remove(element); |
830 processedElements.remove(element); | 833 processedElements.remove(element); |
831 } | 834 } |
832 } | 835 } |
833 | 836 |
834 /// [Enqueuer] which is specific to code generation. | |
835 abstract class CodegenEnqueuer implements Enqueuer { | |
836 Map<Element, js.Expression> get generatedCode; | |
837 | |
838 Set<Element> get newlyEnqueuedElements; | |
839 } | |
840 | |
841 /// Parameterizes filtering of which work items are enqueued. | 837 /// Parameterizes filtering of which work items are enqueued. |
842 class QueueFilter { | 838 class QueueFilter { |
843 bool checkNoEnqueuedInvokedInstanceMethods(Enqueuer enqueuer) { | 839 bool checkNoEnqueuedInvokedInstanceMethods(Enqueuer enqueuer) { |
844 enqueuer.task.measure(() { | 840 enqueuer.task.measure(() { |
845 // Run through the classes and see if we need to compile methods. | 841 // Run through the classes and see if we need to compile methods. |
846 for (ClassElement classElement | 842 for (ClassElement classElement |
847 in enqueuer.universe.directlyInstantiatedClasses) { | 843 in enqueuer.universe.directlyInstantiatedClasses) { |
848 for (ClassElement currentClass = classElement; | 844 for (ClassElement currentClass = classElement; |
849 currentClass != null; | 845 currentClass != null; |
850 currentClass = currentClass.superclass) { | 846 currentClass = currentClass.superclass) { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
922 } | 918 } |
923 | 919 |
924 typedef void _DeferredActionFunction(); | 920 typedef void _DeferredActionFunction(); |
925 | 921 |
926 class _DeferredAction { | 922 class _DeferredAction { |
927 final Element element; | 923 final Element element; |
928 final _DeferredActionFunction action; | 924 final _DeferredActionFunction action; |
929 | 925 |
930 _DeferredAction(this.element, this.action); | 926 _DeferredAction(this.element, this.action); |
931 } | 927 } |
OLD | NEW |