Chromium Code Reviews| 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 |