| 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 | 7 import 'dart:collection' show |
| 8 Queue; | 8 Queue; |
| 9 | 9 |
| 10 import 'common/names.dart' show | 10 import 'common/names.dart' show |
| 11 Identifiers; | 11 Identifiers; |
| 12 import 'common/work.dart' show | 12 import 'common/work.dart' show |
| 13 ItemCompilationContext, | 13 ItemCompilationContext, |
| 14 WorkItem; | 14 WorkItem; |
| 15 import 'common/tasks.dart' show | 15 import 'common/tasks.dart' show |
| 16 CompilerTask, | 16 CompilerTask, |
| 17 DeferredAction, | 17 DeferredAction, |
| 18 DeferredTask; | 18 DeferredTask; |
| 19 import 'common/registry.dart' show | |
| 20 Registry; | |
| 21 import 'common/codegen.dart' show | 19 import 'common/codegen.dart' show |
| 22 CodegenWorkItem; | 20 CodegenWorkItem; |
| 23 import 'common/resolution.dart' show | 21 import 'common/resolution.dart' show |
| 24 ResolutionWorkItem; | 22 ResolutionWorkItem; |
| 25 import 'compiler.dart' show | 23 import 'compiler.dart' show |
| 26 Compiler; | 24 Compiler; |
| 27 import 'dart_types.dart' show | 25 import 'dart_types.dart' show |
| 28 DartType, | 26 DartType, |
| 29 InterfaceType; | 27 InterfaceType; |
| 30 import 'diagnostics/invariant.dart' show | 28 import 'diagnostics/invariant.dart' show |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 worldImpact.dynamicGetters.forEach(registerDynamicGetter); | 181 worldImpact.dynamicGetters.forEach(registerDynamicGetter); |
| 184 worldImpact.dynamicSetters.forEach(registerDynamicSetter); | 182 worldImpact.dynamicSetters.forEach(registerDynamicSetter); |
| 185 worldImpact.staticUses.forEach(registerStaticUse); | 183 worldImpact.staticUses.forEach(registerStaticUse); |
| 186 // TODO(johnniwinther): Register [worldImpact.instantiatedTypes] when it | 184 // TODO(johnniwinther): Register [worldImpact.instantiatedTypes] when it |
| 187 // doesn't require a [Registry]. | 185 // doesn't require a [Registry]. |
| 188 worldImpact.checkedTypes.forEach(registerIsCheck); | 186 worldImpact.checkedTypes.forEach(registerIsCheck); |
| 189 worldImpact.closurizedFunctions.forEach(registerGetOfStaticFunction); | 187 worldImpact.closurizedFunctions.forEach(registerGetOfStaticFunction); |
| 190 } | 188 } |
| 191 | 189 |
| 192 // TODO(johnniwinther): Remove the need for passing the [registry]. | 190 // TODO(johnniwinther): Remove the need for passing the [registry]. |
| 193 void registerInstantiatedType(InterfaceType type, Registry registry, | 191 void registerInstantiatedType(InterfaceType type, |
| 194 {bool mirrorUsage: false}) { | 192 {bool mirrorUsage: false}) { |
| 195 task.measure(() { | 193 task.measure(() { |
| 196 ClassElement cls = type.element; | 194 ClassElement cls = type.element; |
| 197 registry.registerDependency(cls); | |
| 198 cls.ensureResolved(compiler); | 195 cls.ensureResolved(compiler); |
| 199 universe.registerTypeInstantiation( | 196 universe.registerTypeInstantiation( |
| 200 type, | 197 type, |
| 201 byMirrors: mirrorUsage, | 198 byMirrors: mirrorUsage, |
| 202 onImplemented: (ClassElement cls) { | 199 onImplemented: (ClassElement cls) { |
| 203 compiler.backend.registerImplementedClass( | 200 compiler.backend.registerImplementedClass( |
| 204 cls, this, compiler.globalDependencies); | 201 cls, this, compiler.globalDependencies); |
| 205 }); | 202 }); |
| 206 processInstantiatedClass(cls); | 203 processInstantiatedClass(cls); |
| 207 compiler.backend.registerInstantiatedType(type, registry); | |
| 208 }); | 204 }); |
| 209 } | 205 } |
| 210 | 206 |
| 211 bool checkNoEnqueuedInvokedInstanceMethods() { | 207 bool checkNoEnqueuedInvokedInstanceMethods() { |
| 212 return filter.checkNoEnqueuedInvokedInstanceMethods(this); | 208 return filter.checkNoEnqueuedInvokedInstanceMethods(this); |
| 213 } | 209 } |
| 214 | 210 |
| 215 void processInstantiatedClassMembers(ClassElement cls) { | 211 void processInstantiatedClassMembers(ClassElement cls) { |
| 216 strategy.processInstantiatedClass(this, cls); | 212 strategy.processInstantiatedClass(this, cls); |
| 217 } | 213 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 return; | 260 return; |
| 265 } | 261 } |
| 266 } else if (member.isFunction) { | 262 } else if (member.isFunction) { |
| 267 FunctionElement function = member; | 263 FunctionElement function = member; |
| 268 function.computeType(compiler); | 264 function.computeType(compiler); |
| 269 if (function.name == Identifiers.noSuchMethod_) { | 265 if (function.name == Identifiers.noSuchMethod_) { |
| 270 registerNoSuchMethod(function); | 266 registerNoSuchMethod(function); |
| 271 } | 267 } |
| 272 if (function.name == Identifiers.call && | 268 if (function.name == Identifiers.call && |
| 273 !cls.typeVariables.isEmpty) { | 269 !cls.typeVariables.isEmpty) { |
| 274 registerCallMethodWithFreeTypeVariables( | 270 registerCallMethodWithFreeTypeVariables(function); |
| 275 function, compiler.globalDependencies); | |
| 276 } | 271 } |
| 277 // If there is a property access with the same name as a method we | 272 // If there is a property access with the same name as a method we |
| 278 // need to emit the method. | 273 // need to emit the method. |
| 279 if (universe.hasInvokedGetter(function, compiler.world)) { | 274 if (universe.hasInvokedGetter(function, compiler.world)) { |
| 280 registerClosurizedMember(function, compiler.globalDependencies); | 275 registerClosurizedMember(function); |
| 281 addToWorkList(function); | 276 addToWorkList(function); |
| 282 return; | 277 return; |
| 283 } | 278 } |
| 284 // Store the member in [instanceFunctionsByName] to catch | 279 // Store the member in [instanceFunctionsByName] to catch |
| 285 // getters on the function. | 280 // getters on the function. |
| 286 instanceFunctionsByName.putIfAbsent(memberName, () => new Set<Element>()) | 281 instanceFunctionsByName.putIfAbsent(memberName, () => new Set<Element>()) |
| 287 .add(member); | 282 .add(member); |
| 288 if (universe.hasInvocation(function, compiler.world)) { | 283 if (universe.hasInvocation(function, compiler.world)) { |
| 289 addToWorkList(function); | 284 addToWorkList(function); |
| 290 return; | 285 return; |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 /// Enqeue the constructor [ctor] if it is required for reflection. | 390 /// Enqeue the constructor [ctor] if it is required for reflection. |
| 396 /// | 391 /// |
| 397 /// [enclosingWasIncluded] provides a hint whether the enclosing element was | 392 /// [enclosingWasIncluded] provides a hint whether the enclosing element was |
| 398 /// needed for reflection. | 393 /// needed for reflection. |
| 399 void enqueueReflectiveConstructor(ConstructorElement ctor, | 394 void enqueueReflectiveConstructor(ConstructorElement ctor, |
| 400 bool enclosingWasIncluded) { | 395 bool enclosingWasIncluded) { |
| 401 if (shouldIncludeElementDueToMirrors(ctor, | 396 if (shouldIncludeElementDueToMirrors(ctor, |
| 402 includedEnclosing: enclosingWasIncluded)) { | 397 includedEnclosing: enclosingWasIncluded)) { |
| 403 logEnqueueReflectiveAction(ctor); | 398 logEnqueueReflectiveAction(ctor); |
| 404 ClassElement cls = ctor.declaration.enclosingClass; | 399 ClassElement cls = ctor.declaration.enclosingClass; |
| 405 registerInstantiatedType(cls.rawType, compiler.mirrorDependencies, | 400 compiler.backend.registerInstantiatedType( |
| 401 cls.rawType, |
| 402 this, |
| 403 compiler.mirrorDependencies, |
| 406 mirrorUsage: true); | 404 mirrorUsage: true); |
| 407 registerStaticUse(ctor.declaration); | 405 registerStaticUse(ctor.declaration); |
| 408 } | 406 } |
| 409 } | 407 } |
| 410 | 408 |
| 411 /// Enqeue the member [element] if it is required for reflection. | 409 /// Enqeue the member [element] if it is required for reflection. |
| 412 /// | 410 /// |
| 413 /// [enclosingWasIncluded] provides a hint whether the enclosing element was | 411 /// [enclosingWasIncluded] provides a hint whether the enclosing element was |
| 414 /// needed for reflection. | 412 /// needed for reflection. |
| 415 void enqueueReflectiveMember(Element element, bool enclosingWasIncluded) { | 413 void enqueueReflectiveMember(Element element, bool enclosingWasIncluded) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 446 void enqueueReflectiveElementsInClass(ClassElement cls, | 444 void enqueueReflectiveElementsInClass(ClassElement cls, |
| 447 Iterable<ClassElement> recents, | 445 Iterable<ClassElement> recents, |
| 448 bool enclosingWasIncluded) { | 446 bool enclosingWasIncluded) { |
| 449 if (cls.library.isInternalLibrary || cls.isInjected) return; | 447 if (cls.library.isInternalLibrary || cls.isInjected) return; |
| 450 bool includeClass = shouldIncludeElementDueToMirrors(cls, | 448 bool includeClass = shouldIncludeElementDueToMirrors(cls, |
| 451 includedEnclosing: enclosingWasIncluded); | 449 includedEnclosing: enclosingWasIncluded); |
| 452 if (includeClass) { | 450 if (includeClass) { |
| 453 logEnqueueReflectiveAction(cls, "register"); | 451 logEnqueueReflectiveAction(cls, "register"); |
| 454 ClassElement decl = cls.declaration; | 452 ClassElement decl = cls.declaration; |
| 455 decl.ensureResolved(compiler); | 453 decl.ensureResolved(compiler); |
| 456 registerInstantiatedType(decl.rawType, compiler.mirrorDependencies, | 454 compiler.backend.registerInstantiatedType( |
| 455 decl.rawType, |
| 456 this, |
| 457 compiler.mirrorDependencies, |
| 457 mirrorUsage: true); | 458 mirrorUsage: true); |
| 458 } | 459 } |
| 459 // If the class is never instantiated, we know nothing of it can possibly | 460 // If the class is never instantiated, we know nothing of it can possibly |
| 460 // be reflected upon. | 461 // be reflected upon. |
| 461 // TODO(herhut): Add a warning if a mirrors annotation cannot hit. | 462 // TODO(herhut): Add a warning if a mirrors annotation cannot hit. |
| 462 if (recents.contains(cls.declaration)) { | 463 if (recents.contains(cls.declaration)) { |
| 463 logEnqueueReflectiveAction(cls, "members"); | 464 logEnqueueReflectiveAction(cls, "members"); |
| 464 cls.constructors.forEach((Element element) { | 465 cls.constructors.forEach((Element element) { |
| 465 enqueueReflectiveConstructor(element, includeClass); | 466 enqueueReflectiveConstructor(element, includeClass); |
| 466 }); | 467 }); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 477 /// Although it is in an internal library, we mark it as reflectable. Note | 478 /// Although it is in an internal library, we mark it as reflectable. Note |
| 478 /// that none of its methods are reflectable, unless reflectable by | 479 /// that none of its methods are reflectable, unless reflectable by |
| 479 /// inheritance. | 480 /// inheritance. |
| 480 void enqueueReflectiveSpecialClasses() { | 481 void enqueueReflectiveSpecialClasses() { |
| 481 Iterable<ClassElement> classes = | 482 Iterable<ClassElement> classes = |
| 482 compiler.backend.classesRequiredForReflection; | 483 compiler.backend.classesRequiredForReflection; |
| 483 for (ClassElement cls in classes) { | 484 for (ClassElement cls in classes) { |
| 484 if (compiler.backend.referencedFromMirrorSystem(cls)) { | 485 if (compiler.backend.referencedFromMirrorSystem(cls)) { |
| 485 logEnqueueReflectiveAction(cls); | 486 logEnqueueReflectiveAction(cls); |
| 486 cls.ensureResolved(compiler); | 487 cls.ensureResolved(compiler); |
| 487 registerInstantiatedType(cls.rawType, compiler.mirrorDependencies, | 488 compiler.backend.registerInstantiatedType( |
| 489 cls.rawType, |
| 490 this, |
| 491 compiler.mirrorDependencies, |
| 488 mirrorUsage: true); | 492 mirrorUsage: true); |
| 489 } | 493 } |
| 490 } | 494 } |
| 491 } | 495 } |
| 492 | 496 |
| 493 /// Enqeue all local members of the library [lib] if they are required for | 497 /// Enqeue all local members of the library [lib] if they are required for |
| 494 /// reflection. | 498 /// reflection. |
| 495 void enqueueReflectiveElementsInLibrary(LibraryElement lib, | 499 void enqueueReflectiveElementsInLibrary(LibraryElement lib, |
| 496 Iterable<ClassElement> recents) { | 500 Iterable<ClassElement> recents) { |
| 497 bool includeLibrary = shouldIncludeElementDueToMirrors(lib, | 501 bool includeLibrary = shouldIncludeElementDueToMirrors(lib, |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 575 void handleUnseenSelector(UniverseSelector universeSelector) { | 579 void handleUnseenSelector(UniverseSelector universeSelector) { |
| 576 strategy.processSelector(this, universeSelector); | 580 strategy.processSelector(this, universeSelector); |
| 577 } | 581 } |
| 578 | 582 |
| 579 void handleUnseenSelectorInternal(UniverseSelector universeSelector) { | 583 void handleUnseenSelectorInternal(UniverseSelector universeSelector) { |
| 580 Selector selector = universeSelector.selector; | 584 Selector selector = universeSelector.selector; |
| 581 String methodName = selector.name; | 585 String methodName = selector.name; |
| 582 processInstanceMembers(methodName, (Element member) { | 586 processInstanceMembers(methodName, (Element member) { |
| 583 if (universeSelector.appliesUnnamed(member, compiler.world)) { | 587 if (universeSelector.appliesUnnamed(member, compiler.world)) { |
| 584 if (member.isFunction && selector.isGetter) { | 588 if (member.isFunction && selector.isGetter) { |
| 585 registerClosurizedMember(member, compiler.globalDependencies); | 589 registerClosurizedMember(member); |
| 586 } | 590 } |
| 587 if (member.isField && member.enclosingClass.isNative) { | 591 if (member.isField && member.enclosingClass.isNative) { |
| 588 if (selector.isGetter || selector.isCall) { | 592 if (selector.isGetter || selector.isCall) { |
| 589 nativeEnqueuer.registerFieldLoad(member); | 593 nativeEnqueuer.registerFieldLoad(member); |
| 590 // We have to also handle storing to the field because we only get | 594 // We have to also handle storing to the field because we only get |
| 591 // one look at each member and there might be a store we have not | 595 // one look at each member and there might be a store we have not |
| 592 // seen yet. | 596 // seen yet. |
| 593 // TODO(sra): Process fields for storing separately. | 597 // TODO(sra): Process fields for storing separately. |
| 594 nativeEnqueuer.registerFieldStore(member); | 598 nativeEnqueuer.registerFieldStore(member); |
| 595 } else { | 599 } else { |
| 596 assert(selector.isSetter); | 600 assert(selector.isSetter); |
| 597 nativeEnqueuer.registerFieldStore(member); | 601 nativeEnqueuer.registerFieldStore(member); |
| 598 // We have to also handle loading from the field because we only get | 602 // We have to also handle loading from the field because we only get |
| 599 // one look at each member and there might be a load we have not | 603 // one look at each member and there might be a load we have not |
| 600 // seen yet. | 604 // seen yet. |
| 601 // TODO(sra): Process fields for storing separately. | 605 // TODO(sra): Process fields for storing separately. |
| 602 nativeEnqueuer.registerFieldLoad(member); | 606 nativeEnqueuer.registerFieldLoad(member); |
| 603 } | 607 } |
| 604 } | 608 } |
| 605 addToWorkList(member); | 609 addToWorkList(member); |
| 606 return true; | 610 return true; |
| 607 } | 611 } |
| 608 return false; | 612 return false; |
| 609 }); | 613 }); |
| 610 if (selector.isGetter) { | 614 if (selector.isGetter) { |
| 611 processInstanceFunctions(methodName, (Element member) { | 615 processInstanceFunctions(methodName, (Element member) { |
| 612 if (universeSelector.appliesUnnamed(member, compiler.world)) { | 616 if (universeSelector.appliesUnnamed(member, compiler.world)) { |
| 613 registerClosurizedMember(member, compiler.globalDependencies); | 617 registerClosurizedMember(member); |
| 614 return true; | 618 return true; |
| 615 } | 619 } |
| 616 return false; | 620 return false; |
| 617 }); | 621 }); |
| 618 } | 622 } |
| 619 } | 623 } |
| 620 | 624 |
| 621 /** | 625 /** |
| 622 * Documentation wanted -- johnniwinther | 626 * Documentation wanted -- johnniwinther |
| 623 * | 627 * |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 681 | 685 |
| 682 void registerIsCheck(DartType type) { | 686 void registerIsCheck(DartType type) { |
| 683 type = universe.registerIsCheck(type, compiler); | 687 type = universe.registerIsCheck(type, compiler); |
| 684 // Even in checked mode, type annotations for return type and argument | 688 // Even in checked mode, type annotations for return type and argument |
| 685 // types do not imply type checks, so there should never be a check | 689 // types do not imply type checks, so there should never be a check |
| 686 // against the type variable of a typedef. | 690 // against the type variable of a typedef. |
| 687 assert(!type.isTypeVariable || | 691 assert(!type.isTypeVariable || |
| 688 !type.element.enclosingElement.isTypedef); | 692 !type.element.enclosingElement.isTypedef); |
| 689 } | 693 } |
| 690 | 694 |
| 691 void registerCallMethodWithFreeTypeVariables( | 695 void registerCallMethodWithFreeTypeVariables(Element element) { |
| 692 Element element, | |
| 693 Registry registry) { | |
| 694 compiler.backend.registerCallMethodWithFreeTypeVariables( | 696 compiler.backend.registerCallMethodWithFreeTypeVariables( |
| 695 element, this, registry); | 697 element, this, compiler.globalDependencies); |
| 696 universe.callMethodsWithFreeTypeVariables.add(element); | 698 universe.callMethodsWithFreeTypeVariables.add(element); |
| 697 } | 699 } |
| 698 | 700 |
| 699 void registerClosurizedMember(TypedElement element, Registry registry) { | 701 void registerClosurizedMember(TypedElement element) { |
| 700 assert(element.isInstanceMember); | 702 assert(element.isInstanceMember); |
| 701 registerClosureIfFreeTypeVariables(element, registry); | 703 if (element.computeType(compiler).containsTypeVariables) { |
| 704 compiler.backend.registerClosureWithFreeTypeVariables( |
| 705 element, this, compiler.globalDependencies); |
| 706 } |
| 702 compiler.backend.registerBoundClosure(this); | 707 compiler.backend.registerBoundClosure(this); |
| 703 universe.closurizedMembers.add(element); | 708 universe.closurizedMembers.add(element); |
| 704 } | 709 } |
| 705 | 710 |
| 706 void registerClosureIfFreeTypeVariables(TypedElement element, | 711 void registerClosure(LocalFunctionElement element) { |
| 707 Registry registry) { | |
| 708 if (element.computeType(compiler).containsTypeVariables) { | |
| 709 compiler.backend.registerClosureWithFreeTypeVariables( | |
| 710 element, this, registry); | |
| 711 universe.closuresWithFreeTypeVariables.add(element); | |
| 712 } | |
| 713 } | |
| 714 | |
| 715 void registerClosure(LocalFunctionElement element, Registry registry) { | |
| 716 universe.allClosures.add(element); | 712 universe.allClosures.add(element); |
| 717 registerClosureIfFreeTypeVariables(element, registry); | |
| 718 } | 713 } |
| 719 | 714 |
| 720 void forEach(void f(WorkItem work)) { | 715 void forEach(void f(WorkItem work)) { |
| 721 do { | 716 do { |
| 722 while (queue.isNotEmpty) { | 717 while (queue.isNotEmpty) { |
| 723 // TODO(johnniwinther): Find an optimal process order. | 718 // TODO(johnniwinther): Find an optimal process order. |
| 724 filter.processWorkItem(f, queue.removeLast()); | 719 filter.processWorkItem(f, queue.removeLast()); |
| 725 } | 720 } |
| 726 List recents = recentClasses.toList(growable: false); | 721 List recents = recentClasses.toList(growable: false); |
| 727 recentClasses.clear(); | 722 recentClasses.clear(); |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1077 @override | 1072 @override |
| 1078 void processStaticUse(Enqueuer enqueuer, Element element) { | 1073 void processStaticUse(Enqueuer enqueuer, Element element) { |
| 1079 enqueuer.registerStaticUseInternal(element); | 1074 enqueuer.registerStaticUseInternal(element); |
| 1080 } | 1075 } |
| 1081 | 1076 |
| 1082 @override | 1077 @override |
| 1083 void processSelector(Enqueuer enqueuer, UniverseSelector selector) { | 1078 void processSelector(Enqueuer enqueuer, UniverseSelector selector) { |
| 1084 enqueuer.handleUnseenSelectorInternal(selector); | 1079 enqueuer.handleUnseenSelectorInternal(selector); |
| 1085 } | 1080 } |
| 1086 } | 1081 } |
| OLD | NEW |