| 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 universe; | 5 library universe; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import '../cache_strategy.dart'; | 9 import '../cache_strategy.dart'; |
| 10 import '../common.dart'; | 10 import '../common.dart'; |
| 11 import '../common/backend_api.dart' show Backend; | 11 import '../common/backend_api.dart' show Backend; |
| 12 import '../common/names.dart' show Identifiers; | 12 import '../common/names.dart' show Identifiers; |
| 13 import '../common/resolution.dart' show Resolution; | 13 import '../common/resolution.dart' show Resolution; |
| 14 import '../compiler.dart' show Compiler; | 14 import '../compiler.dart' show Compiler; |
| 15 import '../core_types.dart'; |
| 15 import '../dart_types.dart'; | 16 import '../dart_types.dart'; |
| 16 import '../elements/elements.dart'; | 17 import '../elements/elements.dart'; |
| 17 import '../elements/entities.dart'; | 18 import '../elements/entities.dart'; |
| 18 import '../universe/class_set.dart' show Instantiation; | 19 import '../universe/class_set.dart'; |
| 20 import '../universe/function_set.dart' show FunctionSetBuilder; |
| 19 import '../util/enumset.dart'; | 21 import '../util/enumset.dart'; |
| 20 import '../util/util.dart'; | 22 import '../util/util.dart'; |
| 21 import '../world.dart' show World, ClosedWorld, OpenWorld, WorldImpl; | 23 import '../world.dart' show World, ClosedWorld, ClosedWorldImpl, OpenWorld; |
| 22 import 'selector.dart' show Selector; | 24 import 'selector.dart' show Selector; |
| 23 import 'use.dart' show DynamicUse, DynamicUseKind, StaticUse, StaticUseKind; | 25 import 'use.dart' show DynamicUse, DynamicUseKind, StaticUse, StaticUseKind; |
| 24 | 26 |
| 25 /// The known constraint on receiver for a dynamic call site. | 27 /// The known constraint on receiver for a dynamic call site. |
| 26 /// | 28 /// |
| 27 /// This can for instance be used to constrain this dynamic call to `foo` to | 29 /// This can for instance be used to constrain this dynamic call to `foo` to |
| 28 /// 'receivers of the exact instance `Bar`': | 30 /// 'receivers of the exact instance `Bar`': |
| 29 /// | 31 /// |
| 30 /// class Bar { | 32 /// class Bar { |
| 31 /// void foo() {} | 33 /// void foo() {} |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 /// Registers that [type] is checked in this universe. The unaliased type is | 161 /// Registers that [type] is checked in this universe. The unaliased type is |
| 160 /// returned. | 162 /// returned. |
| 161 DartType registerIsCheck(DartType type); | 163 DartType registerIsCheck(DartType type); |
| 162 | 164 |
| 163 /// All directly instantiated types, that is, the types of the directly | 165 /// All directly instantiated types, that is, the types of the directly |
| 164 /// instantiated classes. | 166 /// instantiated classes. |
| 165 // TODO(johnniwinther): Improve semantic precision. | 167 // TODO(johnniwinther): Improve semantic precision. |
| 166 Iterable<DartType> get instantiatedTypes; | 168 Iterable<DartType> get instantiatedTypes; |
| 167 } | 169 } |
| 168 | 170 |
| 169 abstract class ResolutionWorldBuilder implements WorldBuilder { | 171 abstract class ResolutionWorldBuilder implements WorldBuilder, OpenWorld { |
| 170 /// Set of (live) local functions (closures) whose signatures reference type | 172 /// Set of (live) local functions (closures) whose signatures reference type |
| 171 /// variables. | 173 /// variables. |
| 172 /// | 174 /// |
| 173 /// A live function is one whose enclosing member function has been enqueued. | 175 /// A live function is one whose enclosing member function has been enqueued. |
| 174 Iterable<Element> get closuresWithFreeTypeVariables; | 176 Iterable<Element> get closuresWithFreeTypeVariables; |
| 175 | 177 |
| 176 /// Set of (live) `call` methods whose signatures reference type variables. | 178 /// Set of (live) `call` methods whose signatures reference type variables. |
| 177 /// | 179 /// |
| 178 /// A live `call` method is one whose enclosing class has been instantiated. | 180 /// A live `call` method is one whose enclosing class has been instantiated. |
| 179 Iterable<Element> get callMethodsWithFreeTypeVariables; | 181 Iterable<Element> get callMethodsWithFreeTypeVariables; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 195 Iterable<Element> get fieldSetters; | 197 Iterable<Element> get fieldSetters; |
| 196 | 198 |
| 197 /// Call [f] for all classes with instantiated types. This includes the | 199 /// Call [f] for all classes with instantiated types. This includes the |
| 198 /// directly and abstractly instantiated classes but also classes whose type | 200 /// directly and abstractly instantiated classes but also classes whose type |
| 199 /// arguments are used in live factory constructors. | 201 /// arguments are used in live factory constructors. |
| 200 void forEachInstantiatedClass(f(ClassElement cls, InstantiationInfo info)); | 202 void forEachInstantiatedClass(f(ClassElement cls, InstantiationInfo info)); |
| 201 | 203 |
| 202 /// Returns `true` if [member] is invoked as a setter. | 204 /// Returns `true` if [member] is invoked as a setter. |
| 203 bool hasInvokedSetter(Element member); | 205 bool hasInvokedSetter(Element member); |
| 204 | 206 |
| 205 /// The [OpenWorld] being created by this world builder. | |
| 206 // TODO(johnniwinther): Merge this with [ResolutionWorldBuilder]. | |
| 207 OpenWorld get openWorld; | |
| 208 | |
| 209 /// The closed world computed by this world builder. | 207 /// The closed world computed by this world builder. |
| 210 /// | 208 /// |
| 211 /// This is only available after the world builder has been closed. | 209 /// This is only available after the world builder has been closed. |
| 212 ClosedWorld get closedWorldForTesting; | 210 ClosedWorld get closedWorldForTesting; |
| 213 } | 211 } |
| 214 | 212 |
| 215 /// The type and kind of an instantiation registered through | 213 /// The type and kind of an instantiation registered through |
| 216 /// `ResolutionWorldBuilder.registerTypeInstantiation`. | 214 /// `ResolutionWorldBuilder.registerTypeInstantiation`. |
| 217 class Instance { | 215 class Instance { |
| 218 final InterfaceType type; | 216 final InterfaceType type; |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 456 final SelectorConstraintsStrategy selectorConstraintsStrategy; | 454 final SelectorConstraintsStrategy selectorConstraintsStrategy; |
| 457 | 455 |
| 458 bool hasRuntimeTypeSupport = false; | 456 bool hasRuntimeTypeSupport = false; |
| 459 bool hasIsolateSupport = false; | 457 bool hasIsolateSupport = false; |
| 460 bool hasFunctionApplySupport = false; | 458 bool hasFunctionApplySupport = false; |
| 461 | 459 |
| 462 /// Used for testing the new more precise computation of instantiated types | 460 /// Used for testing the new more precise computation of instantiated types |
| 463 /// and classes. | 461 /// and classes. |
| 464 bool useInstantiationMap = false; | 462 bool useInstantiationMap = false; |
| 465 | 463 |
| 466 WorldImpl _openWorld; | |
| 467 | |
| 468 final Backend _backend; | 464 final Backend _backend; |
| 469 final Resolution _resolution; | 465 final Resolution _resolution; |
| 466 bool _closed = false; |
| 467 ClosedWorld _closedWorldCache; |
| 468 FunctionSetBuilder _allFunctions; |
| 469 |
| 470 final Set<TypedefElement> _allTypedefs = new Set<TypedefElement>(); |
| 471 |
| 472 final Map<ClassElement, Set<MixinApplicationElement>> _mixinUses = |
| 473 new Map<ClassElement, Set<MixinApplicationElement>>(); |
| 474 |
| 475 // We keep track of subtype and subclass relationships in four |
| 476 // distinct sets to make class hierarchy analysis faster. |
| 477 final Map<ClassElement, ClassHierarchyNode> _classHierarchyNodes = |
| 478 <ClassElement, ClassHierarchyNode>{}; |
| 479 final Map<ClassElement, ClassSet> _classSets = <ClassElement, ClassSet>{}; |
| 480 |
| 481 final Map<ClassElement, Map<ClassElement, bool>> _subtypeCoveredByCache = |
| 482 <ClassElement, Map<ClassElement, bool>>{}; |
| 483 |
| 484 final Set<Element> alreadyPopulated; |
| 485 |
| 486 final CacheStrategy cacheStrategy; |
| 487 |
| 488 bool get isClosed => _closed; |
| 470 | 489 |
| 471 ResolutionWorldBuilderImpl(Backend backend, Resolution resolution, | 490 ResolutionWorldBuilderImpl(Backend backend, Resolution resolution, |
| 472 CacheStrategy cacheStrategy, this.selectorConstraintsStrategy) | 491 CacheStrategy cacheStrategy, this.selectorConstraintsStrategy) |
| 473 : this._backend = backend, | 492 : this._backend = backend, |
| 474 this._resolution = resolution { | 493 this._resolution = resolution, |
| 475 _openWorld = new WorldImpl(this, backend, resolution.coreClasses, | 494 this.cacheStrategy = cacheStrategy, |
| 476 resolution.coreTypes, cacheStrategy); | 495 alreadyPopulated = cacheStrategy.newSet() { |
| 496 _allFunctions = new FunctionSetBuilder(); |
| 477 } | 497 } |
| 478 | 498 |
| 479 Iterable<ClassElement> get processedClasses => _processedClasses.keys | 499 Iterable<ClassElement> get processedClasses => _processedClasses.keys |
| 480 .where((cls) => _processedClasses[cls].isInstantiated); | 500 .where((cls) => _processedClasses[cls].isInstantiated); |
| 481 | 501 |
| 482 OpenWorld get openWorld => _openWorld; | 502 CommonElements get commonElements => _resolution.commonElements; |
| 503 |
| 504 CoreTypes get coreTypes => _resolution.coreTypes; |
| 483 | 505 |
| 484 ClosedWorld get closedWorldForTesting { | 506 ClosedWorld get closedWorldForTesting { |
| 485 if (!_openWorld.isClosed) { | 507 if (!_closed) { |
| 486 throw new SpannableAssertionFailure( | 508 throw new SpannableAssertionFailure( |
| 487 NO_LOCATION_SPANNABLE, "The world builder has not yet been closed."); | 509 NO_LOCATION_SPANNABLE, "The world builder has not yet been closed."); |
| 488 } | 510 } |
| 489 return _openWorld.closedWorldCache; | 511 return _closedWorldCache; |
| 490 } | 512 } |
| 491 | 513 |
| 492 /// All directly instantiated classes, that is, classes with a generative | 514 /// All directly instantiated classes, that is, classes with a generative |
| 493 /// constructor that has been called directly and not only through a | 515 /// constructor that has been called directly and not only through a |
| 494 /// super-call. | 516 /// super-call. |
| 495 // TODO(johnniwinther): Improve semantic precision. | 517 // TODO(johnniwinther): Improve semantic precision. |
| 496 Iterable<ClassElement> get directlyInstantiatedClasses { | 518 Iterable<ClassElement> get directlyInstantiatedClasses { |
| 497 Set<ClassElement> classes = new Set<ClassElement>(); | 519 Set<ClassElement> classes = new Set<ClassElement>(); |
| 498 getInstantiationMap().forEach((ClassElement cls, InstantiationInfo info) { | 520 getInstantiationMap().forEach((ClassElement cls, InstantiationInfo info) { |
| 499 if (info.hasInstantiation) { | 521 if (info.hasInstantiation) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 void forEachInstantiatedClass(f(ClassElement cls, InstantiationInfo info)) { | 611 void forEachInstantiatedClass(f(ClassElement cls, InstantiationInfo info)) { |
| 590 getInstantiationMap().forEach(f); | 612 getInstantiationMap().forEach(f); |
| 591 } | 613 } |
| 592 | 614 |
| 593 bool _hasMatchingSelector( | 615 bool _hasMatchingSelector( |
| 594 Map<Selector, SelectorConstraints> selectors, Element member) { | 616 Map<Selector, SelectorConstraints> selectors, Element member) { |
| 595 if (selectors == null) return false; | 617 if (selectors == null) return false; |
| 596 for (Selector selector in selectors.keys) { | 618 for (Selector selector in selectors.keys) { |
| 597 if (selector.appliesUnnamed(member)) { | 619 if (selector.appliesUnnamed(member)) { |
| 598 SelectorConstraints masks = selectors[selector]; | 620 SelectorConstraints masks = selectors[selector]; |
| 599 if (masks.applies(member, selector, _openWorld)) { | 621 if (masks.applies(member, selector, this)) { |
| 600 return true; | 622 return true; |
| 601 } | 623 } |
| 602 } | 624 } |
| 603 } | 625 } |
| 604 return false; | 626 return false; |
| 605 } | 627 } |
| 606 | 628 |
| 607 /// Returns the instantiation map used for computing the closed world. | 629 /// Returns the instantiation map used for computing the closed world. |
| 608 /// | 630 /// |
| 609 /// If [useInstantiationMap] is `true`, redirections are removed and | 631 /// If [useInstantiationMap] is `true`, redirections are removed and |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 662 } | 684 } |
| 663 | 685 |
| 664 void registerDynamicUse( | 686 void registerDynamicUse( |
| 665 DynamicUse dynamicUse, MemberUsedCallback memberUsed) { | 687 DynamicUse dynamicUse, MemberUsedCallback memberUsed) { |
| 666 Selector selector = dynamicUse.selector; | 688 Selector selector = dynamicUse.selector; |
| 667 String methodName = selector.name; | 689 String methodName = selector.name; |
| 668 switch (dynamicUse.kind) { | 690 switch (dynamicUse.kind) { |
| 669 case DynamicUseKind.INVOKE: | 691 case DynamicUseKind.INVOKE: |
| 670 if (_registerNewSelector(dynamicUse, _invokedNames)) { | 692 if (_registerNewSelector(dynamicUse, _invokedNames)) { |
| 671 _processInstanceMembers(methodName, (_MemberUsage usage) { | 693 _processInstanceMembers(methodName, (_MemberUsage usage) { |
| 672 if (dynamicUse.appliesUnnamed(usage.entity, _openWorld)) { | 694 if (dynamicUse.appliesUnnamed(usage.entity, this)) { |
| 673 memberUsed(usage.entity, usage.invoke()); | 695 memberUsed(usage.entity, usage.invoke()); |
| 674 return true; | 696 return true; |
| 675 } | 697 } |
| 676 return false; | 698 return false; |
| 677 }); | 699 }); |
| 678 } | 700 } |
| 679 break; | 701 break; |
| 680 case DynamicUseKind.GET: | 702 case DynamicUseKind.GET: |
| 681 if (_registerNewSelector(dynamicUse, _invokedGetters)) { | 703 if (_registerNewSelector(dynamicUse, _invokedGetters)) { |
| 682 _processInstanceMembers(methodName, (_MemberUsage usage) { | 704 _processInstanceMembers(methodName, (_MemberUsage usage) { |
| 683 if (dynamicUse.appliesUnnamed(usage.entity, _openWorld)) { | 705 if (dynamicUse.appliesUnnamed(usage.entity, this)) { |
| 684 memberUsed(usage.entity, usage.read()); | 706 memberUsed(usage.entity, usage.read()); |
| 685 return true; | 707 return true; |
| 686 } | 708 } |
| 687 return false; | 709 return false; |
| 688 }); | 710 }); |
| 689 _processInstanceFunctions(methodName, (_MemberUsage usage) { | 711 _processInstanceFunctions(methodName, (_MemberUsage usage) { |
| 690 if (dynamicUse.appliesUnnamed(usage.entity, _openWorld)) { | 712 if (dynamicUse.appliesUnnamed(usage.entity, this)) { |
| 691 memberUsed(usage.entity, usage.read()); | 713 memberUsed(usage.entity, usage.read()); |
| 692 return true; | 714 return true; |
| 693 } | 715 } |
| 694 return false; | 716 return false; |
| 695 }); | 717 }); |
| 696 } | 718 } |
| 697 break; | 719 break; |
| 698 case DynamicUseKind.SET: | 720 case DynamicUseKind.SET: |
| 699 if (_registerNewSelector(dynamicUse, _invokedSetters)) { | 721 if (_registerNewSelector(dynamicUse, _invokedSetters)) { |
| 700 _processInstanceMembers(methodName, (_MemberUsage usage) { | 722 _processInstanceMembers(methodName, (_MemberUsage usage) { |
| 701 if (dynamicUse.appliesUnnamed(usage.entity, _openWorld)) { | 723 if (dynamicUse.appliesUnnamed(usage.entity, this)) { |
| 702 memberUsed(usage.entity, usage.write()); | 724 memberUsed(usage.entity, usage.write()); |
| 703 return true; | 725 return true; |
| 704 } | 726 } |
| 705 return false; | 727 return false; |
| 706 }); | 728 }); |
| 707 } | 729 } |
| 708 break; | 730 break; |
| 709 } | 731 } |
| 710 } | 732 } |
| 711 | 733 |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 899 // and that may not have happened yet. | 921 // and that may not have happened yet. |
| 900 // So instead we use the enclosing class, which we know have had | 922 // So instead we use the enclosing class, which we know have had |
| 901 // its metadata parsed and analyzed. | 923 // its metadata parsed and analyzed. |
| 902 // Note: this assumes that there are no non-native fields on native | 924 // Note: this assumes that there are no non-native fields on native |
| 903 // classes, which may not be the case when a native class is subclassed. | 925 // classes, which may not be the case when a native class is subclassed. |
| 904 bool isNative = _backend.isNative(cls); | 926 bool isNative = _backend.isNative(cls); |
| 905 _MemberUsage usage = _instanceMemberUsage.putIfAbsent(member, () { | 927 _MemberUsage usage = _instanceMemberUsage.putIfAbsent(member, () { |
| 906 _MemberUsage usage = new _MemberUsage(member, isNative: isNative); | 928 _MemberUsage usage = new _MemberUsage(member, isNative: isNative); |
| 907 useSet.addAll(usage.appliedUse); | 929 useSet.addAll(usage.appliedUse); |
| 908 if (member.isField && isNative) { | 930 if (member.isField && isNative) { |
| 909 _openWorld.registerUsedElement(member); | 931 registerUsedElement(member); |
| 910 } | 932 } |
| 911 if (member.isFunction && | 933 if (member.isFunction && |
| 912 member.name == Identifiers.call && | 934 member.name == Identifiers.call && |
| 913 !cls.typeVariables.isEmpty) { | 935 !cls.typeVariables.isEmpty) { |
| 914 callMethodsWithFreeTypeVariables.add(member); | 936 callMethodsWithFreeTypeVariables.add(member); |
| 915 } | 937 } |
| 916 | 938 |
| 917 if (_hasInvokedGetter(member)) { | 939 if (_hasInvokedGetter(member)) { |
| 918 useSet.addAll(usage.read()); | 940 useSet.addAll(usage.read()); |
| 919 } | 941 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 936 // getters on the function. | 958 // getters on the function. |
| 937 _instanceFunctionsByName | 959 _instanceFunctionsByName |
| 938 .putIfAbsent(memberName, () => new Set<_MemberUsage>()) | 960 .putIfAbsent(memberName, () => new Set<_MemberUsage>()) |
| 939 .add(usage); | 961 .add(usage); |
| 940 } | 962 } |
| 941 | 963 |
| 942 memberUsed(usage.entity, useSet); | 964 memberUsed(usage.entity, useSet); |
| 943 return usage; | 965 return usage; |
| 944 }); | 966 }); |
| 945 } | 967 } |
| 968 |
| 969 /// Returns an iterable over all mixin applications that mixin [cls]. |
| 970 Iterable<MixinApplicationElement> allMixinUsesOf(ClassElement cls) { |
| 971 Iterable<MixinApplicationElement> uses = _mixinUses[cls]; |
| 972 return uses != null ? uses : const <MixinApplicationElement>[]; |
| 973 } |
| 974 |
| 975 /// Called to add [cls] to the set of known classes. |
| 976 /// |
| 977 /// This ensures that class hierarchy queries can be performed on [cls] and |
| 978 /// classes that extend or implement it. |
| 979 void registerClass(ClassElement cls) => _registerClass(cls); |
| 980 |
| 981 void _registerClass(ClassElement cls, {bool isDirectlyInstantiated: false}) { |
| 982 _ensureClassSet(cls); |
| 983 if (isDirectlyInstantiated) { |
| 984 _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true); |
| 985 } |
| 986 } |
| 987 |
| 988 void registerTypedef(TypedefElement typdef) { |
| 989 _allTypedefs.add(typdef); |
| 990 } |
| 991 |
| 992 ClassHierarchyNode _ensureClassHierarchyNode(ClassElement cls) { |
| 993 cls = cls.declaration; |
| 994 return _classHierarchyNodes.putIfAbsent(cls, () { |
| 995 ClassHierarchyNode parentNode; |
| 996 if (cls.superclass != null) { |
| 997 parentNode = _ensureClassHierarchyNode(cls.superclass); |
| 998 } |
| 999 return new ClassHierarchyNode(parentNode, cls); |
| 1000 }); |
| 1001 } |
| 1002 |
| 1003 ClassSet _ensureClassSet(ClassElement cls) { |
| 1004 cls = cls.declaration; |
| 1005 return _classSets.putIfAbsent(cls, () { |
| 1006 ClassHierarchyNode node = _ensureClassHierarchyNode(cls); |
| 1007 ClassSet classSet = new ClassSet(node); |
| 1008 |
| 1009 for (InterfaceType type in cls.allSupertypes) { |
| 1010 // TODO(johnniwinther): Optimization: Avoid adding [cls] to |
| 1011 // superclasses. |
| 1012 ClassSet subtypeSet = _ensureClassSet(type.element); |
| 1013 subtypeSet.addSubtype(node); |
| 1014 } |
| 1015 if (cls.isMixinApplication) { |
| 1016 // TODO(johnniwinther): Store this in the [ClassSet]. |
| 1017 MixinApplicationElement mixinApplication = cls; |
| 1018 if (mixinApplication.mixin != null) { |
| 1019 // If [mixinApplication] is malformed [mixin] is `null`. |
| 1020 registerMixinUse(mixinApplication, mixinApplication.mixin); |
| 1021 } |
| 1022 } |
| 1023 |
| 1024 return classSet; |
| 1025 }); |
| 1026 } |
| 1027 |
| 1028 void _updateSuperClassHierarchyNodeForClass(ClassHierarchyNode node) { |
| 1029 // Ensure that classes implicitly implementing `Function` are in its |
| 1030 // subtype set. |
| 1031 ClassElement cls = node.cls; |
| 1032 if (cls != commonElements.functionClass && |
| 1033 cls.implementsFunction(commonElements)) { |
| 1034 ClassSet subtypeSet = _ensureClassSet(commonElements.functionClass); |
| 1035 subtypeSet.addSubtype(node); |
| 1036 } |
| 1037 if (!node.isInstantiated && node.parentNode != null) { |
| 1038 _updateSuperClassHierarchyNodeForClass(node.parentNode); |
| 1039 } |
| 1040 } |
| 1041 |
| 1042 void _updateClassHierarchyNodeForClass(ClassElement cls, |
| 1043 {bool directlyInstantiated: false, bool abstractlyInstantiated: false}) { |
| 1044 ClassHierarchyNode node = _ensureClassHierarchyNode(cls); |
| 1045 _updateSuperClassHierarchyNodeForClass(node); |
| 1046 if (directlyInstantiated) { |
| 1047 node.isDirectlyInstantiated = true; |
| 1048 } |
| 1049 if (abstractlyInstantiated) { |
| 1050 node.isAbstractlyInstantiated = true; |
| 1051 } |
| 1052 } |
| 1053 |
| 1054 ClosedWorld closeWorld(DiagnosticReporter reporter) { |
| 1055 Map<ClassElement, Set<ClassElement>> typesImplementedBySubclasses = |
| 1056 new Map<ClassElement, Set<ClassElement>>(); |
| 1057 |
| 1058 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` |
| 1059 /// properties of the [ClassHierarchyNode] for [cls]. |
| 1060 |
| 1061 void addSubtypes(ClassElement cls, InstantiationInfo info) { |
| 1062 if (!info.hasInstantiation) { |
| 1063 return; |
| 1064 } |
| 1065 if (cacheStrategy.hasIncrementalSupport && !alreadyPopulated.add(cls)) { |
| 1066 return; |
| 1067 } |
| 1068 assert(cls.isDeclaration); |
| 1069 if (!cls.isResolved) { |
| 1070 reporter.internalError(cls, 'Class "${cls.name}" is not resolved.'); |
| 1071 } |
| 1072 |
| 1073 _updateClassHierarchyNodeForClass(cls, |
| 1074 directlyInstantiated: info.isDirectlyInstantiated, |
| 1075 abstractlyInstantiated: info.isAbstractlyInstantiated); |
| 1076 |
| 1077 // Walk through the superclasses, and record the types |
| 1078 // implemented by that type on the superclasses. |
| 1079 ClassElement superclass = cls.superclass; |
| 1080 while (superclass != null) { |
| 1081 Set<Element> typesImplementedBySubclassesOfCls = |
| 1082 typesImplementedBySubclasses.putIfAbsent( |
| 1083 superclass, () => new Set<ClassElement>()); |
| 1084 for (DartType current in cls.allSupertypes) { |
| 1085 typesImplementedBySubclassesOfCls.add(current.element); |
| 1086 } |
| 1087 superclass = superclass.superclass; |
| 1088 } |
| 1089 } |
| 1090 |
| 1091 // Use the [:seenClasses:] set to include non-instantiated |
| 1092 // classes: if the superclass of these classes require RTI, then |
| 1093 // they also need RTI, so that a constructor passes the type |
| 1094 // variables to the super constructor. |
| 1095 forEachInstantiatedClass(addSubtypes); |
| 1096 |
| 1097 _closed = true; |
| 1098 return _closedWorldCache = new ClosedWorldImpl( |
| 1099 backend: _backend, |
| 1100 commonElements: commonElements, |
| 1101 coreTypes: coreTypes, |
| 1102 resolverWorld: this, |
| 1103 functionSetBuilder: _allFunctions, |
| 1104 allTypedefs: _allTypedefs, |
| 1105 mixinUses: _mixinUses, |
| 1106 typesImplementedBySubclasses: typesImplementedBySubclasses, |
| 1107 classHierarchyNodes: _classHierarchyNodes, |
| 1108 classSets: _classSets); |
| 1109 } |
| 1110 |
| 1111 void registerMixinUse( |
| 1112 MixinApplicationElement mixinApplication, ClassElement mixin) { |
| 1113 // TODO(johnniwinther): Add map restricted to live classes. |
| 1114 // We don't support patch classes as mixin. |
| 1115 assert(mixin.isDeclaration); |
| 1116 Set<MixinApplicationElement> users = |
| 1117 _mixinUses.putIfAbsent(mixin, () => new Set<MixinApplicationElement>()); |
| 1118 users.add(mixinApplication); |
| 1119 } |
| 1120 |
| 1121 void registerUsedElement(Element element) { |
| 1122 if (element.isInstanceMember && !element.isAbstract) { |
| 1123 _allFunctions.add(element); |
| 1124 } |
| 1125 } |
| 1126 |
| 1127 ClosedWorld get closedWorldCache { |
| 1128 assert(isClosed); |
| 1129 return _closedWorldCache; |
| 1130 } |
| 946 } | 1131 } |
| 947 | 1132 |
| 948 /// World builder specific to codegen. | 1133 /// World builder specific to codegen. |
| 949 /// | 1134 /// |
| 950 /// This adds additional access to liveness of selectors and elements. | 1135 /// This adds additional access to liveness of selectors and elements. |
| 951 abstract class CodegenWorldBuilder implements WorldBuilder { | 1136 abstract class CodegenWorldBuilder implements WorldBuilder { |
| 952 void forEachInvokedName( | 1137 void forEachInvokedName( |
| 953 f(String name, Map<Selector, SelectorConstraints> selectors)); | 1138 f(String name, Map<Selector, SelectorConstraints> selectors)); |
| 954 | 1139 |
| 955 void forEachInvokedGetter( | 1140 void forEachInvokedGetter( |
| (...skipping 618 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1574 if (hasClosurization) { | 1759 if (hasClosurization) { |
| 1575 return MemberUses.NONE; | 1760 return MemberUses.NONE; |
| 1576 } | 1761 } |
| 1577 hasNormalUse = hasClosurization = true; | 1762 hasNormalUse = hasClosurization = true; |
| 1578 return _pendingUse.removeAll(MemberUses.ALL_STATIC); | 1763 return _pendingUse.removeAll(MemberUses.ALL_STATIC); |
| 1579 } | 1764 } |
| 1580 | 1765 |
| 1581 @override | 1766 @override |
| 1582 EnumSet<MemberUse> get _originalUse => MemberUses.ALL_STATIC; | 1767 EnumSet<MemberUse> get _originalUse => MemberUses.ALL_STATIC; |
| 1583 } | 1768 } |
| OLD | NEW |