| 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_usage.dart' show BackendUsage; | 21 import 'js_backend/backend.dart' show JavaScriptBackend; |
| 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(); | 367 ClosedWorld closeWorld(DiagnosticReporter reporter); |
| 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 ConstantSystem constantSystem; | 387 final JavaScriptBackend _backend; |
| 388 final NativeData nativeData; | 388 InterceptorData get interceptorData => _backend.interceptorData; |
| 389 final InterceptorData interceptorData; | |
| 390 final BackendUsage _backendUsage; | |
| 391 | |
| 392 FunctionSet _allFunctions; | 389 FunctionSet _allFunctions; |
| 393 | 390 |
| 394 final Iterable<TypedefElement> _allTypedefs; | 391 final Iterable<TypedefElement> _allTypedefs; |
| 395 | 392 |
| 396 final Map<ClassEntity, Set<ClassEntity>> _mixinUses; | 393 final Map<ClassEntity, Set<ClassEntity>> _mixinUses; |
| 397 Map<ClassEntity, List<ClassEntity>> _liveMixinUses; | 394 Map<ClassEntity, List<ClassEntity>> _liveMixinUses; |
| 398 | 395 |
| 399 final Map<ClassEntity, Set<ClassEntity>> _typesImplementedBySubclasses; | 396 final Map<ClassEntity, Set<ClassEntity>> _typesImplementedBySubclasses; |
| 400 | 397 |
| 401 // We keep track of subtype and subclass relationships in four | 398 // We keep track of subtype and subclass relationships in four |
| (...skipping 13 matching lines...) Expand all Loading... |
| 415 | 412 |
| 416 final Set<Entity> _functionsThatMightBePassedToApply = new Set<Entity>(); | 413 final Set<Entity> _functionsThatMightBePassedToApply = new Set<Entity>(); |
| 417 | 414 |
| 418 CommonMasks _commonMasks; | 415 CommonMasks _commonMasks; |
| 419 | 416 |
| 420 final CommonElements commonElements; | 417 final CommonElements commonElements; |
| 421 | 418 |
| 422 final ResolutionWorldBuilder _resolverWorld; | 419 final ResolutionWorldBuilder _resolverWorld; |
| 423 | 420 |
| 424 ClosedWorldBase( | 421 ClosedWorldBase( |
| 425 {this.commonElements, | 422 {JavaScriptBackend backend, |
| 426 this.constantSystem, | 423 this.commonElements, |
| 427 this.nativeData, | |
| 428 this.interceptorData, | |
| 429 BackendUsage backendUsage, | |
| 430 ResolutionWorldBuilder resolutionWorldBuilder, | 424 ResolutionWorldBuilder resolutionWorldBuilder, |
| 431 FunctionSetBuilder functionSetBuilder, | 425 FunctionSetBuilder functionSetBuilder, |
| 432 Iterable<TypedefElement> allTypedefs, | 426 Iterable<TypedefElement> allTypedefs, |
| 433 Map<ClassEntity, Set<ClassEntity>> mixinUses, | 427 Map<ClassEntity, Set<ClassEntity>> mixinUses, |
| 434 Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses, | 428 Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses, |
| 435 Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes, | 429 Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes, |
| 436 Map<ClassEntity, ClassSet> classSets}) | 430 Map<ClassEntity, ClassSet> classSets}) |
| 437 : this._backendUsage = backendUsage, | 431 : this._backend = backend, |
| 438 this._resolverWorld = resolutionWorldBuilder, | 432 this._resolverWorld = resolutionWorldBuilder, |
| 439 this._allTypedefs = allTypedefs, | 433 this._allTypedefs = allTypedefs, |
| 440 this._mixinUses = mixinUses, | 434 this._mixinUses = mixinUses, |
| 441 this._typesImplementedBySubclasses = typesImplementedBySubclasses, | 435 this._typesImplementedBySubclasses = typesImplementedBySubclasses, |
| 442 this._classHierarchyNodes = classHierarchyNodes, | 436 this._classHierarchyNodes = classHierarchyNodes, |
| 443 this._classSets = classSets { | 437 this._classSets = classSets { |
| 444 _commonMasks = new CommonMasks(this); | 438 _commonMasks = new CommonMasks(this); |
| 445 _allFunctions = functionSetBuilder.close(this); | 439 _allFunctions = functionSetBuilder.close(this); |
| 446 } | 440 } |
| 447 | 441 |
| 442 NativeData get nativeData => _backend.nativeData; |
| 443 |
| 448 @override | 444 @override |
| 449 ClosedWorld get closedWorld => this; | 445 ClosedWorld get closedWorld => this; |
| 450 | 446 |
| 451 /// Cache of [FlatTypeMask]s grouped by the 8 possible values of the | 447 /// Cache of [FlatTypeMask]s grouped by the 8 possible values of the |
| 452 /// `FlatTypeMask.flags` property. | 448 /// `FlatTypeMask.flags` property. |
| 453 final List<Map<ClassEntity, TypeMask>> _canonicalizedTypeMasks = | 449 final List<Map<ClassEntity, TypeMask>> _canonicalizedTypeMasks = |
| 454 new List<Map<ClassEntity, TypeMask>>.filled(8, null); | 450 new List<Map<ClassEntity, TypeMask>>.filled(8, null); |
| 455 | 451 |
| 456 FunctionSet get allFunctions => _allFunctions; | 452 FunctionSet get allFunctions => _allFunctions; |
| 457 | 453 |
| 458 CommonMasks get commonMasks { | 454 CommonMasks get commonMasks { |
| 459 return _commonMasks; | 455 return _commonMasks; |
| 460 } | 456 } |
| 461 | 457 |
| 458 ConstantSystem get constantSystem => _backend.constantSystem; |
| 459 |
| 462 TypeMask getCachedMask(ClassEntity base, int flags, TypeMask createMask()) { | 460 TypeMask getCachedMask(ClassEntity base, int flags, TypeMask createMask()) { |
| 463 Map<ClassEntity, TypeMask> cachedMasks = | 461 Map<ClassEntity, TypeMask> cachedMasks = |
| 464 _canonicalizedTypeMasks[flags] ??= <ClassEntity, TypeMask>{}; | 462 _canonicalizedTypeMasks[flags] ??= <ClassEntity, TypeMask>{}; |
| 465 return cachedMasks.putIfAbsent(base, createMask); | 463 return cachedMasks.putIfAbsent(base, createMask); |
| 466 } | 464 } |
| 467 | 465 |
| 468 bool _checkEntity(Entity element); | 466 bool _checkEntity(Entity element); |
| 469 | 467 |
| 470 bool _checkClass(ClassEntity cls); | 468 bool _checkClass(ClassEntity cls); |
| 471 | 469 |
| 472 bool _checkInvariants(ClassEntity cls, {bool mustBeInstantiated: true}); | 470 bool _checkInvariants(ClassEntity cls, {bool mustBeInstantiated: true}); |
| 473 | 471 |
| 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 | |
| 486 @override | 472 @override |
| 487 bool isInstantiated(ClassEntity cls) { | 473 bool isInstantiated(ClassEntity cls) { |
| 488 assert(_checkClass(cls)); | 474 assert(_checkClass(cls)); |
| 489 ClassHierarchyNode node = _classHierarchyNodes[cls]; | 475 ClassHierarchyNode node = _classHierarchyNodes[cls]; |
| 490 return node != null && node.isInstantiated; | 476 return node != null && node.isInstantiated; |
| 491 } | 477 } |
| 492 | 478 |
| 493 @override | 479 @override |
| 494 bool isDirectlyInstantiated(ClassEntity cls) { | 480 bool isDirectlyInstantiated(ClassEntity cls) { |
| 495 assert(_checkClass(cls)); | 481 assert(_checkClass(cls)); |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 816 return subclassesNeedNoSuchMethod(node); | 802 return subclassesNeedNoSuchMethod(node); |
| 817 } else { | 803 } else { |
| 818 if (subclassesNeedNoSuchMethod(node)) return true; | 804 if (subclassesNeedNoSuchMethod(node)) return true; |
| 819 for (ClassHierarchyNode subtypeNode in classSet.subtypeNodes) { | 805 for (ClassHierarchyNode subtypeNode in classSet.subtypeNodes) { |
| 820 if (subclassesNeedNoSuchMethod(subtypeNode)) return true; | 806 if (subclassesNeedNoSuchMethod(subtypeNode)) return true; |
| 821 } | 807 } |
| 822 return false; | 808 return false; |
| 823 } | 809 } |
| 824 } | 810 } |
| 825 | 811 |
| 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 | |
| 950 /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies | 812 /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies |
| 951 /// of known classes. | 813 /// of known classes. |
| 952 /// | 814 /// |
| 953 /// This method is only provided for testing. For queries on classes, use the | 815 /// This method is only provided for testing. For queries on classes, use the |
| 954 /// methods defined in [ClosedWorld]. | 816 /// methods defined in [ClosedWorld]. |
| 955 ClassHierarchyNode getClassHierarchyNode(ClassEntity cls) { | 817 ClassHierarchyNode getClassHierarchyNode(ClassEntity cls) { |
| 956 assert(_checkClass(cls)); | 818 assert(_checkClass(cls)); |
| 957 return _classHierarchyNodes[cls]; | 819 return _classHierarchyNodes[cls]; |
| 958 } | 820 } |
| 959 | 821 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 979 } | 841 } |
| 980 | 842 |
| 981 MemberEntity locateSingleElement(Selector selector, TypeMask mask) { | 843 MemberEntity locateSingleElement(Selector selector, TypeMask mask) { |
| 982 mask ??= commonMasks.dynamicType; | 844 mask ??= commonMasks.dynamicType; |
| 983 return mask.locateSingleElement(selector, this); | 845 return mask.locateSingleElement(selector, this); |
| 984 } | 846 } |
| 985 | 847 |
| 986 TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask) { | 848 TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask) { |
| 987 bool canReachAll = true; | 849 bool canReachAll = true; |
| 988 if (mask != null) { | 850 if (mask != null) { |
| 989 canReachAll = _backendUsage.isInvokeOnUsed && | 851 canReachAll = _backend.backendUsage.isInvokeOnUsed && |
| 990 mask.needsNoSuchMethodHandling(selector, this); | 852 mask.needsNoSuchMethodHandling(selector, this); |
| 991 } | 853 } |
| 992 return canReachAll ? commonMasks.dynamicType : mask; | 854 return canReachAll ? commonMasks.dynamicType : mask; |
| 993 } | 855 } |
| 994 | 856 |
| 995 bool fieldNeverChanges(MemberEntity element) { | 857 bool fieldNeverChanges(MemberEntity element) { |
| 996 if (!element.isField) return false; | 858 if (!element.isField) return false; |
| 997 if (nativeData.isNativeMember(element)) { | 859 if (nativeData.isNativeMember(element)) { |
| 998 // Some native fields are views of data that may be changed by operations. | 860 // Some native fields are views of data that may be changed by operations. |
| 999 // E.g. node.firstChild depends on parentNode.removeBefore(n1, n2). | 861 // E.g. node.firstChild depends on parentNode.removeBefore(n1, n2). |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1097 } | 959 } |
| 1098 | 960 |
| 1099 @override | 961 @override |
| 1100 bool getCurrentlyKnownMightBePassedToApply(Entity element) { | 962 bool getCurrentlyKnownMightBePassedToApply(Entity element) { |
| 1101 return getMightBePassedToApply(element); | 963 return getMightBePassedToApply(element); |
| 1102 } | 964 } |
| 1103 } | 965 } |
| 1104 | 966 |
| 1105 class ClosedWorldImpl extends ClosedWorldBase { | 967 class ClosedWorldImpl extends ClosedWorldBase { |
| 1106 ClosedWorldImpl( | 968 ClosedWorldImpl( |
| 1107 {CommonElements commonElements, | 969 {JavaScriptBackend backend, |
| 1108 ConstantSystem constantSystem, | 970 CommonElements commonElements, |
| 1109 NativeData nativeData, | |
| 1110 InterceptorData interceptorData, | |
| 1111 BackendUsage backendUsage, | |
| 1112 ResolutionWorldBuilder resolutionWorldBuilder, | 971 ResolutionWorldBuilder resolutionWorldBuilder, |
| 1113 FunctionSetBuilder functionSetBuilder, | 972 FunctionSetBuilder functionSetBuilder, |
| 1114 Iterable<TypedefElement> allTypedefs, | 973 Iterable<TypedefElement> allTypedefs, |
| 1115 Map<ClassEntity, Set<ClassEntity>> mixinUses, | 974 Map<ClassEntity, Set<ClassEntity>> mixinUses, |
| 1116 Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses, | 975 Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses, |
| 1117 Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes, | 976 Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes, |
| 1118 Map<ClassEntity, ClassSet> classSets}) | 977 Map<ClassEntity, ClassSet> classSets}) |
| 1119 : super( | 978 : super( |
| 979 backend: backend, |
| 1120 commonElements: commonElements, | 980 commonElements: commonElements, |
| 1121 constantSystem: constantSystem, | |
| 1122 nativeData: nativeData, | |
| 1123 interceptorData: interceptorData, | |
| 1124 backendUsage: backendUsage, | |
| 1125 resolutionWorldBuilder: resolutionWorldBuilder, | 981 resolutionWorldBuilder: resolutionWorldBuilder, |
| 1126 functionSetBuilder: functionSetBuilder, | 982 functionSetBuilder: functionSetBuilder, |
| 1127 allTypedefs: allTypedefs, | 983 allTypedefs: allTypedefs, |
| 1128 mixinUses: mixinUses, | 984 mixinUses: mixinUses, |
| 1129 typesImplementedBySubclasses: typesImplementedBySubclasses, | 985 typesImplementedBySubclasses: typesImplementedBySubclasses, |
| 1130 classHierarchyNodes: classHierarchyNodes, | 986 classHierarchyNodes: classHierarchyNodes, |
| 1131 classSets: classSets); | 987 classSets: classSets); |
| 1132 | 988 |
| 1133 bool _checkClass(ClassElement cls) => cls.isDeclaration; | 989 bool _checkClass(ClassElement cls) => cls.isDeclaration; |
| 1134 | |
| 1135 bool _checkEntity(Element element) => element.isDeclaration; | 990 bool _checkEntity(Element element) => element.isDeclaration; |
| 1136 | 991 |
| 1137 bool _checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) { | 992 bool _checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) { |
| 1138 return invariant(cls, cls.isDeclaration, | 993 return invariant(cls, cls.isDeclaration, |
| 1139 message: '$cls must be the declaration.') && | 994 message: '$cls must be the declaration.') && |
| 1140 invariant(cls, cls.isResolved, | 995 invariant(cls, cls.isResolved, |
| 1141 message: | 996 message: |
| 1142 '$cls must be resolved.') /* && | 997 '$cls must be resolved.') /* && |
| 1143 // TODO(johnniwinther): Reinsert this or similar invariant. Currently | 998 // TODO(johnniwinther): Reinsert this or similar invariant. Currently |
| 1144 // various call sites use uninstantiated classes for isSubtypeOf or | 999 // various call sites use uninstantiated classes for isSubtypeOf or |
| 1145 // isSubclassOf. Some are valid, some are not. Work out better invariants | 1000 // isSubclassOf. Some are valid, some are not. Work out better invariants |
| 1146 // to catch the latter. | 1001 // to catch the latter. |
| 1147 (!mustBeInstantiated || | 1002 (!mustBeInstantiated || |
| 1148 invariant(cls, isInstantiated(cls), | 1003 invariant(cls, isInstantiated(cls), |
| 1149 message: '$cls is not instantiated.'))*/ | 1004 message: '$cls is not instantiated.'))*/ |
| 1150 ; | 1005 ; |
| 1151 } | 1006 } |
| 1152 | 1007 |
| 1153 OrderedTypeSet _getOrderedTypeSet(ClassElement cls) => | 1008 /// Returns an iterable over the common supertypes of the [classes]. |
| 1154 cls.allSupertypesAndSelf; | 1009 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes) { |
| 1010 Iterator<ClassElement> iterator = classes.iterator; |
| 1011 if (!iterator.moveNext()) return const <ClassElement>[]; |
| 1155 | 1012 |
| 1156 int _getHierarchyDepth(ClassElement cls) => cls.hierarchyDepth; | 1013 ClassElement cls = iterator.current; |
| 1014 assert(_checkInvariants(cls)); |
| 1015 OrderedTypeSet typeSet = cls.allSupertypesAndSelf; |
| 1016 if (!iterator.moveNext()) return typeSet.types.map((type) => type.element); |
| 1157 | 1017 |
| 1158 ClassEntity _getSuperClass(ClassElement cls) => cls.superclass; | 1018 int depth = typeSet.maxDepth; |
| 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()); |
| 1159 | 1029 |
| 1160 Iterable<ClassEntity> _getInterfaces(ClassElement cls) sync* { | 1030 List<ClassElement> commonSupertypes = <ClassElement>[]; |
| 1161 for (Link link = cls.interfaces; !link.isEmpty; link = link.tail) { | 1031 OUTER: |
| 1162 yield link.head.element; | 1032 for (Link<InterfaceType> link = typeSet[depth]; |
| 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); |
| 1163 } | 1044 } |
| 1045 commonSupertypes.add(commonElements.objectClass); |
| 1046 return commonSupertypes; |
| 1164 } | 1047 } |
| 1165 | 1048 |
| 1166 bool _isNamedMixinApplication(ClassElement cls) => | 1049 Iterable<ClassEntity> commonSubclasses(ClassEntity cls1, ClassQuery query1, |
| 1167 cls.isNamedMixinApplication; | 1050 ClassEntity cls2, ClassQuery query2) { |
| 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 } |
| 1168 | 1079 |
| 1169 ClassEntity _getAppliedMixin(ClassElement cls) { | 1080 /// Returns an iterable over the live mixin applications that mixin [cls]. |
| 1170 if (cls.isMixinApplication) { | 1081 Iterable<ClassEntity> mixinUsesOf(ClassEntity cls) { |
| 1171 MixinApplicationElement application = cls; | 1082 if (_liveMixinUses == null) { |
| 1172 return application.mixin; | 1083 _liveMixinUses = new Map<ClassEntity, List<ClassEntity>>(); |
| 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 } |
| 1173 } | 1103 } |
| 1174 return null; | 1104 Iterable<ClassEntity> uses = _liveMixinUses[cls]; |
| 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; |
| 1175 } | 1131 } |
| 1176 | 1132 |
| 1177 @override | 1133 @override |
| 1178 bool hasElementIn(ClassEntity cls, Selector selector, Element element) { | 1134 bool hasElementIn(ClassEntity cls, Selector selector, Element element) { |
| 1179 // Use [:implementation:] of [element] | 1135 // Use [:implementation:] of [element] |
| 1180 // because our function set only stores declarations. | 1136 // because our function set only stores declarations. |
| 1181 Element result = findMatchIn(cls, selector); | 1137 Element result = findMatchIn(cls, selector); |
| 1182 return result == null | 1138 return result == null |
| 1183 ? false | 1139 ? false |
| 1184 : result.implementation == element.implementation; | 1140 : result.implementation == element.implementation; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1253 // does not see generative constructor bodies because they are | 1209 // does not see generative constructor bodies because they are |
| 1254 // created by the backend. Also, it does not make any distinction | 1210 // created by the backend. Also, it does not make any distinction |
| 1255 // between a constructor and its body for side effects. This | 1211 // between a constructor and its body for side effects. This |
| 1256 // implies that currently, the side effects of a constructor body | 1212 // implies that currently, the side effects of a constructor body |
| 1257 // contain the side effects of the initializers. | 1213 // contain the side effects of the initializers. |
| 1258 assert(!element.isGenerativeConstructorBody); | 1214 assert(!element.isGenerativeConstructorBody); |
| 1259 assert(!element.isField); | 1215 assert(!element.isField); |
| 1260 return super.getSideEffectsOfElement(element); | 1216 return super.getSideEffectsOfElement(element); |
| 1261 } | 1217 } |
| 1262 } | 1218 } |
| 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 |