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

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: Updated cf. comments 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
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 507 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/enqueuer.dart ('k') | tests/compiler/dart2js/kernel/try_catch_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698