| 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 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 518 kind = Instantiation.DIRECTLY_INSTANTIATED; | 518 kind = Instantiation.DIRECTLY_INSTANTIATED; |
| 519 } | 519 } |
| 520 _processInstantiatedClass(cls, classUsed); | 520 _processInstantiatedClass(cls, classUsed); |
| 521 } | 521 } |
| 522 info.addInstantiation(constructor, type, kind, | 522 info.addInstantiation(constructor, type, kind, |
| 523 isRedirection: isRedirection); | 523 isRedirection: isRedirection); |
| 524 | 524 |
| 525 // TODO(johnniwinther): Use [_instantiationInfo] to compute this information | 525 // TODO(johnniwinther): Use [_instantiationInfo] to compute this information |
| 526 // instead. | 526 // instead. |
| 527 if (_implementedClasses.add(cls)) { | 527 if (_implementedClasses.add(cls)) { |
| 528 void onImplemented(ClassElement cls) { | 528 classUsed(cls, _getClassUsage(cls).implement()); |
| 529 _ClassUsage usage = _getClassUsage(cls); | |
| 530 classUsed(usage.cls, usage.implement()); | |
| 531 } | |
| 532 | |
| 533 onImplemented(cls); | |
| 534 cls.allSupertypes.forEach((InterfaceType supertype) { | 529 cls.allSupertypes.forEach((InterfaceType supertype) { |
| 535 if (_implementedClasses.add(supertype.element)) { | 530 if (_implementedClasses.add(supertype.element)) { |
| 536 onImplemented(supertype.element); | 531 classUsed( |
| 532 supertype.element, _getClassUsage(supertype.element).implement()); |
| 537 } | 533 } |
| 538 }); | 534 }); |
| 539 } | 535 } |
| 540 } | 536 } |
| 541 | 537 |
| 542 @override | 538 @override |
| 543 void forEachInstantiatedClass(f(ClassElement cls, InstantiationInfo info)) { | 539 void forEachInstantiatedClass(f(ClassElement cls, InstantiationInfo info)) { |
| 544 getInstantiationMap().forEach(f); | 540 getInstantiationMap().forEach(f); |
| 545 } | 541 } |
| 546 | 542 |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 807 } | 803 } |
| 808 | 804 |
| 809 /// Computes usage for all members declared by [cls]. Calls [membersUsed] with | 805 /// Computes usage for all members declared by [cls]. Calls [membersUsed] with |
| 810 /// the usage changes for each member. | 806 /// the usage changes for each member. |
| 811 void processClassMembers(ClassElement cls, MemberUsedCallback memberUsed) { | 807 void processClassMembers(ClassElement cls, MemberUsedCallback memberUsed) { |
| 812 cls.implementation.forEachMember((ClassElement cls, MemberElement member) { | 808 cls.implementation.forEachMember((ClassElement cls, MemberElement member) { |
| 813 _processInstantiatedClassMember(cls, member, memberUsed); | 809 _processInstantiatedClassMember(cls, member, memberUsed); |
| 814 }); | 810 }); |
| 815 } | 811 } |
| 816 | 812 |
| 817 /// Call [updateUsage] on all [MemberUsage]s in the set in [map] for | 813 /// Call [updateUsage] on all [_MemberUsage]s in the set in [map] for |
| 818 /// [memberName]. If [updateUsage] returns `true` the usage is removed from | 814 /// [memberName]. If [updateUsage] returns `true` the usage is removed from |
| 819 /// the set. | 815 /// the set. |
| 820 void _processSet(Map<String, Set<_MemberUsage>> map, String memberName, | 816 void _processSet(Map<String, Set<_MemberUsage>> map, String memberName, |
| 821 bool updateUsage(_MemberUsage e)) { | 817 bool updateUsage(_MemberUsage e)) { |
| 822 Set<_MemberUsage> members = map[memberName]; | 818 Set<_MemberUsage> members = map[memberName]; |
| 823 if (members == null) return; | 819 if (members == null) return; |
| 824 // [f] might add elements to [: map[memberName] :] during the loop below | 820 // [f] might add elements to [: map[memberName] :] during the loop below |
| 825 // so we create a new list for [: map[memberName] :] and prepend the | 821 // so we create a new list for [: map[memberName] :] and prepend the |
| 826 // [remaining] members after the loop. | 822 // [remaining] members after the loop. |
| 827 map[memberName] = new Set<_MemberUsage>(); | 823 map[memberName] = new Set<_MemberUsage>(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 840 String name, bool updateUsage(_MemberUsage e)) { | 836 String name, bool updateUsage(_MemberUsage e)) { |
| 841 _processSet(_instanceFunctionsByName, name, updateUsage); | 837 _processSet(_instanceFunctionsByName, name, updateUsage); |
| 842 } | 838 } |
| 843 | 839 |
| 844 void _processInstantiatedClassMember( | 840 void _processInstantiatedClassMember( |
| 845 ClassElement cls, MemberElement member, MemberUsedCallback memberUsed) { | 841 ClassElement cls, MemberElement member, MemberUsedCallback memberUsed) { |
| 846 assert(invariant(member, member.isDeclaration)); | 842 assert(invariant(member, member.isDeclaration)); |
| 847 if (!member.isInstanceMember) return; | 843 if (!member.isInstanceMember) return; |
| 848 String memberName = member.name; | 844 String memberName = member.name; |
| 849 member.computeType(_resolution); | 845 member.computeType(_resolution); |
| 850 EnumSet<MemberUse> useSet = new EnumSet<MemberUse>(); | |
| 851 // The obvious thing to test here would be "member.isNative", | 846 // The obvious thing to test here would be "member.isNative", |
| 852 // however, that only works after metadata has been parsed/analyzed, | 847 // however, that only works after metadata has been parsed/analyzed, |
| 853 // and that may not have happened yet. | 848 // and that may not have happened yet. |
| 854 // So instead we use the enclosing class, which we know have had | 849 // So instead we use the enclosing class, which we know have had |
| 855 // its metadata parsed and analyzed. | 850 // its metadata parsed and analyzed. |
| 856 // Note: this assumes that there are no non-native fields on native | 851 // Note: this assumes that there are no non-native fields on native |
| 857 // classes, which may not be the case when a native class is subclassed. | 852 // classes, which may not be the case when a native class is subclassed. |
| 858 bool isNative = _backend.isNative(cls); | 853 _instanceMemberUsage.putIfAbsent(member, () { |
| 859 _MemberUsage usage = _instanceMemberUsage.putIfAbsent(member, () { | 854 bool isNative = _backend.isNative(cls); |
| 860 _MemberUsage usage = new _MemberUsage(member, isNative: isNative); | 855 _MemberUsage usage = new _MemberUsage(member, isNative: isNative); |
| 856 EnumSet<MemberUse> useSet = new EnumSet<MemberUse>(); |
| 861 useSet.addAll(usage.appliedUse); | 857 useSet.addAll(usage.appliedUse); |
| 862 if (member.isField && isNative) { | 858 if (member.isField && isNative) { |
| 863 _openWorld.registerUsedElement(member); | 859 _openWorld.registerUsedElement(member); |
| 864 } | 860 } |
| 865 if (member.isFunction && | 861 if (member.isFunction && |
| 866 member.name == Identifiers.call && | 862 member.name == Identifiers.call && |
| 867 !cls.typeVariables.isEmpty) { | 863 !cls.typeVariables.isEmpty) { |
| 868 callMethodsWithFreeTypeVariables.add(member); | 864 callMethodsWithFreeTypeVariables.add(member); |
| 869 } | 865 } |
| 870 | 866 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 926 Iterable<FunctionElement> get staticFunctionsNeedingGetter; | 922 Iterable<FunctionElement> get staticFunctionsNeedingGetter; |
| 927 Iterable<FunctionElement> get methodsNeedingSuperGetter; | 923 Iterable<FunctionElement> get methodsNeedingSuperGetter; |
| 928 | 924 |
| 929 /// The set of all referenced static fields. | 925 /// The set of all referenced static fields. |
| 930 /// | 926 /// |
| 931 /// Invariant: Elements are declaration elements. | 927 /// Invariant: Elements are declaration elements. |
| 932 Iterable<FieldElement> get allReferencedStaticFields; | 928 Iterable<FieldElement> get allReferencedStaticFields; |
| 933 } | 929 } |
| 934 | 930 |
| 935 class CodegenWorldBuilderImpl implements CodegenWorldBuilder { | 931 class CodegenWorldBuilderImpl implements CodegenWorldBuilder { |
| 932 final Backend _backend; |
| 933 |
| 936 /// The set of all directly instantiated classes, that is, classes with a | 934 /// The set of all directly instantiated classes, that is, classes with a |
| 937 /// generative constructor that has been called directly and not only through | 935 /// generative constructor that has been called directly and not only through |
| 938 /// a super-call. | 936 /// a super-call. |
| 939 /// | 937 /// |
| 940 /// Invariant: Elements are declaration elements. | 938 /// Invariant: Elements are declaration elements. |
| 941 // TODO(johnniwinther): [_directlyInstantiatedClasses] and | 939 // TODO(johnniwinther): [_directlyInstantiatedClasses] and |
| 942 // [_instantiatedTypes] sets should be merged. | 940 // [_instantiatedTypes] sets should be merged. |
| 943 final Set<ClassElement> _directlyInstantiatedClasses = | 941 final Set<ClassElement> _directlyInstantiatedClasses = |
| 944 new Set<ClassElement>(); | 942 new Set<ClassElement>(); |
| 945 | 943 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 966 new Set<FunctionElement>(); | 964 new Set<FunctionElement>(); |
| 967 final Set<FunctionElement> methodsNeedingSuperGetter = | 965 final Set<FunctionElement> methodsNeedingSuperGetter = |
| 968 new Set<FunctionElement>(); | 966 new Set<FunctionElement>(); |
| 969 final Map<String, Map<Selector, SelectorConstraints>> _invokedNames = | 967 final Map<String, Map<Selector, SelectorConstraints>> _invokedNames = |
| 970 <String, Map<Selector, SelectorConstraints>>{}; | 968 <String, Map<Selector, SelectorConstraints>>{}; |
| 971 final Map<String, Map<Selector, SelectorConstraints>> _invokedGetters = | 969 final Map<String, Map<Selector, SelectorConstraints>> _invokedGetters = |
| 972 <String, Map<Selector, SelectorConstraints>>{}; | 970 <String, Map<Selector, SelectorConstraints>>{}; |
| 973 final Map<String, Map<Selector, SelectorConstraints>> _invokedSetters = | 971 final Map<String, Map<Selector, SelectorConstraints>> _invokedSetters = |
| 974 <String, Map<Selector, SelectorConstraints>>{}; | 972 <String, Map<Selector, SelectorConstraints>>{}; |
| 975 | 973 |
| 974 final Map<ClassElement, _ClassUsage> _processedClasses = |
| 975 <ClassElement, _ClassUsage>{}; |
| 976 |
| 977 /// Map of registered usage of static members of live classes. |
| 978 final Map<Entity, _StaticMemberUsage> _staticMemberUsage = |
| 979 <Entity, _StaticMemberUsage>{}; |
| 980 |
| 981 /// Map of registered usage of instance members of live classes. |
| 982 final Map<MemberEntity, _MemberUsage> _instanceMemberUsage = |
| 983 <MemberEntity, _MemberUsage>{}; |
| 984 |
| 985 /// Map containing instance members of live classes that are not yet live |
| 986 /// themselves. |
| 987 final Map<String, Set<_MemberUsage>> _instanceMembersByName = |
| 988 <String, Set<_MemberUsage>>{}; |
| 989 |
| 990 /// Map containing instance methods of live classes that are not yet |
| 991 /// closurized. |
| 992 final Map<String, Set<_MemberUsage>> _instanceFunctionsByName = |
| 993 <String, Set<_MemberUsage>>{}; |
| 994 |
| 976 final Set<DartType> isChecks = new Set<DartType>(); | 995 final Set<DartType> isChecks = new Set<DartType>(); |
| 977 | 996 |
| 978 final SelectorConstraintsStrategy selectorConstraintsStrategy; | 997 final SelectorConstraintsStrategy selectorConstraintsStrategy; |
| 979 | 998 |
| 980 CodegenWorldBuilderImpl(this.selectorConstraintsStrategy); | 999 CodegenWorldBuilderImpl(this._backend, this.selectorConstraintsStrategy); |
| 1000 |
| 1001 // TODO(johnniwinther): Remove this hack: |
| 1002 ClosedWorld get _world => _backend.compiler.closedWorld; |
| 1003 |
| 1004 Iterable<ClassElement> get processedClasses => _processedClasses.keys |
| 1005 .where((cls) => _processedClasses[cls].isInstantiated); |
| 981 | 1006 |
| 982 /// All directly instantiated classes, that is, classes with a generative | 1007 /// All directly instantiated classes, that is, classes with a generative |
| 983 /// constructor that has been called directly and not only through a | 1008 /// constructor that has been called directly and not only through a |
| 984 /// super-call. | 1009 /// super-call. |
| 985 // TODO(johnniwinther): Improve semantic precision. | 1010 // TODO(johnniwinther): Improve semantic precision. |
| 986 Iterable<ClassElement> get directlyInstantiatedClasses { | 1011 Iterable<ClassElement> get directlyInstantiatedClasses { |
| 987 return _directlyInstantiatedClasses; | 1012 return _directlyInstantiatedClasses; |
| 988 } | 1013 } |
| 989 | 1014 |
| 990 /// All directly instantiated types, that is, the types of the directly | 1015 /// All directly instantiated types, that is, the types of the directly |
| 991 /// instantiated classes. | 1016 /// instantiated classes. |
| 992 /// | 1017 /// |
| 993 /// See [directlyInstantiatedClasses]. | 1018 /// See [directlyInstantiatedClasses]. |
| 994 // TODO(johnniwinther): Improve semantic precision. | 1019 // TODO(johnniwinther): Improve semantic precision. |
| 995 Iterable<DartType> get instantiatedTypes => _instantiatedTypes; | 1020 Iterable<DartType> get instantiatedTypes => _instantiatedTypes; |
| 996 | 1021 |
| 997 /// Register [type] as (directly) instantiated. | 1022 /// Register [type] as (directly) instantiated. |
| 998 /// | 1023 /// |
| 999 /// If [byMirrors] is `true`, the instantiation is through mirrors. | 1024 /// If [byMirrors] is `true`, the instantiation is through mirrors. |
| 1000 // TODO(johnniwinther): Fully enforce the separation between exact, through | 1025 // TODO(johnniwinther): Fully enforce the separation between exact, through |
| 1001 // subclass and through subtype instantiated types/classes. | 1026 // subclass and through subtype instantiated types/classes. |
| 1002 // TODO(johnniwinther): Support unknown type arguments for generic types. | 1027 // TODO(johnniwinther): Support unknown type arguments for generic types. |
| 1003 void registerTypeInstantiation(InterfaceType type, | 1028 void registerTypeInstantiation( |
| 1004 {bool byMirrors: false, | 1029 InterfaceType type, ClassUsedCallback classUsed, |
| 1005 bool isNative: false, | 1030 {bool byMirrors: false}) { |
| 1006 void onImplemented(ClassElement cls)}) { | 1031 ClassElement cls = type.element; |
| 1032 bool isNative = _backend.isNative(cls); |
| 1007 _instantiatedTypes.add(type); | 1033 _instantiatedTypes.add(type); |
| 1008 ClassElement cls = type.element; | |
| 1009 if (!cls.isAbstract | 1034 if (!cls.isAbstract |
| 1010 // We can't use the closed-world assumption with native abstract | 1035 // We can't use the closed-world assumption with native abstract |
| 1011 // classes; a native abstract class may have non-abstract subclasses | 1036 // classes; a native abstract class may have non-abstract subclasses |
| 1012 // not declared to the program. Instances of these classes are | 1037 // not declared to the program. Instances of these classes are |
| 1013 // indistinguishable from the abstract class. | 1038 // indistinguishable from the abstract class. |
| 1014 || | 1039 || |
| 1015 isNative | 1040 isNative |
| 1016 // Likewise, if this registration comes from the mirror system, | 1041 // Likewise, if this registration comes from the mirror system, |
| 1017 // all bets are off. | 1042 // all bets are off. |
| 1018 // TODO(herhut): Track classes required by mirrors separately. | 1043 // TODO(herhut): Track classes required by mirrors separately. |
| 1019 || | 1044 || |
| 1020 byMirrors) { | 1045 byMirrors) { |
| 1021 _directlyInstantiatedClasses.add(cls); | 1046 _directlyInstantiatedClasses.add(cls); |
| 1047 _processInstantiatedClass(cls, classUsed); |
| 1022 } | 1048 } |
| 1023 | 1049 |
| 1024 // TODO(johnniwinther): Replace this by separate more specific mappings that | 1050 // TODO(johnniwinther): Replace this by separate more specific mappings that |
| 1025 // include the type arguments. | 1051 // include the type arguments. |
| 1026 if (_implementedClasses.add(cls)) { | 1052 if (_implementedClasses.add(cls)) { |
| 1027 onImplemented(cls); | 1053 classUsed(cls, _getClassUsage(cls).implement()); |
| 1028 cls.allSupertypes.forEach((InterfaceType supertype) { | 1054 cls.allSupertypes.forEach((InterfaceType supertype) { |
| 1029 if (_implementedClasses.add(supertype.element)) { | 1055 if (_implementedClasses.add(supertype.element)) { |
| 1030 onImplemented(supertype.element); | 1056 classUsed( |
| 1057 supertype.element, _getClassUsage(supertype.element).implement()); |
| 1031 } | 1058 } |
| 1032 }); | 1059 }); |
| 1033 } | 1060 } |
| 1034 } | 1061 } |
| 1035 | 1062 |
| 1036 bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors, | 1063 bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors, |
| 1037 Element member, ClosedWorld world) { | 1064 Element member, ClosedWorld world) { |
| 1038 if (selectors == null) return false; | 1065 if (selectors == null) return false; |
| 1039 for (Selector selector in selectors.keys) { | 1066 for (Selector selector in selectors.keys) { |
| 1040 if (selector.appliesUnnamed(member)) { | 1067 if (selector.appliesUnnamed(member)) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1053 | 1080 |
| 1054 bool hasInvokedGetter(Element member, ClosedWorld world) { | 1081 bool hasInvokedGetter(Element member, ClosedWorld world) { |
| 1055 return _hasMatchingSelector(_invokedGetters[member.name], member, world) || | 1082 return _hasMatchingSelector(_invokedGetters[member.name], member, world) || |
| 1056 member.isFunction && methodsNeedingSuperGetter.contains(member); | 1083 member.isFunction && methodsNeedingSuperGetter.contains(member); |
| 1057 } | 1084 } |
| 1058 | 1085 |
| 1059 bool hasInvokedSetter(Element member, ClosedWorld world) { | 1086 bool hasInvokedSetter(Element member, ClosedWorld world) { |
| 1060 return _hasMatchingSelector(_invokedSetters[member.name], member, world); | 1087 return _hasMatchingSelector(_invokedSetters[member.name], member, world); |
| 1061 } | 1088 } |
| 1062 | 1089 |
| 1063 bool registerDynamicUse(DynamicUse dynamicUse) { | 1090 bool registerDynamicUse( |
| 1091 DynamicUse dynamicUse, MemberUsedCallback memberUsed) { |
| 1092 Selector selector = dynamicUse.selector; |
| 1093 String methodName = selector.name; |
| 1064 switch (dynamicUse.kind) { | 1094 switch (dynamicUse.kind) { |
| 1065 case DynamicUseKind.INVOKE: | 1095 case DynamicUseKind.INVOKE: |
| 1066 return _registerNewSelector(dynamicUse, _invokedNames); | 1096 if (_registerNewSelector(dynamicUse, _invokedNames)) { |
| 1097 _processInstanceMembers(methodName, (_MemberUsage member) { |
| 1098 if (dynamicUse.appliesUnnamed(member.entity, _world)) { |
| 1099 memberUsed(member.entity, member.invoke()); |
| 1100 return true; |
| 1101 } |
| 1102 return false; |
| 1103 }); |
| 1104 return true; |
| 1105 } |
| 1106 break; |
| 1067 case DynamicUseKind.GET: | 1107 case DynamicUseKind.GET: |
| 1068 return _registerNewSelector(dynamicUse, _invokedGetters); | 1108 if (_registerNewSelector(dynamicUse, _invokedGetters)) { |
| 1109 _processInstanceMembers(methodName, (_MemberUsage member) { |
| 1110 if (dynamicUse.appliesUnnamed(member.entity, _world)) { |
| 1111 memberUsed(member.entity, member.read()); |
| 1112 return true; |
| 1113 } |
| 1114 return false; |
| 1115 }); |
| 1116 _processInstanceFunctions(methodName, (_MemberUsage member) { |
| 1117 if (dynamicUse.appliesUnnamed(member.entity, _world)) { |
| 1118 memberUsed(member.entity, member.read()); |
| 1119 return true; |
| 1120 } |
| 1121 return false; |
| 1122 }); |
| 1123 return true; |
| 1124 } |
| 1125 break; |
| 1069 case DynamicUseKind.SET: | 1126 case DynamicUseKind.SET: |
| 1070 return _registerNewSelector(dynamicUse, _invokedSetters); | 1127 if (_registerNewSelector(dynamicUse, _invokedSetters)) { |
| 1128 _processInstanceMembers(methodName, (_MemberUsage member) { |
| 1129 if (dynamicUse.appliesUnnamed(member.entity, _world)) { |
| 1130 memberUsed(member.entity, member.write()); |
| 1131 return true; |
| 1132 } |
| 1133 return false; |
| 1134 }); |
| 1135 return true; |
| 1136 } |
| 1137 break; |
| 1071 } | 1138 } |
| 1139 return false; |
| 1072 } | 1140 } |
| 1073 | 1141 |
| 1074 bool _registerNewSelector(DynamicUse dynamicUse, | 1142 bool _registerNewSelector(DynamicUse dynamicUse, |
| 1075 Map<String, Map<Selector, SelectorConstraints>> selectorMap) { | 1143 Map<String, Map<Selector, SelectorConstraints>> selectorMap) { |
| 1076 Selector selector = dynamicUse.selector; | 1144 Selector selector = dynamicUse.selector; |
| 1077 String name = selector.name; | 1145 String name = selector.name; |
| 1078 ReceiverConstraint mask = dynamicUse.mask; | 1146 ReceiverConstraint mask = dynamicUse.mask; |
| 1079 Map<Selector, SelectorConstraints> selectors = selectorMap.putIfAbsent( | 1147 Map<Selector, SelectorConstraints> selectors = selectorMap.putIfAbsent( |
| 1080 name, () => new Maplet<Selector, SelectorConstraints>()); | 1148 name, () => new Maplet<Selector, SelectorConstraints>()); |
| 1081 UniverseSelectorConstraints constraints = | 1149 UniverseSelectorConstraints constraints = |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1120 | 1188 |
| 1121 DartType registerIsCheck(DartType type) { | 1189 DartType registerIsCheck(DartType type) { |
| 1122 type = type.unaliased; | 1190 type = type.unaliased; |
| 1123 // Even in checked mode, type annotations for return type and argument | 1191 // Even in checked mode, type annotations for return type and argument |
| 1124 // types do not imply type checks, so there should never be a check | 1192 // types do not imply type checks, so there should never be a check |
| 1125 // against the type variable of a typedef. | 1193 // against the type variable of a typedef. |
| 1126 isChecks.add(type); | 1194 isChecks.add(type); |
| 1127 return type; | 1195 return type; |
| 1128 } | 1196 } |
| 1129 | 1197 |
| 1130 void registerStaticUse(StaticUse staticUse) { | 1198 void _registerStaticUse(StaticUse staticUse) { |
| 1131 Element element = staticUse.element; | 1199 Element element = staticUse.element; |
| 1132 if (Elements.isStaticOrTopLevel(element) && element.isField) { | 1200 if (Elements.isStaticOrTopLevel(element) && element.isField) { |
| 1133 allReferencedStaticFields.add(element); | 1201 allReferencedStaticFields.add(element); |
| 1134 } | 1202 } |
| 1135 switch (staticUse.kind) { | 1203 switch (staticUse.kind) { |
| 1136 case StaticUseKind.STATIC_TEAR_OFF: | 1204 case StaticUseKind.STATIC_TEAR_OFF: |
| 1137 staticFunctionsNeedingGetter.add(element); | 1205 staticFunctionsNeedingGetter.add(element); |
| 1138 break; | 1206 break; |
| 1139 case StaticUseKind.SUPER_TEAR_OFF: | 1207 case StaticUseKind.SUPER_TEAR_OFF: |
| 1140 methodsNeedingSuperGetter.add(element); | 1208 methodsNeedingSuperGetter.add(element); |
| 1141 break; | 1209 break; |
| 1142 case StaticUseKind.SUPER_FIELD_SET: | 1210 case StaticUseKind.SUPER_FIELD_SET: |
| 1143 case StaticUseKind.FIELD_SET: | 1211 case StaticUseKind.FIELD_SET: |
| 1144 case StaticUseKind.GENERAL: | 1212 case StaticUseKind.GENERAL: |
| 1145 case StaticUseKind.DIRECT_USE: | 1213 case StaticUseKind.DIRECT_USE: |
| 1146 case StaticUseKind.CLOSURE: | 1214 case StaticUseKind.CLOSURE: |
| 1147 case StaticUseKind.FIELD_GET: | 1215 case StaticUseKind.FIELD_GET: |
| 1148 case StaticUseKind.CONSTRUCTOR_INVOKE: | 1216 case StaticUseKind.CONSTRUCTOR_INVOKE: |
| 1149 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: | 1217 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: |
| 1150 case StaticUseKind.REDIRECTION: | 1218 case StaticUseKind.REDIRECTION: |
| 1151 case StaticUseKind.DIRECT_INVOKE: | 1219 case StaticUseKind.DIRECT_INVOKE: |
| 1152 break; | 1220 break; |
| 1153 } | 1221 } |
| 1154 } | 1222 } |
| 1155 | 1223 |
| 1224 void registerStaticUse(StaticUse staticUse, MemberUsedCallback memberUsed) { |
| 1225 Element element = staticUse.element; |
| 1226 assert(invariant(element, element.isDeclaration, |
| 1227 message: "Element ${element} is not the declaration.")); |
| 1228 _registerStaticUse(staticUse); |
| 1229 _StaticMemberUsage usage = _staticMemberUsage.putIfAbsent(element, () { |
| 1230 if ((element.isStatic || element.isTopLevel) && element.isFunction) { |
| 1231 return new _StaticFunctionUsage(element); |
| 1232 } else { |
| 1233 return new _GeneralStaticMemberUsage(element); |
| 1234 } |
| 1235 }); |
| 1236 EnumSet<MemberUse> useSet = new EnumSet<MemberUse>(); |
| 1237 switch (staticUse.kind) { |
| 1238 case StaticUseKind.STATIC_TEAR_OFF: |
| 1239 useSet.addAll(usage.tearOff()); |
| 1240 break; |
| 1241 case StaticUseKind.FIELD_GET: |
| 1242 case StaticUseKind.FIELD_SET: |
| 1243 case StaticUseKind.CLOSURE: |
| 1244 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and |
| 1245 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue. |
| 1246 // Also [CLOSURE] contains [LocalFunctionElement] which we cannot |
| 1247 // enqueue. |
| 1248 break; |
| 1249 case StaticUseKind.SUPER_FIELD_SET: |
| 1250 case StaticUseKind.SUPER_TEAR_OFF: |
| 1251 case StaticUseKind.GENERAL: |
| 1252 case StaticUseKind.DIRECT_USE: |
| 1253 useSet.addAll(usage.normalUse()); |
| 1254 break; |
| 1255 case StaticUseKind.CONSTRUCTOR_INVOKE: |
| 1256 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: |
| 1257 case StaticUseKind.REDIRECTION: |
| 1258 useSet.addAll(usage.normalUse()); |
| 1259 break; |
| 1260 case StaticUseKind.DIRECT_INVOKE: |
| 1261 _MemberUsage instanceUsage = |
| 1262 _getMemberUsage(staticUse.element, memberUsed); |
| 1263 memberUsed(instanceUsage.entity, instanceUsage.invoke()); |
| 1264 _instanceMembersByName[instanceUsage.entity.name] |
| 1265 ?.remove(instanceUsage); |
| 1266 useSet.addAll(usage.normalUse()); |
| 1267 break; |
| 1268 } |
| 1269 memberUsed(usage.entity, useSet); |
| 1270 } |
| 1271 |
| 1156 void forgetElement(Element element, Compiler compiler) { | 1272 void forgetElement(Element element, Compiler compiler) { |
| 1273 _processedClasses.remove(element); |
| 1157 _directlyInstantiatedClasses.remove(element); | 1274 _directlyInstantiatedClasses.remove(element); |
| 1158 if (element is ClassElement) { | 1275 if (element is ClassElement) { |
| 1159 assert(invariant(element, element.thisType.isRaw, | 1276 assert(invariant(element, element.thisType.isRaw, |
| 1160 message: 'Generic classes not supported (${element.thisType}).')); | 1277 message: 'Generic classes not supported (${element.thisType}).')); |
| 1161 _instantiatedTypes..remove(element.rawType)..remove(element.thisType); | 1278 _instantiatedTypes..remove(element.rawType)..remove(element.thisType); |
| 1162 } | 1279 } |
| 1280 removeFromSet(_instanceMembersByName, element); |
| 1281 removeFromSet(_instanceFunctionsByName, element); |
| 1282 if (element is MemberElement) { |
| 1283 for (Element closure in element.nestedClosures) { |
| 1284 removeFromSet(_instanceMembersByName, closure); |
| 1285 removeFromSet(_instanceFunctionsByName, closure); |
| 1286 } |
| 1287 } |
| 1288 } |
| 1289 |
| 1290 void processClassMembers(ClassElement cls, MemberUsedCallback memberUsed) { |
| 1291 cls.implementation.forEachMember((_, MemberElement member) { |
| 1292 assert(invariant(member, member.isDeclaration)); |
| 1293 if (!member.isInstanceMember) return; |
| 1294 _getMemberUsage(member, memberUsed); |
| 1295 }); |
| 1296 } |
| 1297 |
| 1298 _MemberUsage _getMemberUsage( |
| 1299 MemberElement member, MemberUsedCallback memberUsed) { |
| 1300 assert(invariant(member, member.isDeclaration)); |
| 1301 return _instanceMemberUsage.putIfAbsent(member, () { |
| 1302 String memberName = member.name; |
| 1303 ClassElement cls = member.enclosingClass; |
| 1304 bool isNative = _backend.isNative(cls); |
| 1305 _MemberUsage usage = new _MemberUsage(member, isNative: isNative); |
| 1306 EnumSet<MemberUse> useSet = new EnumSet<MemberUse>(); |
| 1307 useSet.addAll(usage.appliedUse); |
| 1308 if (hasInvokedGetter(member, _world)) { |
| 1309 useSet.addAll(usage.read()); |
| 1310 } |
| 1311 if (hasInvokedSetter(member, _world)) { |
| 1312 useSet.addAll(usage.write()); |
| 1313 } |
| 1314 if (hasInvocation(member, _world)) { |
| 1315 useSet.addAll(usage.invoke()); |
| 1316 } |
| 1317 |
| 1318 if (usage.pendingUse.contains(MemberUse.CLOSURIZE_INSTANCE)) { |
| 1319 // Store the member in [instanceFunctionsByName] to catch |
| 1320 // getters on the function. |
| 1321 _instanceFunctionsByName |
| 1322 .putIfAbsent(usage.entity.name, () => new Set<_MemberUsage>()) |
| 1323 .add(usage); |
| 1324 } |
| 1325 if (usage.pendingUse.contains(MemberUse.NORMAL)) { |
| 1326 // The element is not yet used. Add it to the list of instance |
| 1327 // members to still be processed. |
| 1328 _instanceMembersByName |
| 1329 .putIfAbsent(memberName, () => new Set<_MemberUsage>()) |
| 1330 .add(usage); |
| 1331 } |
| 1332 memberUsed(member, useSet); |
| 1333 return usage; |
| 1334 }); |
| 1335 } |
| 1336 |
| 1337 void _processSet(Map<String, Set<_MemberUsage>> map, String memberName, |
| 1338 bool f(_MemberUsage e)) { |
| 1339 Set<_MemberUsage> members = map[memberName]; |
| 1340 if (members == null) return; |
| 1341 // [f] might add elements to [: map[memberName] :] during the loop below |
| 1342 // so we create a new list for [: map[memberName] :] and prepend the |
| 1343 // [remaining] members after the loop. |
| 1344 map[memberName] = new Set<_MemberUsage>(); |
| 1345 Set<_MemberUsage> remaining = new Set<_MemberUsage>(); |
| 1346 for (_MemberUsage member in members) { |
| 1347 if (!f(member)) remaining.add(member); |
| 1348 } |
| 1349 map[memberName].addAll(remaining); |
| 1350 } |
| 1351 |
| 1352 void _processInstanceMembers(String n, bool f(_MemberUsage e)) { |
| 1353 _processSet(_instanceMembersByName, n, f); |
| 1354 } |
| 1355 |
| 1356 void _processInstanceFunctions(String n, bool f(_MemberUsage e)) { |
| 1357 _processSet(_instanceFunctionsByName, n, f); |
| 1358 } |
| 1359 |
| 1360 /// Return the canonical [_ClassUsage] for [cls]. |
| 1361 _ClassUsage _getClassUsage(ClassElement cls) { |
| 1362 return _processedClasses.putIfAbsent(cls, () => new _ClassUsage(cls)); |
| 1363 } |
| 1364 |
| 1365 void _processInstantiatedClass( |
| 1366 ClassElement cls, ClassUsedCallback classUsed) { |
| 1367 // Registers [superclass] as instantiated. Returns `true` if it wasn't |
| 1368 // already instantiated and we therefore have to process its superclass as |
| 1369 // well. |
| 1370 bool processClass(ClassElement superclass) { |
| 1371 _ClassUsage usage = _getClassUsage(superclass); |
| 1372 if (!usage.isInstantiated) { |
| 1373 classUsed(usage.cls, usage.instantiate()); |
| 1374 return true; |
| 1375 } |
| 1376 return false; |
| 1377 } |
| 1378 |
| 1379 while (cls != null && processClass(cls)) { |
| 1380 cls = cls.superclass; |
| 1381 } |
| 1163 } | 1382 } |
| 1164 } | 1383 } |
| 1165 | 1384 |
| 1166 abstract class _AbstractUsage<T> { | 1385 abstract class _AbstractUsage<T> { |
| 1167 final EnumSet<T> _pendingUse = new EnumSet<T>(); | 1386 final EnumSet<T> _pendingUse = new EnumSet<T>(); |
| 1168 | 1387 |
| 1169 _AbstractUsage() { | 1388 _AbstractUsage() { |
| 1170 _pendingUse.addAll(_originalUse); | 1389 _pendingUse.addAll(_originalUse); |
| 1171 } | 1390 } |
| 1172 | 1391 |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1528 if (hasClosurization) { | 1747 if (hasClosurization) { |
| 1529 return MemberUses.NONE; | 1748 return MemberUses.NONE; |
| 1530 } | 1749 } |
| 1531 hasNormalUse = hasClosurization = true; | 1750 hasNormalUse = hasClosurization = true; |
| 1532 return _pendingUse.removeAll(MemberUses.ALL_STATIC); | 1751 return _pendingUse.removeAll(MemberUses.ALL_STATIC); |
| 1533 } | 1752 } |
| 1534 | 1753 |
| 1535 @override | 1754 @override |
| 1536 EnumSet<MemberUse> get _originalUse => MemberUses.ALL_STATIC; | 1755 EnumSet<MemberUse> get _originalUse => MemberUses.ALL_STATIC; |
| 1537 } | 1756 } |
| 1757 |
| 1758 void removeFromSet(Map<String, Set<_MemberUsage>> map, Element element) { |
| 1759 Set<_MemberUsage> set = map[element.name]; |
| 1760 if (set == null) return; |
| 1761 set.removeAll( |
| 1762 set.where((_MemberUsage usage) => usage.entity == element).toList()); |
| 1763 } |
| OLD | NEW |