Index: pkg/compiler/lib/src/world.dart |
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart |
index c6a20e07be0c3dee272dbb1560d2cbd0a9eaf229..dbeee8a9338826debdf0a4553368319e350acd46 100644 |
--- a/pkg/compiler/lib/src/world.dart |
+++ b/pkg/compiler/lib/src/world.dart |
@@ -25,6 +25,7 @@ import 'universe/class_set.dart'; |
import 'universe/function_set.dart' show FunctionSet; |
import 'universe/selector.dart' show Selector; |
import 'universe/side_effects.dart' show SideEffects; |
+import 'util/enumset.dart'; |
import 'util/util.dart' show Link; |
/// Common superinterface for [OpenWorld] and [ClosedWorld]. |
@@ -48,9 +49,26 @@ abstract class ClosedWorld implements World { |
/// Returns `true` if [cls] is either directly or indirectly instantiated. |
bool isInstantiated(ClassElement cls); |
- /// Returns `true` if [cls] is directly instantiated. |
+ /// Returns `true` if [cls] is directly instantiated. This means that at |
+ /// runtime instances of exactly [cls] are assumed to exist. |
bool isDirectlyInstantiated(ClassElement cls); |
+ /// Returns `true` if [cls] is abstractly instantiated. This means that at |
+ /// runtime instances of [cls] or unknown subclasses of [cls] are assumed to |
+ /// exist. |
+ /// |
+ /// This is used to mark native and/or reflectable classes as instantiated. |
+ /// For native classes we do not know the exact class that instantiates [cls] |
+ /// so [cls] here represents the root of the subclasses. For reflectable |
+ /// classes we need event abstract classes to be 'live' even though they |
+ /// cannot themselves be instantiated. |
+ bool isAbstractlyInstantiated(ClassElement cls); |
+ |
+ /// Returns `true` if [cls] is either directly or abstractly instantiated. |
+ /// |
+ /// See [isDirectlyInstantiated] and [isAbstractlyInstantiated]. |
+ bool isExplicitlyInstantiated(ClassElement cls); |
+ |
/// Returns `true` if [cls] is indirectly instantiated, that is through a |
/// subclass. |
bool isIndirectlyInstantiated(ClassElement cls); |
@@ -393,6 +411,20 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { |
} |
@override |
+ bool isAbstractlyInstantiated(ClassElement cls) { |
+ assert(isClosed); |
+ ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; |
+ return node != null && node.isAbstractlyInstantiated; |
+ } |
+ |
+ @override |
+ bool isExplicitlyInstantiated(ClassElement cls) { |
+ assert(isClosed); |
+ ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; |
+ return node != null && node.isExplicitlyInstantiated; |
+ } |
+ |
+ @override |
bool isIndirectlyInstantiated(ClassElement cls) { |
assert(isClosed); |
ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; |
@@ -414,7 +446,8 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { |
assert(isClosed); |
ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; |
if (hierarchy == null) return const <ClassElement>[]; |
- return hierarchy.subclassesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED); |
+ return hierarchy |
+ .subclassesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED); |
} |
/// Returns an iterable over the directly instantiated classes that extend |
@@ -423,7 +456,8 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { |
assert(isClosed); |
ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
if (subclasses == null) return const <ClassElement>[]; |
- return subclasses.subclassesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
+ return subclasses.subclassesByMask( |
+ ClassHierarchyNode.EXPLICITLY_INSTANTIATED, |
strict: true); |
} |
@@ -443,7 +477,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { |
assert(isClosed); |
ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
if (subclasses == null) return; |
- subclasses.forEachSubclass(f, ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
+ subclasses.forEachSubclass(f, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, |
strict: true); |
} |
@@ -454,7 +488,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { |
ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
if (subclasses == null) return false; |
return subclasses.anySubclass( |
- predicate, ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
+ predicate, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, |
strict: true); |
} |
@@ -466,7 +500,8 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { |
if (classSet == null) { |
return const <ClassElement>[]; |
} else { |
- return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED); |
+ return classSet |
+ .subtypesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED); |
} |
} |
@@ -478,7 +513,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { |
if (classSet == null) { |
return const <ClassElement>[]; |
} else { |
- return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
+ return classSet.subtypesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED, |
strict: true); |
} |
} |
@@ -499,7 +534,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { |
assert(isClosed); |
ClassSet classSet = _classSets[cls.declaration]; |
if (classSet == null) return; |
- classSet.forEachSubtype(f, ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
+ classSet.forEachSubtype(f, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, |
strict: true); |
} |
@@ -510,7 +545,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { |
ClassSet classSet = _classSets[cls.declaration]; |
if (classSet == null) return false; |
return classSet.anySubtype( |
- predicate, ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
+ predicate, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, |
strict: true); |
} |
@@ -769,7 +804,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { |
// The root subclass has a concrete implementation so no subclass needs |
// noSuchMethod handling. |
return false; |
- } else if (rootNode.isDirectlyInstantiated) { |
+ } else if (rootNode.isExplicitlyInstantiated) { |
// The root class need noSuchMethod handling. |
return true; |
} |
@@ -781,7 +816,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { |
// Stop fast - we found a need for noSuchMethod handling. |
return IterationStep.STOP; |
} |
- }, ClassHierarchyNode.DIRECTLY_INSTANTIATED, strict: true); |
+ }, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, strict: true); |
// We stopped fast so we need noSuchMethod handling. |
return result == IterationStep.STOP; |
} |
@@ -943,19 +978,22 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { |
} |
void _updateClassHierarchyNodeForClass(ClassElement cls, |
- {bool directlyInstantiated: false}) { |
+ {bool directlyInstantiated: false, bool abstractlyInstantiated: false}) { |
ClassHierarchyNode node = getClassHierarchyNode(cls); |
_updateSuperClassHierarchyNodeForClass(node); |
if (directlyInstantiated) { |
node.isDirectlyInstantiated = true; |
} |
+ if (abstractlyInstantiated) { |
+ node.isAbstractlyInstantiated = true; |
+ } |
} |
ClosedWorld closeWorld() { |
/// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` |
/// properties of the [ClassHierarchyNode] for [cls]. |
- void addSubtypes(ClassElement cls) { |
+ void addSubtypes(ClassElement cls, EnumSet<Instantiation> instantiations) { |
if (_compiler.options.hasIncrementalSupport && |
!alreadyPopulated.add(cls)) { |
return; |
@@ -965,7 +1003,11 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { |
reporter.internalError(cls, 'Class "${cls.name}" is not resolved.'); |
} |
- _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true); |
+ _updateClassHierarchyNodeForClass(cls, |
+ directlyInstantiated: |
+ instantiations.contains(Instantiation.DIRECTLY_INSTANTIATED), |
+ abstractlyInstantiated: |
+ instantiations.contains(Instantiation.ABSTRACTLY_INSTANTIATED)); |
// Walk through the superclasses, and record the types |
// implemented by that type on the superclasses. |
@@ -985,7 +1027,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { |
// classes: if the superclass of these classes require RTI, then |
// they also need RTI, so that a constructor passes the type |
// variables to the super constructor. |
- _compiler.resolverWorld.directlyInstantiatedClasses.forEach(addSubtypes); |
+ _compiler.resolverWorld.forEachInstantiatedClass(addSubtypes); |
_closed = true; |
return this; |