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 'cache_strategy.dart'; | 9 import 'cache_strategy.dart'; |
10 import 'common/backend_api.dart' show Backend; | 10 import 'common/backend_api.dart' show Backend; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
72 resolution.forgetElement(element, compiler); | 72 resolution.forgetElement(element, compiler); |
73 codegen.forgetElement(element, compiler); | 73 codegen.forgetElement(element, compiler); |
74 } | 74 } |
75 } | 75 } |
76 | 76 |
77 abstract class Enqueuer { | 77 abstract class Enqueuer { |
78 CompilerTask get task; | 78 CompilerTask get task; |
79 WorldBuilder get universe; | 79 WorldBuilder get universe; |
80 native.NativeEnqueuer get nativeEnqueuer; | 80 native.NativeEnqueuer get nativeEnqueuer; |
81 void forgetElement(Element element, Compiler compiler); | 81 void forgetElement(Element element, Compiler compiler); |
82 | |
83 // TODO(johnniwinther): Initialize [_impactStrategy] to `null`. | |
84 ImpactStrategy _impactStrategy = const ImpactStrategy(); | |
85 | |
86 ImpactStrategy get impactStrategy => _impactStrategy; | |
87 | |
88 void open(ImpactStrategy impactStrategy) { | |
89 _impactStrategy = impactStrategy; | |
90 } | |
91 | |
92 void close() { | |
93 // TODO(johnniwinther): Set [_impactStrategy] to `null` and [queueIsClosed] | |
94 // to `false` here. | |
Harry Terkelsen
2016/11/28 19:03:06
you mean set [queueIsClosed] to true?
Johnni Winther
2016/11/29 08:01:37
Yes :)
| |
95 _impactStrategy = const ImpactStrategy(); | |
96 } | |
97 | |
82 void processInstantiatedClassMembers(ClassElement cls); | 98 void processInstantiatedClassMembers(ClassElement cls); |
83 void processInstantiatedClassMember(ClassElement cls, Element member); | 99 void processInstantiatedClassMember(ClassElement cls, Element member); |
84 void handleUnseenSelectorInternal(DynamicUse dynamicUse); | 100 void handleUnseenSelectorInternal(DynamicUse dynamicUse); |
85 void registerStaticUse(StaticUse staticUse); | 101 void registerStaticUse(StaticUse staticUse); |
86 void registerStaticUseInternal(StaticUse staticUse); | 102 void registerStaticUseInternal(StaticUse staticUse); |
87 void registerDynamicUse(DynamicUse dynamicUse); | 103 void registerDynamicUse(DynamicUse dynamicUse); |
88 | 104 |
89 /// Returns [:true:] if this enqueuer is the resolution enqueuer. | 105 /// Returns [:true:] if this enqueuer is the resolution enqueuer. |
90 bool get isResolutionQueue; | 106 bool get isResolutionQueue; |
91 | 107 |
(...skipping 11 matching lines...) Expand all Loading... | |
103 void addToWorkList(Element element); | 119 void addToWorkList(Element element); |
104 | 120 |
105 void enableIsolateSupport(); | 121 void enableIsolateSupport(); |
106 | 122 |
107 void registerInstantiatedType(InterfaceType type); | 123 void registerInstantiatedType(InterfaceType type); |
108 void forEach(void f(WorkItem work)); | 124 void forEach(void f(WorkItem work)); |
109 | 125 |
110 /// Apply the [worldImpact] to this enqueuer. If the [impactSource] is provide d | 126 /// Apply the [worldImpact] to this enqueuer. If the [impactSource] is provide d |
111 /// the impact strategy will remove it from the element impact cache, if it is | 127 /// the impact strategy will remove it from the element impact cache, if it is |
112 /// no longer needed. | 128 /// no longer needed. |
113 void applyImpact(ImpactStrategy impactStrategy, WorldImpact worldImpact, | 129 void applyImpact(WorldImpact worldImpact, {Element impactSource}); |
114 {Element impactSource}); | |
115 bool checkNoEnqueuedInvokedInstanceMethods(); | 130 bool checkNoEnqueuedInvokedInstanceMethods(); |
116 void logSummary(log(message)); | 131 void logSummary(log(message)); |
117 | 132 |
118 /// Returns [:true:] if [member] has been processed by this enqueuer. | 133 /// Returns [:true:] if [member] has been processed by this enqueuer. |
119 bool isProcessed(Element member); | 134 bool isProcessed(Element member); |
120 | 135 |
121 Iterable<Entity> get processedEntities; | 136 Iterable<Entity> get processedEntities; |
122 | 137 |
123 Iterable<ClassElement> get processedClasses; | 138 Iterable<ClassElement> get processedClasses; |
124 } | 139 } |
(...skipping 16 matching lines...) Expand all Loading... | |
141 final Map<String, Set<Element>> instanceFunctionsByName = | 156 final Map<String, Set<Element>> instanceFunctionsByName = |
142 new Map<String, Set<Element>>(); | 157 new Map<String, Set<Element>>(); |
143 final Set<ClassElement> _processedClasses = new Set<ClassElement>(); | 158 final Set<ClassElement> _processedClasses = new Set<ClassElement>(); |
144 Set<ClassElement> recentClasses = new Setlet<ClassElement>(); | 159 Set<ClassElement> recentClasses = new Setlet<ClassElement>(); |
145 final ResolutionWorldBuilderImpl _universe; | 160 final ResolutionWorldBuilderImpl _universe; |
146 | 161 |
147 bool queueIsClosed = false; | 162 bool queueIsClosed = false; |
148 | 163 |
149 WorldImpactVisitor impactVisitor; | 164 WorldImpactVisitor impactVisitor; |
150 | 165 |
151 ImpactStrategy impactStrategy; | |
152 | |
153 ResolutionEnqueuer( | 166 ResolutionEnqueuer( |
154 this.task, | 167 this.task, |
155 this.options, | 168 this.options, |
156 this.resolution, | 169 this.resolution, |
157 this.filter, | 170 this.filter, |
158 this.strategy, | 171 this.strategy, |
159 this.globalDependencies, | 172 this.globalDependencies, |
160 Backend backend, | 173 Backend backend, |
161 CommonElements commonElements, | 174 CommonElements commonElements, |
162 CacheStrategy cacheStrategy, | 175 CacheStrategy cacheStrategy, |
(...skipping 24 matching lines...) Expand all Loading... | |
187 /** | 200 /** |
188 * Documentation wanted -- johnniwinther | 201 * Documentation wanted -- johnniwinther |
189 * | 202 * |
190 * Invariant: [element] must be a declaration element. | 203 * Invariant: [element] must be a declaration element. |
191 */ | 204 */ |
192 void addToWorkList(Element element) { | 205 void addToWorkList(Element element) { |
193 assert(invariant(element, element.isDeclaration)); | 206 assert(invariant(element, element.isDeclaration)); |
194 internalAddToWorkList(element); | 207 internalAddToWorkList(element); |
195 } | 208 } |
196 | 209 |
197 void applyImpact(ImpactStrategy impactStrategy, WorldImpact worldImpact, | 210 void applyImpact(WorldImpact worldImpact, {Element impactSource}) { |
198 {Element impactSource}) { | 211 if (worldImpact.isEmpty) return; |
199 impactStrategy.visitImpact( | 212 impactStrategy.visitImpact( |
200 impactSource, worldImpact, impactVisitor, impactUse); | 213 impactSource, worldImpact, impactVisitor, impactUse); |
201 } | 214 } |
202 | 215 |
203 void registerInstantiatedType(InterfaceType type) { | 216 void registerInstantiatedType(InterfaceType type) { |
204 _registerInstantiatedType(type, globalDependency: true); | 217 _registerInstantiatedType(type, globalDependency: true); |
205 } | 218 } |
206 | 219 |
207 void _registerInstantiatedType(InterfaceType type, | 220 void _registerInstantiatedType(InterfaceType type, |
208 {ConstructorElement constructor, | 221 {ConstructorElement constructor, |
209 bool mirrorUsage: false, | 222 bool mirrorUsage: false, |
210 bool nativeUsage: false, | 223 bool nativeUsage: false, |
211 bool globalDependency: false, | 224 bool globalDependency: false, |
212 bool isRedirection: false}) { | 225 bool isRedirection: false}) { |
213 task.measure(() { | 226 task.measure(() { |
214 ClassElement cls = type.element; | 227 ClassElement cls = type.element; |
215 cls.ensureResolved(resolution); | 228 cls.ensureResolved(resolution); |
216 bool isNative = backend.isNative(cls); | 229 bool isNative = backend.isNative(cls); |
217 _universe.registerTypeInstantiation(type, | 230 _universe.registerTypeInstantiation(type, |
218 constructor: constructor, | 231 constructor: constructor, |
219 isNative: isNative, | 232 isNative: isNative, |
220 byMirrors: mirrorUsage, | 233 byMirrors: mirrorUsage, |
221 isRedirection: isRedirection, onImplemented: (ClassElement cls) { | 234 isRedirection: isRedirection, onImplemented: (ClassElement cls) { |
222 backend.registerImplementedClass(cls, this); | 235 applyImpact(backend.registerImplementedClass(cls, forResolution: true)); |
223 }); | 236 }); |
224 if (globalDependency && !mirrorUsage) { | 237 if (globalDependency && !mirrorUsage) { |
225 globalDependencies.registerDependency(type.element); | 238 globalDependencies.registerDependency(type.element); |
226 } | 239 } |
227 if (nativeUsage) { | 240 if (nativeUsage) { |
228 nativeEnqueuer.onInstantiatedType(type); | 241 nativeEnqueuer.onInstantiatedType(type); |
229 } | 242 } |
230 backend.registerInstantiatedType(type); | 243 backend.registerInstantiatedType(type); |
231 // TODO(johnniwinther): Share this reasoning with [Universe]. | 244 // TODO(johnniwinther): Share this reasoning with [Universe]. |
232 if (!cls.isAbstract || isNative || mirrorUsage) { | 245 if (!cls.isAbstract || isNative || mirrorUsage) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
277 addToWorkList(member); | 290 addToWorkList(member); |
278 return; | 291 return; |
279 } | 292 } |
280 } else if (member.isFunction) { | 293 } else if (member.isFunction) { |
281 FunctionElement function = member; | 294 FunctionElement function = member; |
282 function.computeType(resolution); | 295 function.computeType(resolution); |
283 if (function.name == Identifiers.noSuchMethod_) { | 296 if (function.name == Identifiers.noSuchMethod_) { |
284 registerNoSuchMethod(function); | 297 registerNoSuchMethod(function); |
285 } | 298 } |
286 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) { | 299 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) { |
287 registerCallMethodWithFreeTypeVariables(function); | 300 _registerCallMethodWithFreeTypeVariables(function); |
288 } | 301 } |
289 // If there is a property access with the same name as a method we | 302 // If there is a property access with the same name as a method we |
290 // need to emit the method. | 303 // need to emit the method. |
291 if (_universe.hasInvokedGetter(function, openWorld)) { | 304 if (_universe.hasInvokedGetter(function, openWorld)) { |
292 registerClosurizedMember(function); | 305 registerClosurizedMember(function); |
293 addToWorkList(function); | 306 addToWorkList(function); |
294 return; | 307 return; |
295 } | 308 } |
296 // Store the member in [instanceFunctionsByName] to catch | 309 // Store the member in [instanceFunctionsByName] to catch |
297 // getters on the function. | 310 // getters on the function. |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
342 if (_processedClasses.contains(superclass)) return; | 355 if (_processedClasses.contains(superclass)) return; |
343 | 356 |
344 _processedClasses.add(superclass); | 357 _processedClasses.add(superclass); |
345 recentClasses.add(superclass); | 358 recentClasses.add(superclass); |
346 superclass.ensureResolved(resolution); | 359 superclass.ensureResolved(resolution); |
347 superclass.implementation.forEachMember(processInstantiatedClassMember); | 360 superclass.implementation.forEachMember(processInstantiatedClassMember); |
348 resolution.ensureClassMembers(superclass); | 361 resolution.ensureClassMembers(superclass); |
349 // We only tell the backend once that [superclass] was instantiated, so | 362 // We only tell the backend once that [superclass] was instantiated, so |
350 // any additional dependencies must be treated as global | 363 // any additional dependencies must be treated as global |
351 // dependencies. | 364 // dependencies. |
352 backend.registerInstantiatedClass(superclass, this); | 365 applyImpact( |
366 backend.registerInstantiatedClass(superclass, forResolution: true)); | |
353 } | 367 } |
354 | 368 |
355 ClassElement superclass = cls; | 369 ClassElement superclass = cls; |
356 while (superclass != null) { | 370 while (superclass != null) { |
357 processClass(superclass); | 371 processClass(superclass); |
358 superclass = superclass.superclass; | 372 superclass = superclass.superclass; |
359 } | 373 } |
360 }); | 374 }); |
361 } | 375 } |
362 | 376 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
426 */ | 440 */ |
427 void registerStaticUse(StaticUse staticUse) { | 441 void registerStaticUse(StaticUse staticUse) { |
428 strategy.processStaticUse(this, staticUse); | 442 strategy.processStaticUse(this, staticUse); |
429 } | 443 } |
430 | 444 |
431 void registerStaticUseInternal(StaticUse staticUse) { | 445 void registerStaticUseInternal(StaticUse staticUse) { |
432 Element element = staticUse.element; | 446 Element element = staticUse.element; |
433 assert(invariant(element, element.isDeclaration, | 447 assert(invariant(element, element.isDeclaration, |
434 message: "Element ${element} is not the declaration.")); | 448 message: "Element ${element} is not the declaration.")); |
435 _universe.registerStaticUse(staticUse); | 449 _universe.registerStaticUse(staticUse); |
436 backend.registerStaticUse(this, element); | 450 applyImpact(backend.registerStaticUse(element, forResolution: true)); |
437 bool addElement = true; | 451 bool addElement = true; |
438 switch (staticUse.kind) { | 452 switch (staticUse.kind) { |
439 case StaticUseKind.STATIC_TEAR_OFF: | 453 case StaticUseKind.STATIC_TEAR_OFF: |
440 backend.registerGetOfStaticFunction(this); | 454 applyImpact(backend.registerGetOfStaticFunction()); |
441 break; | 455 break; |
442 case StaticUseKind.FIELD_GET: | 456 case StaticUseKind.FIELD_GET: |
443 case StaticUseKind.FIELD_SET: | 457 case StaticUseKind.FIELD_SET: |
444 case StaticUseKind.CLOSURE: | 458 case StaticUseKind.CLOSURE: |
445 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and | 459 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and |
446 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue. | 460 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue. |
447 // Also [CLOSURE] contains [LocalFunctionElement] which we cannot | 461 // Also [CLOSURE] contains [LocalFunctionElement] which we cannot |
448 // enqueue. | 462 // enqueue. |
449 LocalFunctionElement closure = staticUse.element; | 463 LocalFunctionElement closure = staticUse.element; |
450 if (closure.type.containsTypeVariables) { | 464 if (closure.type.containsTypeVariables) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
507 } | 521 } |
508 | 522 |
509 void _registerIsCheck(DartType type) { | 523 void _registerIsCheck(DartType type) { |
510 type = _universe.registerIsCheck(type, resolution); | 524 type = _universe.registerIsCheck(type, resolution); |
511 // Even in checked mode, type annotations for return type and argument | 525 // Even in checked mode, type annotations for return type and argument |
512 // types do not imply type checks, so there should never be a check | 526 // types do not imply type checks, so there should never be a check |
513 // against the type variable of a typedef. | 527 // against the type variable of a typedef. |
514 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef); | 528 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef); |
515 } | 529 } |
516 | 530 |
517 void registerCallMethodWithFreeTypeVariables(Element element) { | 531 void _registerCallMethodWithFreeTypeVariables(Element element) { |
518 backend.registerCallMethodWithFreeTypeVariables(element, this); | 532 applyImpact(backend.registerCallMethodWithFreeTypeVariables(element, |
533 forResolution: true)); | |
519 _universe.callMethodsWithFreeTypeVariables.add(element); | 534 _universe.callMethodsWithFreeTypeVariables.add(element); |
520 } | 535 } |
521 | 536 |
522 void registerClosurizedMember(TypedElement element) { | 537 void registerClosurizedMember(TypedElement element) { |
523 assert(element.isInstanceMember); | 538 assert(element.isInstanceMember); |
524 if (element.computeType(resolution).containsTypeVariables) { | 539 if (element.computeType(resolution).containsTypeVariables) { |
525 backend.registerClosureWithFreeTypeVariables(element, this); | 540 applyImpact(backend.registerClosureWithFreeTypeVariables(element, |
541 forResolution: true)); | |
526 _universe.closuresWithFreeTypeVariables.add(element); | 542 _universe.closuresWithFreeTypeVariables.add(element); |
527 } | 543 } |
528 backend.registerBoundClosure(this); | 544 applyImpact(backend.registerBoundClosure()); |
529 _universe.closurizedMembers.add(element); | 545 _universe.closurizedMembers.add(element); |
530 } | 546 } |
531 | 547 |
532 void forEach(void f(WorkItem work)) { | 548 void forEach(void f(WorkItem work)) { |
533 do { | 549 do { |
534 while (queue.isNotEmpty) { | 550 while (queue.isNotEmpty) { |
535 // TODO(johnniwinther): Find an optimal process order. | 551 // TODO(johnniwinther): Find an optimal process order. |
536 filter.processWorkItem(f, queue.removeLast()); | 552 filter.processWorkItem(f, queue.removeLast()); |
537 } | 553 } |
538 List recents = recentClasses.toList(growable: false); | 554 List recents = recentClasses.toList(growable: false); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
618 } | 634 } |
619 } | 635 } |
620 | 636 |
621 if (element.isGetter && element.name == Identifiers.runtimeType_) { | 637 if (element.isGetter && element.name == Identifiers.runtimeType_) { |
622 // Enable runtime type support if we discover a getter called runtimeType. | 638 // Enable runtime type support if we discover a getter called runtimeType. |
623 // We have to enable runtime type before hitting the codegen, so | 639 // We have to enable runtime type before hitting the codegen, so |
624 // that constructors know whether they need to generate code for | 640 // that constructors know whether they need to generate code for |
625 // runtime type. | 641 // runtime type. |
626 _universe.hasRuntimeTypeSupport = true; | 642 _universe.hasRuntimeTypeSupport = true; |
627 // TODO(ahe): Record precise dependency here. | 643 // TODO(ahe): Record precise dependency here. |
628 backend.registerRuntimeType(this); | 644 applyImpact(backend.registerRuntimeType()); |
629 } else if (commonElements.isFunctionApplyMethod(element)) { | 645 } else if (commonElements.isFunctionApplyMethod(element)) { |
630 _universe.hasFunctionApplySupport = true; | 646 _universe.hasFunctionApplySupport = true; |
631 } | 647 } |
632 | 648 |
633 return true; | 649 return true; |
634 } | 650 } |
635 | 651 |
636 void registerNoSuchMethod(Element element) { | 652 void registerNoSuchMethod(Element element) { |
637 backend.registerNoSuchMethod(element); | 653 backend.registerNoSuchMethod(element); |
638 } | 654 } |
639 | 655 |
640 void enableIsolateSupport() { | 656 void enableIsolateSupport() { |
641 _universe.hasIsolateSupport = true; | 657 _universe.hasIsolateSupport = true; |
642 backend.enableIsolateSupport(this); | 658 applyImpact(backend.enableIsolateSupport(forResolution: true)); |
643 } | 659 } |
644 | 660 |
645 /** | 661 /** |
646 * Adds an action to the deferred task queue. | 662 * Adds an action to the deferred task queue. |
647 * | 663 * |
648 * The action is performed the next time the resolution queue has been | 664 * The action is performed the next time the resolution queue has been |
649 * emptied. | 665 * emptied. |
650 * | 666 * |
651 * The queue is processed in FIFO order. | 667 * The queue is processed in FIFO order. |
652 */ | 668 */ |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
774 } | 790 } |
775 | 791 |
776 typedef void _DeferredActionFunction(); | 792 typedef void _DeferredActionFunction(); |
777 | 793 |
778 class _DeferredAction { | 794 class _DeferredAction { |
779 final Element element; | 795 final Element element; |
780 final _DeferredActionFunction action; | 796 final _DeferredActionFunction action; |
781 | 797 |
782 _DeferredAction(this.element, this.action); | 798 _DeferredAction(this.element, this.action); |
783 } | 799 } |
OLD | NEW |