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

Side by Side Diff: pkg/compiler/lib/src/world.dart

Issue 2826673002: Remove JavaScriptBackend from ClosedWorldBase (Closed)
Patch Set: Created 3 years, 8 months 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 dart2js.world; 5 library dart2js.world;
6 6
7 import 'closure.dart' show ClosureClassElement, SynthesizedCallMethodElementX; 7 import 'closure.dart' show ClosureClassElement, SynthesizedCallMethodElementX;
8 import 'common.dart'; 8 import 'common.dart';
9 import 'constants/constant_system.dart'; 9 import 'constants/constant_system.dart';
10 import 'common_elements.dart' show CommonElements; 10 import 'common_elements.dart' show CommonElements;
11 import 'elements/entities.dart'; 11 import 'elements/entities.dart';
12 import 'elements/elements.dart' 12 import 'elements/elements.dart'
13 show 13 show
14 ClassElement, 14 ClassElement,
15 Element, 15 Element,
16 MemberElement, 16 MemberElement,
17 MixinApplicationElement, 17 MixinApplicationElement,
18 TypedefElement; 18 TypedefElement;
19 import 'elements/resolution_types.dart'; 19 import 'elements/resolution_types.dart';
20 import 'elements/types.dart'; 20 import 'elements/types.dart';
21 import 'js_backend/backend.dart' show JavaScriptBackend; 21 import 'js_backend/backend_usage.dart' show BackendUsage;
22 import 'js_backend/interceptor_data.dart' show InterceptorData; 22 import 'js_backend/interceptor_data.dart' show InterceptorData;
23 import 'js_backend/native_data.dart' show NativeData; 23 import 'js_backend/native_data.dart' show NativeData;
24 import 'ordered_typeset.dart'; 24 import 'ordered_typeset.dart';
25 import 'types/masks.dart' show CommonMasks, FlatTypeMask, TypeMask; 25 import 'types/masks.dart' show CommonMasks, FlatTypeMask, TypeMask;
26 import 'universe/class_set.dart'; 26 import 'universe/class_set.dart';
27 import 'universe/function_set.dart' show FunctionSet, FunctionSetBuilder; 27 import 'universe/function_set.dart' show FunctionSet, FunctionSetBuilder;
28 import 'universe/selector.dart' show Selector; 28 import 'universe/selector.dart' show Selector;
29 import 'universe/side_effects.dart' show SideEffects; 29 import 'universe/side_effects.dart' show SideEffects;
30 import 'universe/world_builder.dart' show ResolutionWorldBuilder; 30 import 'universe/world_builder.dart' show ResolutionWorldBuilder;
31 import 'util/util.dart' show Link; 31 import 'util/util.dart' show Link;
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 abstract class OpenWorld implements World { 357 abstract class OpenWorld implements World {
358 /// Called to add [cls] to the set of known classes. 358 /// Called to add [cls] to the set of known classes.
359 /// 359 ///
360 /// This ensures that class hierarchy queries can be performed on [cls] and 360 /// This ensures that class hierarchy queries can be performed on [cls] and
361 /// classes that extend or implement it. 361 /// classes that extend or implement it.
362 void registerClass(ClassEntity cls); 362 void registerClass(ClassEntity cls);
363 363
364 void registerUsedElement(MemberEntity element); 364 void registerUsedElement(MemberEntity element);
365 void registerTypedef(TypedefElement typedef); 365 void registerTypedef(TypedefElement typedef);
366 366
367 ClosedWorld closeWorld(DiagnosticReporter reporter); 367 ClosedWorld closeWorld();
368 368
369 /// Returns an iterable over all mixin applications that mixin [cls]. 369 /// Returns an iterable over all mixin applications that mixin [cls].
370 Iterable<ClassEntity> allMixinUsesOf(ClassEntity cls); 370 Iterable<ClassEntity> allMixinUsesOf(ClassEntity cls);
371 } 371 }
372 372
373 /// Enum values defining subset of classes included in queries. 373 /// Enum values defining subset of classes included in queries.
374 enum ClassQuery { 374 enum ClassQuery {
375 /// Only the class itself is included. 375 /// Only the class itself is included.
376 EXACT, 376 EXACT,
377 377
378 /// The class and all subclasses (transitively) are included. 378 /// The class and all subclasses (transitively) are included.
379 SUBCLASS, 379 SUBCLASS,
380 380
381 /// The class and all classes that implement or subclass it (transitively) 381 /// The class and all classes that implement or subclass it (transitively)
382 /// are included. 382 /// are included.
383 SUBTYPE, 383 SUBTYPE,
384 } 384 }
385 385
386 abstract class ClosedWorldBase implements ClosedWorld, ClosedWorldRefiner { 386 abstract class ClosedWorldBase implements ClosedWorld, ClosedWorldRefiner {
387 final JavaScriptBackend _backend; 387 final ConstantSystem constantSystem;
388 InterceptorData get interceptorData => _backend.interceptorData; 388 final NativeData nativeData;
389 final InterceptorData interceptorData;
390 final BackendUsage _backendUsage;
391
389 FunctionSet _allFunctions; 392 FunctionSet _allFunctions;
390 393
391 final Iterable<TypedefElement> _allTypedefs; 394 final Iterable<TypedefElement> _allTypedefs;
392 395
393 final Map<ClassEntity, Set<ClassEntity>> _mixinUses; 396 final Map<ClassEntity, Set<ClassEntity>> _mixinUses;
394 Map<ClassEntity, List<ClassEntity>> _liveMixinUses; 397 Map<ClassEntity, List<ClassEntity>> _liveMixinUses;
395 398
396 final Map<ClassEntity, Set<ClassEntity>> _typesImplementedBySubclasses; 399 final Map<ClassEntity, Set<ClassEntity>> _typesImplementedBySubclasses;
397 400
398 // We keep track of subtype and subclass relationships in four 401 // We keep track of subtype and subclass relationships in four
(...skipping 13 matching lines...) Expand all
412 415
413 final Set<Entity> _functionsThatMightBePassedToApply = new Set<Entity>(); 416 final Set<Entity> _functionsThatMightBePassedToApply = new Set<Entity>();
414 417
415 CommonMasks _commonMasks; 418 CommonMasks _commonMasks;
416 419
417 final CommonElements commonElements; 420 final CommonElements commonElements;
418 421
419 final ResolutionWorldBuilder _resolverWorld; 422 final ResolutionWorldBuilder _resolverWorld;
420 423
421 ClosedWorldBase( 424 ClosedWorldBase(
422 {JavaScriptBackend backend, 425 {this.commonElements,
423 this.commonElements, 426 this.constantSystem,
427 this.nativeData,
428 this.interceptorData,
429 BackendUsage backendUsage,
424 ResolutionWorldBuilder resolutionWorldBuilder, 430 ResolutionWorldBuilder resolutionWorldBuilder,
425 FunctionSetBuilder functionSetBuilder, 431 FunctionSetBuilder functionSetBuilder,
426 Iterable<TypedefElement> allTypedefs, 432 Iterable<TypedefElement> allTypedefs,
427 Map<ClassEntity, Set<ClassEntity>> mixinUses, 433 Map<ClassEntity, Set<ClassEntity>> mixinUses,
428 Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses, 434 Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses,
429 Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes, 435 Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes,
430 Map<ClassEntity, ClassSet> classSets}) 436 Map<ClassEntity, ClassSet> classSets})
431 : this._backend = backend, 437 : this._backendUsage = backendUsage,
432 this._resolverWorld = resolutionWorldBuilder, 438 this._resolverWorld = resolutionWorldBuilder,
433 this._allTypedefs = allTypedefs, 439 this._allTypedefs = allTypedefs,
434 this._mixinUses = mixinUses, 440 this._mixinUses = mixinUses,
435 this._typesImplementedBySubclasses = typesImplementedBySubclasses, 441 this._typesImplementedBySubclasses = typesImplementedBySubclasses,
436 this._classHierarchyNodes = classHierarchyNodes, 442 this._classHierarchyNodes = classHierarchyNodes,
437 this._classSets = classSets { 443 this._classSets = classSets {
438 _commonMasks = new CommonMasks(this); 444 _commonMasks = new CommonMasks(this);
439 _allFunctions = functionSetBuilder.close(this); 445 _allFunctions = functionSetBuilder.close(this);
440 } 446 }
441 447
442 NativeData get nativeData => _backend.nativeData;
443
444 @override 448 @override
445 ClosedWorld get closedWorld => this; 449 ClosedWorld get closedWorld => this;
446 450
447 /// Cache of [FlatTypeMask]s grouped by the 8 possible values of the 451 /// Cache of [FlatTypeMask]s grouped by the 8 possible values of the
448 /// `FlatTypeMask.flags` property. 452 /// `FlatTypeMask.flags` property.
449 final List<Map<ClassEntity, TypeMask>> _canonicalizedTypeMasks = 453 final List<Map<ClassEntity, TypeMask>> _canonicalizedTypeMasks =
450 new List<Map<ClassEntity, TypeMask>>.filled(8, null); 454 new List<Map<ClassEntity, TypeMask>>.filled(8, null);
451 455
452 FunctionSet get allFunctions => _allFunctions; 456 FunctionSet get allFunctions => _allFunctions;
453 457
454 CommonMasks get commonMasks { 458 CommonMasks get commonMasks {
455 return _commonMasks; 459 return _commonMasks;
456 } 460 }
457 461
458 ConstantSystem get constantSystem => _backend.constantSystem;
459
460 TypeMask getCachedMask(ClassEntity base, int flags, TypeMask createMask()) { 462 TypeMask getCachedMask(ClassEntity base, int flags, TypeMask createMask()) {
461 Map<ClassEntity, TypeMask> cachedMasks = 463 Map<ClassEntity, TypeMask> cachedMasks =
462 _canonicalizedTypeMasks[flags] ??= <ClassEntity, TypeMask>{}; 464 _canonicalizedTypeMasks[flags] ??= <ClassEntity, TypeMask>{};
463 return cachedMasks.putIfAbsent(base, createMask); 465 return cachedMasks.putIfAbsent(base, createMask);
464 } 466 }
465 467
466 bool _checkEntity(Entity element); 468 bool _checkEntity(Entity element);
467 469
468 bool _checkClass(ClassEntity cls); 470 bool _checkClass(ClassEntity cls);
469 471
470 bool _checkInvariants(ClassEntity cls, {bool mustBeInstantiated: true}); 472 bool _checkInvariants(ClassEntity cls, {bool mustBeInstantiated: true});
471 473
474 OrderedTypeSet _getOrderedTypeSet(ClassEntity cls);
475
476 int _getHierarchyDepth(ClassEntity cls);
477
478 ClassEntity _getSuperClass(ClassEntity cls);
479
480 Iterable<ClassEntity> _getInterfaces(ClassEntity cls);
481
482 ClassEntity _getAppliedMixin(ClassEntity cls);
483
484 bool _isNamedMixinApplication(ClassEntity cls);
485
472 @override 486 @override
473 bool isInstantiated(ClassEntity cls) { 487 bool isInstantiated(ClassEntity cls) {
474 assert(_checkClass(cls)); 488 assert(_checkClass(cls));
475 ClassHierarchyNode node = _classHierarchyNodes[cls]; 489 ClassHierarchyNode node = _classHierarchyNodes[cls];
476 return node != null && node.isInstantiated; 490 return node != null && node.isInstantiated;
477 } 491 }
478 492
479 @override 493 @override
480 bool isDirectlyInstantiated(ClassEntity cls) { 494 bool isDirectlyInstantiated(ClassEntity cls) {
481 assert(_checkClass(cls)); 495 assert(_checkClass(cls));
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 return subclassesNeedNoSuchMethod(node); 816 return subclassesNeedNoSuchMethod(node);
803 } else { 817 } else {
804 if (subclassesNeedNoSuchMethod(node)) return true; 818 if (subclassesNeedNoSuchMethod(node)) return true;
805 for (ClassHierarchyNode subtypeNode in classSet.subtypeNodes) { 819 for (ClassHierarchyNode subtypeNode in classSet.subtypeNodes) {
806 if (subclassesNeedNoSuchMethod(subtypeNode)) return true; 820 if (subclassesNeedNoSuchMethod(subtypeNode)) return true;
807 } 821 }
808 return false; 822 return false;
809 } 823 }
810 } 824 }
811 825
826 /// Returns an iterable over the common supertypes of the [classes].
827 Iterable<ClassEntity> commonSupertypesOf(Iterable<ClassEntity> classes) {
828 Iterator<ClassEntity> iterator = classes.iterator;
829 if (!iterator.moveNext()) return const <ClassEntity>[];
830
831 ClassEntity cls = iterator.current;
832 assert(_checkInvariants(cls));
833 OrderedTypeSet typeSet = _getOrderedTypeSet(cls);
834 if (!iterator.moveNext()) return typeSet.types.map((type) => type.element);
835
836 int depth = typeSet.maxDepth;
837 Link<OrderedTypeSet> otherTypeSets = const Link<OrderedTypeSet>();
838 do {
839 ClassEntity otherClass = iterator.current;
840 assert(_checkInvariants(otherClass));
841 OrderedTypeSet otherTypeSet = _getOrderedTypeSet(otherClass);
842 otherTypeSets = otherTypeSets.prepend(otherTypeSet);
843 if (otherTypeSet.maxDepth < depth) {
844 depth = otherTypeSet.maxDepth;
845 }
846 } while (iterator.moveNext());
847
848 List<ClassEntity> commonSupertypes = <ClassEntity>[];
849 OUTER:
850 for (Link<InterfaceType> link = typeSet[depth];
851 link.head.element != commonElements.objectClass;
852 link = link.tail) {
853 ClassEntity cls = link.head.element;
854 for (Link<OrderedTypeSet> link = otherTypeSets;
855 !link.isEmpty;
856 link = link.tail) {
857 if (link.head.asInstanceOf(cls, _getHierarchyDepth(cls)) == null) {
858 continue OUTER;
859 }
860 }
861 commonSupertypes.add(cls);
862 }
863 commonSupertypes.add(commonElements.objectClass);
864 return commonSupertypes;
865 }
866
867 Iterable<ClassEntity> commonSubclasses(ClassEntity cls1, ClassQuery query1,
868 ClassEntity cls2, ClassQuery query2) {
869 // TODO(johnniwinther): Use [ClassSet] to compute this.
870 // Compute the set of classes that are contained in both class subsets.
871 Set<ClassEntity> common =
872 _commonContainedClasses(cls1, query1, cls2, query2);
873 if (common == null || common.isEmpty) return const <ClassEntity>[];
874 // Narrow down the candidates by only looking at common classes
875 // that do not have a superclass or supertype that will be a
876 // better candidate.
877 return common.where((ClassEntity each) {
878 bool containsSuperclass = common.contains(_getSuperClass(each));
879 // If the superclass is also a candidate, then we don't want to
880 // deal with this class. If we're only looking for a subclass we
881 // know we don't have to look at the list of interfaces because
882 // they can never be in the common set.
883 if (containsSuperclass ||
884 query1 == ClassQuery.SUBCLASS ||
885 query2 == ClassQuery.SUBCLASS) {
886 return !containsSuperclass;
887 }
888 // Run through the direct supertypes of the class. If the common
889 // set contains the direct supertype of the class, we ignore the
890 // the class because the supertype is a better candidate.
891
892 for (ClassEntity interface in _getInterfaces(each)) {
893 if (common.contains(interface)) return false;
894 }
895 return true;
896 });
897 }
898
899 /// Returns an iterable over the live mixin applications that mixin [cls].
900 Iterable<ClassEntity> mixinUsesOf(ClassEntity cls) {
901 if (_liveMixinUses == null) {
902 _liveMixinUses = new Map<ClassEntity, List<ClassEntity>>();
903 for (ClassEntity mixin in _mixinUses.keys) {
904 List<ClassEntity> uses = <ClassEntity>[];
905
906 void addLiveUse(ClassEntity mixinApplication) {
907 if (isInstantiated(mixinApplication)) {
908 uses.add(mixinApplication);
909 } else if (_isNamedMixinApplication(mixinApplication)) {
910 Set<ClassEntity> next = _mixinUses[mixinApplication];
911 if (next != null) {
912 next.forEach(addLiveUse);
913 }
914 }
915 }
916
917 _mixinUses[mixin].forEach(addLiveUse);
918 if (uses.isNotEmpty) {
919 _liveMixinUses[mixin] = uses;
920 }
921 }
922 }
923 Iterable<ClassEntity> uses = _liveMixinUses[cls];
924 return uses != null ? uses : const <ClassEntity>[];
925 }
926
927 /// Returns `true` if any live class that mixes in [mixin] is also a subclass
928 /// of [superclass].
929 bool hasAnySubclassThatMixes(ClassEntity superclass, ClassEntity mixin) {
930 return mixinUsesOf(mixin).any((ClassEntity each) {
931 return isSubclassOf(each, superclass);
932 });
933 }
934
935 /// Returns `true` if [cls] or any superclass mixes in [mixin].
936 bool isSubclassOfMixinUseOf(ClassEntity cls, ClassEntity mixin) {
937 assert(_checkClass(cls));
938 assert(_checkClass(mixin));
939 if (isUsedAsMixin(mixin)) {
940 ClassEntity current = cls;
941 while (current != null) {
942 ClassEntity currentMixin = _getAppliedMixin(cls);
943 if (currentMixin == mixin) return true;
944 current = _getSuperClass(current);
945 }
946 }
947 return false;
948 }
949
812 /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies 950 /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies
813 /// of known classes. 951 /// of known classes.
814 /// 952 ///
815 /// This method is only provided for testing. For queries on classes, use the 953 /// This method is only provided for testing. For queries on classes, use the
816 /// methods defined in [ClosedWorld]. 954 /// methods defined in [ClosedWorld].
817 ClassHierarchyNode getClassHierarchyNode(ClassEntity cls) { 955 ClassHierarchyNode getClassHierarchyNode(ClassEntity cls) {
818 assert(_checkClass(cls)); 956 assert(_checkClass(cls));
819 return _classHierarchyNodes[cls]; 957 return _classHierarchyNodes[cls];
820 } 958 }
821 959
(...skipping 19 matching lines...) Expand all
841 } 979 }
842 980
843 MemberEntity locateSingleElement(Selector selector, TypeMask mask) { 981 MemberEntity locateSingleElement(Selector selector, TypeMask mask) {
844 mask ??= commonMasks.dynamicType; 982 mask ??= commonMasks.dynamicType;
845 return mask.locateSingleElement(selector, this); 983 return mask.locateSingleElement(selector, this);
846 } 984 }
847 985
848 TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask) { 986 TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask) {
849 bool canReachAll = true; 987 bool canReachAll = true;
850 if (mask != null) { 988 if (mask != null) {
851 canReachAll = _backend.backendUsage.isInvokeOnUsed && 989 canReachAll = _backendUsage.isInvokeOnUsed &&
852 mask.needsNoSuchMethodHandling(selector, this); 990 mask.needsNoSuchMethodHandling(selector, this);
853 } 991 }
854 return canReachAll ? commonMasks.dynamicType : mask; 992 return canReachAll ? commonMasks.dynamicType : mask;
855 } 993 }
856 994
857 bool fieldNeverChanges(MemberEntity element) { 995 bool fieldNeverChanges(MemberEntity element) {
858 if (!element.isField) return false; 996 if (!element.isField) return false;
859 if (nativeData.isNativeMember(element)) { 997 if (nativeData.isNativeMember(element)) {
860 // Some native fields are views of data that may be changed by operations. 998 // Some native fields are views of data that may be changed by operations.
861 // E.g. node.firstChild depends on parentNode.removeBefore(n1, n2). 999 // E.g. node.firstChild depends on parentNode.removeBefore(n1, n2).
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
959 } 1097 }
960 1098
961 @override 1099 @override
962 bool getCurrentlyKnownMightBePassedToApply(Entity element) { 1100 bool getCurrentlyKnownMightBePassedToApply(Entity element) {
963 return getMightBePassedToApply(element); 1101 return getMightBePassedToApply(element);
964 } 1102 }
965 } 1103 }
966 1104
967 class ClosedWorldImpl extends ClosedWorldBase { 1105 class ClosedWorldImpl extends ClosedWorldBase {
968 ClosedWorldImpl( 1106 ClosedWorldImpl(
969 {JavaScriptBackend backend, 1107 {CommonElements commonElements,
970 CommonElements commonElements, 1108 ConstantSystem constantSystem,
1109 NativeData nativeData,
1110 InterceptorData interceptorData,
1111 BackendUsage backendUsage,
971 ResolutionWorldBuilder resolutionWorldBuilder, 1112 ResolutionWorldBuilder resolutionWorldBuilder,
972 FunctionSetBuilder functionSetBuilder, 1113 FunctionSetBuilder functionSetBuilder,
973 Iterable<TypedefElement> allTypedefs, 1114 Iterable<TypedefElement> allTypedefs,
974 Map<ClassEntity, Set<ClassEntity>> mixinUses, 1115 Map<ClassEntity, Set<ClassEntity>> mixinUses,
975 Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses, 1116 Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses,
976 Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes, 1117 Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes,
977 Map<ClassEntity, ClassSet> classSets}) 1118 Map<ClassEntity, ClassSet> classSets})
978 : super( 1119 : super(
979 backend: backend,
980 commonElements: commonElements, 1120 commonElements: commonElements,
1121 constantSystem: constantSystem,
1122 nativeData: nativeData,
1123 interceptorData: interceptorData,
1124 backendUsage: backendUsage,
981 resolutionWorldBuilder: resolutionWorldBuilder, 1125 resolutionWorldBuilder: resolutionWorldBuilder,
982 functionSetBuilder: functionSetBuilder, 1126 functionSetBuilder: functionSetBuilder,
983 allTypedefs: allTypedefs, 1127 allTypedefs: allTypedefs,
984 mixinUses: mixinUses, 1128 mixinUses: mixinUses,
985 typesImplementedBySubclasses: typesImplementedBySubclasses, 1129 typesImplementedBySubclasses: typesImplementedBySubclasses,
986 classHierarchyNodes: classHierarchyNodes, 1130 classHierarchyNodes: classHierarchyNodes,
987 classSets: classSets); 1131 classSets: classSets);
988 1132
989 bool _checkClass(ClassElement cls) => cls.isDeclaration; 1133 bool _checkClass(ClassElement cls) => cls.isDeclaration;
1134
990 bool _checkEntity(Element element) => element.isDeclaration; 1135 bool _checkEntity(Element element) => element.isDeclaration;
991 1136
992 bool _checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) { 1137 bool _checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) {
993 return invariant(cls, cls.isDeclaration, 1138 return invariant(cls, cls.isDeclaration,
994 message: '$cls must be the declaration.') && 1139 message: '$cls must be the declaration.') &&
995 invariant(cls, cls.isResolved, 1140 invariant(cls, cls.isResolved,
996 message: 1141 message:
997 '$cls must be resolved.') /* && 1142 '$cls must be resolved.') /* &&
998 // TODO(johnniwinther): Reinsert this or similar invariant. Currently 1143 // TODO(johnniwinther): Reinsert this or similar invariant. Currently
999 // various call sites use uninstantiated classes for isSubtypeOf or 1144 // various call sites use uninstantiated classes for isSubtypeOf or
1000 // isSubclassOf. Some are valid, some are not. Work out better invariants 1145 // isSubclassOf. Some are valid, some are not. Work out better invariants
1001 // to catch the latter. 1146 // to catch the latter.
1002 (!mustBeInstantiated || 1147 (!mustBeInstantiated ||
1003 invariant(cls, isInstantiated(cls), 1148 invariant(cls, isInstantiated(cls),
1004 message: '$cls is not instantiated.'))*/ 1149 message: '$cls is not instantiated.'))*/
1005 ; 1150 ;
1006 } 1151 }
1007 1152
1008 /// Returns an iterable over the common supertypes of the [classes]. 1153 OrderedTypeSet _getOrderedTypeSet(ClassElement cls) =>
1009 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes) { 1154 cls.allSupertypesAndSelf;
1010 Iterator<ClassElement> iterator = classes.iterator;
1011 if (!iterator.moveNext()) return const <ClassElement>[];
1012 1155
1013 ClassElement cls = iterator.current; 1156 int _getHierarchyDepth(ClassElement cls) => cls.hierarchyDepth;
1014 assert(_checkInvariants(cls));
1015 OrderedTypeSet typeSet = cls.allSupertypesAndSelf;
1016 if (!iterator.moveNext()) return typeSet.types.map((type) => type.element);
1017 1157
1018 int depth = typeSet.maxDepth; 1158 ClassEntity _getSuperClass(ClassElement cls) => cls.superclass;
1019 Link<OrderedTypeSet> otherTypeSets = const Link<OrderedTypeSet>();
1020 do {
1021 ClassElement otherClass = iterator.current;
1022 assert(_checkInvariants(otherClass));
1023 OrderedTypeSet otherTypeSet = otherClass.allSupertypesAndSelf;
1024 otherTypeSets = otherTypeSets.prepend(otherTypeSet);
1025 if (otherTypeSet.maxDepth < depth) {
1026 depth = otherTypeSet.maxDepth;
1027 }
1028 } while (iterator.moveNext());
1029 1159
1030 List<ClassElement> commonSupertypes = <ClassElement>[]; 1160 Iterable<ClassEntity> _getInterfaces(ClassElement cls) sync* {
1031 OUTER: 1161 for (Link link = cls.interfaces; !link.isEmpty; link = link.tail) {
1032 for (Link<InterfaceType> link = typeSet[depth]; 1162 yield link.head.element;
1033 link.head.element != commonElements.objectClass;
1034 link = link.tail) {
1035 ClassElement cls = link.head.element;
1036 for (Link<OrderedTypeSet> link = otherTypeSets;
1037 !link.isEmpty;
1038 link = link.tail) {
1039 if (link.head.asInstanceOf(cls, cls.hierarchyDepth) == null) {
1040 continue OUTER;
1041 }
1042 }
1043 commonSupertypes.add(cls);
1044 } 1163 }
1045 commonSupertypes.add(commonElements.objectClass);
1046 return commonSupertypes;
1047 } 1164 }
1048 1165
1049 Iterable<ClassEntity> commonSubclasses(ClassEntity cls1, ClassQuery query1, 1166 bool _isNamedMixinApplication(ClassElement cls) =>
1050 ClassEntity cls2, ClassQuery query2) { 1167 cls.isNamedMixinApplication;
1051 // TODO(johnniwinther): Use [ClassSet] to compute this.
1052 // Compute the set of classes that are contained in both class subsets.
1053 Set<ClassEntity> common =
1054 _commonContainedClasses(cls1, query1, cls2, query2);
1055 if (common == null || common.isEmpty) return const <ClassEntity>[];
1056 // Narrow down the candidates by only looking at common classes
1057 // that do not have a superclass or supertype that will be a
1058 // better candidate.
1059 return common.where((ClassElement each) {
1060 bool containsSuperclass = common.contains(each.supertype.element);
1061 // If the superclass is also a candidate, then we don't want to
1062 // deal with this class. If we're only looking for a subclass we
1063 // know we don't have to look at the list of interfaces because
1064 // they can never be in the common set.
1065 if (containsSuperclass ||
1066 query1 == ClassQuery.SUBCLASS ||
1067 query2 == ClassQuery.SUBCLASS) {
1068 return !containsSuperclass;
1069 }
1070 // Run through the direct supertypes of the class. If the common
1071 // set contains the direct supertype of the class, we ignore the
1072 // the class because the supertype is a better candidate.
1073 for (Link link = each.interfaces; !link.isEmpty; link = link.tail) {
1074 if (common.contains(link.head.element)) return false;
1075 }
1076 return true;
1077 });
1078 }
1079 1168
1080 /// Returns an iterable over the live mixin applications that mixin [cls]. 1169 ClassEntity _getAppliedMixin(ClassElement cls) {
1081 Iterable<ClassEntity> mixinUsesOf(ClassEntity cls) { 1170 if (cls.isMixinApplication) {
1082 if (_liveMixinUses == null) { 1171 MixinApplicationElement application = cls;
1083 _liveMixinUses = new Map<ClassEntity, List<ClassEntity>>(); 1172 return application.mixin;
1084 for (ClassElement mixin in _mixinUses.keys) {
1085 List<ClassEntity> uses = <ClassEntity>[];
1086
1087 void addLiveUse(MixinApplicationElement mixinApplication) {
1088 if (isInstantiated(mixinApplication)) {
1089 uses.add(mixinApplication);
1090 } else if (mixinApplication.isNamedMixinApplication) {
1091 Set<ClassEntity> next = _mixinUses[mixinApplication];
1092 if (next != null) {
1093 next.forEach(addLiveUse);
1094 }
1095 }
1096 }
1097
1098 _mixinUses[mixin].forEach(addLiveUse);
1099 if (uses.isNotEmpty) {
1100 _liveMixinUses[mixin] = uses;
1101 }
1102 }
1103 } 1173 }
1104 Iterable<ClassEntity> uses = _liveMixinUses[cls]; 1174 return null;
1105 return uses != null ? uses : const <ClassEntity>[];
1106 }
1107
1108 /// Returns `true` if any live class that mixes in [mixin] is also a subclass
1109 /// of [superclass].
1110 bool hasAnySubclassThatMixes(ClassEntity superclass, ClassEntity mixin) {
1111 return mixinUsesOf(mixin).any((ClassElement each) {
1112 return each.isSubclassOf(superclass);
1113 });
1114 }
1115
1116 /// Returns `true` if [cls] or any superclass mixes in [mixin].
1117 bool isSubclassOfMixinUseOf(ClassEntity cls, ClassEntity mixin) {
1118 assert(_checkClass(cls));
1119 assert(_checkClass(mixin));
1120 if (isUsedAsMixin(mixin)) {
1121 ClassElement current = cls;
1122 while (current != null) {
1123 if (current.isMixinApplication) {
1124 MixinApplicationElement application = current;
1125 if (application.mixin == mixin) return true;
1126 }
1127 current = current.superclass;
1128 }
1129 }
1130 return false;
1131 } 1175 }
1132 1176
1133 @override 1177 @override
1134 bool hasElementIn(ClassEntity cls, Selector selector, Element element) { 1178 bool hasElementIn(ClassEntity cls, Selector selector, Element element) {
1135 // Use [:implementation:] of [element] 1179 // Use [:implementation:] of [element]
1136 // because our function set only stores declarations. 1180 // because our function set only stores declarations.
1137 Element result = findMatchIn(cls, selector); 1181 Element result = findMatchIn(cls, selector);
1138 return result == null 1182 return result == null
1139 ? false 1183 ? false
1140 : result.implementation == element.implementation; 1184 : result.implementation == element.implementation;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1209 // does not see generative constructor bodies because they are 1253 // does not see generative constructor bodies because they are
1210 // created by the backend. Also, it does not make any distinction 1254 // created by the backend. Also, it does not make any distinction
1211 // between a constructor and its body for side effects. This 1255 // between a constructor and its body for side effects. This
1212 // implies that currently, the side effects of a constructor body 1256 // implies that currently, the side effects of a constructor body
1213 // contain the side effects of the initializers. 1257 // contain the side effects of the initializers.
1214 assert(!element.isGenerativeConstructorBody); 1258 assert(!element.isGenerativeConstructorBody);
1215 assert(!element.isField); 1259 assert(!element.isField);
1216 return super.getSideEffectsOfElement(element); 1260 return super.getSideEffectsOfElement(element);
1217 } 1261 }
1218 } 1262 }
1263
1264 class KernelClosedWorld extends ClosedWorldBase {
1265 KernelClosedWorld(
1266 {CommonElements commonElements,
1267 ConstantSystem constantSystem,
1268 NativeData nativeData,
1269 InterceptorData interceptorData,
1270 BackendUsage backendUsage,
1271 ResolutionWorldBuilder resolutionWorldBuilder,
1272 FunctionSetBuilder functionSetBuilder,
1273 Iterable<TypedefElement> allTypedefs,
1274 Map<ClassEntity, Set<ClassEntity>> mixinUses,
1275 Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses,
1276 Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes,
1277 Map<ClassEntity, ClassSet> classSets})
1278 : super(
1279 commonElements: commonElements,
1280 constantSystem: constantSystem,
1281 nativeData: nativeData,
1282 interceptorData: interceptorData,
1283 backendUsage: backendUsage,
1284 resolutionWorldBuilder: resolutionWorldBuilder,
1285 functionSetBuilder: functionSetBuilder,
1286 allTypedefs: allTypedefs,
1287 mixinUses: mixinUses,
1288 typesImplementedBySubclasses: typesImplementedBySubclasses,
1289 classHierarchyNodes: classHierarchyNodes,
1290 classSets: classSets);
1291
1292 @override
1293 bool hasConcreteMatch(ClassEntity cls, Selector selector,
1294 {ClassEntity stopAtSuperclass}) {
1295 throw new UnimplementedError('KernelClosedWorld.hasConcreteMatch');
1296 }
1297
1298 @override
1299 bool _isNamedMixinApplication(ClassEntity cls) {
1300 throw new UnimplementedError('KernelClosedWorld._isNamedMixinApplication');
1301 }
1302
1303 @override
1304 ClassEntity _getAppliedMixin(ClassEntity cls) {
1305 throw new UnimplementedError('KernelClosedWorld._getAppliedMixin');
1306 }
1307
1308 @override
1309 Iterable<ClassEntity> _getInterfaces(ClassEntity cls) {
1310 throw new UnimplementedError('KernelClosedWorld._getInterfaces');
1311 }
1312
1313 @override
1314 ClassEntity _getSuperClass(ClassEntity cls) {
1315 throw new UnimplementedError('KernelClosedWorld._getSuperClass');
1316 }
1317
1318 @override
1319 int _getHierarchyDepth(ClassEntity cls) {
1320 throw new UnimplementedError('KernelClosedWorld._getHierarchyDepth');
1321 }
1322
1323 @override
1324 OrderedTypeSet _getOrderedTypeSet(ClassEntity cls) {
1325 throw new UnimplementedError('KernelClosedWorld._getOrderedTypeSet');
1326 }
1327
1328 @override
1329 bool _checkInvariants(ClassEntity cls, {bool mustBeInstantiated: true}) =>
1330 true;
1331
1332 @override
1333 bool _checkClass(ClassEntity cls) => true;
1334
1335 @override
1336 bool _checkEntity(Entity element) => true;
1337
1338 @override
1339 void registerClosureClass(ClassElement cls) {
1340 throw new UnimplementedError('KernelClosedWorld.registerClosureClass');
1341 }
1342
1343 @override
1344 String dump([ClassEntity cls]) {
1345 throw new UnimplementedError('KernelClosedWorld.dump');
1346 }
1347
1348 @override
1349 bool hasElementIn(ClassEntity cls, Selector selector, Entity element) {
1350 throw new UnimplementedError('KernelClosedWorld.hasElementIn');
1351 }
1352 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698