Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(237)

Side by Side Diff: pkg/compiler/lib/src/universe/world_builder.dart

Issue 2587913004: Move class/member computation from CodegenEnqueuer to CodegenWorldBuilder. (Closed)
Patch Set: Cleanup. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/compiler/lib/src/js_backend/enqueuer.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/enqueuer.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698