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 universe; | 5 library universe; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import '../cache_strategy.dart'; | 9 import '../cache_strategy.dart'; |
| 10 import '../common.dart'; | 10 import '../common.dart'; |
| 11 import '../common/backend_api.dart' show Backend; | 11 import '../common/backend_api.dart' show Backend; |
| 12 import '../common/resolution.dart' show Resolution; | 12 import '../common/resolution.dart' show Resolution; |
| 13 import '../compiler.dart' show Compiler; | 13 import '../compiler.dart' show Compiler; |
| 14 import '../core_types.dart' show CoreClasses; | 14 import '../core_types.dart' show CoreClasses; |
| 15 import '../dart_types.dart'; | 15 import '../dart_types.dart'; |
| 16 import '../elements/elements.dart'; | 16 import '../elements/elements.dart'; |
| 17 import '../elements/entities.dart'; | |
| 17 import '../universe/class_set.dart' show Instantiation; | 18 import '../universe/class_set.dart' show Instantiation; |
| 19 import '../util/enumset.dart'; | |
| 18 import '../util/util.dart'; | 20 import '../util/util.dart'; |
| 19 import '../world.dart' show World, ClosedWorld, OpenWorld, WorldImpl; | 21 import '../world.dart' show World, ClosedWorld, OpenWorld, WorldImpl; |
| 20 import 'selector.dart' show Selector; | 22 import 'selector.dart' show Selector; |
| 21 import 'use.dart' show DynamicUse, DynamicUseKind, StaticUse, StaticUseKind; | 23 import 'use.dart' show DynamicUse, DynamicUseKind, StaticUse, StaticUseKind; |
| 22 | 24 |
| 23 /// The known constraint on receiver for a dynamic call site. | 25 /// The known constraint on receiver for a dynamic call site. |
| 24 /// | 26 /// |
| 25 /// This can for instance be used to constrain this dynamic call to `foo` to | 27 /// This can for instance be used to constrain this dynamic call to `foo` to |
| 26 /// 'receivers of the exact instance `Bar`': | 28 /// 'receivers of the exact instance `Bar`': |
| 27 /// | 29 /// |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 122 Iterable<DartType> get isChecks; | 124 Iterable<DartType> get isChecks; |
| 123 | 125 |
| 124 /// Registers that [type] is checked in this universe. The unaliased type is | 126 /// Registers that [type] is checked in this universe. The unaliased type is |
| 125 /// returned. | 127 /// returned. |
| 126 DartType registerIsCheck(DartType type, Resolution resolution); | 128 DartType registerIsCheck(DartType type, Resolution resolution); |
| 127 | 129 |
| 128 /// All directly instantiated types, that is, the types of the directly | 130 /// All directly instantiated types, that is, the types of the directly |
| 129 /// instantiated classes. | 131 /// instantiated classes. |
| 130 // TODO(johnniwinther): Improve semantic precision. | 132 // TODO(johnniwinther): Improve semantic precision. |
| 131 Iterable<DartType> get instantiatedTypes; | 133 Iterable<DartType> get instantiatedTypes; |
| 132 | |
| 133 /// Returns `true` if [member] is invoked as a setter. | |
| 134 bool hasInvokedSetter(Element member, World world); | |
| 135 } | 134 } |
| 136 | 135 |
| 137 abstract class ResolutionWorldBuilder implements WorldBuilder { | 136 abstract class ResolutionWorldBuilder implements WorldBuilder { |
| 138 /// Set of (live) local functions (closures) whose signatures reference type | 137 /// Set of (live) local functions (closures) whose signatures reference type |
| 139 /// variables. | 138 /// variables. |
| 140 /// | 139 /// |
| 141 /// A live function is one whose enclosing member function has been enqueued. | 140 /// A live function is one whose enclosing member function has been enqueued. |
| 142 Iterable<Element> get closuresWithFreeTypeVariables; | 141 Iterable<Element> get closuresWithFreeTypeVariables; |
| 143 | 142 |
| 144 /// Set of (live) `call` methods whose signatures reference type variables. | 143 /// Set of (live) `call` methods whose signatures reference type variables. |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 160 bool isImplemented(ClassElement cls); | 159 bool isImplemented(ClassElement cls); |
| 161 | 160 |
| 162 /// Set of all fields that are statically known to be written to. | 161 /// Set of all fields that are statically known to be written to. |
| 163 Iterable<Element> get fieldSetters; | 162 Iterable<Element> get fieldSetters; |
| 164 | 163 |
| 165 /// Call [f] for all classes with instantiated types. This includes the | 164 /// Call [f] for all classes with instantiated types. This includes the |
| 166 /// directly and abstractly instantiated classes but also classes whose type | 165 /// directly and abstractly instantiated classes but also classes whose type |
| 167 /// arguments are used in live factory constructors. | 166 /// arguments are used in live factory constructors. |
| 168 void forEachInstantiatedClass(f(ClassElement cls, InstantiationInfo info)); | 167 void forEachInstantiatedClass(f(ClassElement cls, InstantiationInfo info)); |
| 169 | 168 |
| 169 /// Returns `true` if [member] is invoked as a setter. | |
| 170 bool hasInvokedSetter(Element member); | |
| 171 | |
| 170 /// `true` of `Object.runtimeType` is supported. | 172 /// `true` of `Object.runtimeType` is supported. |
| 171 bool get hasRuntimeTypeSupport; | 173 bool get hasRuntimeTypeSupport; |
| 172 | 174 |
| 173 /// `true` of use of the `dart:isolate` library is supported. | 175 /// `true` of use of the `dart:isolate` library is supported. |
| 174 bool get hasIsolateSupport; | 176 bool get hasIsolateSupport; |
| 175 | 177 |
| 176 /// `true` of `Function.apply` is supported. | 178 /// `true` of `Function.apply` is supported. |
| 177 bool get hasFunctionApplySupport; | 179 bool get hasFunctionApplySupport; |
| 178 | 180 |
| 179 /// The [OpenWorld] being created by this world builder. | 181 /// The [OpenWorld] being created by this world builder. |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 363 */ | 365 */ |
| 364 final Set<FunctionElement> methodsNeedingSuperGetter = | 366 final Set<FunctionElement> methodsNeedingSuperGetter = |
| 365 new Set<FunctionElement>(); | 367 new Set<FunctionElement>(); |
| 366 final Map<String, Map<Selector, SelectorConstraints>> _invokedNames = | 368 final Map<String, Map<Selector, SelectorConstraints>> _invokedNames = |
| 367 <String, Map<Selector, SelectorConstraints>>{}; | 369 <String, Map<Selector, SelectorConstraints>>{}; |
| 368 final Map<String, Map<Selector, SelectorConstraints>> _invokedGetters = | 370 final Map<String, Map<Selector, SelectorConstraints>> _invokedGetters = |
| 369 <String, Map<Selector, SelectorConstraints>>{}; | 371 <String, Map<Selector, SelectorConstraints>>{}; |
| 370 final Map<String, Map<Selector, SelectorConstraints>> _invokedSetters = | 372 final Map<String, Map<Selector, SelectorConstraints>> _invokedSetters = |
| 371 <String, Map<Selector, SelectorConstraints>>{}; | 373 <String, Map<Selector, SelectorConstraints>>{}; |
| 372 | 374 |
| 375 /// Map of registers usage of instance members of live classes. | |
| 376 final Map<MemberEntity, MemberUsage> _instanceMemberUsage = | |
| 377 <MemberEntity, MemberUsage>{}; | |
| 378 | |
| 379 /// Map containing instance members of live classes that are not yet live | |
| 380 /// themselves. | |
| 381 final Map<String, Set<MemberUsage>> _instanceMembersByName = | |
| 382 <String, Set<MemberUsage>>{}; | |
| 383 | |
| 384 /// Map containing instance methods of live classes that are not yet | |
| 385 /// closurized. | |
| 386 final Map<String, Set<MemberUsage>> _instanceFunctionsByName = | |
| 387 <String, Set<MemberUsage>>{}; | |
| 388 | |
| 373 /// Fields set. | 389 /// Fields set. |
| 374 final Set<Element> fieldSetters = new Set<Element>(); | 390 final Set<Element> fieldSetters = new Set<Element>(); |
| 375 final Set<DartType> isChecks = new Set<DartType>(); | 391 final Set<DartType> isChecks = new Set<DartType>(); |
| 376 | 392 |
| 377 /** | 393 /** |
| 378 * Set of (live) [:call:] methods whose signatures reference type variables. | 394 * Set of (live) [:call:] methods whose signatures reference type variables. |
| 379 * | 395 * |
| 380 * A live [:call:] method is one whose enclosing class has been instantiated. | 396 * A live [:call:] method is one whose enclosing class has been instantiated. |
| 381 */ | 397 */ |
| 382 final Set<Element> callMethodsWithFreeTypeVariables = new Set<Element>(); | 398 final Set<Element> callMethodsWithFreeTypeVariables = new Set<Element>(); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 406 bool hasRuntimeTypeSupport = false; | 422 bool hasRuntimeTypeSupport = false; |
| 407 bool hasIsolateSupport = false; | 423 bool hasIsolateSupport = false; |
| 408 bool hasFunctionApplySupport = false; | 424 bool hasFunctionApplySupport = false; |
| 409 | 425 |
| 410 /// Used for testing the new more precise computation of instantiated types | 426 /// Used for testing the new more precise computation of instantiated types |
| 411 /// and classes. | 427 /// and classes. |
| 412 bool useInstantiationMap = false; | 428 bool useInstantiationMap = false; |
| 413 | 429 |
| 414 OpenWorld _openWorld; | 430 OpenWorld _openWorld; |
| 415 | 431 |
| 416 ResolutionWorldBuilderImpl(Backend backend, CoreClasses coreClasses, | 432 final Backend _backend; |
| 417 CacheStrategy cacheStrategy, this.selectorConstraintsStrategy) { | 433 final Resolution _resolution; |
| 418 _openWorld = new WorldImpl(this, backend, coreClasses, cacheStrategy); | 434 |
| 435 ResolutionWorldBuilderImpl(Backend backend, Resolution resolution, | |
| 436 CacheStrategy cacheStrategy, this.selectorConstraintsStrategy) | |
| 437 : this._backend = backend, | |
| 438 this._resolution = resolution { | |
| 439 _openWorld = | |
| 440 new WorldImpl(this, backend, resolution.coreClasses, cacheStrategy); | |
| 419 } | 441 } |
| 420 | 442 |
| 421 OpenWorld get openWorld => _openWorld; | 443 OpenWorld get openWorld => _openWorld; |
| 422 | 444 |
| 423 /// All directly instantiated classes, that is, classes with a generative | 445 /// All directly instantiated classes, that is, classes with a generative |
| 424 /// constructor that has been called directly and not only through a | 446 /// constructor that has been called directly and not only through a |
| 425 /// super-call. | 447 /// super-call. |
| 426 // TODO(johnniwinther): Improve semantic precision. | 448 // TODO(johnniwinther): Improve semantic precision. |
| 427 Iterable<ClassElement> get directlyInstantiatedClasses { | 449 Iterable<ClassElement> get directlyInstantiatedClasses { |
| 428 Set<ClassElement> classes = new Set<ClassElement>(); | 450 Set<ClassElement> classes = new Set<ClassElement>(); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 509 } | 531 } |
| 510 }); | 532 }); |
| 511 } | 533 } |
| 512 } | 534 } |
| 513 | 535 |
| 514 @override | 536 @override |
| 515 void forEachInstantiatedClass(f(ClassElement cls, InstantiationInfo info)) { | 537 void forEachInstantiatedClass(f(ClassElement cls, InstantiationInfo info)) { |
| 516 getInstantiationMap().forEach(f); | 538 getInstantiationMap().forEach(f); |
| 517 } | 539 } |
| 518 | 540 |
| 519 bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors, | 541 bool _hasMatchingSelector( |
| 520 Element member, OpenWorld world) { | 542 Map<Selector, SelectorConstraints> selectors, Element member) { |
| 521 if (selectors == null) return false; | 543 if (selectors == null) return false; |
| 522 for (Selector selector in selectors.keys) { | 544 for (Selector selector in selectors.keys) { |
| 523 if (selector.appliesUnnamed(member)) { | 545 if (selector.appliesUnnamed(member)) { |
| 524 SelectorConstraints masks = selectors[selector]; | 546 SelectorConstraints masks = selectors[selector]; |
| 525 if (masks.applies(member, selector, world)) { | 547 if (masks.applies(member, selector, _openWorld)) { |
| 526 return true; | 548 return true; |
| 527 } | 549 } |
| 528 } | 550 } |
| 529 } | 551 } |
| 530 return false; | 552 return false; |
| 531 } | 553 } |
| 532 | 554 |
| 533 /// Returns the instantiation map used for computing the closed world. | 555 /// Returns the instantiation map used for computing the closed world. |
| 534 /// | 556 /// |
| 535 /// If [useInstantiationMap] is `true`, redirections are removed and | 557 /// If [useInstantiationMap] is `true`, redirections are removed and |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 567 infoFor(targetType.element) | 589 infoFor(targetType.element) |
| 568 .addInstantiation(target, targetType, kind); | 590 .addInstantiation(target, targetType, kind); |
| 569 } | 591 } |
| 570 } | 592 } |
| 571 }); | 593 }); |
| 572 } | 594 } |
| 573 }); | 595 }); |
| 574 return instantiationMap; | 596 return instantiationMap; |
| 575 } | 597 } |
| 576 | 598 |
| 577 bool hasInvocation(Element member, OpenWorld world) { | 599 bool _hasInvocation(Element member) { |
| 578 return _hasMatchingSelector(_invokedNames[member.name], member, world); | 600 return _hasMatchingSelector(_invokedNames[member.name], member); |
| 579 } | 601 } |
| 580 | 602 |
| 581 bool hasInvokedGetter(Element member, OpenWorld world) { | 603 bool _hasInvokedGetter(Element member) { |
| 582 return _hasMatchingSelector(_invokedGetters[member.name], member, world) || | 604 return _hasMatchingSelector(_invokedGetters[member.name], member) || |
| 583 member.isFunction && methodsNeedingSuperGetter.contains(member); | 605 member.isFunction && methodsNeedingSuperGetter.contains(member); |
| 584 } | 606 } |
| 585 | 607 |
| 586 bool hasInvokedSetter(Element member, OpenWorld world) { | 608 bool hasInvokedSetter(Element member) { |
| 587 return _hasMatchingSelector(_invokedSetters[member.name], member, world); | 609 return _hasMatchingSelector(_invokedSetters[member.name], member); |
| 588 } | 610 } |
| 589 | 611 |
| 590 bool registerDynamicUse(DynamicUse dynamicUse) { | 612 void registerDynamicUse(DynamicUse dynamicUse, MemberUsed memberUsed) { |
| 613 Selector selector = dynamicUse.selector; | |
| 614 String methodName = selector.name; | |
| 591 switch (dynamicUse.kind) { | 615 switch (dynamicUse.kind) { |
| 592 case DynamicUseKind.INVOKE: | 616 case DynamicUseKind.INVOKE: |
| 593 return _registerNewSelector(dynamicUse, _invokedNames); | 617 if (_registerNewSelector(dynamicUse, _invokedNames)) { |
| 618 _processInstanceMembers(methodName, (MemberUsage usage) { | |
| 619 if (dynamicUse.appliesUnnamed(usage.member, _openWorld)) { | |
| 620 memberUsed(usage.member, usage.invoke()); | |
| 621 return true; | |
| 622 } | |
| 623 return false; | |
| 624 }); | |
| 625 } | |
| 626 break; | |
| 594 case DynamicUseKind.GET: | 627 case DynamicUseKind.GET: |
| 595 return _registerNewSelector(dynamicUse, _invokedGetters); | 628 if (_registerNewSelector(dynamicUse, _invokedGetters)) { |
| 629 _processInstanceMembers(methodName, (MemberUsage usage) { | |
| 630 if (dynamicUse.appliesUnnamed(usage.member, _openWorld)) { | |
| 631 memberUsed(usage.member, usage.read()); | |
| 632 return true; | |
| 633 } | |
| 634 return false; | |
| 635 }); | |
| 636 _processInstanceFunctions(methodName, (MemberUsage usage) { | |
| 637 if (dynamicUse.appliesUnnamed(usage.member, _openWorld)) { | |
| 638 memberUsed(usage.member, usage.read()); | |
| 639 return true; | |
| 640 } | |
| 641 return false; | |
| 642 }); | |
| 643 } | |
| 644 break; | |
| 596 case DynamicUseKind.SET: | 645 case DynamicUseKind.SET: |
| 597 return _registerNewSelector(dynamicUse, _invokedSetters); | 646 if (_registerNewSelector(dynamicUse, _invokedSetters)) { |
| 647 _processInstanceMembers(methodName, (MemberUsage usage) { | |
| 648 if (dynamicUse.appliesUnnamed(usage.member, _openWorld)) { | |
| 649 memberUsed(usage.member, usage.write()); | |
| 650 return true; | |
| 651 } | |
| 652 return false; | |
| 653 }); | |
| 654 } | |
| 655 break; | |
| 598 } | 656 } |
| 599 } | 657 } |
| 600 | 658 |
| 601 bool _registerNewSelector(DynamicUse dynamicUse, | 659 bool _registerNewSelector(DynamicUse dynamicUse, |
| 602 Map<String, Map<Selector, SelectorConstraints>> selectorMap) { | 660 Map<String, Map<Selector, SelectorConstraints>> selectorMap) { |
| 603 Selector selector = dynamicUse.selector; | 661 Selector selector = dynamicUse.selector; |
| 604 String name = selector.name; | 662 String name = selector.name; |
| 605 ReceiverConstraint mask = dynamicUse.mask; | 663 ReceiverConstraint mask = dynamicUse.mask; |
| 606 Map<Selector, SelectorConstraints> selectors = selectorMap.putIfAbsent( | 664 Map<Selector, SelectorConstraints> selectors = selectorMap.putIfAbsent( |
| 607 name, () => new Maplet<Selector, SelectorConstraints>()); | 665 name, () => new Maplet<Selector, SelectorConstraints>()); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 652 break; | 710 break; |
| 653 } | 711 } |
| 654 } | 712 } |
| 655 | 713 |
| 656 void forgetElement(Element element, Compiler compiler) { | 714 void forgetElement(Element element, Compiler compiler) { |
| 657 allClosures.remove(element); | 715 allClosures.remove(element); |
| 658 slowDirectlyNestedClosures(element).forEach(compiler.forgetElement); | 716 slowDirectlyNestedClosures(element).forEach(compiler.forgetElement); |
| 659 closurizedMembers.remove(element); | 717 closurizedMembers.remove(element); |
| 660 fieldSetters.remove(element); | 718 fieldSetters.remove(element); |
| 661 _instantiationInfo.remove(element); | 719 _instantiationInfo.remove(element); |
| 720 | |
| 721 void removeUsage(Set<MemberUsage> set, Element element) { | |
| 722 if (set == null) return; | |
| 723 set.removeAll( | |
| 724 set.where((MemberUsage usage) => usage.member == element).toList()); | |
|
Harry Terkelsen
2016/12/05 22:48:53
is toList() necessary to prevent the 'where' from
Johnni Winther
2016/12/06 09:28:05
Yes.
| |
| 725 } | |
| 726 | |
| 727 removeUsage(_instanceMembersByName[element.name], element); | |
| 728 removeUsage(_instanceFunctionsByName[element.name], element); | |
| 662 } | 729 } |
| 663 | 730 |
| 664 // TODO(ahe): Replace this method with something that is O(1), for example, | 731 // TODO(ahe): Replace this method with something that is O(1), for example, |
| 665 // by using a map. | 732 // by using a map. |
| 666 List<LocalFunctionElement> slowDirectlyNestedClosures(Element element) { | 733 List<LocalFunctionElement> slowDirectlyNestedClosures(Element element) { |
| 667 // Return new list to guard against concurrent modifications. | 734 // Return new list to guard against concurrent modifications. |
| 668 return new List<LocalFunctionElement>.from( | 735 return new List<LocalFunctionElement>.from( |
| 669 allClosures.where((LocalFunctionElement closure) { | 736 allClosures.where((LocalFunctionElement closure) { |
| 670 return closure.executableContext == element; | 737 return closure.executableContext == element; |
| 671 })); | 738 })); |
| 672 } | 739 } |
| 740 | |
| 741 void _processSet(Map<String, Set<MemberUsage>> map, String memberName, | |
| 742 bool f(MemberUsage e)) { | |
| 743 Set<MemberUsage> members = map[memberName]; | |
| 744 if (members == null) return; | |
| 745 // [f] might add elements to [: map[memberName] :] during the loop below | |
| 746 // so we create a new list for [: map[memberName] :] and prepend the | |
| 747 // [remaining] members after the loop. | |
| 748 map[memberName] = new Set<MemberUsage>(); | |
| 749 Set<MemberUsage> remaining = new Set<MemberUsage>(); | |
| 750 for (MemberUsage usage in members) { | |
| 751 if (!f(usage)) remaining.add(usage); | |
| 752 } | |
| 753 map[memberName].addAll(remaining); | |
| 754 } | |
| 755 | |
| 756 void _processInstanceMembers(String n, bool f(MemberUsage e)) { | |
|
Harry Terkelsen
2016/12/05 22:48:53
give these params full names
Johnni Winther
2016/12/06 09:28:06
Done.
| |
| 757 _processSet(_instanceMembersByName, n, f); | |
| 758 } | |
| 759 | |
| 760 void _processInstanceFunctions(String n, bool f(MemberUsage e)) { | |
| 761 _processSet(_instanceFunctionsByName, n, f); | |
| 762 } | |
| 763 | |
| 764 // TODO(johnniwinther): Make this private when | |
| 765 // [ResolutionEnqueuer._processClass] is move to [ResolutionWorldBuilderImpl]. | |
| 766 void processInstantiatedClassMember( | |
| 767 ClassElement cls, MemberElement member, MemberUsed memberUsed) { | |
| 768 assert(invariant(member, member.isDeclaration)); | |
| 769 if (!member.isInstanceMember) return; | |
| 770 String memberName = member.name; | |
| 771 member.computeType(_resolution); | |
| 772 EnumSet<MemberUse> useSet = new EnumSet<MemberUse>(); | |
| 773 // The obvious thing to test here would be "member.isNative", | |
| 774 // however, that only works after metadata has been parsed/analyzed, | |
| 775 // and that may not have happened yet. | |
| 776 // So instead we use the enclosing class, which we know have had | |
| 777 // its metadata parsed and analyzed. | |
| 778 // Note: this assumes that there are no non-native fields on native | |
| 779 // classes, which may not be the case when a native class is subclassed. | |
| 780 bool isNative = _backend.isNative(cls); | |
| 781 MemberUsage usage = _instanceMemberUsage.putIfAbsent(member, () { | |
| 782 MemberUsage usage = new MemberUsage(member, isNative: isNative); | |
| 783 useSet.addAll(usage.appliedUse); | |
| 784 if (member.isField && isNative) { | |
| 785 _openWorld.registerUsedElement(member); | |
| 786 } | |
| 787 | |
| 788 if (_hasInvokedGetter(member)) { | |
| 789 useSet.addAll(usage.read()); | |
| 790 } | |
| 791 if (_hasInvocation(member)) { | |
| 792 useSet.addAll(usage.invoke()); | |
| 793 } | |
| 794 if (hasInvokedSetter(member)) { | |
| 795 useSet.addAll(usage.write()); | |
| 796 } | |
| 797 | |
| 798 if (usage.pendingUse.contains(MemberUse.NORMAL)) { | |
| 799 // The element is not yet used. Add it to the list of instance | |
| 800 // members to still be processed. | |
| 801 _instanceMembersByName | |
| 802 .putIfAbsent(memberName, () => new Set<MemberUsage>()) | |
| 803 .add(usage); | |
| 804 } | |
| 805 if (usage.pendingUse.contains(MemberUse.CLOSURIZE)) { | |
| 806 // Store the member in [instanceFunctionsByName] to catch | |
| 807 // getters on the function. | |
| 808 _instanceFunctionsByName | |
| 809 .putIfAbsent(memberName, () => new Set<MemberUsage>()) | |
| 810 .add(usage); | |
| 811 } | |
| 812 | |
| 813 memberUsed(usage.member, useSet); | |
| 814 return usage; | |
| 815 }); | |
| 816 } | |
| 673 } | 817 } |
| 674 | 818 |
| 675 /// World builder specific to codegen. | 819 /// World builder specific to codegen. |
| 676 /// | 820 /// |
| 677 /// This adds additional access to liveness of selectors and elements. | 821 /// This adds additional access to liveness of selectors and elements. |
| 678 abstract class CodegenWorldBuilder implements WorldBuilder { | 822 abstract class CodegenWorldBuilder implements WorldBuilder { |
| 679 void forEachInvokedName( | 823 void forEachInvokedName( |
| 680 f(String name, Map<Selector, SelectorConstraints> selectors)); | 824 f(String name, Map<Selector, SelectorConstraints> selectors)); |
| 681 | 825 |
| 682 void forEachInvokedGetter( | 826 void forEachInvokedGetter( |
| 683 f(String name, Map<Selector, SelectorConstraints> selectors)); | 827 f(String name, Map<Selector, SelectorConstraints> selectors)); |
| 684 | 828 |
| 685 void forEachInvokedSetter( | 829 void forEachInvokedSetter( |
| 686 f(String name, Map<Selector, SelectorConstraints> selectors)); | 830 f(String name, Map<Selector, SelectorConstraints> selectors)); |
| 687 | 831 |
| 832 /// Returns `true` if [member] is invoked as a setter. | |
| 833 bool hasInvokedSetter(Element member, ClosedWorld world); | |
| 834 | |
| 688 bool hasInvokedGetter(Element member, ClosedWorld world); | 835 bool hasInvokedGetter(Element member, ClosedWorld world); |
| 689 | 836 |
| 690 Map<Selector, SelectorConstraints> invocationsByName(String name); | 837 Map<Selector, SelectorConstraints> invocationsByName(String name); |
| 691 | 838 |
| 692 Map<Selector, SelectorConstraints> getterInvocationsByName(String name); | 839 Map<Selector, SelectorConstraints> getterInvocationsByName(String name); |
| 693 | 840 |
| 694 Map<Selector, SelectorConstraints> setterInvocationsByName(String name); | 841 Map<Selector, SelectorConstraints> setterInvocationsByName(String name); |
| 695 | 842 |
| 696 Iterable<FunctionElement> get staticFunctionsNeedingGetter; | 843 Iterable<FunctionElement> get staticFunctionsNeedingGetter; |
| 697 Iterable<FunctionElement> get methodsNeedingSuperGetter; | 844 Iterable<FunctionElement> get methodsNeedingSuperGetter; |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 925 | 1072 |
| 926 void forgetElement(Element element, Compiler compiler) { | 1073 void forgetElement(Element element, Compiler compiler) { |
| 927 _directlyInstantiatedClasses.remove(element); | 1074 _directlyInstantiatedClasses.remove(element); |
| 928 if (element is ClassElement) { | 1075 if (element is ClassElement) { |
| 929 assert(invariant(element, element.thisType.isRaw, | 1076 assert(invariant(element, element.thisType.isRaw, |
| 930 message: 'Generic classes not supported (${element.thisType}).')); | 1077 message: 'Generic classes not supported (${element.thisType}).')); |
| 931 _instantiatedTypes..remove(element.rawType)..remove(element.thisType); | 1078 _instantiatedTypes..remove(element.rawType)..remove(element.thisType); |
| 932 } | 1079 } |
| 933 } | 1080 } |
| 934 } | 1081 } |
| 1082 | |
| 1083 /// Registry for the observed use of [member] in the open world. | |
| 1084 abstract class MemberUsage { | |
| 1085 // TODO(johnniwinther): Change [Entity] to [MemberEntity]. | |
| 1086 final Entity member; | |
| 1087 final EnumSet<MemberUse> _pendingUse = new EnumSet<MemberUse>(); | |
| 1088 | |
| 1089 MemberUsage.internal(this.member) { | |
| 1090 _pendingUse.addAll(_originalUse); | |
| 1091 } | |
| 1092 | |
| 1093 factory MemberUsage(MemberEntity member, {bool isNative: false}) { | |
| 1094 if (member.isField) { | |
| 1095 if (member.isAssignable) { | |
| 1096 return new _FieldUsage(member, isNative: isNative); | |
| 1097 } else { | |
| 1098 return new _FinalFieldUsage(member, isNative: isNative); | |
| 1099 } | |
| 1100 } else if (member.isGetter) { | |
| 1101 return new _GetterUsage(member); | |
| 1102 } else if (member.isSetter) { | |
| 1103 return new _SetterUsage(member); | |
| 1104 } else { | |
| 1105 assert(member.isFunction); | |
| 1106 return new _FunctionUsage(member); | |
| 1107 } | |
| 1108 } | |
| 1109 | |
| 1110 /// `true` if [member] has be read as a value. For a field this is a normal | |
|
Harry Terkelsen
2016/12/05 22:48:53
be -> been
Johnni Winther
2016/12/06 09:28:06
Done.
| |
| 1111 /// read access, for a function this is a closurization. | |
| 1112 bool get hasRead => false; | |
| 1113 | |
| 1114 /// `true` if a value as been written to [member]. | |
|
Harry Terkelsen
2016/12/05 22:48:53
as -> has
Johnni Winther
2016/12/06 09:28:05
Done.
| |
| 1115 bool get hasWrite => false; | |
| 1116 | |
| 1117 /// `true` if an invocation has been performed on the value [member]. For a | |
| 1118 /// function this is a normal invocation, for a field this is a read access | |
| 1119 /// followed by an invocation of the function-like value. | |
| 1120 bool get hasInvoke => false; | |
| 1121 | |
| 1122 /// `true` if [member] has been used in all the ways possible. | |
| 1123 bool get fullyUsed; | |
| 1124 | |
| 1125 /// Registers a read of the value of [member] and returns the new [MemberUse]s | |
| 1126 /// that it caused. | |
| 1127 /// | |
| 1128 /// For a field this is a normal read access, for a function this is a | |
| 1129 /// closurization. | |
| 1130 EnumSet<MemberUse> read() => MemberUse.NONE; | |
| 1131 | |
| 1132 /// Registers a write of a value to [member] and returns the new [MemberUse]s | |
| 1133 /// that it caused. | |
| 1134 EnumSet<MemberUse> write() => MemberUse.NONE; | |
| 1135 | |
| 1136 /// Registers an invocation on the value of [member] and returns the new | |
| 1137 /// [MemberUse]s that it caused. | |
| 1138 /// | |
| 1139 /// For a function this is a normal invocation, for a field this is a read | |
| 1140 /// access followed by an invocation of the function-like value. | |
| 1141 EnumSet<MemberUse> invoke() => MemberUse.NONE; | |
| 1142 | |
| 1143 /// Registers all possible uses of [member] and returns the new [MemberUse]s | |
| 1144 /// that it caused. | |
| 1145 EnumSet<MemberUse> fullyUse() => MemberUse.NONE; | |
| 1146 | |
| 1147 /// Returns the possible [MemberUse]s of [member] that have not yet been | |
| 1148 /// registered. | |
| 1149 EnumSet<MemberUse> get pendingUse => _pendingUse; | |
| 1150 | |
| 1151 /// Returns the [MemberUse]s of [member] that have been registered. | |
| 1152 EnumSet<MemberUse> get appliedUse => _originalUse.minus(_pendingUse); | |
| 1153 | |
| 1154 EnumSet<MemberUse> get _originalUse; | |
| 1155 | |
| 1156 int get hashCode => member.hashCode; | |
| 1157 | |
| 1158 bool operator ==(other) { | |
| 1159 if (identical(this, other)) return true; | |
| 1160 if (other is! MemberUsage) return false; | |
| 1161 return member == other.member; | |
| 1162 } | |
| 1163 | |
| 1164 String toString() => member.toString(); | |
| 1165 } | |
| 1166 | |
| 1167 class _FieldUsage extends MemberUsage { | |
| 1168 bool hasRead = false; | |
| 1169 bool hasWrite = false; | |
| 1170 | |
| 1171 _FieldUsage(FieldEntity field, {bool isNative: false}) | |
| 1172 : super.internal(field) { | |
| 1173 if (!isNative) { | |
| 1174 // All field initializers must be resolved as they could | |
| 1175 // have an observable side-effect (and cannot be tree-shaken | |
| 1176 // away). | |
| 1177 fullyUse(); | |
| 1178 } | |
| 1179 } | |
| 1180 | |
| 1181 EnumSet<MemberUse> get _originalUse => MemberUse.NORMAL_ONLY; | |
| 1182 | |
| 1183 @override | |
| 1184 bool get fullyUsed => hasRead && hasWrite; | |
| 1185 | |
| 1186 @override | |
| 1187 EnumSet<MemberUse> read() { | |
| 1188 if (fullyUsed) { | |
| 1189 return MemberUse.NONE; | |
| 1190 } | |
| 1191 hasRead = true; | |
| 1192 return _pendingUse.removeAll(MemberUse.NORMAL_ONLY); | |
| 1193 } | |
| 1194 | |
| 1195 @override | |
| 1196 EnumSet<MemberUse> write() { | |
| 1197 if (fullyUsed) { | |
| 1198 return MemberUse.NONE; | |
| 1199 } | |
| 1200 hasWrite = true; | |
| 1201 return _pendingUse.removeAll(MemberUse.NORMAL_ONLY); | |
| 1202 } | |
| 1203 | |
| 1204 @override | |
| 1205 EnumSet<MemberUse> invoke() => read(); | |
| 1206 | |
| 1207 @override | |
| 1208 EnumSet<MemberUse> fullyUse() { | |
| 1209 if (fullyUsed) { | |
| 1210 return MemberUse.NONE; | |
| 1211 } | |
| 1212 hasRead = hasWrite = true; | |
| 1213 return _pendingUse.removeAll(MemberUse.NORMAL_ONLY); | |
| 1214 } | |
| 1215 } | |
| 1216 | |
| 1217 class _FinalFieldUsage extends MemberUsage { | |
| 1218 bool hasRead = false; | |
| 1219 | |
| 1220 _FinalFieldUsage(FieldEntity field, {bool isNative: false}) | |
| 1221 : super.internal(field) { | |
| 1222 if (!isNative) { | |
| 1223 // All field initializers must be resolved as they could | |
| 1224 // have an observable side-effect (and cannot be tree-shaken | |
| 1225 // away). | |
| 1226 read(); | |
| 1227 } | |
| 1228 } | |
| 1229 | |
| 1230 EnumSet<MemberUse> get _originalUse => MemberUse.NORMAL_ONLY; | |
| 1231 | |
| 1232 @override | |
| 1233 bool get fullyUsed => hasRead; | |
| 1234 | |
| 1235 @override | |
| 1236 EnumSet<MemberUse> read() { | |
| 1237 if (hasRead) { | |
| 1238 return MemberUse.NONE; | |
| 1239 } | |
| 1240 hasRead = true; | |
| 1241 return _pendingUse.removeAll(MemberUse.NORMAL_ONLY); | |
| 1242 } | |
| 1243 | |
| 1244 @override | |
| 1245 EnumSet<MemberUse> invoke() => read(); | |
| 1246 | |
| 1247 @override | |
| 1248 EnumSet<MemberUse> fullyUse() => read(); | |
| 1249 } | |
| 1250 | |
| 1251 class _FunctionUsage extends MemberUsage { | |
| 1252 bool hasInvoke = false; | |
| 1253 bool hasRead = false; | |
| 1254 | |
| 1255 _FunctionUsage(FunctionEntity function) : super.internal(function); | |
| 1256 | |
| 1257 EnumSet<MemberUse> get _originalUse => MemberUse.ALL; | |
| 1258 | |
| 1259 @override | |
| 1260 EnumSet<MemberUse> read() => fullyUse(); | |
| 1261 | |
| 1262 @override | |
| 1263 EnumSet<MemberUse> invoke() { | |
| 1264 if (hasInvoke) { | |
| 1265 return MemberUse.NONE; | |
| 1266 } | |
| 1267 hasInvoke = true; | |
| 1268 return _pendingUse | |
| 1269 .removeAll(hasRead ? MemberUse.NONE : MemberUse.NORMAL_ONLY); | |
| 1270 } | |
| 1271 | |
| 1272 @override | |
| 1273 EnumSet<MemberUse> fullyUse() { | |
| 1274 if (hasInvoke) { | |
| 1275 if (hasRead) { | |
| 1276 return MemberUse.NONE; | |
| 1277 } | |
| 1278 hasRead = true; | |
| 1279 return _pendingUse.removeAll(MemberUse.CLOSURIZE_ONLY); | |
| 1280 } else if (hasRead) { | |
| 1281 hasInvoke = true; | |
| 1282 return _pendingUse.removeAll(MemberUse.NORMAL_ONLY); | |
| 1283 } else { | |
| 1284 hasRead = hasInvoke = true; | |
| 1285 return _pendingUse.removeAll(MemberUse.ALL); | |
| 1286 } | |
| 1287 } | |
| 1288 | |
| 1289 @override | |
| 1290 bool get fullyUsed => hasInvoke && hasRead; | |
| 1291 } | |
| 1292 | |
| 1293 class _GetterUsage extends MemberUsage { | |
| 1294 bool hasRead = false; | |
| 1295 | |
| 1296 _GetterUsage(FunctionEntity getter) : super.internal(getter); | |
| 1297 | |
| 1298 EnumSet<MemberUse> get _originalUse => MemberUse.NORMAL_ONLY; | |
| 1299 | |
| 1300 @override | |
| 1301 bool get fullyUsed => hasRead; | |
| 1302 | |
| 1303 @override | |
| 1304 EnumSet<MemberUse> read() { | |
| 1305 if (hasRead) { | |
| 1306 return MemberUse.NONE; | |
| 1307 } | |
| 1308 hasRead = true; | |
| 1309 return _pendingUse.removeAll(MemberUse.NORMAL_ONLY); | |
| 1310 } | |
| 1311 | |
| 1312 @override | |
| 1313 EnumSet<MemberUse> invoke() => read(); | |
| 1314 | |
| 1315 @override | |
| 1316 EnumSet<MemberUse> fullyUse() => read(); | |
| 1317 } | |
| 1318 | |
| 1319 class _SetterUsage extends MemberUsage { | |
| 1320 bool hasWrite = false; | |
| 1321 | |
| 1322 _SetterUsage(FunctionEntity setter) : super.internal(setter); | |
| 1323 | |
| 1324 EnumSet<MemberUse> get _originalUse => MemberUse.NORMAL_ONLY; | |
|
Harry Terkelsen
2016/12/05 22:48:53
maybe make _originalUse have a default NORMAL_ONLY
Johnni Winther
2016/12/06 09:28:06
Done.
| |
| 1325 | |
| 1326 @override | |
| 1327 bool get fullyUsed => hasWrite; | |
| 1328 | |
| 1329 @override | |
| 1330 EnumSet<MemberUse> write() { | |
| 1331 if (hasWrite) { | |
| 1332 return MemberUse.NONE; | |
| 1333 } | |
| 1334 hasWrite = true; | |
| 1335 return MemberUse.NORMAL_ONLY; | |
| 1336 } | |
| 1337 | |
| 1338 @override | |
| 1339 EnumSet<MemberUse> fullyUse() => write(); | |
| 1340 } | |
| 1341 | |
| 1342 /// Enum-like class for the possible kind of use of [MemberEntity] objects. | |
| 1343 class MemberUse { | |
|
Harry Terkelsen
2016/12/05 22:48:53
why not just use an actual enum? and move the stat
Johnni Winther
2016/12/06 09:28:06
Done.
| |
| 1344 final int index; | |
| 1345 | |
| 1346 const MemberUse._(this.index); | |
| 1347 | |
| 1348 static const List<MemberUse> values = const <MemberUse>[NORMAL, CLOSURIZE]; | |
| 1349 | |
| 1350 static const MemberUse NORMAL = const MemberUse._(0); | |
| 1351 static const MemberUse CLOSURIZE = const MemberUse._(1); | |
| 1352 | |
| 1353 static const EnumSet<MemberUse> NONE = const EnumSet<MemberUse>.fixed(0); | |
| 1354 static const EnumSet<MemberUse> NORMAL_ONLY = | |
| 1355 const EnumSet<MemberUse>.fixed(1); | |
| 1356 static const EnumSet<MemberUse> CLOSURIZE_ONLY = | |
| 1357 const EnumSet<MemberUse>.fixed(2); | |
| 1358 static const EnumSet<MemberUse> ALL = const EnumSet<MemberUse>.fixed(3); | |
| 1359 } | |
| 1360 | |
| 1361 typedef void MemberUsed(MemberEntity member, EnumSet<MemberUse> useSet); | |
| OLD | NEW |