| OLD | NEW |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 part of world_builder; | 5 part of world_builder; |
| 6 | 6 |
| 7 abstract class ResolutionWorldBuilder implements WorldBuilder, OpenWorld { | 7 abstract class ResolutionWorldBuilder implements WorldBuilder, OpenWorld { |
| 8 /// Set of all local functions in the program. Used by the mirror tracking |
| 9 /// system to find all live closure instances. |
| 10 Iterable<LocalFunctionElement> get localFunctions; |
| 11 |
| 8 /// Set of (live) local functions (closures) whose signatures reference type | 12 /// Set of (live) local functions (closures) whose signatures reference type |
| 9 /// variables. | 13 /// variables. |
| 10 /// | 14 /// |
| 11 /// A live function is one whose enclosing member function has been enqueued. | 15 /// A live function is one whose enclosing member function has been enqueued. |
| 12 Iterable<Element> get closuresWithFreeTypeVariables; | 16 Iterable<LocalFunctionElement> get localFunctionsWithFreeTypeVariables; |
| 13 | |
| 14 /// Set of (live) `call` methods whose signatures reference type variables. | |
| 15 /// | |
| 16 /// A live `call` method is one whose enclosing class has been instantiated. | |
| 17 Iterable<Element> get callMethodsWithFreeTypeVariables; | |
| 18 | |
| 19 /// Set of all closures in the program. Used by the mirror tracking system | |
| 20 /// to find all live closure instances. | |
| 21 Iterable<LocalFunctionElement> get allClosures; | |
| 22 | 17 |
| 23 /// Set of methods in instantiated classes that are potentially closurized. | 18 /// Set of methods in instantiated classes that are potentially closurized. |
| 24 Iterable<Element> get closurizedMembers; | 19 Iterable<MethodElement> get closurizedMembers; |
| 20 |
| 21 /// Set of live closurized members whose signatures reference type variables. |
| 22 /// |
| 23 /// A closurized method is considered live if the enclosing class has been |
| 24 /// instantiated. |
| 25 Iterable<MethodElement> get closurizedMembersWithFreeTypeVariables; |
| 25 | 26 |
| 26 /// Returns `true` if [cls] is considered to be implemented by an | 27 /// Returns `true` if [cls] is considered to be implemented by an |
| 27 /// instantiated class, either directly, through subclasses or through | 28 /// instantiated class, either directly, through subclasses or through |
| 28 /// subtypes. The latter case only contains spurious information from | 29 /// subtypes. The latter case only contains spurious information from |
| 29 /// instantiations through factory constructors and mixins. | 30 /// instantiations through factory constructors and mixins. |
| 30 bool isImplemented(ClassElement cls); | 31 bool isImplemented(ClassElement cls); |
| 31 | 32 |
| 32 /// Set of all fields that are statically known to be written to. | 33 /// Set of all fields that are statically known to be written to. |
| 33 Iterable<Element> get fieldSetters; | 34 Iterable<Element> get fieldSetters; |
| 34 | 35 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 50 /// This is only available after the world builder has been closed. | 51 /// This is only available after the world builder has been closed. |
| 51 ClosedWorld get closedWorldForTesting; | 52 ClosedWorld get closedWorldForTesting; |
| 52 } | 53 } |
| 53 | 54 |
| 54 /// Extended [ResolutionWorldBuilder] interface used by the | 55 /// Extended [ResolutionWorldBuilder] interface used by the |
| 55 /// [ResolutionEnqueuer]. | 56 /// [ResolutionEnqueuer]. |
| 56 abstract class ResolutionEnqueuerWorldBuilder extends ResolutionWorldBuilder { | 57 abstract class ResolutionEnqueuerWorldBuilder extends ResolutionWorldBuilder { |
| 57 /// Returns the classes registered as directly or indirectly instantiated. | 58 /// Returns the classes registered as directly or indirectly instantiated. |
| 58 Iterable<ClassEntity> get processedClasses; | 59 Iterable<ClassEntity> get processedClasses; |
| 59 | 60 |
| 60 /// Registers that the generic [element] has been closurized. | |
| 61 void registerClosureWithFreeTypeVariables(MemberEntity element); | |
| 62 | |
| 63 /// Registers that [element] has been closurized. | 61 /// Registers that [element] has been closurized. |
| 64 void registerClosurizedMember(MemberEntity element); | 62 void registerClosurizedMember(MemberEntity element); |
| 65 | 63 |
| 66 /// Register [type] as (directly) instantiated. | 64 /// Register [type] as (directly) instantiated. |
| 67 /// | 65 /// |
| 68 /// If [byMirrors] is `true`, the instantiation is through mirrors. | 66 /// If [byMirrors] is `true`, the instantiation is through mirrors. |
| 69 // TODO(johnniwinther): Fully enforce the separation between exact, through | 67 // TODO(johnniwinther): Fully enforce the separation between exact, through |
| 70 // subclass and through subtype instantiated types/classes. | 68 // subclass and through subtype instantiated types/classes. |
| 71 // TODO(johnniwinther): Support unknown type arguments for generic types. | 69 // TODO(johnniwinther): Support unknown type arguments for generic types. |
| 72 void registerTypeInstantiation( | 70 void registerTypeInstantiation( |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 | 294 |
| 297 /// Map containing instance methods of live classes that are not yet | 295 /// Map containing instance methods of live classes that are not yet |
| 298 /// closurized. | 296 /// closurized. |
| 299 final Map<String, Set<_MemberUsage>> _instanceFunctionsByName = | 297 final Map<String, Set<_MemberUsage>> _instanceFunctionsByName = |
| 300 <String, Set<_MemberUsage>>{}; | 298 <String, Set<_MemberUsage>>{}; |
| 301 | 299 |
| 302 /// Fields set. | 300 /// Fields set. |
| 303 final Set<Element> fieldSetters = new Set<Element>(); | 301 final Set<Element> fieldSetters = new Set<Element>(); |
| 304 final Set<ResolutionDartType> isChecks = new Set<ResolutionDartType>(); | 302 final Set<ResolutionDartType> isChecks = new Set<ResolutionDartType>(); |
| 305 | 303 |
| 306 /** | 304 /// Set of all closures in the program. Used by the mirror tracking system |
| 307 * Set of (live) [:call:] methods whose signatures reference type variables. | 305 /// to find all live closure instances. |
| 308 * | 306 final Set<LocalFunctionElement> localFunctions = |
| 309 * A live [:call:] method is one whose enclosing class has been instantiated. | 307 new Set<LocalFunctionElement>(); |
| 310 */ | |
| 311 final Set<Element> callMethodsWithFreeTypeVariables = new Set<Element>(); | |
| 312 | 308 |
| 313 /** | 309 /// Set of live local functions (closures) whose signatures reference type |
| 314 * Set of (live) local functions (closures) whose signatures reference type | 310 /// variables. |
| 315 * variables. | 311 /// |
| 316 * | 312 /// A local function is considered live if the enclosing member function is |
| 317 * A live function is one whose enclosing member function has been enqueued. | 313 /// live. |
| 318 */ | 314 final Set<LocalFunctionElement> localFunctionsWithFreeTypeVariables = |
| 319 final Set<Element> closuresWithFreeTypeVariables = new Set<Element>(); | 315 new Set<LocalFunctionElement>(); |
| 320 | 316 |
| 321 /** | 317 /// Set of methods in instantiated classes that are potentially closurized. |
| 322 * Set of all closures in the program. Used by the mirror tracking system | 318 final Set<MethodElement> closurizedMembers = new Set<MethodElement>(); |
| 323 * to find all live closure instances. | |
| 324 */ | |
| 325 final Set<LocalFunctionElement> allClosures = new Set<LocalFunctionElement>(); | |
| 326 | 319 |
| 327 /** | 320 /// Set of live closurized members whose signatures reference type variables. |
| 328 * Set of methods in instantiated classes that are potentially | 321 /// |
| 329 * closurized. | 322 /// A closurized method is considered live if the enclosing class has been |
| 330 */ | 323 /// instantiated. |
| 331 final Set<Element> closurizedMembers = new Set<Element>(); | 324 final Set<MethodElement> closurizedMembersWithFreeTypeVariables = |
| 325 new Set<MethodElement>(); |
| 332 | 326 |
| 333 final SelectorConstraintsStrategy selectorConstraintsStrategy; | 327 final SelectorConstraintsStrategy selectorConstraintsStrategy; |
| 334 | 328 |
| 335 bool hasRuntimeTypeSupport = false; | 329 bool hasRuntimeTypeSupport = false; |
| 336 bool hasIsolateSupport = false; | 330 bool hasIsolateSupport = false; |
| 337 bool hasFunctionApplySupport = false; | 331 bool hasFunctionApplySupport = false; |
| 338 | 332 |
| 339 /// Used for testing the new more precise computation of instantiated types | 333 /// Used for testing the new more precise computation of instantiated types |
| 340 /// and classes. | 334 /// and classes. |
| 341 bool useInstantiationMap = false; | 335 bool useInstantiationMap = false; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 | 406 |
| 413 /// Returns `true` if [cls] is considered to be implemented by an | 407 /// Returns `true` if [cls] is considered to be implemented by an |
| 414 /// instantiated class, either directly, through subclasses or through | 408 /// instantiated class, either directly, through subclasses or through |
| 415 /// subtypes. The latter case only contains spurious information from | 409 /// subtypes. The latter case only contains spurious information from |
| 416 /// instantiations through factory constructors and mixins. | 410 /// instantiations through factory constructors and mixins. |
| 417 // TODO(johnniwinther): Improve semantic precision. | 411 // TODO(johnniwinther): Improve semantic precision. |
| 418 bool isImplemented(ClassElement cls) { | 412 bool isImplemented(ClassElement cls) { |
| 419 return _implementedClasses.contains(cls.declaration); | 413 return _implementedClasses.contains(cls.declaration); |
| 420 } | 414 } |
| 421 | 415 |
| 422 void registerClosureWithFreeTypeVariables(MemberElement element) { | |
| 423 closuresWithFreeTypeVariables.add(element); | |
| 424 } | |
| 425 | |
| 426 void registerClosurizedMember(MemberElement element) { | 416 void registerClosurizedMember(MemberElement element) { |
| 427 closurizedMembers.add(element); | 417 closurizedMembers.add(element); |
| 418 if (element.type.containsTypeVariables) { |
| 419 closurizedMembersWithFreeTypeVariables.add(element); |
| 420 } |
| 428 } | 421 } |
| 429 | 422 |
| 430 /// Register [type] as (directly) instantiated. | 423 /// Register [type] as (directly) instantiated. |
| 431 /// | 424 /// |
| 432 /// If [byMirrors] is `true`, the instantiation is through mirrors. | 425 /// If [byMirrors] is `true`, the instantiation is through mirrors. |
| 433 // TODO(johnniwinther): Fully enforce the separation between exact, through | 426 // TODO(johnniwinther): Fully enforce the separation between exact, through |
| 434 // subclass and through subtype instantiated types/classes. | 427 // subclass and through subtype instantiated types/classes. |
| 435 // TODO(johnniwinther): Support unknown type arguments for generic types. | 428 // TODO(johnniwinther): Support unknown type arguments for generic types. |
| 436 void registerTypeInstantiation( | 429 void registerTypeInstantiation( |
| 437 ResolutionInterfaceType type, ClassUsedCallback classUsed, | 430 ResolutionInterfaceType type, ClassUsedCallback classUsed, |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 633 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue. | 626 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue. |
| 634 // Also [CLOSURE] contains [LocalFunctionElement] which we cannot | 627 // Also [CLOSURE] contains [LocalFunctionElement] which we cannot |
| 635 // enqueue. | 628 // enqueue. |
| 636 switch (staticUse.kind) { | 629 switch (staticUse.kind) { |
| 637 case StaticUseKind.FIELD_GET: | 630 case StaticUseKind.FIELD_GET: |
| 638 break; | 631 break; |
| 639 case StaticUseKind.FIELD_SET: | 632 case StaticUseKind.FIELD_SET: |
| 640 fieldSetters.add(element); | 633 fieldSetters.add(element); |
| 641 break; | 634 break; |
| 642 case StaticUseKind.CLOSURE: | 635 case StaticUseKind.CLOSURE: |
| 643 LocalFunctionElement closure = staticUse.element; | 636 LocalFunctionElement localFunction = staticUse.element; |
| 644 if (closure.type.containsTypeVariables) { | 637 if (localFunction.type.containsTypeVariables) { |
| 645 closuresWithFreeTypeVariables.add(closure); | 638 localFunctionsWithFreeTypeVariables.add(localFunction); |
| 646 } | 639 } |
| 647 allClosures.add(element); | 640 localFunctions.add(element); |
| 648 break; | 641 break; |
| 649 case StaticUseKind.SUPER_TEAR_OFF: | 642 case StaticUseKind.SUPER_TEAR_OFF: |
| 650 useSet.addAll(usage.tearOff()); | 643 useSet.addAll(usage.tearOff()); |
| 651 methodsNeedingSuperGetter.add(element); | 644 methodsNeedingSuperGetter.add(element); |
| 652 break; | 645 break; |
| 653 case StaticUseKind.SUPER_FIELD_SET: | 646 case StaticUseKind.SUPER_FIELD_SET: |
| 654 fieldSetters.add(element); | 647 fieldSetters.add(element); |
| 655 useSet.addAll(usage.normalUse()); | 648 useSet.addAll(usage.normalUse()); |
| 656 break; | 649 break; |
| 657 case StaticUseKind.STATIC_TEAR_OFF: | 650 case StaticUseKind.STATIC_TEAR_OFF: |
| 658 useSet.addAll(usage.tearOff()); | 651 useSet.addAll(usage.tearOff()); |
| 659 break; | 652 break; |
| 660 case StaticUseKind.GENERAL: | 653 case StaticUseKind.GENERAL: |
| 661 case StaticUseKind.DIRECT_USE: | 654 case StaticUseKind.DIRECT_USE: |
| 662 case StaticUseKind.CONSTRUCTOR_INVOKE: | 655 case StaticUseKind.CONSTRUCTOR_INVOKE: |
| 663 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: | 656 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: |
| 664 case StaticUseKind.REDIRECTION: | 657 case StaticUseKind.REDIRECTION: |
| 665 useSet.addAll(usage.normalUse()); | 658 useSet.addAll(usage.normalUse()); |
| 666 break; | 659 break; |
| 667 case StaticUseKind.DIRECT_INVOKE: | 660 case StaticUseKind.DIRECT_INVOKE: |
| 668 invariant( | 661 invariant( |
| 669 element, 'Direct static use is not supported for resolution.'); | 662 element, 'Direct static use is not supported for resolution.'); |
| 670 break; | 663 break; |
| 671 } | 664 } |
| 672 if (useSet.isNotEmpty) { | 665 if (useSet.isNotEmpty) { |
| 673 memberUsed(usage.entity, useSet); | 666 memberUsed(usage.entity, useSet); |
| 674 } | 667 } |
| 675 } | 668 } |
| 676 | 669 |
| 677 // TODO(ahe): Replace this method with something that is O(1), for example, | |
| 678 // by using a map. | |
| 679 List<LocalFunctionElement> slowDirectlyNestedClosures(Element element) { | |
| 680 // Return new list to guard against concurrent modifications. | |
| 681 return new List<LocalFunctionElement>.from( | |
| 682 allClosures.where((LocalFunctionElement closure) { | |
| 683 return closure.executableContext == element; | |
| 684 })); | |
| 685 } | |
| 686 | |
| 687 /// Return the canonical [_ClassUsage] for [cls]. | 670 /// Return the canonical [_ClassUsage] for [cls]. |
| 688 _ClassUsage _getClassUsage(ClassElement cls) { | 671 _ClassUsage _getClassUsage(ClassElement cls) { |
| 689 return _processedClasses.putIfAbsent(cls, () { | 672 return _processedClasses.putIfAbsent(cls, () { |
| 690 cls.ensureResolved(_resolution); | 673 cls.ensureResolved(_resolution); |
| 691 _ClassUsage usage = new _ClassUsage(cls); | 674 _ClassUsage usage = new _ClassUsage(cls); |
| 692 _resolution.ensureClassMembers(cls); | 675 _resolution.ensureClassMembers(cls); |
| 693 return usage; | 676 return usage; |
| 694 }); | 677 }); |
| 695 } | 678 } |
| 696 | 679 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 757 bool isNative = _backend.nativeData.isNativeClass(cls); | 740 bool isNative = _backend.nativeData.isNativeClass(cls); |
| 758 _MemberUsage usage = new _MemberUsage(member, isNative: isNative); | 741 _MemberUsage usage = new _MemberUsage(member, isNative: isNative); |
| 759 EnumSet<MemberUse> useSet = new EnumSet<MemberUse>(); | 742 EnumSet<MemberUse> useSet = new EnumSet<MemberUse>(); |
| 760 useSet.addAll(usage.appliedUse); | 743 useSet.addAll(usage.appliedUse); |
| 761 if (member.isField && isNative) { | 744 if (member.isField && isNative) { |
| 762 registerUsedElement(member); | 745 registerUsedElement(member); |
| 763 } | 746 } |
| 764 if (member.isFunction && | 747 if (member.isFunction && |
| 765 member.name == Identifiers.call && | 748 member.name == Identifiers.call && |
| 766 !cls.typeVariables.isEmpty) { | 749 !cls.typeVariables.isEmpty) { |
| 767 callMethodsWithFreeTypeVariables.add(member); | 750 closurizedMembersWithFreeTypeVariables.add(member); |
| 768 } | 751 } |
| 769 | 752 |
| 770 if (_hasInvokedGetter(member)) { | 753 if (_hasInvokedGetter(member)) { |
| 771 useSet.addAll(usage.read()); | 754 useSet.addAll(usage.read()); |
| 772 } | 755 } |
| 773 if (_hasInvocation(member)) { | 756 if (_hasInvocation(member)) { |
| 774 useSet.addAll(usage.invoke()); | 757 useSet.addAll(usage.invoke()); |
| 775 } | 758 } |
| 776 if (hasInvokedSetter(member)) { | 759 if (hasInvokedSetter(member)) { |
| 777 useSet.addAll(usage.write()); | 760 useSet.addAll(usage.write()); |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 959 @override | 942 @override |
| 960 bool isMemberUsed(MemberEntity member) { | 943 bool isMemberUsed(MemberEntity member) { |
| 961 if (member.isInstanceMember) { | 944 if (member.isInstanceMember) { |
| 962 _MemberUsage usage = _instanceMemberUsage[member]; | 945 _MemberUsage usage = _instanceMemberUsage[member]; |
| 963 if (usage != null && usage.hasUse) return true; | 946 if (usage != null && usage.hasUse) return true; |
| 964 } | 947 } |
| 965 _StaticMemberUsage usage = _staticMemberUsage[member]; | 948 _StaticMemberUsage usage = _staticMemberUsage[member]; |
| 966 return usage != null && usage.hasUse; | 949 return usage != null && usage.hasUse; |
| 967 } | 950 } |
| 968 } | 951 } |
| OLD | NEW |