Chromium Code Reviews| Index: pkg/compiler/lib/src/world.dart |
| diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart |
| index b4d78dd860c647d5ae058451f3deb9e5b93a5f38..701c6d3588ae143969157c4ac0f3300232cbf2cd 100644 |
| --- a/pkg/compiler/lib/src/world.dart |
| +++ b/pkg/compiler/lib/src/world.dart |
| @@ -46,6 +46,10 @@ abstract class ClassWorld { |
| /// instance of [y]. |
| bool isSubtypeOf(ClassElement x, ClassElement y); |
| + /// Returns an iterable over the live classes that extend [cls] including |
| + /// [cls] itself. |
| + Iterable<ClassElement> subclassesOf(ClassElement cls); |
| + |
| /// Returns an iterable over the live classes that extend [cls] _not_ |
| /// including [cls] itself. |
| Iterable<ClassElement> strictSubclassesOf(ClassElement cls); |
| @@ -145,34 +149,51 @@ class World implements ClassWorld { |
| return compiler.resolverWorld.isInstantiated(cls); |
| } |
| - /// Returns an iterable over the live classes that extend [cls] _not_ |
| - /// including [cls] itself. |
| + /// Returns an iterable over the directly instantiated classes that extend |
| + /// [cls] possibly including [cls] itself. |
| + Iterable<ClassElement> subclassesOf(ClassElement cls) { |
| + SubclassNode subclasses = _subclassNodes[cls.declaration]; |
| + if (subclasses == null) return const <ClassElement>[]; |
| + assert(invariant(cls, isInstantiated(cls.declaration), |
| + message: 'Class $cls has not been instantiated.')); |
| + return subclasses.subclasses(); |
| + } |
| + |
| + /// Returns an iterable over the directly instantiated classes that extend |
| + /// [cls] _not_ including [cls] itself. |
| Iterable<ClassElement> strictSubclassesOf(ClassElement cls) { |
| - Set<ClassElement> subclasses = _subclasses[cls.declaration]; |
| + SubclassNode subclasses = _subclassNodes[cls.declaration]; |
| if (subclasses == null) return const <ClassElement>[]; |
| assert(invariant(cls, isInstantiated(cls.declaration), |
| message: 'Class $cls has not been instantiated.')); |
| - return subclasses; |
| + return subclasses.strictSubclasses(); |
| } |
| - /// Returns an iterable over the live classes that implement [cls] _not_ |
| - /// including [cls] if it is live. |
| + /// Returns an iterable over the directly instantiated that implement [cls] |
| + /// _not_ including [cls] if it is live. |
| Iterable<ClassElement> strictSubtypesOf(ClassElement cls) { |
| Set<ClassElement> subtypes = _subtypes[cls.declaration]; |
| return subtypes != null ? subtypes : const <ClassElement>[]; |
| } |
| - /// Returns `true` if any live class other than [cls] extends [cls]. |
| + /// Returns `true` if any directly instantiated class other than [cls] extends |
| + /// [cls]. |
| bool hasAnyStrictSubclass(ClassElement cls) { |
| - return !strictSubclassesOf(cls).isEmpty; |
| + SubclassNode subclasses = _subclassNodes[cls.declaration]; |
| + if (subclasses == null) return false; |
| + assert(invariant(cls, isInstantiated(cls.declaration), |
| + message: 'Class $cls has not been instantiated.')); |
| + return subclasses.isIndirectlyInstantiated; |
| } |
| - /// Returns `true` if any live class other than [cls] implements [cls]. |
| + /// Returns `true` if any directly instantiated class other than [cls] |
| + /// implements [cls]. |
| bool hasAnyStrictSubtype(ClassElement cls) { |
| return !strictSubtypesOf(cls).isEmpty; |
| } |
| - /// Returns `true` if all live classes that implement [cls] extend it. |
| + /// Returns `true` if all directly instantiated classes that implement [cls] |
| + /// extend it. |
| bool hasOnlySubclasses(ClassElement cls) { |
| Iterable<ClassElement> subtypes = strictSubtypesOf(cls); |
| if (subtypes == null) return true; |
| @@ -284,8 +305,8 @@ class World implements ClassWorld { |
| // We keep track of subtype and subclass relationships in four |
| // distinct sets to make class hierarchy analysis faster. |
| - final Map<ClassElement, Set<ClassElement>> _subclasses = |
| - new Map<ClassElement, Set<ClassElement>>(); |
| + final Map<ClassElement, SubclassNode> _subclassNodes = |
| + <ClassElement, SubclassNode>{}; |
| final Map<ClassElement, Set<ClassElement>> _subtypes = |
| new Map<ClassElement, Set<ClassElement>>(); |
| @@ -319,7 +340,37 @@ class World implements ClassWorld { |
| this.compiler = compiler, |
| alreadyPopulated = compiler.cacheStrategy.newSet(); |
| + SubclassNode subclassNode(ClassElement cls) { |
| + return _subclassNodes[cls]; |
| + } |
| + |
| + /// Ensure that a [SubclassNode] exists for [cls]. Updates the |
| + /// `isDirectlyInstantiated` and `isIndirectlyInstantiated` property of the |
| + /// node according the provided arguments and returns the node. |
| + SubclassNode createNodeForClass(ClassElement cls, |
|
Siggi Cherem (dart-lang)
2015/07/14 23:51:07
nit, rename to: `ensureNodeForClass` (that helps c
|
| + {bool directlyInstantiated: false, |
| + bool indirectlyInstantiated: false}) { |
| + SubclassNode node = _subclassNodes.putIfAbsent(cls, () { |
| + SubclassNode node = new SubclassNode(cls); |
| + if (cls.superclass != null) { |
| + createNodeForClass(cls.superclass, |
| + indirectlyInstantiated: |
| + directlyInstantiated || indirectlyInstantiated) |
| + .addDirectSubclass(node); |
| + } |
| + return node; |
| + }); |
| + if (directlyInstantiated) { |
| + node.isDirectlyInstantiated = true; |
| + } |
| + if (indirectlyInstantiated) { |
| + node.isIndirectlyInstantiated = true; |
| + } |
| + return node; |
| + } |
| + |
| void populate() { |
| + |
| void addSubtypes(ClassElement cls) { |
| if (compiler.hasIncrementalSupport && !alreadyPopulated.add(cls)) { |
| return; |
| @@ -329,6 +380,8 @@ class World implements ClassWorld { |
| compiler.internalError(cls, 'Class "${cls.name}" is not resolved.'); |
| } |
| + createNodeForClass(cls, directlyInstantiated: true); |
| + |
| for (DartType type in cls.allSupertypes) { |
| Set<Element> subtypesOfSupertype = |
| _subtypes.putIfAbsent(type.element, () => new Set<ClassElement>()); |
| @@ -339,10 +392,6 @@ class World implements ClassWorld { |
| // implemented by that type on the superclasses. |
| ClassElement superclass = cls.superclass; |
| while (superclass != null) { |
| - Set<Element> subclassesOfSuperclass = |
| - _subclasses.putIfAbsent(superclass, () => new Set<ClassElement>()); |
| - subclassesOfSuperclass.add(cls); |
| - |
| Set<Element> typesImplementedBySubclassesOfCls = |
| _typesImplementedBySubclasses.putIfAbsent( |
| superclass, () => new Set<ClassElement>()); |