Chromium Code Reviews| 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 ac856a2802b6f84db10c158034822b74b4c3a9a6..7be19571ab84db0fe0a684300640f6c3867788ec 100644 |
| --- a/pkg/compiler/lib/src/universe/class_set.dart |
| +++ b/pkg/compiler/lib/src/universe/class_set.dart |
| @@ -4,9 +4,21 @@ |
| library dart2js.world.class_set; |
| -import 'dart:collection' show IterableBase; |
| -import '../elements/elements.dart' show ClassElement; |
| -import '../util/util.dart' show Link; |
| +import 'dart:collection' show |
| + IterableBase; |
| +import '../elements/elements.dart' show |
| + ClassElement; |
| +import '../util/enumset.dart' show |
| + EnumSet; |
| +import '../util/util.dart' show |
| + Link; |
| + |
| +/// Enum for the different kinds of instantiation of a class. |
| +enum Instantiation { |
| + UNINSTANTIATED, |
| + DIRECTLY_INSTANTIATED, |
| + INDIRECTLY_INSTANTIATED, |
| +} |
| /// Node for [cls] in a tree forming the subclass relation of [ClassElement]s. |
| /// |
| @@ -34,7 +46,57 @@ import '../util/util.dart' show Link; |
| /// E |
| /// |
| class ClassHierarchyNode { |
| + /// Enum set for selecting instantiated classes in |
| + /// [ClassHierarchyNode.subclassesByMask], |
| + /// [ClassHierarchyNode.subclassesByMask] and [ClassSet.subtypesByMask]. |
| + static final EnumSet<Instantiation> INSTANTIATED = |
| + new EnumSet<Instantiation>.fromValues( |
| + const <Instantiation>[ |
| + Instantiation.DIRECTLY_INSTANTIATED, |
| + Instantiation.INDIRECTLY_INSTANTIATED], |
| + fixed: true); |
| + |
| + /// Enum set for selecting directly instantiated classes in |
| + /// [ClassHierarchyNode.subclassesByMask], |
| + /// [ClassHierarchyNode.subclassesByMask] and [ClassSet.subtypesByMask]. |
| + static final EnumSet<Instantiation> DIRECTLY_INSTANTIATED = |
| + new EnumSet<Instantiation>.fromValues( |
| + const <Instantiation>[Instantiation.DIRECTLY_INSTANTIATED], |
| + fixed: true); |
| + |
| + /// Enum set for selecting all classes in |
| + /// [ClassHierarchyNode.subclassesByMask], |
| + /// [ClassHierarchyNode.subclassesByMask] and [ClassSet.subtypesByMask]. |
| + static final EnumSet<Instantiation> ALL = |
| + new EnumSet<Instantiation>.fromValues( |
| + Instantiation.values, |
| + fixed: true); |
| + |
| + /// Creates an enum set for selecting the returned classes in |
| + /// [ClassHierarchyNode.subclassesByMask], |
| + /// [ClassHierarchyNode.subclassesByMask] and [ClassSet.subtypesByMask]. |
| + static EnumSet<Instantiation> createMask( |
| + {bool includeDirectlyInstantiated: true, |
| + bool includeIndirectlyInstantiated: true, |
| + bool includeUninstantiated: true}) { |
| + EnumSet<Instantiation> mask = new EnumSet<Instantiation>(); |
| + if (includeDirectlyInstantiated) { |
| + mask.add(Instantiation.DIRECTLY_INSTANTIATED); |
| + } |
| + if (includeIndirectlyInstantiated) { |
| + mask.add(Instantiation.INDIRECTLY_INSTANTIATED); |
| + } |
| + if (includeUninstantiated) { |
| + mask.add(Instantiation.UNINSTANTIATED); |
| + } |
| + return mask; |
| + } |
| + |
| final ClassElement cls; |
| + final EnumSet<Instantiation> _mask = |
| + new EnumSet<Instantiation>.fromValues( |
| + const <Instantiation>[Instantiation.UNINSTANTIATED]); |
| + |
| ClassElement _leastUpperInstantiatedSubclass; |
| /// `true` if [cls] has been directly instantiated. |
| @@ -44,7 +106,22 @@ class ClassHierarchyNode { |
| /// class C extends B {} |
| /// main() => new C(); |
| /// |
| - bool isDirectlyInstantiated = false; |
| + bool get isDirectlyInstantiated => |
| + _mask.contains(Instantiation.DIRECTLY_INSTANTIATED); |
| + |
| + void set isDirectlyInstantiated(bool value) { |
| + if (value != isDirectlyInstantiated) { |
| + if (value) { |
| + _mask.remove(Instantiation.UNINSTANTIATED); |
| + _mask.add(Instantiation.DIRECTLY_INSTANTIATED); |
| + } else { |
| + _mask.remove(Instantiation.DIRECTLY_INSTANTIATED); |
| + if (_mask.isEmpty) { |
| + _mask.add(Instantiation.UNINSTANTIATED); |
| + } |
| + } |
| + } |
| + } |
| /// `true` if [cls] has been instantiated through subclasses. |
| /// |
| @@ -54,7 +131,22 @@ class ClassHierarchyNode { |
| /// class C extends B {} |
| /// main() => [new B(), new C()]; |
| /// |
| - bool isIndirectlyInstantiated = false; |
| + 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 { |
| + _mask.remove(Instantiation.INDIRECTLY_INSTANTIATED); |
| + if (_mask.isEmpty) { |
| + _mask.add(Instantiation.UNINSTANTIATED); |
| + } |
| + } |
| + } |
| + } |
| /// The nodes for the direct subclasses of [cls]. |
| Link<ClassHierarchyNode> _directSubclasses = const Link<ClassHierarchyNode>(); |
| @@ -94,12 +186,23 @@ class ClassHierarchyNode { |
| bool includeIndirectlyInstantiated: true, |
| bool includeUninstantiated: true, |
| bool strict: false}) { |
| - return new ClassHierarchyNodeIterable( |
| - this, |
| - includeRoot: !strict, |
| + EnumSet<Instantiation> mask = createMask( |
| includeDirectlyInstantiated: includeDirectlyInstantiated, |
| - includeIndirectlyInstantiated: includeIndirectlyInstantiated, |
| + includeIndirectlyInstantiated:includeIndirectlyInstantiated, |
| includeUninstantiated: includeUninstantiated); |
| + return subclassesByMask(mask, strict: strict); |
| + } |
| + |
| + /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls]. |
| + /// |
| + /// The [mask] defines the included subset of the subclasses based on their |
| + /// instantiation properties. If [strict] is `true`, [cls] itself is _not_ |
| + /// returned. |
| + Iterable<ClassElement> subclassesByMask( |
| + EnumSet<Instantiation> mask, |
| + {bool strict: false}) { |
| + return new ClassHierarchyNodeIterable( |
| + this, mask, includeRoot: !strict); |
| } |
| /// Returns the most specific subclass of [cls] (including [cls]) that is |
| @@ -275,11 +378,22 @@ class ClassSet { |
| bool includeIndirectlyInstantiated: true, |
| bool includeUninstantiated: true, |
| bool strict: false}) { |
| - return node.subclasses( |
| - strict: strict, |
| + EnumSet<Instantiation> mask = ClassHierarchyNode.createMask( |
| includeDirectlyInstantiated: includeDirectlyInstantiated, |
| - includeIndirectlyInstantiated: includeIndirectlyInstantiated, |
| + includeIndirectlyInstantiated:includeIndirectlyInstantiated, |
| includeUninstantiated: includeUninstantiated); |
| + return subclassesByMask(mask, strict: strict); |
| + } |
| + |
| + /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls]. |
| + /// |
| + /// The [mask] defines the included subset of the subclasses based on their |
| + /// instantiation properties. If [strict] is `true`, [cls] itself is _not_ |
| + /// returned. |
| + Iterable<ClassElement> subclassesByMask( |
| + EnumSet<Instantiation> mask, |
| + {bool strict: false}) { |
| + return node.subclassesByMask(mask, strict: strict); |
| } |
| /// Returns an [Iterable] of the subtypes of [cls] possibly including [cls]. |
| @@ -293,18 +407,31 @@ class ClassSet { |
| bool includeIndirectlyInstantiated: true, |
| bool includeUninstantiated: true, |
| bool strict: false}) { |
| + EnumSet<Instantiation> mask = ClassHierarchyNode.createMask( |
| + includeDirectlyInstantiated: includeDirectlyInstantiated, |
| + includeIndirectlyInstantiated:includeIndirectlyInstantiated, |
| + includeUninstantiated: includeUninstantiated); |
| + return subtypesByMask(mask, strict: strict); |
| + } |
| + |
| + |
| + /// Returns an [Iterable] of the subtypes of [cls] possibly including [cls]. |
| + /// |
| + /// The [mask] defines the included subset of the subtypes based on their |
|
sigurdm
2016/01/11 08:48:55
It is not clear from the description of `mask` tha
Johnni Winther
2016/01/22 11:54:13
Updated the comments.
|
| + /// instantiation properties. If [strict] is `true`, [cls] itself is _not_ |
| + /// returned. |
| + Iterable<ClassElement> subtypesByMask( |
| + EnumSet<Instantiation> mask, |
| + {bool strict: false}) { |
| if (_directSubtypes == null) { |
| - return node.subclasses( |
| - strict: strict, |
| - includeDirectlyInstantiated: includeDirectlyInstantiated, |
| - includeIndirectlyInstantiated: includeIndirectlyInstantiated, |
| - includeUninstantiated: includeUninstantiated); |
| + return node.subclassesByMask( |
| + mask, |
| + strict: strict); |
| } |
| + |
| return new SubtypesIterable.SubtypesIterator(this, |
| - includeRoot: !strict, |
| - includeDirectlyInstantiated: includeDirectlyInstantiated, |
| - includeIndirectlyInstantiated: includeIndirectlyInstantiated, |
| - includeUninstantiated: includeUninstantiated); |
| + mask, |
| + includeRoot: !strict); |
| } |
| /// Adds [subtype] as a subtype of [cls]. |
| @@ -412,17 +539,13 @@ class ClassSet { |
| /// Iterable for subclasses of a [ClassHierarchyNode]. |
| class ClassHierarchyNodeIterable extends IterableBase<ClassElement> { |
| final ClassHierarchyNode root; |
| + final EnumSet<Instantiation> mask; |
| final bool includeRoot; |
| - final bool includeDirectlyInstantiated; |
| - final bool includeIndirectlyInstantiated; |
| - final bool includeUninstantiated; |
| ClassHierarchyNodeIterable( |
| this.root, |
| - {this.includeRoot: true, |
| - this.includeDirectlyInstantiated: true, |
| - this.includeIndirectlyInstantiated: true, |
| - this.includeUninstantiated: true}) { |
| + this.mask, |
| + {this.includeRoot: true}) { |
| if (root == null) throw new StateError("No root for iterable."); |
| } |
| @@ -455,14 +578,12 @@ class ClassHierarchyNodeIterator implements Iterator<ClassElement> { |
| bool get includeRoot => iterable.includeRoot; |
| - bool get includeDirectlyInstantiated => iterable.includeDirectlyInstantiated; |
| + EnumSet<Instantiation> get mask => iterable.mask; |
| - bool get includeIndirectlyInstantiated { |
| - return iterable.includeIndirectlyInstantiated; |
| + bool get includeUninstantiated { |
| + return mask.contains(Instantiation.UNINSTANTIATED); |
| } |
| - bool get includeUninstantiated => iterable.includeUninstantiated; |
| - |
| @override |
| ClassElement get current { |
| return currentNode != null ? currentNode.cls : null; |
| @@ -511,33 +632,20 @@ class ClassHierarchyNodeIterator implements Iterator<ClassElement> { |
| /// Returns `true` if the class of [node] is a valid result for this iterator. |
| bool _isValid(ClassHierarchyNode node) { |
| if (!includeRoot && node == root) return false; |
| - if (includeDirectlyInstantiated && node.isDirectlyInstantiated) { |
| - return true; |
| - } |
| - if (includeIndirectlyInstantiated && node.isIndirectlyInstantiated) { |
| - return true; |
| - } |
| - if (includeUninstantiated && !node.isInstantiated) { |
| - return true; |
| - } |
| - return false; |
| + return mask.intersects(node._mask); |
| } |
| } |
| /// Iterable for the subtypes in a [ClassSet]. |
| class SubtypesIterable extends IterableBase<ClassElement> { |
| final ClassSet subtypeSet; |
| + final EnumSet<Instantiation> mask; |
| final bool includeRoot; |
| - final bool includeDirectlyInstantiated; |
| - final bool includeIndirectlyInstantiated; |
| - final bool includeUninstantiated; |
| SubtypesIterable.SubtypesIterator( |
| this.subtypeSet, |
| - {this.includeRoot: true, |
| - this.includeDirectlyInstantiated: true, |
| - this.includeIndirectlyInstantiated: true, |
| - this.includeUninstantiated: true}); |
| + this.mask, |
| + {this.includeRoot: true}); |
| @override |
| Iterator<ClassElement> get iterator => new SubtypesIterator(this); |
| @@ -553,13 +661,7 @@ class SubtypesIterator extends Iterator<ClassElement> { |
| bool get includeRoot => iterable.includeRoot; |
| - bool get includeDirectlyInstantiated => iterable.includeDirectlyInstantiated; |
| - |
| - bool get includeIndirectlyInstantiated { |
| - return iterable.includeIndirectlyInstantiated; |
| - } |
| - |
| - bool get includeUninstantiated => iterable.includeUninstantiated; |
| + EnumSet<Instantiation> get mask => iterable.mask; |
| @override |
| ClassElement get current { |
| @@ -573,11 +675,9 @@ class SubtypesIterator extends Iterator<ClassElement> { |
| bool moveNext() { |
| if (elements == null && hierarchyNodes == null) { |
| // Initial state. Iterate through subclasses. |
| - elements = iterable.subtypeSet.node.subclasses( |
| - strict: !includeRoot, |
| - includeDirectlyInstantiated: includeDirectlyInstantiated, |
| - includeIndirectlyInstantiated: includeIndirectlyInstantiated, |
| - includeUninstantiated: includeUninstantiated).iterator; |
| + elements = iterable.subtypeSet.node.subclassesByMask( |
| + mask, |
| + strict: !includeRoot).iterator; |
| } |
| if (elements != null && elements.moveNext()) { |
| return true; |
| @@ -587,10 +687,7 @@ class SubtypesIterator extends Iterator<ClassElement> { |
| hierarchyNodes = iterable.subtypeSet._directSubtypes.iterator; |
| } |
| while (hierarchyNodes.moveNext()) { |
| - elements = hierarchyNodes.current.subclasses( |
| - includeDirectlyInstantiated: includeDirectlyInstantiated, |
| - includeIndirectlyInstantiated: includeIndirectlyInstantiated, |
| - includeUninstantiated: includeUninstantiated).iterator; |
| + elements = hierarchyNodes.current.subclassesByMask(mask).iterator; |
| if (elements.moveNext()) { |
| return true; |
| } |