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