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'; |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 365 */ | 365 */ |
| 366 final Set<FunctionElement> methodsNeedingSuperGetter = | 366 final Set<FunctionElement> methodsNeedingSuperGetter = |
| 367 new Set<FunctionElement>(); | 367 new Set<FunctionElement>(); |
| 368 final Map<String, Map<Selector, SelectorConstraints>> _invokedNames = | 368 final Map<String, Map<Selector, SelectorConstraints>> _invokedNames = |
| 369 <String, Map<Selector, SelectorConstraints>>{}; | 369 <String, Map<Selector, SelectorConstraints>>{}; |
| 370 final Map<String, Map<Selector, SelectorConstraints>> _invokedGetters = | 370 final Map<String, Map<Selector, SelectorConstraints>> _invokedGetters = |
| 371 <String, Map<Selector, SelectorConstraints>>{}; | 371 <String, Map<Selector, SelectorConstraints>>{}; |
| 372 final Map<String, Map<Selector, SelectorConstraints>> _invokedSetters = | 372 final Map<String, Map<Selector, SelectorConstraints>> _invokedSetters = |
| 373 <String, Map<Selector, SelectorConstraints>>{}; | 373 <String, Map<Selector, SelectorConstraints>>{}; |
| 374 | 374 |
| 375 final Map<ClassElement, _ClassUsage> _processedClasses = | |
| 376 <ClassElement, _ClassUsage>{}; | |
| 377 | |
| 375 /// Map of registers usage of instance members of live classes. | 378 /// Map of registers usage of instance members of live classes. |
| 376 final Map<MemberEntity, MemberUsage> _instanceMemberUsage = | 379 final Map<MemberEntity, _MemberUsage> _instanceMemberUsage = |
| 377 <MemberEntity, MemberUsage>{}; | 380 <MemberEntity, _MemberUsage>{}; |
| 378 | 381 |
| 379 /// Map containing instance members of live classes that are not yet live | 382 /// Map containing instance members of live classes that are not yet live |
| 380 /// themselves. | 383 /// themselves. |
| 381 final Map<String, Set<MemberUsage>> _instanceMembersByName = | 384 final Map<String, Set<_MemberUsage>> _instanceMembersByName = |
| 382 <String, Set<MemberUsage>>{}; | 385 <String, Set<_MemberUsage>>{}; |
| 383 | 386 |
| 384 /// Map containing instance methods of live classes that are not yet | 387 /// Map containing instance methods of live classes that are not yet |
| 385 /// closurized. | 388 /// closurized. |
| 386 final Map<String, Set<MemberUsage>> _instanceFunctionsByName = | 389 final Map<String, Set<_MemberUsage>> _instanceFunctionsByName = |
| 387 <String, Set<MemberUsage>>{}; | 390 <String, Set<_MemberUsage>>{}; |
| 388 | 391 |
| 389 /// Fields set. | 392 /// Fields set. |
| 390 final Set<Element> fieldSetters = new Set<Element>(); | 393 final Set<Element> fieldSetters = new Set<Element>(); |
| 391 final Set<DartType> isChecks = new Set<DartType>(); | 394 final Set<DartType> isChecks = new Set<DartType>(); |
| 392 | 395 |
| 393 /** | 396 /** |
| 394 * Set of (live) [:call:] methods whose signatures reference type variables. | 397 * Set of (live) [:call:] methods whose signatures reference type variables. |
| 395 * | 398 * |
| 396 * A live [:call:] method is one whose enclosing class has been instantiated. | 399 * A live [:call:] method is one whose enclosing class has been instantiated. |
| 397 */ | 400 */ |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 433 final Resolution _resolution; | 436 final Resolution _resolution; |
| 434 | 437 |
| 435 ResolutionWorldBuilderImpl(Backend backend, Resolution resolution, | 438 ResolutionWorldBuilderImpl(Backend backend, Resolution resolution, |
| 436 CacheStrategy cacheStrategy, this.selectorConstraintsStrategy) | 439 CacheStrategy cacheStrategy, this.selectorConstraintsStrategy) |
| 437 : this._backend = backend, | 440 : this._backend = backend, |
| 438 this._resolution = resolution { | 441 this._resolution = resolution { |
| 439 _openWorld = | 442 _openWorld = |
| 440 new WorldImpl(this, backend, resolution.coreClasses, cacheStrategy); | 443 new WorldImpl(this, backend, resolution.coreClasses, cacheStrategy); |
| 441 } | 444 } |
| 442 | 445 |
| 446 Iterable<ClassElement> get processedClasses => _processedClasses.keys | |
| 447 .where((cls) => _processedClasses[cls].isInstantiated); | |
| 448 | |
| 443 OpenWorld get openWorld => _openWorld; | 449 OpenWorld get openWorld => _openWorld; |
| 444 | 450 |
| 445 /// All directly instantiated classes, that is, classes with a generative | 451 /// All directly instantiated classes, that is, classes with a generative |
| 446 /// constructor that has been called directly and not only through a | 452 /// constructor that has been called directly and not only through a |
| 447 /// super-call. | 453 /// super-call. |
| 448 // TODO(johnniwinther): Improve semantic precision. | 454 // TODO(johnniwinther): Improve semantic precision. |
| 449 Iterable<ClassElement> get directlyInstantiatedClasses { | 455 Iterable<ClassElement> get directlyInstantiatedClasses { |
| 450 Set<ClassElement> classes = new Set<ClassElement>(); | 456 Set<ClassElement> classes = new Set<ClassElement>(); |
| 451 getInstantiationMap().forEach((ClassElement cls, InstantiationInfo info) { | 457 getInstantiationMap().forEach((ClassElement cls, InstantiationInfo info) { |
| 452 if (info.hasInstantiation) { | 458 if (info.hasInstantiation) { |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 483 bool isImplemented(ClassElement cls) { | 489 bool isImplemented(ClassElement cls) { |
| 484 return _implementedClasses.contains(cls.declaration); | 490 return _implementedClasses.contains(cls.declaration); |
| 485 } | 491 } |
| 486 | 492 |
| 487 /// Register [type] as (directly) instantiated. | 493 /// Register [type] as (directly) instantiated. |
| 488 /// | 494 /// |
| 489 /// If [byMirrors] is `true`, the instantiation is through mirrors. | 495 /// If [byMirrors] is `true`, the instantiation is through mirrors. |
| 490 // TODO(johnniwinther): Fully enforce the separation between exact, through | 496 // TODO(johnniwinther): Fully enforce the separation between exact, through |
| 491 // subclass and through subtype instantiated types/classes. | 497 // subclass and through subtype instantiated types/classes. |
| 492 // TODO(johnniwinther): Support unknown type arguments for generic types. | 498 // TODO(johnniwinther): Support unknown type arguments for generic types. |
| 493 void registerTypeInstantiation(InterfaceType type, | 499 void registerTypeInstantiation(InterfaceType type, ClassUsed classUsed, |
| 494 {ConstructorElement constructor, | 500 {ConstructorElement constructor, |
| 495 bool byMirrors: false, | 501 bool byMirrors: false, |
| 496 bool isNative: false, | 502 bool isRedirection: false}) { |
| 497 bool isRedirection: false, | |
| 498 void onImplemented(ClassElement cls)}) { | |
| 499 ClassElement cls = type.element; | 503 ClassElement cls = type.element; |
| 504 cls.ensureResolved(_resolution); | |
| 500 InstantiationInfo info = | 505 InstantiationInfo info = |
| 501 _instantiationInfo.putIfAbsent(cls, () => new InstantiationInfo()); | 506 _instantiationInfo.putIfAbsent(cls, () => new InstantiationInfo()); |
| 502 Instantiation kind = Instantiation.UNINSTANTIATED; | 507 Instantiation kind = Instantiation.UNINSTANTIATED; |
| 508 bool isNative = _backend.isNative(cls); | |
| 503 if (!cls.isAbstract | 509 if (!cls.isAbstract |
| 504 // We can't use the closed-world assumption with native abstract | 510 // We can't use the closed-world assumption with native abstract |
| 505 // classes; a native abstract class may have non-abstract subclasses | 511 // classes; a native abstract class may have non-abstract subclasses |
| 506 // not declared to the program. Instances of these classes are | 512 // not declared to the program. Instances of these classes are |
| 507 // indistinguishable from the abstract class. | 513 // indistinguishable from the abstract class. |
| 508 || | 514 || |
|
Harry Terkelsen
2016/12/05 23:18:12
nitpick: I've been moving these '||' to the end of
Johnni Winther
2016/12/06 09:58:42
Done.
| |
| 509 isNative | 515 isNative |
| 510 // Likewise, if this registration comes from the mirror system, | 516 // Likewise, if this registration comes from the mirror system, |
| 511 // all bets are off. | 517 // all bets are off. |
| 512 // TODO(herhut): Track classes required by mirrors seperately. | 518 // TODO(herhut): Track classes required by mirrors seperately. |
| 513 || | 519 || |
| 514 byMirrors) { | 520 byMirrors) { |
| 515 if (isNative || byMirrors) { | 521 if (isNative || byMirrors) { |
| 516 kind = Instantiation.ABSTRACTLY_INSTANTIATED; | 522 kind = Instantiation.ABSTRACTLY_INSTANTIATED; |
| 517 } else { | 523 } else { |
| 518 kind = Instantiation.DIRECTLY_INSTANTIATED; | 524 kind = Instantiation.DIRECTLY_INSTANTIATED; |
| 519 } | 525 } |
| 526 _processInstantiatedClass(cls, classUsed); | |
| 520 } | 527 } |
| 521 info.addInstantiation(constructor, type, kind, | 528 info.addInstantiation(constructor, type, kind, |
| 522 isRedirection: isRedirection); | 529 isRedirection: isRedirection); |
| 523 | 530 |
| 524 // TODO(johnniwinther): Use [_instantiationInfo] to compute this information | 531 // TODO(johnniwinther): Use [_instantiationInfo] to compute this information |
| 525 // instead. | 532 // instead. |
| 526 if (_implementedClasses.add(cls)) { | 533 if (_implementedClasses.add(cls)) { |
| 534 void onImplemented(ClassElement cls) { | |
| 535 _ClassUsage usage = _getClassUsage(cls); | |
| 536 classUsed(usage.cls, usage.implement()); | |
| 537 } | |
| 538 | |
| 527 onImplemented(cls); | 539 onImplemented(cls); |
| 528 cls.allSupertypes.forEach((InterfaceType supertype) { | 540 cls.allSupertypes.forEach((InterfaceType supertype) { |
| 529 if (_implementedClasses.add(supertype.element)) { | 541 if (_implementedClasses.add(supertype.element)) { |
| 530 onImplemented(supertype.element); | 542 onImplemented(supertype.element); |
| 531 } | 543 } |
| 532 }); | 544 }); |
| 533 } | 545 } |
| 534 } | 546 } |
| 535 | 547 |
| 536 @override | 548 @override |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 608 bool hasInvokedSetter(Element member) { | 620 bool hasInvokedSetter(Element member) { |
| 609 return _hasMatchingSelector(_invokedSetters[member.name], member); | 621 return _hasMatchingSelector(_invokedSetters[member.name], member); |
| 610 } | 622 } |
| 611 | 623 |
| 612 void registerDynamicUse(DynamicUse dynamicUse, MemberUsed memberUsed) { | 624 void registerDynamicUse(DynamicUse dynamicUse, MemberUsed memberUsed) { |
| 613 Selector selector = dynamicUse.selector; | 625 Selector selector = dynamicUse.selector; |
| 614 String methodName = selector.name; | 626 String methodName = selector.name; |
| 615 switch (dynamicUse.kind) { | 627 switch (dynamicUse.kind) { |
| 616 case DynamicUseKind.INVOKE: | 628 case DynamicUseKind.INVOKE: |
| 617 if (_registerNewSelector(dynamicUse, _invokedNames)) { | 629 if (_registerNewSelector(dynamicUse, _invokedNames)) { |
| 618 _processInstanceMembers(methodName, (MemberUsage usage) { | 630 _processInstanceMembers(methodName, (_MemberUsage usage) { |
| 619 if (dynamicUse.appliesUnnamed(usage.member, _openWorld)) { | 631 if (dynamicUse.appliesUnnamed(usage.entity, _openWorld)) { |
| 620 memberUsed(usage.member, usage.invoke()); | 632 memberUsed(usage.entity, usage.invoke()); |
| 621 return true; | 633 return true; |
| 622 } | 634 } |
| 623 return false; | 635 return false; |
| 624 }); | 636 }); |
| 625 } | 637 } |
| 626 break; | 638 break; |
| 627 case DynamicUseKind.GET: | 639 case DynamicUseKind.GET: |
| 628 if (_registerNewSelector(dynamicUse, _invokedGetters)) { | 640 if (_registerNewSelector(dynamicUse, _invokedGetters)) { |
| 629 _processInstanceMembers(methodName, (MemberUsage usage) { | 641 _processInstanceMembers(methodName, (_MemberUsage usage) { |
| 630 if (dynamicUse.appliesUnnamed(usage.member, _openWorld)) { | 642 if (dynamicUse.appliesUnnamed(usage.entity, _openWorld)) { |
| 631 memberUsed(usage.member, usage.read()); | 643 memberUsed(usage.entity, usage.read()); |
| 632 return true; | 644 return true; |
| 633 } | 645 } |
| 634 return false; | 646 return false; |
| 635 }); | 647 }); |
| 636 _processInstanceFunctions(methodName, (MemberUsage usage) { | 648 _processInstanceFunctions(methodName, (_MemberUsage usage) { |
| 637 if (dynamicUse.appliesUnnamed(usage.member, _openWorld)) { | 649 if (dynamicUse.appliesUnnamed(usage.entity, _openWorld)) { |
| 638 memberUsed(usage.member, usage.read()); | 650 memberUsed(usage.entity, usage.read()); |
| 639 return true; | 651 return true; |
| 640 } | 652 } |
| 641 return false; | 653 return false; |
| 642 }); | 654 }); |
| 643 } | 655 } |
| 644 break; | 656 break; |
| 645 case DynamicUseKind.SET: | 657 case DynamicUseKind.SET: |
| 646 if (_registerNewSelector(dynamicUse, _invokedSetters)) { | 658 if (_registerNewSelector(dynamicUse, _invokedSetters)) { |
| 647 _processInstanceMembers(methodName, (MemberUsage usage) { | 659 _processInstanceMembers(methodName, (_MemberUsage usage) { |
| 648 if (dynamicUse.appliesUnnamed(usage.member, _openWorld)) { | 660 if (dynamicUse.appliesUnnamed(usage.entity, _openWorld)) { |
| 649 memberUsed(usage.member, usage.write()); | 661 memberUsed(usage.entity, usage.write()); |
| 650 return true; | 662 return true; |
| 651 } | 663 } |
| 652 return false; | 664 return false; |
| 653 }); | 665 }); |
| 654 } | 666 } |
| 655 break; | 667 break; |
| 656 } | 668 } |
| 657 } | 669 } |
| 658 | 670 |
| 659 bool _registerNewSelector(DynamicUse dynamicUse, | 671 bool _registerNewSelector(DynamicUse dynamicUse, |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 711 } | 723 } |
| 712 } | 724 } |
| 713 | 725 |
| 714 void forgetElement(Element element, Compiler compiler) { | 726 void forgetElement(Element element, Compiler compiler) { |
| 715 allClosures.remove(element); | 727 allClosures.remove(element); |
| 716 slowDirectlyNestedClosures(element).forEach(compiler.forgetElement); | 728 slowDirectlyNestedClosures(element).forEach(compiler.forgetElement); |
| 717 closurizedMembers.remove(element); | 729 closurizedMembers.remove(element); |
| 718 fieldSetters.remove(element); | 730 fieldSetters.remove(element); |
| 719 _instantiationInfo.remove(element); | 731 _instantiationInfo.remove(element); |
| 720 | 732 |
| 721 void removeUsage(Set<MemberUsage> set, Element element) { | 733 void removeUsage(Set<_MemberUsage> set, Element element) { |
| 722 if (set == null) return; | 734 if (set == null) return; |
| 723 set.removeAll( | 735 set.removeAll( |
| 724 set.where((MemberUsage usage) => usage.member == element).toList()); | 736 set.where((_MemberUsage usage) => usage.entity == element).toList()); |
| 725 } | 737 } |
| 726 | 738 |
| 739 _processedClasses.remove(element); | |
| 727 removeUsage(_instanceMembersByName[element.name], element); | 740 removeUsage(_instanceMembersByName[element.name], element); |
| 728 removeUsage(_instanceFunctionsByName[element.name], element); | 741 removeUsage(_instanceFunctionsByName[element.name], element); |
| 729 } | 742 } |
| 730 | 743 |
| 731 // TODO(ahe): Replace this method with something that is O(1), for example, | 744 // TODO(ahe): Replace this method with something that is O(1), for example, |
| 732 // by using a map. | 745 // by using a map. |
| 733 List<LocalFunctionElement> slowDirectlyNestedClosures(Element element) { | 746 List<LocalFunctionElement> slowDirectlyNestedClosures(Element element) { |
| 734 // Return new list to guard against concurrent modifications. | 747 // Return new list to guard against concurrent modifications. |
| 735 return new List<LocalFunctionElement>.from( | 748 return new List<LocalFunctionElement>.from( |
| 736 allClosures.where((LocalFunctionElement closure) { | 749 allClosures.where((LocalFunctionElement closure) { |
| 737 return closure.executableContext == element; | 750 return closure.executableContext == element; |
| 738 })); | 751 })); |
| 739 } | 752 } |
| 740 | 753 |
| 741 void _processSet(Map<String, Set<MemberUsage>> map, String memberName, | 754 /// Return the canonical [_ClassUsage] for [cls]. |
| 742 bool f(MemberUsage e)) { | 755 _ClassUsage _getClassUsage(ClassElement cls) { |
| 743 Set<MemberUsage> members = map[memberName]; | 756 return _processedClasses.putIfAbsent(cls, () { |
| 757 cls.ensureResolved(_resolution); | |
| 758 _ClassUsage usage = new _ClassUsage(cls); | |
| 759 _resolution.ensureClassMembers(cls); | |
| 760 return usage; | |
| 761 }); | |
| 762 } | |
| 763 | |
| 764 /// Register [cls] and all its superclasses as instantiated. | |
| 765 void _processInstantiatedClass(ClassElement cls, ClassUsed classUsed) { | |
| 766 bool processClass(ClassElement superclass) { | |
| 767 _ClassUsage usage = _getClassUsage(superclass); | |
| 768 if (!usage.isInstantiated) { | |
| 769 classUsed(usage.cls, usage.instantiate()); | |
| 770 return true; | |
| 771 } | |
| 772 return false; | |
| 773 } | |
| 774 | |
| 775 while (cls != null && processClass(cls)) { | |
|
Harry Terkelsen
2016/12/05 23:18:12
is the assumption that we stop going up the superc
Johnni Winther
2016/12/06 09:58:42
Yes. Added as comment.
| |
| 776 cls = cls.superclass; | |
| 777 } | |
| 778 } | |
| 779 | |
| 780 /// Computes usage for all members declared by [cls]. Calls [membersUsed] with | |
| 781 /// the usage changes for each member. | |
| 782 void processClassMembers(ClassElement cls, MemberUsed memberUsed) { | |
| 783 cls.implementation.forEachMember((ClassElement cls, MemberElement member) { | |
| 784 _processInstantiatedClassMember(cls, member, memberUsed); | |
| 785 }); | |
| 786 } | |
| 787 | |
| 788 void _processSet(Map<String, Set<_MemberUsage>> map, String memberName, | |
| 789 bool f(_MemberUsage e)) { | |
| 790 Set<_MemberUsage> members = map[memberName]; | |
| 744 if (members == null) return; | 791 if (members == null) return; |
| 745 // [f] might add elements to [: map[memberName] :] during the loop below | 792 // [f] might add elements to [: map[memberName] :] during the loop below |
| 746 // so we create a new list for [: map[memberName] :] and prepend the | 793 // so we create a new list for [: map[memberName] :] and prepend the |
| 747 // [remaining] members after the loop. | 794 // [remaining] members after the loop. |
| 748 map[memberName] = new Set<MemberUsage>(); | 795 map[memberName] = new Set<_MemberUsage>(); |
| 749 Set<MemberUsage> remaining = new Set<MemberUsage>(); | 796 Set<_MemberUsage> remaining = new Set<_MemberUsage>(); |
| 750 for (MemberUsage usage in members) { | 797 for (_MemberUsage usage in members) { |
| 751 if (!f(usage)) remaining.add(usage); | 798 if (!f(usage)) remaining.add(usage); |
| 752 } | 799 } |
| 753 map[memberName].addAll(remaining); | 800 map[memberName].addAll(remaining); |
| 754 } | 801 } |
| 755 | 802 |
| 756 void _processInstanceMembers(String n, bool f(MemberUsage e)) { | 803 void _processInstanceMembers(String name, bool f(_MemberUsage e)) { |
| 757 _processSet(_instanceMembersByName, n, f); | 804 _processSet(_instanceMembersByName, name, f); |
| 758 } | 805 } |
| 759 | 806 |
| 760 void _processInstanceFunctions(String n, bool f(MemberUsage e)) { | 807 void _processInstanceFunctions(String n, bool f(_MemberUsage e)) { |
| 761 _processSet(_instanceFunctionsByName, n, f); | 808 _processSet(_instanceFunctionsByName, n, f); |
| 762 } | 809 } |
| 763 | 810 |
| 764 // TODO(johnniwinther): Make this private when | 811 void _processInstantiatedClassMember( |
| 765 // [ResolutionEnqueuer._processClass] is move to [ResolutionWorldBuilderImpl]. | |
| 766 void processInstantiatedClassMember( | |
| 767 ClassElement cls, MemberElement member, MemberUsed memberUsed) { | 812 ClassElement cls, MemberElement member, MemberUsed memberUsed) { |
| 768 assert(invariant(member, member.isDeclaration)); | 813 assert(invariant(member, member.isDeclaration)); |
| 769 if (!member.isInstanceMember) return; | 814 if (!member.isInstanceMember) return; |
| 770 String memberName = member.name; | 815 String memberName = member.name; |
| 771 member.computeType(_resolution); | 816 member.computeType(_resolution); |
| 772 EnumSet<MemberUse> useSet = new EnumSet<MemberUse>(); | 817 EnumSet<MemberUse> useSet = new EnumSet<MemberUse>(); |
| 773 // The obvious thing to test here would be "member.isNative", | 818 // The obvious thing to test here would be "member.isNative", |
| 774 // however, that only works after metadata has been parsed/analyzed, | 819 // however, that only works after metadata has been parsed/analyzed, |
| 775 // and that may not have happened yet. | 820 // and that may not have happened yet. |
| 776 // So instead we use the enclosing class, which we know have had | 821 // So instead we use the enclosing class, which we know have had |
| 777 // its metadata parsed and analyzed. | 822 // its metadata parsed and analyzed. |
| 778 // Note: this assumes that there are no non-native fields on native | 823 // 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. | 824 // classes, which may not be the case when a native class is subclassed. |
| 780 bool isNative = _backend.isNative(cls); | 825 bool isNative = _backend.isNative(cls); |
| 781 MemberUsage usage = _instanceMemberUsage.putIfAbsent(member, () { | 826 _MemberUsage usage = _instanceMemberUsage.putIfAbsent(member, () { |
| 782 MemberUsage usage = new MemberUsage(member, isNative: isNative); | 827 _MemberUsage usage = new _MemberUsage(member, isNative: isNative); |
| 783 useSet.addAll(usage.appliedUse); | 828 useSet.addAll(usage.appliedUse); |
| 784 if (member.isField && isNative) { | 829 if (member.isField && isNative) { |
| 785 _openWorld.registerUsedElement(member); | 830 _openWorld.registerUsedElement(member); |
| 786 } | 831 } |
| 787 | 832 |
| 788 if (_hasInvokedGetter(member)) { | 833 if (_hasInvokedGetter(member)) { |
| 789 useSet.addAll(usage.read()); | 834 useSet.addAll(usage.read()); |
| 790 } | 835 } |
| 791 if (_hasInvocation(member)) { | 836 if (_hasInvocation(member)) { |
| 792 useSet.addAll(usage.invoke()); | 837 useSet.addAll(usage.invoke()); |
| 793 } | 838 } |
| 794 if (hasInvokedSetter(member)) { | 839 if (hasInvokedSetter(member)) { |
| 795 useSet.addAll(usage.write()); | 840 useSet.addAll(usage.write()); |
| 796 } | 841 } |
| 797 | 842 |
| 798 if (usage.pendingUse.contains(MemberUse.NORMAL)) { | 843 if (usage.pendingUse.contains(MemberUse.NORMAL)) { |
| 799 // The element is not yet used. Add it to the list of instance | 844 // The element is not yet used. Add it to the list of instance |
| 800 // members to still be processed. | 845 // members to still be processed. |
| 801 _instanceMembersByName | 846 _instanceMembersByName |
| 802 .putIfAbsent(memberName, () => new Set<MemberUsage>()) | 847 .putIfAbsent(memberName, () => new Set<_MemberUsage>()) |
| 803 .add(usage); | 848 .add(usage); |
| 804 } | 849 } |
| 805 if (usage.pendingUse.contains(MemberUse.CLOSURIZE)) { | 850 if (usage.pendingUse.contains(MemberUse.CLOSURIZE)) { |
| 806 // Store the member in [instanceFunctionsByName] to catch | 851 // Store the member in [instanceFunctionsByName] to catch |
| 807 // getters on the function. | 852 // getters on the function. |
| 808 _instanceFunctionsByName | 853 _instanceFunctionsByName |
| 809 .putIfAbsent(memberName, () => new Set<MemberUsage>()) | 854 .putIfAbsent(memberName, () => new Set<_MemberUsage>()) |
| 810 .add(usage); | 855 .add(usage); |
| 811 } | 856 } |
| 812 | 857 |
| 813 memberUsed(usage.member, useSet); | 858 memberUsed(usage.entity, useSet); |
| 814 return usage; | 859 return usage; |
| 815 }); | 860 }); |
| 816 } | 861 } |
| 817 } | 862 } |
| 818 | 863 |
| 819 /// World builder specific to codegen. | 864 /// World builder specific to codegen. |
| 820 /// | 865 /// |
| 821 /// This adds additional access to liveness of selectors and elements. | 866 /// This adds additional access to liveness of selectors and elements. |
| 822 abstract class CodegenWorldBuilder implements WorldBuilder { | 867 abstract class CodegenWorldBuilder implements WorldBuilder { |
| 823 void forEachInvokedName( | 868 void forEachInvokedName( |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1073 void forgetElement(Element element, Compiler compiler) { | 1118 void forgetElement(Element element, Compiler compiler) { |
| 1074 _directlyInstantiatedClasses.remove(element); | 1119 _directlyInstantiatedClasses.remove(element); |
| 1075 if (element is ClassElement) { | 1120 if (element is ClassElement) { |
| 1076 assert(invariant(element, element.thisType.isRaw, | 1121 assert(invariant(element, element.thisType.isRaw, |
| 1077 message: 'Generic classes not supported (${element.thisType}).')); | 1122 message: 'Generic classes not supported (${element.thisType}).')); |
| 1078 _instantiatedTypes..remove(element.rawType)..remove(element.thisType); | 1123 _instantiatedTypes..remove(element.rawType)..remove(element.thisType); |
| 1079 } | 1124 } |
| 1080 } | 1125 } |
| 1081 } | 1126 } |
| 1082 | 1127 |
| 1083 /// Registry for the observed use of [member] in the open world. | 1128 abstract class _AbstractUsage<T> { |
| 1084 abstract class MemberUsage { | 1129 final EnumSet<T> _pendingUse = new EnumSet<T>(); |
| 1085 // TODO(johnniwinther): Change [Entity] to [MemberEntity]. | |
| 1086 final Entity member; | |
| 1087 final EnumSet<MemberUse> _pendingUse = new EnumSet<MemberUse>(); | |
| 1088 | 1130 |
| 1089 MemberUsage.internal(this.member) { | 1131 _AbstractUsage() { |
| 1090 _pendingUse.addAll(_originalUse); | 1132 _pendingUse.addAll(_originalUse); |
| 1091 } | 1133 } |
| 1092 | 1134 |
| 1093 factory MemberUsage(MemberEntity member, {bool isNative: false}) { | 1135 /// Returns the possible uses of [entity] that have not yet been registered. |
| 1136 EnumSet<T> get pendingUse => _pendingUse; | |
| 1137 | |
| 1138 /// Returns the uses of [entity] that have been registered. | |
| 1139 EnumSet<T> get appliedUse => _originalUse.minus(_pendingUse); | |
| 1140 | |
| 1141 EnumSet<T> get _originalUse; | |
| 1142 } | |
| 1143 | |
| 1144 /// Registry for the observed use of a member [entity] in the open world. | |
| 1145 abstract class _MemberUsage extends _AbstractUsage<MemberUse> { | |
| 1146 // TODO(johnniwinther): Change [Entity] to [MemberEntity]. | |
| 1147 final Entity entity; | |
| 1148 | |
| 1149 _MemberUsage.internal(this.entity); | |
| 1150 | |
| 1151 factory _MemberUsage(MemberEntity member, {bool isNative: false}) { | |
| 1094 if (member.isField) { | 1152 if (member.isField) { |
| 1095 if (member.isAssignable) { | 1153 if (member.isAssignable) { |
| 1096 return new _FieldUsage(member, isNative: isNative); | 1154 return new _FieldUsage(member, isNative: isNative); |
| 1097 } else { | 1155 } else { |
| 1098 return new _FinalFieldUsage(member, isNative: isNative); | 1156 return new _FinalFieldUsage(member, isNative: isNative); |
| 1099 } | 1157 } |
| 1100 } else if (member.isGetter) { | 1158 } else if (member.isGetter) { |
| 1101 return new _GetterUsage(member); | 1159 return new _GetterUsage(member); |
| 1102 } else if (member.isSetter) { | 1160 } else if (member.isSetter) { |
| 1103 return new _SetterUsage(member); | 1161 return new _SetterUsage(member); |
| 1104 } else { | 1162 } else { |
| 1105 assert(member.isFunction); | 1163 assert(member.isFunction); |
| 1106 return new _FunctionUsage(member); | 1164 return new _FunctionUsage(member); |
| 1107 } | 1165 } |
| 1108 } | 1166 } |
| 1109 | 1167 |
| 1110 /// `true` if [member] has be read as a value. For a field this is a normal | 1168 /// `true` if [entity] has be read as a value. For a field this is a normal |
| 1111 /// read access, for a function this is a closurization. | 1169 /// read access, for a function this is a closurization. |
| 1112 bool get hasRead => false; | 1170 bool get hasRead => false; |
| 1113 | 1171 |
| 1114 /// `true` if a value as been written to [member]. | 1172 /// `true` if a value as been written to [entity]. |
| 1115 bool get hasWrite => false; | 1173 bool get hasWrite => false; |
| 1116 | 1174 |
| 1117 /// `true` if an invocation has been performed on the value [member]. For a | 1175 /// `true` if an invocation has been performed on the value [entity]. For a |
| 1118 /// function this is a normal invocation, for a field this is a read access | 1176 /// function this is a normal invocation, for a field this is a read access |
| 1119 /// followed by an invocation of the function-like value. | 1177 /// followed by an invocation of the function-like value. |
| 1120 bool get hasInvoke => false; | 1178 bool get hasInvoke => false; |
| 1121 | 1179 |
| 1122 /// `true` if [member] has been used in all the ways possible. | 1180 /// `true` if [entity] has been used in all the ways possible. |
| 1123 bool get fullyUsed; | 1181 bool get fullyUsed; |
| 1124 | 1182 |
| 1125 /// Registers a read of the value of [member] and returns the new [MemberUse]s | 1183 /// Registers a read of the value of [entity] and returns the new [MemberUse]s |
| 1126 /// that it caused. | 1184 /// that it caused. |
| 1127 /// | 1185 /// |
| 1128 /// For a field this is a normal read access, for a function this is a | 1186 /// For a field this is a normal read access, for a function this is a |
| 1129 /// closurization. | 1187 /// closurization. |
| 1130 EnumSet<MemberUse> read() => MemberUse.NONE; | 1188 EnumSet<MemberUse> read() => MemberUse.NONE; |
| 1131 | 1189 |
| 1132 /// Registers a write of a value to [member] and returns the new [MemberUse]s | 1190 /// Registers a write of a value to [entity] and returns the new [MemberUse]s |
| 1133 /// that it caused. | 1191 /// that it caused. |
| 1134 EnumSet<MemberUse> write() => MemberUse.NONE; | 1192 EnumSet<MemberUse> write() => MemberUse.NONE; |
| 1135 | 1193 |
| 1136 /// Registers an invocation on the value of [member] and returns the new | 1194 /// Registers an invocation on the value of [entity] and returns the new |
| 1137 /// [MemberUse]s that it caused. | 1195 /// [MemberUse]s that it caused. |
| 1138 /// | 1196 /// |
| 1139 /// For a function this is a normal invocation, for a field this is a read | 1197 /// 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. | 1198 /// access followed by an invocation of the function-like value. |
| 1141 EnumSet<MemberUse> invoke() => MemberUse.NONE; | 1199 EnumSet<MemberUse> invoke() => MemberUse.NONE; |
| 1142 | 1200 |
| 1143 /// Registers all possible uses of [member] and returns the new [MemberUse]s | 1201 /// Registers all possible uses of [entity] and returns the new [MemberUse]s |
| 1144 /// that it caused. | 1202 /// that it caused. |
| 1145 EnumSet<MemberUse> fullyUse() => MemberUse.NONE; | 1203 EnumSet<MemberUse> fullyUse() => MemberUse.NONE; |
| 1146 | 1204 |
| 1147 /// Returns the possible [MemberUse]s of [member] that have not yet been | 1205 int get hashCode => entity.hashCode; |
| 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 | 1206 |
| 1158 bool operator ==(other) { | 1207 bool operator ==(other) { |
| 1159 if (identical(this, other)) return true; | 1208 if (identical(this, other)) return true; |
| 1160 if (other is! MemberUsage) return false; | 1209 if (other is! _MemberUsage) return false; |
| 1161 return member == other.member; | 1210 return entity == other.entity; |
| 1162 } | 1211 } |
| 1163 | 1212 |
| 1164 String toString() => member.toString(); | 1213 String toString() => entity.toString(); |
| 1165 } | 1214 } |
| 1166 | 1215 |
| 1167 class _FieldUsage extends MemberUsage { | 1216 class _FieldUsage extends _MemberUsage { |
| 1168 bool hasRead = false; | 1217 bool hasRead = false; |
| 1169 bool hasWrite = false; | 1218 bool hasWrite = false; |
| 1170 | 1219 |
| 1171 _FieldUsage(FieldEntity field, {bool isNative: false}) | 1220 _FieldUsage(FieldEntity field, {bool isNative: false}) |
| 1172 : super.internal(field) { | 1221 : super.internal(field) { |
| 1173 if (!isNative) { | 1222 if (!isNative) { |
| 1174 // All field initializers must be resolved as they could | 1223 // All field initializers must be resolved as they could |
| 1175 // have an observable side-effect (and cannot be tree-shaken | 1224 // have an observable side-effect (and cannot be tree-shaken |
| 1176 // away). | 1225 // away). |
| 1177 fullyUse(); | 1226 fullyUse(); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 1207 @override | 1256 @override |
| 1208 EnumSet<MemberUse> fullyUse() { | 1257 EnumSet<MemberUse> fullyUse() { |
| 1209 if (fullyUsed) { | 1258 if (fullyUsed) { |
| 1210 return MemberUse.NONE; | 1259 return MemberUse.NONE; |
| 1211 } | 1260 } |
| 1212 hasRead = hasWrite = true; | 1261 hasRead = hasWrite = true; |
| 1213 return _pendingUse.removeAll(MemberUse.NORMAL_ONLY); | 1262 return _pendingUse.removeAll(MemberUse.NORMAL_ONLY); |
| 1214 } | 1263 } |
| 1215 } | 1264 } |
| 1216 | 1265 |
| 1217 class _FinalFieldUsage extends MemberUsage { | 1266 class _FinalFieldUsage extends _MemberUsage { |
| 1218 bool hasRead = false; | 1267 bool hasRead = false; |
| 1219 | 1268 |
| 1220 _FinalFieldUsage(FieldEntity field, {bool isNative: false}) | 1269 _FinalFieldUsage(FieldEntity field, {bool isNative: false}) |
| 1221 : super.internal(field) { | 1270 : super.internal(field) { |
| 1222 if (!isNative) { | 1271 if (!isNative) { |
| 1223 // All field initializers must be resolved as they could | 1272 // All field initializers must be resolved as they could |
| 1224 // have an observable side-effect (and cannot be tree-shaken | 1273 // have an observable side-effect (and cannot be tree-shaken |
| 1225 // away). | 1274 // away). |
| 1226 read(); | 1275 read(); |
| 1227 } | 1276 } |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1241 return _pendingUse.removeAll(MemberUse.NORMAL_ONLY); | 1290 return _pendingUse.removeAll(MemberUse.NORMAL_ONLY); |
| 1242 } | 1291 } |
| 1243 | 1292 |
| 1244 @override | 1293 @override |
| 1245 EnumSet<MemberUse> invoke() => read(); | 1294 EnumSet<MemberUse> invoke() => read(); |
| 1246 | 1295 |
| 1247 @override | 1296 @override |
| 1248 EnumSet<MemberUse> fullyUse() => read(); | 1297 EnumSet<MemberUse> fullyUse() => read(); |
| 1249 } | 1298 } |
| 1250 | 1299 |
| 1251 class _FunctionUsage extends MemberUsage { | 1300 class _FunctionUsage extends _MemberUsage { |
| 1252 bool hasInvoke = false; | 1301 bool hasInvoke = false; |
| 1253 bool hasRead = false; | 1302 bool hasRead = false; |
| 1254 | 1303 |
| 1255 _FunctionUsage(FunctionEntity function) : super.internal(function); | 1304 _FunctionUsage(FunctionEntity function) : super.internal(function); |
| 1256 | 1305 |
| 1257 EnumSet<MemberUse> get _originalUse => MemberUse.ALL; | 1306 EnumSet<MemberUse> get _originalUse => MemberUse.ALL; |
| 1258 | 1307 |
| 1259 @override | 1308 @override |
| 1260 EnumSet<MemberUse> read() => fullyUse(); | 1309 EnumSet<MemberUse> read() => fullyUse(); |
| 1261 | 1310 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1283 } else { | 1332 } else { |
| 1284 hasRead = hasInvoke = true; | 1333 hasRead = hasInvoke = true; |
| 1285 return _pendingUse.removeAll(MemberUse.ALL); | 1334 return _pendingUse.removeAll(MemberUse.ALL); |
| 1286 } | 1335 } |
| 1287 } | 1336 } |
| 1288 | 1337 |
| 1289 @override | 1338 @override |
| 1290 bool get fullyUsed => hasInvoke && hasRead; | 1339 bool get fullyUsed => hasInvoke && hasRead; |
| 1291 } | 1340 } |
| 1292 | 1341 |
| 1293 class _GetterUsage extends MemberUsage { | 1342 class _GetterUsage extends _MemberUsage { |
| 1294 bool hasRead = false; | 1343 bool hasRead = false; |
| 1295 | 1344 |
| 1296 _GetterUsage(FunctionEntity getter) : super.internal(getter); | 1345 _GetterUsage(FunctionEntity getter) : super.internal(getter); |
| 1297 | 1346 |
| 1298 EnumSet<MemberUse> get _originalUse => MemberUse.NORMAL_ONLY; | 1347 EnumSet<MemberUse> get _originalUse => MemberUse.NORMAL_ONLY; |
| 1299 | 1348 |
| 1300 @override | 1349 @override |
| 1301 bool get fullyUsed => hasRead; | 1350 bool get fullyUsed => hasRead; |
| 1302 | 1351 |
| 1303 @override | 1352 @override |
| 1304 EnumSet<MemberUse> read() { | 1353 EnumSet<MemberUse> read() { |
| 1305 if (hasRead) { | 1354 if (hasRead) { |
| 1306 return MemberUse.NONE; | 1355 return MemberUse.NONE; |
| 1307 } | 1356 } |
| 1308 hasRead = true; | 1357 hasRead = true; |
| 1309 return _pendingUse.removeAll(MemberUse.NORMAL_ONLY); | 1358 return _pendingUse.removeAll(MemberUse.NORMAL_ONLY); |
| 1310 } | 1359 } |
| 1311 | 1360 |
| 1312 @override | 1361 @override |
| 1313 EnumSet<MemberUse> invoke() => read(); | 1362 EnumSet<MemberUse> invoke() => read(); |
| 1314 | 1363 |
| 1315 @override | 1364 @override |
| 1316 EnumSet<MemberUse> fullyUse() => read(); | 1365 EnumSet<MemberUse> fullyUse() => read(); |
| 1317 } | 1366 } |
| 1318 | 1367 |
| 1319 class _SetterUsage extends MemberUsage { | 1368 class _SetterUsage extends _MemberUsage { |
| 1320 bool hasWrite = false; | 1369 bool hasWrite = false; |
| 1321 | 1370 |
| 1322 _SetterUsage(FunctionEntity setter) : super.internal(setter); | 1371 _SetterUsage(FunctionEntity setter) : super.internal(setter); |
| 1323 | 1372 |
| 1324 EnumSet<MemberUse> get _originalUse => MemberUse.NORMAL_ONLY; | 1373 EnumSet<MemberUse> get _originalUse => MemberUse.NORMAL_ONLY; |
| 1325 | 1374 |
| 1326 @override | 1375 @override |
| 1327 bool get fullyUsed => hasWrite; | 1376 bool get fullyUsed => hasWrite; |
| 1328 | 1377 |
| 1329 @override | 1378 @override |
| 1330 EnumSet<MemberUse> write() { | 1379 EnumSet<MemberUse> write() { |
| 1331 if (hasWrite) { | 1380 if (hasWrite) { |
| 1332 return MemberUse.NONE; | 1381 return MemberUse.NONE; |
| 1333 } | 1382 } |
| 1334 hasWrite = true; | 1383 hasWrite = true; |
| 1335 return MemberUse.NORMAL_ONLY; | 1384 return MemberUse.NORMAL_ONLY; |
| 1336 } | 1385 } |
| 1337 | 1386 |
| 1338 @override | 1387 @override |
| 1339 EnumSet<MemberUse> fullyUse() => write(); | 1388 EnumSet<MemberUse> fullyUse() => write(); |
| 1340 } | 1389 } |
| 1341 | 1390 |
| 1342 /// Enum-like class for the possible kind of use of [MemberEntity] objects. | 1391 /// Enum-like class for the possible kind of use of [MemberEntity] objects. |
| 1343 class MemberUse { | 1392 class MemberUse { |
| 1344 final int index; | 1393 final int index; |
| 1345 | 1394 |
| 1346 const MemberUse._(this.index); | 1395 const MemberUse._(this.index); |
| 1347 | 1396 |
| 1397 String toString() => 'MemberUse($index)'; | |
| 1398 | |
| 1348 static const List<MemberUse> values = const <MemberUse>[NORMAL, CLOSURIZE]; | 1399 static const List<MemberUse> values = const <MemberUse>[NORMAL, CLOSURIZE]; |
| 1349 | 1400 |
| 1350 static const MemberUse NORMAL = const MemberUse._(0); | 1401 static const MemberUse NORMAL = const MemberUse._(0); |
| 1351 static const MemberUse CLOSURIZE = const MemberUse._(1); | 1402 static const MemberUse CLOSURIZE = const MemberUse._(1); |
| 1352 | 1403 |
| 1353 static const EnumSet<MemberUse> NONE = const EnumSet<MemberUse>.fixed(0); | 1404 static const EnumSet<MemberUse> NONE = const EnumSet<MemberUse>.fixed(0); |
| 1354 static const EnumSet<MemberUse> NORMAL_ONLY = | 1405 static const EnumSet<MemberUse> NORMAL_ONLY = |
| 1355 const EnumSet<MemberUse>.fixed(1); | 1406 const EnumSet<MemberUse>.fixed(1); |
| 1356 static const EnumSet<MemberUse> CLOSURIZE_ONLY = | 1407 static const EnumSet<MemberUse> CLOSURIZE_ONLY = |
| 1357 const EnumSet<MemberUse>.fixed(2); | 1408 const EnumSet<MemberUse>.fixed(2); |
| 1358 static const EnumSet<MemberUse> ALL = const EnumSet<MemberUse>.fixed(3); | 1409 static const EnumSet<MemberUse> ALL = const EnumSet<MemberUse>.fixed(3); |
| 1359 } | 1410 } |
| 1360 | 1411 |
| 1361 typedef void MemberUsed(MemberEntity member, EnumSet<MemberUse> useSet); | 1412 typedef void MemberUsed(MemberEntity member, EnumSet<MemberUse> useSet); |
| 1413 | |
| 1414 /// Registry for the observed use of a class [entity] in the open world. | |
| 1415 // TODO(johnniwinther): Merge this with [InstantiationInfo]. | |
| 1416 class _ClassUsage extends _AbstractUsage<ClassUse> { | |
| 1417 bool isInstantiated = false; | |
| 1418 bool isImplemented = false; | |
| 1419 | |
| 1420 final ClassEntity cls; | |
| 1421 | |
| 1422 _ClassUsage(this.cls); | |
| 1423 | |
| 1424 EnumSet<ClassUse> instantiate() { | |
| 1425 if (isInstantiated) { | |
| 1426 return ClassUse.NONE; | |
| 1427 } | |
| 1428 isInstantiated = true; | |
| 1429 return _pendingUse.removeAll(ClassUse.INSTANTIATED_ONLY); | |
| 1430 } | |
| 1431 | |
| 1432 EnumSet<ClassUse> implement() { | |
| 1433 if (isImplemented) { | |
| 1434 return ClassUse.NONE; | |
| 1435 } | |
| 1436 isImplemented = true; | |
| 1437 return _pendingUse.removeAll(ClassUse.IMPLEMENTED_ONLY); | |
| 1438 } | |
| 1439 | |
| 1440 @override | |
| 1441 EnumSet<ClassUse> get _originalUse => ClassUse.ALL; | |
| 1442 | |
| 1443 String toString() => cls.toString(); | |
| 1444 } | |
| 1445 | |
| 1446 /// Enum-like class for the possible kind of use of [ClassEntity] objects. | |
| 1447 class ClassUse { | |
|
Harry Terkelsen
2016/12/05 23:18:12
same comment as with MemberUse, can't this be an e
Johnni Winther
2016/12/06 09:58:42
Done.
| |
| 1448 final int index; | |
| 1449 | |
| 1450 const ClassUse._(this.index); | |
| 1451 | |
| 1452 String toString() => 'ClassUse($index)'; | |
| 1453 | |
| 1454 static const List<ClassUse> values = const <ClassUse>[ | |
| 1455 INSTANTIATED, | |
| 1456 IMPLEMENTED | |
| 1457 ]; | |
| 1458 | |
| 1459 static const ClassUse INSTANTIATED = const ClassUse._(0); | |
| 1460 static const ClassUse IMPLEMENTED = const ClassUse._(1); | |
| 1461 | |
| 1462 static const EnumSet<ClassUse> NONE = const EnumSet<ClassUse>.fixed(0); | |
| 1463 static const EnumSet<ClassUse> INSTANTIATED_ONLY = | |
| 1464 const EnumSet<ClassUse>.fixed(1); | |
| 1465 static const EnumSet<ClassUse> IMPLEMENTED_ONLY = | |
| 1466 const EnumSet<ClassUse>.fixed(2); | |
| 1467 static const EnumSet<ClassUse> ALL = const EnumSet<ClassUse>.fixed(3); | |
| 1468 } | |
| 1469 | |
| 1470 typedef void ClassUsed(ClassEntity cls, EnumSet<ClassUse> useSet); | |
| OLD | NEW |