| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |