| 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 |