| Index: pkg/compiler/lib/src/universe/class_set.dart
|
| diff --git a/pkg/compiler/lib/src/universe/class_set.dart b/pkg/compiler/lib/src/universe/class_set.dart
|
| index e2497361aedd673b708652987e00a08bb2d9e7b2..d895de29edc85d86e2cd0b6fc35277210e082a09 100644
|
| --- a/pkg/compiler/lib/src/universe/class_set.dart
|
| +++ b/pkg/compiler/lib/src/universe/class_set.dart
|
| @@ -6,7 +6,6 @@ library dart2js.world.class_set;
|
|
|
| import 'dart:collection' show
|
| IterableBase;
|
| -import '../common.dart';
|
| import '../elements/elements.dart' show
|
| ClassElement;
|
| import '../util/enumset.dart' show
|
| @@ -93,14 +92,12 @@ class ClassHierarchyNode {
|
| return mask;
|
| }
|
|
|
| - final ClassHierarchyNode parentNode;
|
| final ClassElement cls;
|
| final EnumSet<Instantiation> _mask =
|
| new EnumSet<Instantiation>.fromValues(
|
| const <Instantiation>[Instantiation.UNINSTANTIATED]);
|
|
|
| ClassElement _leastUpperInstantiatedSubclass;
|
| - int _instantiatedSubclassCount = 0;
|
|
|
| /// `true` if [cls] has been directly instantiated.
|
| ///
|
| @@ -114,23 +111,14 @@ class ClassHierarchyNode {
|
|
|
| void set isDirectlyInstantiated(bool value) {
|
| if (value != isDirectlyInstantiated) {
|
| - ClassHierarchyNode parent = parentNode;
|
| if (value) {
|
| _mask.remove(Instantiation.UNINSTANTIATED);
|
| _mask.add(Instantiation.DIRECTLY_INSTANTIATED);
|
| - while (parent != null) {
|
| - parent._updateInstantiatedSubclassCount(1);
|
| - parent = parent.parentNode;
|
| - }
|
| } else {
|
| _mask.remove(Instantiation.DIRECTLY_INSTANTIATED);
|
| if (_mask.isEmpty) {
|
| _mask.add(Instantiation.UNINSTANTIATED);
|
| }
|
| - while (parent != null) {
|
| - parent._updateInstantiatedSubclassCount(-1);
|
| - parent = parent.parentNode;
|
| - }
|
| }
|
| }
|
| }
|
| @@ -143,18 +131,12 @@ class ClassHierarchyNode {
|
| /// class C extends B {}
|
| /// main() => [new B(), new C()];
|
| ///
|
| - bool get isIndirectlyInstantiated => _instantiatedSubclassCount > 0;
|
| -
|
| - /// The number of strict subclasses that are directly or indirectly
|
| - /// instantiated.
|
| - int get instantiatedSubclassCount => _instantiatedSubclassCount;
|
| -
|
| - void _updateInstantiatedSubclassCount(int change) {
|
| - bool before = isIndirectlyInstantiated;
|
| - _instantiatedSubclassCount += change;
|
| - bool after = isIndirectlyInstantiated;
|
| - if (before != after) {
|
| - if (after) {
|
| + bool get isIndirectlyInstantiated =>
|
| + _mask.contains(Instantiation.INDIRECTLY_INSTANTIATED);
|
| +
|
| + void set isIndirectlyInstantiated(bool value) {
|
| + if (value != isIndirectlyInstantiated) {
|
| + if (value) {
|
| _mask.remove(Instantiation.UNINSTANTIATED);
|
| _mask.add(Instantiation.INDIRECTLY_INSTANTIATED);
|
| } else {
|
| @@ -169,11 +151,7 @@ class ClassHierarchyNode {
|
| /// The nodes for the direct subclasses of [cls].
|
| Link<ClassHierarchyNode> _directSubclasses = const Link<ClassHierarchyNode>();
|
|
|
| - ClassHierarchyNode(this.parentNode, this.cls) {
|
| - if (parentNode != null) {
|
| - parentNode.addDirectSubclass(this);
|
| - }
|
| - }
|
| + ClassHierarchyNode(this.cls);
|
|
|
| /// Adds [subclass] as a direct subclass of [cls].
|
| void addDirectSubclass(ClassHierarchyNode subclass) {
|
| @@ -199,6 +177,24 @@ class ClassHierarchyNode {
|
|
|
| /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
|
| ///
|
| + /// The directly instantiated, indirectly instantiated and uninstantiated
|
| + /// subclasses of [cls] are returned if [includeDirectlyInstantiated],
|
| + /// [includeIndirectlyInstantiated], and [includeUninstantiated] are `true`,
|
| + /// respectively. If [strict] is `true`, [cls] itself is _not_ returned.
|
| + Iterable<ClassElement> subclasses(
|
| + {bool includeDirectlyInstantiated: true,
|
| + bool includeIndirectlyInstantiated: true,
|
| + bool includeUninstantiated: true,
|
| + bool strict: false}) {
|
| + EnumSet<Instantiation> mask = createMask(
|
| + includeDirectlyInstantiated: includeDirectlyInstantiated,
|
| + includeIndirectlyInstantiated:includeIndirectlyInstantiated,
|
| + includeUninstantiated: includeUninstantiated);
|
| + return subclassesByMask(mask, strict: strict);
|
| + }
|
| +
|
| + /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
|
| + ///
|
| /// Subclasses are included if their instantiation properties intersect with
|
| /// their corresponding [Instantiation] values in [mask]. If [strict] is
|
| /// `true`, [cls] itself is _not_ returned.
|
| @@ -209,64 +205,6 @@ class ClassHierarchyNode {
|
| this, mask, includeRoot: !strict);
|
| }
|
|
|
| - /// Applies [predicate] to each subclass of [cls] matching the criteria
|
| - /// specified by [mask] and [strict]. If [predicate] returns `true` on a
|
| - /// class, visitation is stopped immediately and the function returns `true`.
|
| - ///
|
| - /// [predicate] is applied to subclasses if their instantiation properties
|
| - /// intersect with their corresponding [Instantiation] values in [mask]. If
|
| - /// [strict] is `true`, [predicate] is _not_ called on [cls] itself.
|
| - bool anySubclass(
|
| - bool predicate(ClassElement cls),
|
| - EnumSet<Instantiation> mask,
|
| - {bool strict: false}) {
|
| -
|
| - ForEach wrapper(ClassElement cls) {
|
| - return predicate(cls) ? ForEach.STOP : ForEach.CONTINUE;
|
| - }
|
| - return forEachSubclass(wrapper, mask, strict: strict) == ForEach.STOP;
|
| - }
|
| -
|
| - /// Applies [f] to each subclass of [cls] matching the criteria specified by
|
| - /// [mask] and [strict].
|
| - ///
|
| - /// [f] is a applied to subclasses if their instantiation properties intersect
|
| - /// with their corresponding [Instantiation] values in [mask]. If [strict] is
|
| - /// `true`, [f] is _not_ called on [cls] itself.
|
| - ///
|
| - /// The visitation of subclasses can be cut short by the return value of [f].
|
| - /// If [ForEach.STOP] is returned, no further classes are visited and the
|
| - /// function stops immediately. If [ForEach.SKIP_CHILDREN] is returned, the
|
| - /// subclasses of the last visited class are skipped, but visitation
|
| - /// continues. The return value of the function is either [ForEach.STOP], if
|
| - /// visitation was stopped, or [ForEach.CONTINUE] if visitation continued to
|
| - /// the end.
|
| - ForEach forEachSubclass(
|
| - ForEachFunction f,
|
| - EnumSet<Instantiation> mask,
|
| - {bool strict: false}) {
|
| - ForEach forEach;
|
| - if (!strict && mask.intersects(_mask)) {
|
| - forEach = f(cls);
|
| - }
|
| - // Interpret `forEach == null` as `forEach == ForEach.CONTINUE`.
|
| - forEach ??= ForEach.CONTINUE;
|
| -
|
| - if (!mask.contains(Instantiation.UNINSTANTIATED) && !isInstantiated) {
|
| - // Bypass children since all are uninstantiated.
|
| - return forEach;
|
| - }
|
| - if (forEach == ForEach.CONTINUE) {
|
| - for (ClassHierarchyNode subclass in _directSubclasses) {
|
| - ForEach subForEach = subclass.forEachSubclass(f, mask);
|
| - if (subForEach == ForEach.STOP) {
|
| - return subForEach;
|
| - }
|
| - }
|
| - }
|
| - return forEach;
|
| - }
|
| -
|
| /// Returns the most specific subclass of [cls] (including [cls]) that is
|
| /// directly instantiated or a superclass of all directly instantiated
|
| /// subclasses. If [cls] is not instantiated, `null` is returned.
|
| @@ -337,8 +275,7 @@ class ClassHierarchyNode {
|
| if (instantiatedOnly && !child.isInstantiated) {
|
| continue;
|
| }
|
| - if (withRespectTo != null &&
|
| - !child.anySubclass(isRelatedTo, ClassHierarchyNode.ALL)) {
|
| + if (withRespectTo != null && !child.subclasses().any(isRelatedTo)) {
|
| continue;
|
| }
|
| if (needsComma) {
|
| @@ -430,31 +367,22 @@ class ClassSet {
|
|
|
| ClassElement get cls => node.cls;
|
|
|
| - /// Returns the number of directly instantiated subtypes of [cls].
|
| - int get instantiatedSubtypeCount {
|
| - int count = node.instantiatedSubclassCount;
|
| - if (_directSubtypes != null) {
|
| - for (ClassHierarchyNode subtypeNode in _directSubtypes) {
|
| - if (subtypeNode.isDirectlyInstantiated) {
|
| - count++;
|
| - }
|
| - count += subtypeNode.instantiatedSubclassCount;
|
| - }
|
| - }
|
| - return count;
|
| - }
|
| -
|
| - /// Returns `true` if all instantiated subtypes of [cls] are subclasses of
|
| - /// [cls].
|
| - bool get hasOnlyInstantiatedSubclasses {
|
| - if (_directSubtypes != null) {
|
| - for (ClassHierarchyNode subtypeNode in _directSubtypes) {
|
| - if (subtypeNode.isInstantiated) {
|
| - return false;
|
| - }
|
| - }
|
| - }
|
| - return true;
|
| + /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
|
| + ///
|
| + /// The directly instantiated, indirectly instantiated and uninstantiated
|
| + /// subclasses of [cls] are returned if [includeDirectlyInstantiated],
|
| + /// [includeIndirectlyInstantiated], and [includeUninstantiated] are `true`,
|
| + /// respectively. If [strict] is `true`, [cls] itself is _not_ returned.
|
| + Iterable<ClassElement> subclasses(
|
| + {bool includeDirectlyInstantiated: true,
|
| + bool includeIndirectlyInstantiated: true,
|
| + bool includeUninstantiated: true,
|
| + bool strict: false}) {
|
| + EnumSet<Instantiation> mask = ClassHierarchyNode.createMask(
|
| + includeDirectlyInstantiated: includeDirectlyInstantiated,
|
| + includeIndirectlyInstantiated:includeIndirectlyInstantiated,
|
| + includeUninstantiated: includeUninstantiated);
|
| + return subclassesByMask(mask, strict: strict);
|
| }
|
|
|
| /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
|
| @@ -486,6 +414,7 @@ class ClassSet {
|
| return subtypesByMask(mask, strict: strict);
|
| }
|
|
|
| +
|
| /// Returns an [Iterable] of the subtypes of [cls] possibly including [cls].
|
| ///
|
| /// Subtypes are included if their instantiation properties intersect with
|
| @@ -505,94 +434,6 @@ class ClassSet {
|
| includeRoot: !strict);
|
| }
|
|
|
| - /// Applies [predicate] to each subclass of [cls] matching the criteria
|
| - /// specified by [mask] and [strict]. If [predicate] returns `true` on a
|
| - /// class, visitation is stopped immediately and the function returns `true`.
|
| - ///
|
| - /// [predicate] is applied to subclasses if their instantiation properties
|
| - /// intersect with their corresponding [Instantiation] values in [mask]. If
|
| - /// [strict] is `true`, [predicate] is _not_ called on [cls] itself.
|
| - bool anySubclass(
|
| - bool predicate(ClassElement cls),
|
| - EnumSet<Instantiation> mask,
|
| - {bool strict: false}) {
|
| - return node.anySubclass(predicate, mask, strict: strict);
|
| - }
|
| -
|
| - /// Applies [f] to each subclass of [cls] matching the criteria specified by
|
| - /// [mask] and [strict].
|
| - ///
|
| - /// [f] is a applied to subclasses if their instantiation properties intersect
|
| - /// with their corresponding [Instantiation] values in [mask]. If [strict] is
|
| - /// `true`, [f] is _not_ called on [cls] itself.
|
| - ///
|
| - /// The visitation of subclasses can be cut short by the return value of [f].
|
| - /// If [ForEach.STOP] is returned, no further classes are visited and the
|
| - /// function stops immediately. If [ForEach.SKIP_CHILDREN] is returned, the
|
| - /// subclasses of the last visited class are skipped, but visitation
|
| - /// continues. The return value of the function is either [ForEach.STOP], if
|
| - /// visitation was stopped, or [ForEach.CONTINUE] if visitation continued to
|
| - /// the end.
|
| - ForEach forEachSubclass(
|
| - ForEachFunction f,
|
| - EnumSet<Instantiation> mask,
|
| - {bool strict: false}) {
|
| - return node.forEachSubclass(f, mask, strict: strict);
|
| - }
|
| -
|
| - /// Applies [predicate] to each subtype of [cls] matching the criteria
|
| - /// specified by [mask] and [strict]. If [predicate] returns `true` on a
|
| - /// class, visitation is stopped immediately and the function returns `true`.
|
| - ///
|
| - /// [predicate] is applied to subtypes if their instantiation properties
|
| - /// intersect with their corresponding [Instantiation] values in [mask]. If
|
| - /// [strict] is `true`, [predicate] is _not_ called on [cls] itself.
|
| - bool anySubtype(
|
| - bool predicate(ClassElement cls),
|
| - EnumSet<Instantiation> mask,
|
| - {bool strict: false}) {
|
| -
|
| - ForEach wrapper(ClassElement cls) {
|
| - return predicate(cls) ? ForEach.STOP : ForEach.CONTINUE;
|
| - }
|
| - return forEachSubtype(wrapper, mask, strict: strict) == ForEach.STOP;
|
| - }
|
| -
|
| - /// Applies [f] to each subtype of [cls] matching the criteria specified by
|
| - /// [mask] and [strict].
|
| - ///
|
| - /// [f] is a applied to subtypes if their instantiation properties intersect
|
| - /// with their corresponding [Instantiation] values in [mask]. If [strict] is
|
| - /// `true`, [f] is _not_ called on [cls] itself.
|
| - ///
|
| - /// The visitation of subtypes can be cut short by the return value of [f].
|
| - /// If [ForEach.STOP] is returned, no further classes are visited and the
|
| - /// function stops immediately. If [ForEach.SKIP_CHILDREN] is returned, the
|
| - /// subclasses of the last visited class are skipped, but visitation
|
| - /// continues. The return value of the function is either [ForEach.STOP], if
|
| - /// visitation was stopped, or [ForEach.CONTINUE] if visitation continued to
|
| - /// the end.
|
| - ForEach forEachSubtype(
|
| - ForEachFunction f,
|
| - EnumSet<Instantiation> mask,
|
| - {bool strict: false}) {
|
| - if (!mask.contains(Instantiation.UNINSTANTIATED) && !node.isInstantiated) {
|
| - // Bypass children since all are uninstantiated.
|
| - return ForEach.CONTINUE;
|
| - }
|
| - ForEach forEach = node.forEachSubclass(f, mask, strict: strict);
|
| - forEach ??= ForEach.CONTINUE;
|
| - if (forEach == ForEach.CONTINUE && _directSubtypes != null) {
|
| - for (ClassHierarchyNode subclass in _directSubtypes) {
|
| - ForEach subForEach = subclass.forEachSubclass(f, mask);
|
| - if (subForEach == ForEach.STOP) {
|
| - return subForEach;
|
| - }
|
| - }
|
| - }
|
| - return forEach;
|
| - }
|
| -
|
| /// Adds [subtype] as a subtype of [cls].
|
| void addSubtype(ClassHierarchyNode subtype) {
|
| if (node.contains(subtype.cls)) {
|
| @@ -854,20 +695,3 @@ class SubtypesIterator extends Iterator<ClassElement> {
|
| return false;
|
| }
|
| }
|
| -
|
| -/// Enum values returned from the [ForEachFunction] provided to the `forEachX`
|
| -/// functions of [ClassHierarchyNode] and [ClassSet]. The value is used to
|
| -/// control the continued iteration.
|
| -enum ForEach {
|
| - /// Iteration continues.
|
| - CONTINUE,
|
| - /// Iteration stops immediately.
|
| - STOP,
|
| - /// Iteration skips the child classes of the current class.
|
| - SKIP_CHILDREN,
|
| -}
|
| -
|
| -/// Visiting function used for the `forEachX` functions of [ClassHierarchyNode]
|
| -/// and [ClassSet]. The return value controls the continued iteration. If `null`
|
| -/// is returned, iteration continues to the end.
|
| -typedef ForEach ForEachFunction(ClassElement cls);
|
|
|