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