 Chromium Code Reviews
 Chromium Code Reviews Issue 2363773005:
  Move closed world reasoning methods from ClassWorld to ClosedWorld.  (Closed)
    
  
    Issue 2363773005:
  Move closed world reasoning methods from ClassWorld to ClosedWorld.  (Closed) 
  | Index: pkg/compiler/lib/src/world.dart | 
| diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart | 
| index e89f221f5c7ff5f436def89337dcdf130122bb31..c348c770498b6dd26e7e2db9991a00211665c525 100644 | 
| --- a/pkg/compiler/lib/src/world.dart | 
| +++ b/pkg/compiler/lib/src/world.dart | 
| @@ -41,6 +41,43 @@ abstract class ClassWorld { | 
| CoreClasses get coreClasses; | 
| + /// Returns `true` if the class world is closed. | 
| + bool get isClosed; | 
| + | 
| + /// Returns `true` if closed-world assumptions can be made, that is, | 
| + /// incremental compilation isn't enabled. | 
| + bool get hasClosedWorldAssumption; | 
| + | 
| + /// Returns a string representation of the closed world. | 
| + /// | 
| + /// If [cls] is provided, the dump will contain only classes related to [cls]. | 
| + String dump([ClassElement cls]); | 
| 
Harry Terkelsen
2016/09/23 17:20:27
@OnlyForTesting? Or whatever the annotation is?
 
Johnni Winther
2016/09/26 14:02:47
Haven't heard of it. Can you find its exactly loca
 | 
| + | 
| + /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies | 
| + /// of known classes. | 
| + /// | 
| + /// This method is only provided for testing. For queries on classes, use the | 
| + /// methods defined in [ClassWorld]. | 
| + ClassHierarchyNode getClassHierarchyNode(ClassElement cls); | 
| + | 
| + /// Returns [ClassSet] for [cls] used to model the extends and implements | 
| + /// relations of known classes. | 
| + /// | 
| + /// This method is only provided for testing. For queries on classes, use the | 
| + /// methods defined in [ClassWorld]. | 
| + ClassSet getClassSet(ClassElement cls); | 
| + | 
| + // TODO(johnniwinther): Find a better strategy for caching these. | 
| + @deprecated | 
| + List<Map<ClassElement, TypeMask>> get canonicalizedTypeMasks; | 
| +} | 
| + | 
| +/// The [ClosedWorld] represents the information known about a program when | 
| +/// compiling with closed-world semantics. | 
| +/// | 
| +/// This expands [ClassWorld] with information about live functions, | 
| +/// side effects, and selectors with known single targets. | 
| +abstract class ClosedWorld extends ClassWorld { | 
| /// Returns `true` if [cls] is either directly or indirectly instantiated. | 
| bool isInstantiated(ClassElement cls); | 
| @@ -54,9 +91,6 @@ abstract class ClassWorld { | 
| /// Returns `true` if [cls] is implemented by an instantiated class. | 
| bool isImplemented(ClassElement cls); | 
| - /// Returns `true` if the class world is closed. | 
| - bool get isClosed; | 
| - | 
| /// Return `true` if [x] is a subclass of [y]. | 
| bool isSubclassOf(ClassElement x, ClassElement y); | 
| @@ -155,40 +189,6 @@ abstract class ClassWorld { | 
| /// Returns `true` if any subclass of [superclass] implements [type]. | 
| bool hasAnySubclassThatImplements(ClassElement superclass, ClassElement type); | 
| - /// Returns `true` if closed-world assumptions can be made, that is, | 
| - /// incremental compilation isn't enabled. | 
| - bool get hasClosedWorldAssumption; | 
| - | 
| - /// Returns a string representation of the closed world. | 
| - /// | 
| - /// If [cls] is provided, the dump will contain only classes related to [cls]. | 
| - String dump([ClassElement cls]); | 
| - | 
| - /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies | 
| - /// of known classes. | 
| - /// | 
| - /// This method is only provided for testing. For queries on classes, use the | 
| - /// methods defined in [ClassWorld]. | 
| - ClassHierarchyNode getClassHierarchyNode(ClassElement cls); | 
| - | 
| - /// Returns [ClassSet] for [cls] used to model the extends and implements | 
| - /// relations of known classes. | 
| - /// | 
| - /// This method is only provided for testing. For queries on classes, use the | 
| - /// methods defined in [ClassWorld]. | 
| - ClassSet getClassSet(ClassElement cls); | 
| - | 
| - // TODO(johnniwinther): Find a better strategy for caching these. | 
| - @deprecated | 
| - List<Map<ClassElement, TypeMask>> get canonicalizedTypeMasks; | 
| -} | 
| - | 
| -/// The [ClosedWorld] represents the information known about a program when | 
| -/// compiling with closed-world semantics. | 
| -/// | 
| -/// This expands [ClassWorld] with information about live functions, | 
| -/// side effects, and selectors with known single targets. | 
| -abstract class ClosedWorld extends ClassWorld { | 
| /// Returns the [FunctionSet] containing all live functions in the closed | 
| /// world. | 
| FunctionSet get allFunctions; | 
| @@ -305,6 +305,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an | 
| /// instance of [y]. | 
| bool isSubtypeOf(ClassElement x, ClassElement y) { | 
| + assert(isClosed); | 
| assert(checkInvariants(x)); | 
| assert(checkInvariants(y, mustBeInstantiated: false)); | 
| @@ -317,6 +318,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| /// Return `true` if [x] is a (non-strict) subclass of [y]. | 
| bool isSubclassOf(ClassElement x, ClassElement y) { | 
| + assert(isClosed); | 
| assert(checkInvariants(x)); | 
| assert(checkInvariants(y)); | 
| @@ -331,30 +333,35 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| @override | 
| bool isInstantiated(ClassElement cls) { | 
| + assert(isClosed); | 
| ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; | 
| return node != null && node.isInstantiated; | 
| } | 
| @override | 
| bool isDirectlyInstantiated(ClassElement cls) { | 
| + assert(isClosed); | 
| ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; | 
| return node != null && node.isDirectlyInstantiated; | 
| } | 
| @override | 
| bool isIndirectlyInstantiated(ClassElement cls) { | 
| + assert(isClosed); | 
| ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; | 
| return node != null && node.isIndirectlyInstantiated; | 
| } | 
| /// Returns `true` if [cls] is implemented by an instantiated class. | 
| bool isImplemented(ClassElement cls) { | 
| + assert(isClosed); | 
| return _compiler.resolverWorld.isImplemented(cls); | 
| } | 
| /// Returns an iterable over the directly instantiated classes that extend | 
| /// [cls] possibly including [cls] itself, if it is live. | 
| Iterable<ClassElement> subclassesOf(ClassElement cls) { | 
| + assert(isClosed); | 
| ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; | 
| if (hierarchy == null) return const <ClassElement>[]; | 
| return hierarchy.subclassesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED); | 
| @@ -363,6 +370,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| /// Returns an iterable over the directly instantiated classes that extend | 
| /// [cls] _not_ including [cls] itself. | 
| Iterable<ClassElement> strictSubclassesOf(ClassElement cls) { | 
| + assert(isClosed); | 
| ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 
| if (subclasses == null) return const <ClassElement>[]; | 
| return subclasses.subclassesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED, | 
| @@ -372,6 +380,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| /// Returns the number of live classes that extend [cls] _not_ | 
| /// including [cls] itself. | 
| int strictSubclassCount(ClassElement cls) { | 
| + assert(isClosed); | 
| ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 
| if (subclasses == null) return 0; | 
| return subclasses.instantiatedSubclassCount; | 
| @@ -381,6 +390,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| /// itself. | 
| void forEachStrictSubclassOf( | 
| ClassElement cls, IterationStep f(ClassElement cls)) { | 
| + assert(isClosed); | 
| ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 
| if (subclasses == null) return; | 
| subclasses.forEachSubclass(f, ClassHierarchyNode.DIRECTLY_INSTANTIATED, | 
| @@ -390,6 +400,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| /// Returns `true` if [predicate] applies to any live class that extend [cls] | 
| /// _not_ including [cls] itself. | 
| bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls)) { | 
| + assert(isClosed); | 
| ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 
| if (subclasses == null) return false; | 
| return subclasses.anySubclass( | 
| @@ -400,6 +411,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| /// Returns an iterable over the directly instantiated that implement [cls] | 
| /// possibly including [cls] itself, if it is live. | 
| Iterable<ClassElement> subtypesOf(ClassElement cls) { | 
| + assert(isClosed); | 
| ClassSet classSet = _classSets[cls.declaration]; | 
| if (classSet == null) { | 
| return const <ClassElement>[]; | 
| @@ -411,6 +423,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| /// Returns an iterable over the directly instantiated that implement [cls] | 
| /// _not_ including [cls]. | 
| Iterable<ClassElement> strictSubtypesOf(ClassElement cls) { | 
| + assert(isClosed); | 
| ClassSet classSet = _classSets[cls.declaration]; | 
| if (classSet == null) { | 
| return const <ClassElement>[]; | 
| @@ -423,6 +436,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| /// Returns the number of live classes that implement [cls] _not_ | 
| /// including [cls] itself. | 
| int strictSubtypeCount(ClassElement cls) { | 
| + assert(isClosed); | 
| ClassSet classSet = _classSets[cls.declaration]; | 
| if (classSet == null) return 0; | 
| return classSet.instantiatedSubtypeCount; | 
| @@ -432,6 +446,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| /// itself. | 
| void forEachStrictSubtypeOf( | 
| ClassElement cls, IterationStep f(ClassElement cls)) { | 
| + assert(isClosed); | 
| ClassSet classSet = _classSets[cls.declaration]; | 
| if (classSet == null) return; | 
| classSet.forEachSubtype(f, ClassHierarchyNode.DIRECTLY_INSTANTIATED, | 
| @@ -441,6 +456,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| /// Returns `true` if [predicate] applies to any live class that extend [cls] | 
| /// _not_ including [cls] itself. | 
| bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls)) { | 
| + assert(isClosed); | 
| ClassSet classSet = _classSets[cls.declaration]; | 
| if (classSet == null) return false; | 
| return classSet.anySubtype( | 
| @@ -450,6 +466,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| /// Returns `true` if [a] and [b] have any known common subtypes. | 
| bool haveAnyCommonSubtypes(ClassElement a, ClassElement b) { | 
| + assert(isClosed); | 
| ClassSet classSetA = _classSets[a.declaration]; | 
| ClassSet classSetB = _classSets[b.declaration]; | 
| if (classSetA == null || classSetB == null) return false; | 
| @@ -466,6 +483,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| /// Returns `true` if any directly instantiated class other than [cls] extends | 
| /// [cls]. | 
| bool hasAnyStrictSubclass(ClassElement cls) { | 
| + assert(isClosed); | 
| ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 
| if (subclasses == null) return false; | 
| return subclasses.isIndirectlyInstantiated; | 
| @@ -480,6 +498,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| /// Returns `true` if all directly instantiated classes that implement [cls] | 
| /// extend it. | 
| bool hasOnlySubclasses(ClassElement cls) { | 
| + assert(isClosed); | 
| // TODO(johnniwinther): move this to ClassSet? | 
| if (cls == coreClasses.objectClass) return true; | 
| ClassSet classSet = _classSets[cls.declaration]; | 
| @@ -492,6 +511,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| @override | 
| ClassElement getLubOfInstantiatedSubclasses(ClassElement cls) { | 
| + assert(isClosed); | 
| if (backend.isJsInterop(cls)) { | 
| return backend.helpers.jsJavaScriptObjectClass; | 
| } | 
| @@ -503,6 +523,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| @override | 
| ClassElement getLubOfInstantiatedSubtypes(ClassElement cls) { | 
| + assert(isClosed); | 
| if (backend.isJsInterop(cls)) { | 
| return backend.helpers.jsJavaScriptObjectClass; | 
| } | 
| @@ -512,6 +533,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| /// Returns an iterable over the common supertypes of the [classes]. | 
| Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes) { | 
| + assert(isClosed); | 
| Iterator<ClassElement> iterator = classes.iterator; | 
| if (!iterator.moveNext()) return const <ClassElement>[]; | 
| @@ -588,12 +610,14 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| /// Returns `true` if [cls] is mixed into a live class. | 
| bool isUsedAsMixin(ClassElement cls) { | 
| + assert(isClosed); | 
| return !mixinUsesOf(cls).isEmpty; | 
| } | 
| /// Returns `true` if any live class that mixes in [cls] implements [type]. | 
| bool hasAnySubclassOfMixinUseThatImplements( | 
| ClassElement cls, ClassElement type) { | 
| + assert(isClosed); | 
| return mixinUsesOf(cls) | 
| .any((use) => hasAnySubclassThatImplements(use, type)); | 
| } | 
| @@ -601,11 +625,13 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| /// Returns `true` if any live class that mixes in [mixin] is also a subclass | 
| /// of [superclass]. | 
| bool hasAnySubclassThatMixes(ClassElement superclass, ClassElement mixin) { | 
| + assert(isClosed); | 
| return mixinUsesOf(mixin).any((each) => each.isSubclassOf(superclass)); | 
| } | 
| /// Returns `true` if [cls] or any superclass mixes in [mixin]. | 
| bool isSubclassOfMixinUseOf(ClassElement cls, ClassElement mixin) { | 
| + assert(isClosed); | 
| if (isUsedAsMixin(mixin)) { | 
| ClassElement current = cls.declaration; | 
| mixin = mixin.declaration; | 
| @@ -624,6 +650,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| /// Returns `true` if every subtype of [x] is a subclass of [y] or a subclass | 
| /// of a mixin application of [y]. | 
| bool everySubtypeIsSubclassOfOrMixinUseOf(ClassElement x, ClassElement y) { | 
| + assert(isClosed); | 
| x = x.declaration; | 
| y = y.declaration; | 
| Map<ClassElement, bool> secondMap = | 
| @@ -635,6 +662,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 
| /// Returns `true` if any subclass of [superclass] implements [type]. | 
| bool hasAnySubclassThatImplements( | 
| ClassElement superclass, ClassElement type) { | 
| + assert(isClosed); | 
| Set<ClassElement> subclasses = typesImplementedBySubclassesOf(superclass); | 
| if (subclasses == null) return false; | 
| return subclasses.contains(type); |