Move more methods to ClassHierarchy.
Change-Id: I6f7f0266a77db1e64a40307a4878bfd9b1ca5f07
Reviewed-on: https://dart-review.googlesource.com/61932
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index 7abea41..8a440d5 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -113,7 +113,8 @@
FieldInfo visitField(FieldEntity field, {ClassEntity containingClass}) {
var isInInstantiatedClass = false;
if (containingClass != null) {
- isInInstantiatedClass = closedWorld.isInstantiated(containingClass);
+ isInInstantiatedClass =
+ closedWorld.classHierarchy.isInstantiated(containingClass);
}
if (!isInInstantiatedClass && !_hasBeenResolved(field)) {
return null;
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index 0587561..c028b90 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -116,7 +116,7 @@
bool _isInClassOrSubclass(MemberEntity member) {
ClassEntity cls = _elementMap.getMemberThisType(_analyzedMember)?.element;
if (cls == null) return false;
- return _closedWorld.isSubclassOf(member.enclosingClass, cls);
+ return _closedWorld.classHierarchy.isSubclassOf(member.enclosingClass, cls);
}
/// Checks whether the access or update of [selector] on [mask] potentially
@@ -274,7 +274,7 @@
_inferrer.recordExposesThis(_analyzedMember, _isThisExposed);
if (cls.isAbstract) {
- if (_closedWorld.isInstantiated(cls)) {
+ if (_closedWorld.classHierarchy.isInstantiated(cls)) {
_returnType = _types.nonNullSubclass(cls);
} else {
// TODO(johnniwinther): Avoid analyzing [_analyzedMember] in this
@@ -1048,9 +1048,10 @@
ClassEntity cls = constructor.enclosingClass;
return cls.library.canonicalUri == Uris.dart__native_typed_data &&
_closedWorld.nativeData.isNativeClass(cls) &&
- _closedWorld.isSubtypeOf(
- cls, _closedWorld.commonElements.typedDataClass) &&
- _closedWorld.isSubtypeOf(cls, _closedWorld.commonElements.listClass) &&
+ _closedWorld.classHierarchy
+ .isSubtypeOf(cls, _closedWorld.commonElements.typedDataClass) &&
+ _closedWorld.classHierarchy
+ .isSubtypeOf(cls, _closedWorld.commonElements.listClass) &&
constructor.name == '';
}
diff --git a/pkg/compiler/lib/src/inferrer/type_system.dart b/pkg/compiler/lib/src/inferrer/type_system.dart
index 6fa9191..d761d3f 100644
--- a/pkg/compiler/lib/src/inferrer/type_system.dart
+++ b/pkg/compiler/lib/src/inferrer/type_system.dart
@@ -458,7 +458,7 @@
assert(strategy.checkListNode(node));
ClassEntity typedDataClass = _closedWorld.commonElements.typedDataClass;
bool isTypedArray = typedDataClass != null &&
- _closedWorld.isInstantiated(typedDataClass) &&
+ _closedWorld.classHierarchy.isInstantiated(typedDataClass) &&
_abstractValueDomain.isInstanceOfOrNull(type.type, typedDataClass);
bool isConst = (type.type == _abstractValueDomain.constListType);
bool isFixed = (type.type == _abstractValueDomain.fixedListType) ||
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/flat_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/flat_type_mask.dart
index a270a6f..20150d5 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/flat_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/flat_type_mask.dart
@@ -55,11 +55,13 @@
return new FlatTypeMask.internal(base, flags);
}
if ((flags >> 1) == SUBTYPE) {
- if (!world.hasAnyStrictSubtype(base) || world.hasOnlySubclasses(base)) {
+ if (!world.classHierarchy.hasAnyStrictSubtype(base) ||
+ world.classHierarchy.hasOnlySubclasses(base)) {
flags = (flags & 0x1) | (SUBCLASS << 1);
}
}
- if (((flags >> 1) == SUBCLASS) && !world.hasAnyStrictSubclass(base)) {
+ if (((flags >> 1) == SUBCLASS) &&
+ !world.classHierarchy.hasAnyStrictSubclass(base)) {
flags = (flags & 0x1) | (EXACT << 1);
}
CommonMasks commonMasks = world.abstractValueDomain;
@@ -102,10 +104,10 @@
} else if (isExact) {
return false;
} else if (isSubclass) {
- return closedWorld.isSubclassOf(other, base);
+ return closedWorld.classHierarchy.isSubclassOf(other, base);
} else {
assert(isSubtype);
- return closedWorld.isSubtypeOf(other, base);
+ return closedWorld.classHierarchy.isSubtypeOf(other, base);
}
}
@@ -164,7 +166,7 @@
if (flatOther.isSubclass) {
if (isSubtype)
return (otherBase == closedWorld.commonElements.objectClass);
- return closedWorld.isSubclassOf(base, otherBase);
+ return closedWorld.classHierarchy.isSubclassOf(base, otherBase);
}
assert(flatOther.isSubtype);
// Check whether this TypeMask satisfies otherBase's interface.
@@ -212,7 +214,7 @@
bool satisfies(ClassEntity cls, JClosedWorld closedWorld) {
if (isEmptyOrNull) return false;
- if (closedWorld.isSubtypeOf(base, cls)) return true;
+ if (closedWorld.classHierarchy.isSubtypeOf(base, cls)) return true;
return false;
}
@@ -224,7 +226,9 @@
if (isExact) {
return base;
} else if (isSubclass) {
- return closedWorld.hasAnyStrictSubclass(base) ? null : base;
+ return closedWorld.classHierarchy.hasAnyStrictSubclass(base)
+ ? null
+ : base;
} else {
assert(isSubtype);
return null;
@@ -251,13 +255,13 @@
return flatOther.isNullable ? nullable() : this;
} else if (base == flatOther.base) {
return unionSame(flatOther, closedWorld);
- } else if (closedWorld.isSubclassOf(flatOther.base, base)) {
+ } else if (closedWorld.classHierarchy.isSubclassOf(flatOther.base, base)) {
return unionStrictSubclass(flatOther, closedWorld);
- } else if (closedWorld.isSubclassOf(base, flatOther.base)) {
+ } else if (closedWorld.classHierarchy.isSubclassOf(base, flatOther.base)) {
return flatOther.unionStrictSubclass(this, closedWorld);
- } else if (closedWorld.isSubtypeOf(flatOther.base, base)) {
+ } else if (closedWorld.classHierarchy.isSubtypeOf(flatOther.base, base)) {
return unionStrictSubtype(flatOther, closedWorld);
- } else if (closedWorld.isSubtypeOf(base, flatOther.base)) {
+ } else if (closedWorld.classHierarchy.isSubtypeOf(base, flatOther.base)) {
return flatOther.unionStrictSubtype(this, closedWorld);
} else {
return new UnionTypeMask._internal(<FlatTypeMask>[this, flatOther]);
@@ -286,7 +290,7 @@
TypeMask unionStrictSubclass(FlatTypeMask other, JClosedWorld closedWorld) {
assert(base != other.base);
- assert(closedWorld.isSubclassOf(other.base, base));
+ assert(closedWorld.classHierarchy.isSubclassOf(other.base, base));
assert(TypeMask.assertIsNormalized(this, closedWorld));
assert(TypeMask.assertIsNormalized(other, closedWorld));
int combined;
@@ -313,8 +317,8 @@
TypeMask unionStrictSubtype(FlatTypeMask other, JClosedWorld closedWorld) {
assert(base != other.base);
- assert(!closedWorld.isSubclassOf(other.base, base));
- assert(closedWorld.isSubtypeOf(other.base, base));
+ assert(!closedWorld.classHierarchy.isSubclassOf(other.base, base));
+ assert(closedWorld.classHierarchy.isSubtypeOf(other.base, base));
assert(TypeMask.assertIsNormalized(this, closedWorld));
assert(TypeMask.assertIsNormalized(other, closedWorld));
// Since the other mask is a subtype of this mask, we need the
@@ -416,8 +420,12 @@
// Normalization guarantees that isExact === !isSubclass && !isSubtype.
// Both are subclass or subtype masks, so if there is a subclass
// relationship, they are not disjoint.
- if (closedWorld.isSubclassOf(flatOther.base, base)) return false;
- if (closedWorld.isSubclassOf(base, flatOther.base)) return false;
+ if (closedWorld.classHierarchy.isSubclassOf(flatOther.base, base)) {
+ return false;
+ }
+ if (closedWorld.classHierarchy.isSubclassOf(base, flatOther.base)) {
+ return false;
+ }
// Two different base classes have no common subclass unless one is a
// subclass of the other (checked above).
@@ -434,10 +442,10 @@
assert(a.isSubclass || a.isSubtype);
assert(b.isSubtype);
var elements = a.isSubclass
- ? closedWorld.strictSubclassesOf(a.base)
- : closedWorld.strictSubtypesOf(a.base);
+ ? closedWorld.classHierarchy.strictSubclassesOf(a.base)
+ : closedWorld.classHierarchy.strictSubtypesOf(a.base);
for (var element in elements) {
- if (closedWorld.isSubtypeOf(element, b.base)) return false;
+ if (closedWorld.classHierarchy.isSubtypeOf(element, b.base)) return false;
}
return true;
}
@@ -463,7 +471,7 @@
TypeMask intersectionStrictSubclass(
FlatTypeMask other, JClosedWorld closedWorld) {
assert(base != other.base);
- assert(closedWorld.isSubclassOf(other.base, base));
+ assert(closedWorld.classHierarchy.isSubclassOf(other.base, base));
// If this mask isn't at least a subclass mask, then the
// intersection with the other mask is empty.
if (isExact) return intersectionEmpty(other);
@@ -508,12 +516,12 @@
return closedWorld.hasElementIn(base, selector, element);
} else if (isSubclass) {
return closedWorld.hasElementIn(base, selector, element) ||
- closedWorld.isSubclassOf(other, base) ||
+ closedWorld.classHierarchy.isSubclassOf(other, base) ||
closedWorld.hasAnySubclassThatMixes(base, other);
} else {
assert(isSubtype);
bool result = closedWorld.hasElementIn(base, selector, element) ||
- closedWorld.isSubtypeOf(other, base) ||
+ closedWorld.classHierarchy.isSubtypeOf(other, base) ||
closedWorld.hasAnySubclassThatImplements(other, base) ||
closedWorld.hasAnySubclassOfMixinUseThatImplements(other, base);
if (result) return true;
@@ -522,7 +530,7 @@
Iterable<ClassEntity> mixinUses = closedWorld.mixinUsesOf(base);
return mixinUses.any((mixinApplication) =>
closedWorld.hasElementIn(mixinApplication, selector, element) ||
- closedWorld.isSubclassOf(other, mixinApplication) ||
+ closedWorld.classHierarchy.isSubclassOf(other, mixinApplication) ||
closedWorld.hasAnySubclassThatMixes(mixinApplication, other));
}
}
@@ -560,7 +568,9 @@
//}
return null;
} else {
- if (closedWorld.isSubclassOf(base, enclosing)) return result;
+ if (closedWorld.classHierarchy.isSubclassOf(base, enclosing)) {
+ return result;
+ }
if (closedWorld.isSubclassOfMixinUseOf(base, enclosing)) return result;
}
return null;
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/masks.dart b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
index 23752a0..df920fc 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
@@ -198,7 +198,7 @@
// interface `JavaScriptIndexingBehavior`.
ClassEntity typedDataClass = _closedWorld.commonElements.typedDataClass;
return typedDataClass != null &&
- _closedWorld.isInstantiated(typedDataClass) &&
+ _closedWorld.classHierarchy.isInstantiated(typedDataClass) &&
mask.satisfies(typedDataClass, _closedWorld) &&
mask.satisfies(_closedWorld.commonElements.jsIndexingBehaviorInterface,
_closedWorld);
@@ -212,7 +212,7 @@
// jsIndexingBehaviourInterface.
ClassEntity typedDataClass = _closedWorld.commonElements.typedDataClass;
return typedDataClass != null &&
- _closedWorld.isInstantiated(typedDataClass) &&
+ _closedWorld.classHierarchy.isInstantiated(typedDataClass) &&
intersects(mask, new TypeMask.subtype(typedDataClass, _closedWorld)) &&
intersects(
mask,
@@ -254,13 +254,14 @@
@override
bool containsType(TypeMask typeMask, ClassEntity cls) {
- return _closedWorld.isInstantiated(cls) &&
+ return _closedWorld.classHierarchy.isInstantiated(cls) &&
typeMask.contains(cls, _closedWorld);
}
@override
bool containsOnlyType(TypeMask typeMask, ClassEntity cls) {
- return _closedWorld.isInstantiated(cls) && typeMask.containsOnly(cls);
+ return _closedWorld.classHierarchy.isInstantiated(cls) &&
+ typeMask.containsOnly(cls);
}
@override
@@ -550,7 +551,7 @@
@override
AbstractValue computeReceiver(Iterable<MemberEntity> members) {
- assert(_closedWorld
+ assert(_closedWorld.classHierarchy
.hasAnyStrictSubclass(_closedWorld.commonElements.objectClass));
return new TypeMask.unionOf(
members.expand((MemberEntity element) {
@@ -559,7 +560,7 @@
}).map((cls) {
if (_closedWorld.commonElements.jsNullClass == cls) {
return const TypeMask.empty();
- } else if (_closedWorld.isInstantiated(cls)) {
+ } else if (_closedWorld.classHierarchy.isInstantiated(cls)) {
return new TypeMask.nonNullSubclass(cls, _closedWorld);
} else {
// TODO(johnniwinther): Avoid the need for this case.
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/type_mask.dart
index ee7d4b2..225f21c 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/type_mask.dart
@@ -107,30 +107,31 @@
factory TypeMask.exact(ClassEntity base, JClosedWorld closedWorld) {
assert(
- closedWorld.isInstantiated(base),
+ closedWorld.classHierarchy.isInstantiated(base),
failedAt(
base ?? CURRENT_ELEMENT_SPANNABLE,
"Cannot create exact type mask for uninstantiated "
- "class $base.\n${closedWorld.dump(base)}"));
+ "class $base.\n${closedWorld.classHierarchy.dump(base)}"));
return new FlatTypeMask.exact(base);
}
factory TypeMask.exactOrEmpty(ClassEntity base, JClosedWorld closedWorld) {
- if (closedWorld.isInstantiated(base)) return new FlatTypeMask.exact(base);
+ if (closedWorld.classHierarchy.isInstantiated(base))
+ return new FlatTypeMask.exact(base);
return const TypeMask.empty();
}
factory TypeMask.subclass(ClassEntity base, JClosedWorld closedWorld) {
assert(
- closedWorld.isInstantiated(base),
+ closedWorld.classHierarchy.isInstantiated(base),
failedAt(
base ?? CURRENT_ELEMENT_SPANNABLE,
"Cannot create subclass type mask for uninstantiated "
- "class $base.\n${closedWorld.dump(base)}"));
+ "class $base.\n${closedWorld.classHierarchy.dump(base)}"));
ClassEntity topmost = closedWorld.getLubOfInstantiatedSubclasses(base);
if (topmost == null) {
return new TypeMask.empty();
- } else if (closedWorld.hasAnyStrictSubclass(topmost)) {
+ } else if (closedWorld.classHierarchy.hasAnyStrictSubclass(topmost)) {
return new FlatTypeMask.subclass(topmost);
} else {
return new TypeMask.exact(topmost, closedWorld);
@@ -142,10 +143,10 @@
if (topmost == null) {
return new TypeMask.empty();
}
- if (closedWorld.hasOnlySubclasses(topmost)) {
+ if (closedWorld.classHierarchy.hasOnlySubclasses(topmost)) {
return new TypeMask.subclass(topmost, closedWorld);
}
- if (closedWorld.hasAnyStrictSubtype(topmost)) {
+ if (closedWorld.classHierarchy.hasAnyStrictSubtype(topmost)) {
return new FlatTypeMask.subtype(topmost);
} else {
return new TypeMask.exact(topmost, closedWorld);
@@ -156,17 +157,17 @@
factory TypeMask.nonNullExact(ClassEntity base, JClosedWorld closedWorld) {
assert(
- closedWorld.isInstantiated(base),
+ closedWorld.classHierarchy.isInstantiated(base),
failedAt(
base ?? CURRENT_ELEMENT_SPANNABLE,
"Cannot create exact type mask for uninstantiated "
- "class $base.\n${closedWorld.dump(base)}"));
+ "class $base.\n${closedWorld.classHierarchy.dump(base)}"));
return new FlatTypeMask.nonNullExact(base);
}
factory TypeMask.nonNullExactOrEmpty(
ClassEntity base, JClosedWorld closedWorld) {
- if (closedWorld.isInstantiated(base)) {
+ if (closedWorld.classHierarchy.isInstantiated(base)) {
return new FlatTypeMask.nonNullExact(base);
}
return const TypeMask.nonNullEmpty();
@@ -174,15 +175,15 @@
factory TypeMask.nonNullSubclass(ClassEntity base, JClosedWorld closedWorld) {
assert(
- closedWorld.isInstantiated(base),
+ closedWorld.classHierarchy.isInstantiated(base),
failedAt(
base ?? CURRENT_ELEMENT_SPANNABLE,
"Cannot create subclass type mask for uninstantiated "
- "class $base.\n${closedWorld.dump(base)}"));
+ "class $base.\n${closedWorld.classHierarchy.dump(base)}"));
ClassEntity topmost = closedWorld.getLubOfInstantiatedSubclasses(base);
if (topmost == null) {
return new TypeMask.nonNullEmpty();
- } else if (closedWorld.hasAnyStrictSubclass(topmost)) {
+ } else if (closedWorld.classHierarchy.hasAnyStrictSubclass(topmost)) {
return new FlatTypeMask.nonNullSubclass(topmost);
} else {
return new TypeMask.nonNullExact(topmost, closedWorld);
@@ -194,10 +195,10 @@
if (topmost == null) {
return new TypeMask.nonNullEmpty();
}
- if (closedWorld.hasOnlySubclasses(topmost)) {
+ if (closedWorld.classHierarchy.hasOnlySubclasses(topmost)) {
return new TypeMask.nonNullSubclass(topmost, closedWorld);
}
- if (closedWorld.hasAnyStrictSubtype(topmost)) {
+ if (closedWorld.classHierarchy.hasAnyStrictSubtype(topmost)) {
return new FlatTypeMask.nonNullSubtype(topmost);
} else {
return new TypeMask.nonNullExact(topmost, closedWorld);
@@ -239,22 +240,22 @@
if (mask is FlatTypeMask) {
if (mask.isEmptyOrNull) return null;
if (mask.isExact) {
- if (!closedWorld.isInstantiated(mask.base)) {
+ if (!closedWorld.classHierarchy.isInstantiated(mask.base)) {
return 'Exact ${mask.base} is not instantiated.';
}
return null;
}
if (mask.isSubclass) {
- if (!closedWorld.hasAnyStrictSubclass(mask.base)) {
+ if (!closedWorld.classHierarchy.hasAnyStrictSubclass(mask.base)) {
return 'Subclass ${mask.base} does not have any subclasses.';
}
return null;
}
assert(mask.isSubtype);
- if (!closedWorld.hasAnyStrictSubtype(mask.base)) {
+ if (!closedWorld.classHierarchy.hasAnyStrictSubtype(mask.base)) {
return 'Subtype ${mask.base} does not have any subclasses.';
}
- if (closedWorld.hasOnlySubclasses(mask.base)) {
+ if (closedWorld.classHierarchy.hasOnlySubclasses(mask.base)) {
return 'Subtype ${mask.base} only has subclasses.';
}
return null;
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/union_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/union_type_mask.dart
index 6121c08..0da519c 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/union_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/union_type_mask.dart
@@ -107,8 +107,8 @@
for (ClassEntity candidate in candidates) {
bool isInstantiatedStrictSubclass(cls) =>
cls != candidate &&
- closedWorld.isExplicitlyInstantiated(cls) &&
- closedWorld.isSubclassOf(cls, candidate);
+ closedWorld.classHierarchy.isExplicitlyInstantiated(cls) &&
+ closedWorld.classHierarchy.isSubclassOf(cls, candidate);
int size;
int kind;
@@ -121,11 +121,12 @@
// TODO(sigmund, johnniwinther): computing length here (and below) is
// expensive. If we can't prevent `flatten` from being called a lot, it
// might be worth caching results.
- size = closedWorld.strictSubclassCount(candidate);
- assert(size <= closedWorld.strictSubtypeCount(candidate));
+ size = closedWorld.classHierarchy.strictSubclassCount(candidate);
+ assert(
+ size <= closedWorld.classHierarchy.strictSubtypeCount(candidate));
} else {
kind = FlatTypeMask.SUBTYPE;
- size = closedWorld.strictSubtypeCount(candidate);
+ size = closedWorld.classHierarchy.strictSubtypeCount(candidate);
}
// Update the best candidate if the new one is better.
if (bestElement == null || size < bestSize) {
@@ -237,10 +238,10 @@
// Check for other members.
Iterable<ClassEntity> members;
if (flat.isSubclass) {
- members = closedWorld.strictSubclassesOf(flat.base);
+ members = closedWorld.classHierarchy.strictSubclassesOf(flat.base);
} else {
assert(flat.isSubtype);
- members = closedWorld.strictSubtypesOf(flat.base);
+ members = closedWorld.classHierarchy.strictSubtypesOf(flat.base);
}
return members.every((ClassEntity cls) => this.contains(cls, closedWorld));
}
diff --git a/pkg/compiler/lib/src/js_backend/interceptor_data.dart b/pkg/compiler/lib/src/js_backend/interceptor_data.dart
index abed251..f621411 100644
--- a/pkg/compiler/lib/src/js_backend/interceptor_data.dart
+++ b/pkg/compiler/lib/src/js_backend/interceptor_data.dart
@@ -182,7 +182,8 @@
Iterable<ClassEntity> uses = closedWorld.mixinUsesOf(mixin);
Set<ClassEntity> result = null;
for (ClassEntity use in uses) {
- closedWorld.forEachStrictSubclassOf(use, (ClassEntity subclass) {
+ closedWorld.classHierarchy.forEachStrictSubclassOf(use,
+ (ClassEntity subclass) {
if (_nativeData.isNativeOrExtendsNative(subclass)) {
if (result == null) result = new Set<ClassEntity>();
result.add(subclass);
@@ -212,7 +213,7 @@
InterfaceType interfaceType = type;
ClassEntity classElement = interfaceType.element;
if (isInterceptedClass(classElement)) return false;
- return closedWorld.hasOnlySubclasses(classElement);
+ return closedWorld.classHierarchy.hasOnlySubclasses(classElement);
}
}
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 118dddf..0835bf8 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -242,7 +242,7 @@
rtiChecksBuilderClosed = true;
Map<ClassEntity, ClassUse> classUseMap = <ClassEntity, ClassUse>{};
- for (ClassEntity cls in _closedWorld
+ for (ClassEntity cls in _closedWorld.classHierarchy
.getClassSet(_closedWorld.commonElements.objectClass)
.subtypes()) {
ClassUse classUse = new ClassUse()
@@ -261,7 +261,7 @@
Set<ClassEntity> computeCheckedClasses(
CodegenWorldBuilder codegenWorldBuilder, Set<DartType> implicitIsChecks) {
- return _closedWorld
+ return _closedWorld.classHierarchy
.getClassSet(_closedWorld.commonElements.objectClass)
.subtypes()
.toSet();
diff --git a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
index f5d7ab1..547f81d 100644
--- a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
@@ -301,8 +301,8 @@
bool containsJsIndexable = _closedWorld
.isImplemented(_commonElements.jsIndexingBehaviorInterface) &&
classes.any((cls) {
- return _closedWorld.isSubtypeOf(
- cls, _commonElements.jsIndexingBehaviorInterface);
+ return _closedWorld.classHierarchy
+ .isSubtypeOf(cls, _commonElements.jsIndexingBehaviorInterface);
});
// The index set operator requires a check on its set value in
// checked mode, so we don't optimize the interceptor if the
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index f6aa274..1ede50a 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -674,11 +674,6 @@
AbstractValueDomain get abstractValueDomain {
return _abstractValueDomain;
}
-
- @override
- void registerClosureClass(ClassEntity cls) {
- throw new UnsupportedError('JsClosedWorld.registerClosureClass');
- }
}
class ConstantConverter implements ConstantValueVisitor<ConstantValue, Null> {
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 1f3fbe8..0623dec 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -2013,8 +2013,8 @@
@override
bool hasConcreteMatch(ClassEntity cls, Selector selector,
{ClassEntity stopAtSuperclass}) {
- assert(
- isInstantiated(cls), failedAt(cls, '$cls has not been instantiated.'));
+ assert(classHierarchy.isInstantiated(cls),
+ failedAt(cls, '$cls has not been instantiated.'));
MemberEntity element = elementEnvironment
.lookupClassMember(cls, selector.name, setter: selector.isSetter);
if (element == null) return false;
@@ -2057,13 +2057,6 @@
OrderedTypeSet getOrderedTypeSet(ClassEntity cls) {
return elementMap._getOrderedTypeSet(cls);
}
-
- @override
- bool checkInvariants(ClassEntity cls, {bool mustBeInstantiated: true}) =>
- true;
-
- @override
- bool checkEntity(Entity element) => true;
}
class KClosedWorldImpl extends ClosedWorldRtiNeedMixin implements KClosedWorld {
@@ -2996,10 +2989,4 @@
ClassEntity getAppliedMixin(ClassEntity cls) {
return elementMap._getAppliedMixin(cls);
}
-
- @override
- bool validateClass(ClassEntity cls) => true;
-
- @override
- bool checkClass(ClassEntity cls) => true;
}
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 40d863f..4254b73 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -4144,10 +4144,10 @@
Selector selector, MemberEntity element) {
bool isLength = selector.isGetter && selector.name == "length";
if (isLength || selector.isIndex) {
- return closedWorld.isSubtypeOf(
+ return closedWorld.classHierarchy.isSubtypeOf(
element.enclosingClass, commonElements.jsIndexableClass);
} else if (selector.isIndexSet) {
- return closedWorld.isSubtypeOf(
+ return closedWorld.classHierarchy.isSubtypeOf(
element.enclosingClass, commonElements.jsMutableIndexableClass);
} else {
return false;
@@ -4830,11 +4830,12 @@
js.Name operator = namer.operatorIs(element);
HInstruction isFieldName =
graph.addConstantStringFromName(operator, closedWorld);
- HInstruction asFieldName = closedWorld.hasAnyStrictSubtype(element) ||
- closedWorld.nativeData.isJsInteropClass(element)
- ? graph.addConstantStringFromName(
- namer.substitutionName(element), closedWorld)
- : graph.addConstantNull(closedWorld);
+ HInstruction asFieldName =
+ closedWorld.classHierarchy.hasAnyStrictSubtype(element) ||
+ closedWorld.nativeData.isJsInteropClass(element)
+ ? graph.addConstantStringFromName(
+ namer.substitutionName(element), closedWorld)
+ : graph.addConstantNull(closedWorld);
List<HInstruction> inputs = <HInstruction>[
expression,
isFieldName,
@@ -5581,8 +5582,8 @@
// constructor's factory. A simplified version is to check this is a
// constructor body for a leaf class.
ClassEntity class_ = element.enclosingClass;
- if (closedWorld.isDirectlyInstantiated(class_)) {
- return !closedWorld.isIndirectlyInstantiated(class_);
+ if (closedWorld.classHierarchy.isDirectlyInstantiated(class_)) {
+ return !closedWorld.classHierarchy.isIndirectlyInstantiated(class_);
}
return false;
}
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 3d08315..d72a6b5 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -1835,7 +1835,7 @@
// type because our optimizations might end up in a state where the
// invoke dynamic knows more than the receiver.
ClassEntity enclosing = node.element.enclosingClass;
- if (_closedWorld.isInstantiated(enclosing)) {
+ if (_closedWorld.classHierarchy.isInstantiated(enclosing)) {
return _abstractValueDomain.createNonNullExact(enclosing);
} else {
// The element is mixed in so a non-null subtype mask is the most
@@ -3141,7 +3141,8 @@
if (_closedWorld.isUsedAsMixin(cls)) return true;
- return _closedWorld.anyStrictSubclassOf(cls, (ClassEntity subclass) {
+ return _closedWorld.classHierarchy.anyStrictSubclassOf(cls,
+ (ClassEntity subclass) {
return !_rtiSubstitutions.isTrivialSubstitution(subclass, cls);
});
}
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index a0ac620..0837246 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -1326,7 +1326,8 @@
bool needsSubstitutionForTypeVariableAccess(ClassEntity cls) {
if (_closedWorld.isUsedAsMixin(cls)) return true;
- return _closedWorld.anyStrictSubclassOf(cls, (ClassEntity subclass) {
+ return _closedWorld.classHierarchy.anyStrictSubclassOf(cls,
+ (ClassEntity subclass) {
return !_rtiSubstitutions.isTrivialSubstitution(subclass, cls);
});
}
diff --git a/pkg/compiler/lib/src/universe/class_hierarchy.dart b/pkg/compiler/lib/src/universe/class_hierarchy.dart
index e0d14f1..cc91490 100644
--- a/pkg/compiler/lib/src/universe/class_hierarchy.dart
+++ b/pkg/compiler/lib/src/universe/class_hierarchy.dart
@@ -11,24 +11,94 @@
// TODO(johnniwinther): Move more methods from `JClosedWorld` to
// `ClassHierarchy`.
abstract class ClassHierarchy {
- /// 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 [JClosedWorld].
- ClassHierarchyNode getClassHierarchyNode(ClassEntity cls);
+ /// Returns `true` if [cls] is either directly or indirectly instantiated.
+ bool isInstantiated(ClassEntity cls);
- /// Returns [ClassSet] for [cls] used to model the extends and implements
- /// relations of known classes.
+ /// Returns `true` if [cls] is directly instantiated. This means that at
+ /// runtime instances of exactly [cls] are assumed to exist.
+ bool isDirectlyInstantiated(ClassEntity 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 method is only provided for testing. For queries on classes, use the
- /// methods defined in [JClosedWorld].
- ClassSet getClassSet(ClassEntity cls);
+ /// 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(ClassEntity cls);
+
+ /// Returns `true` if [cls] is either directly or abstractly instantiated.
+ ///
+ /// See [isDirectlyInstantiated] and [isAbstractlyInstantiated].
+ bool isExplicitlyInstantiated(ClassEntity cls);
+
+ /// Returns `true` if [cls] is indirectly instantiated, that is through a
+ /// subclass.
+ bool isIndirectlyInstantiated(ClassEntity cls);
+
+ /// Return `true` if [x] is a subclass of [y].
+ bool isSubclassOf(ClassEntity x, ClassEntity y);
/// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an
/// instance of [y].
bool isSubtypeOf(ClassEntity x, ClassEntity y);
+ /// Returns an iterable over the live classes that extend [cls] including
+ /// [cls] itself.
+ Iterable<ClassEntity> subclassesOf(ClassEntity cls);
+
+ /// Returns an iterable over the live classes that extend [cls] _not_
+ /// including [cls] itself.
+ Iterable<ClassEntity> strictSubclassesOf(ClassEntity cls);
+
+ /// Returns the number of live classes that extend [cls] _not_
+ /// including [cls] itself.
+ int strictSubclassCount(ClassEntity cls);
+
+ /// Applies [f] to each live class that extend [cls] _not_ including [cls]
+ /// itself.
+ void forEachStrictSubclassOf(
+ ClassEntity cls, IterationStep f(ClassEntity cls));
+
+ /// Returns `true` if [predicate] applies to any live class that extend [cls]
+ /// _not_ including [cls] itself.
+ bool anyStrictSubclassOf(ClassEntity cls, bool predicate(ClassEntity cls));
+
+ /// Returns an iterable over the directly instantiated that implement [cls]
+ /// possibly including [cls] itself, if it is live.
+ Iterable<ClassEntity> subtypesOf(ClassEntity cls);
+
+ /// Returns an iterable over the live classes that implement [cls] _not_
+ /// including [cls] if it is live.
+ Iterable<ClassEntity> strictSubtypesOf(ClassEntity cls);
+
+ /// Returns the number of live classes that implement [cls] _not_
+ /// including [cls] itself.
+ int strictSubtypeCount(ClassEntity cls);
+
+ /// Applies [f] to each live class that implements [cls] _not_ including [cls]
+ /// itself.
+ void forEachStrictSubtypeOf(
+ ClassEntity cls, IterationStep f(ClassEntity cls));
+
+ /// Returns `true` if [predicate] applies to any live class that implements
+ /// [cls] _not_ including [cls] itself.
+ bool anyStrictSubtypeOf(ClassEntity cls, bool predicate(ClassEntity cls));
+
+ /// Returns `true` if [a] and [b] have any known common subtypes.
+ bool haveAnyCommonSubtypes(ClassEntity a, ClassEntity b);
+
+ /// Returns `true` if any live class other than [cls] extends [cls].
+ bool hasAnyStrictSubclass(ClassEntity cls);
+
+ /// Returns `true` if any live class other than [cls] implements [cls].
+ bool hasAnyStrictSubtype(ClassEntity cls);
+
+ /// Returns `true` if all live classes that implement [cls] extend it.
+ bool hasOnlySubclasses(ClassEntity cls);
+
/// Returns a [SubclassResult] for the subclasses that are contained in
/// the subclass/subtype sets of both [cls1] and [cls2].
///
@@ -50,18 +120,24 @@
SubclassResult commonSubclasses(
ClassEntity cls1, ClassQuery query1, ClassEntity cls2, ClassQuery query2);
- /// Returns an iterable over the directly instantiated that implement [cls]
- /// possibly including [cls] itself, if it is live.
- Iterable<ClassEntity> subtypesOf(ClassEntity 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 [JClosedWorld].
+ ClassHierarchyNode getClassHierarchyNode(ClassEntity cls);
- /// Returns an iterable over the live classes that extend [cls] including
- /// [cls] itself.
- Iterable<ClassEntity> subclassesOf(ClassEntity 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 [JClosedWorld].
+ ClassSet getClassSet(ClassEntity cls);
- /// Applies [f] to each live class that implements [cls] _not_ including [cls]
- /// itself.
- void forEachStrictSubtypeOf(
- ClassEntity cls, IterationStep f(ClassEntity cls));
+ /// Returns a string representation of the closed world.
+ ///
+ /// If [cls] is provided, the dump will contain only classes related to [cls].
+ String dump([ClassEntity cls]);
}
class ClassHierarchyImpl implements ClassHierarchy {
@@ -72,33 +148,49 @@
ClassHierarchyImpl(
this._commonElements, this._classHierarchyNodes, this._classSets);
- /// 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 [JClosedWorld].
- ClassHierarchyNode getClassHierarchyNode(ClassEntity cls) {
- return _classHierarchyNodes[cls];
+ @override
+ bool isInstantiated(ClassEntity cls) {
+ ClassHierarchyNode node = _classHierarchyNodes[cls];
+ return node != null && node.isInstantiated;
}
- /// 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 [JClosedWorld].
- ClassSet getClassSet(ClassEntity cls) {
- return _classSets[cls];
+ @override
+ bool isDirectlyInstantiated(ClassEntity cls) {
+ ClassHierarchyNode node = _classHierarchyNodes[cls];
+ return node != null && node.isDirectlyInstantiated;
+ }
+
+ @override
+ bool isAbstractlyInstantiated(ClassEntity cls) {
+ ClassHierarchyNode node = _classHierarchyNodes[cls];
+ return node != null && node.isAbstractlyInstantiated;
+ }
+
+ @override
+ bool isExplicitlyInstantiated(ClassEntity cls) {
+ ClassHierarchyNode node = _classHierarchyNodes[cls];
+ return node != null && node.isExplicitlyInstantiated;
+ }
+
+ @override
+ bool isIndirectlyInstantiated(ClassEntity cls) {
+ ClassHierarchyNode node = _classHierarchyNodes[cls];
+ return node != null && node.isIndirectlyInstantiated;
}
/// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an
/// instance of [y].
bool isSubtypeOf(ClassEntity x, ClassEntity y) {
ClassSet classSet = _classSets[y];
- assert(classSet != null,
- failedAt(y, "No ClassSet for $y (${y.runtimeType}): ${_classSets}"));
+ assert(
+ classSet != null,
+ failedAt(
+ y,
+ "No ClassSet for $y (${y.runtimeType}): "
+ "${dump(y)} : ${_classSets}"));
ClassHierarchyNode classHierarchyNode = _classHierarchyNodes[x];
assert(classHierarchyNode != null,
- failedAt(x, "No ClassHierarchyNode for $x"));
+ failedAt(x, "No ClassHierarchyNode for $x: ${dump(x)}"));
return classSet.hasSubtype(classHierarchyNode);
}
@@ -107,6 +199,53 @@
return _classHierarchyNodes[y].hasSubclass(_classHierarchyNodes[x]);
}
+ /// Returns an iterable over the directly instantiated classes that extend
+ /// [cls] possibly including [cls] itself, if it is live.
+ Iterable<ClassEntity> subclassesOf(ClassEntity cls) {
+ ClassHierarchyNode hierarchy = _classHierarchyNodes[cls];
+ if (hierarchy == null) return const <ClassEntity>[];
+ return hierarchy
+ .subclassesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED);
+ }
+
+ /// Returns an iterable over the directly instantiated classes that extend
+ /// [cls] _not_ including [cls] itself.
+ Iterable<ClassEntity> strictSubclassesOf(ClassEntity cls) {
+ ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
+ if (subclasses == null) return const <ClassEntity>[];
+ return subclasses.subclassesByMask(
+ ClassHierarchyNode.EXPLICITLY_INSTANTIATED,
+ strict: true);
+ }
+
+ /// Returns the number of live classes that extend [cls] _not_
+ /// including [cls] itself.
+ int strictSubclassCount(ClassEntity cls) {
+ ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
+ if (subclasses == null) return 0;
+ return subclasses.instantiatedSubclassCount;
+ }
+
+ /// Applies [f] to each live class that extend [cls] _not_ including [cls]
+ /// itself.
+ void forEachStrictSubclassOf(
+ ClassEntity cls, IterationStep f(ClassEntity cls)) {
+ ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
+ if (subclasses == null) return;
+ subclasses.forEachSubclass(f, ClassHierarchyNode.EXPLICITLY_INSTANTIATED,
+ strict: true);
+ }
+
+ /// Returns `true` if [predicate] applies to any live class that extend [cls]
+ /// _not_ including [cls] itself.
+ bool anyStrictSubclassOf(ClassEntity cls, bool predicate(ClassEntity cls)) {
+ ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
+ if (subclasses == null) return false;
+ return subclasses.anySubclass(
+ predicate, ClassHierarchyNode.EXPLICITLY_INSTANTIATED,
+ strict: true);
+ }
+
/// Returns an iterable over the directly instantiated that implement [cls]
/// possibly including [cls] itself, if it is live.
Iterable<ClassEntity> subtypesOf(ClassEntity cls) {
@@ -119,15 +258,6 @@
}
}
- /// Returns an iterable over the directly instantiated classes that extend
- /// [cls] possibly including [cls] itself, if it is live.
- Iterable<ClassEntity> subclassesOf(ClassEntity cls) {
- ClassHierarchyNode hierarchy = _classHierarchyNodes[cls];
- if (hierarchy == null) return const <ClassEntity>[];
- return hierarchy
- .subclassesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED);
- }
-
/// Returns an iterable over the directly instantiated that implement [cls]
/// _not_ including [cls].
Iterable<ClassEntity> strictSubtypesOf(ClassEntity cls) {
@@ -140,24 +270,12 @@
}
}
- /// Returns an iterable over the directly instantiated classes that extend
- /// [cls] _not_ including [cls] itself.
- Iterable<ClassEntity> strictSubclassesOf(ClassEntity cls) {
- ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
- if (subclasses == null) return const <ClassEntity>[];
- return subclasses.subclassesByMask(
- ClassHierarchyNode.EXPLICITLY_INSTANTIATED,
- strict: true);
- }
-
- /// Applies [f] to each live class that extend [cls] _not_ including [cls]
- /// itself.
- void forEachStrictSubclassOf(
- ClassEntity cls, IterationStep f(ClassEntity cls)) {
- ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
- if (subclasses == null) return;
- subclasses.forEachSubclass(f, ClassHierarchyNode.EXPLICITLY_INSTANTIATED,
- strict: true);
+ /// Returns the number of live classes that implement [cls] _not_
+ /// including [cls] itself.
+ int strictSubtypeCount(ClassEntity cls) {
+ ClassSet classSet = _classSets[cls];
+ if (classSet == null) return 0;
+ return classSet.instantiatedSubtypeCount;
}
/// Applies [f] to each live class that implements [cls] _not_ including [cls]
@@ -170,6 +288,58 @@
strict: true);
}
+ /// Returns `true` if [predicate] applies to any live class that extend [cls]
+ /// _not_ including [cls] itself.
+ bool anyStrictSubtypeOf(ClassEntity cls, bool predicate(ClassEntity cls)) {
+ ClassSet classSet = _classSets[cls];
+ if (classSet == null) return false;
+ return classSet.anySubtype(
+ predicate, ClassHierarchyNode.EXPLICITLY_INSTANTIATED,
+ strict: true);
+ }
+
+ /// Returns `true` if [a] and [b] have any known common subtypes.
+ bool haveAnyCommonSubtypes(ClassEntity a, ClassEntity b) {
+ ClassSet classSetA = _classSets[a];
+ ClassSet classSetB = _classSets[b];
+ if (classSetA == null || classSetB == null) return false;
+ // TODO(johnniwinther): Implement an optimized query on [ClassSet].
+ Set<ClassEntity> subtypesOfB = classSetB.subtypes().toSet();
+ for (ClassEntity subtypeOfA in classSetA.subtypes()) {
+ if (subtypesOfB.contains(subtypeOfA)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /// Returns `true` if any directly instantiated class other than [cls] extends
+ /// [cls].
+ bool hasAnyStrictSubclass(ClassEntity cls) {
+ ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
+ if (subclasses == null) return false;
+ return subclasses.isIndirectlyInstantiated;
+ }
+
+ /// Returns `true` if any directly instantiated class other than [cls]
+ /// implements [cls].
+ bool hasAnyStrictSubtype(ClassEntity cls) {
+ return strictSubtypeCount(cls) > 0;
+ }
+
+ /// Returns `true` if all directly instantiated classes that implement [cls]
+ /// extend it.
+ bool hasOnlySubclasses(ClassEntity cls) {
+ // TODO(johnniwinther): move this to ClassSet?
+ if (cls == _commonElements.objectClass) return true;
+ ClassSet classSet = _classSets[cls];
+ if (classSet == null) {
+ // Vacuously true.
+ return true;
+ }
+ return classSet.hasOnlyInstantiatedSubclasses;
+ }
+
SubclassResult commonSubclasses(ClassEntity cls1, ClassQuery query1,
ClassEntity cls2, ClassQuery query2) {
if (query1 == ClassQuery.EXACT && query2 == ClassQuery.EXACT) {
@@ -314,6 +484,37 @@
return new SubclassResult(classes);
}
}
+
+ /// 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 [JClosedWorld].
+ ClassHierarchyNode getClassHierarchyNode(ClassEntity cls) {
+ return _classHierarchyNodes[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 [JClosedWorld].
+ ClassSet getClassSet(ClassEntity cls) {
+ return _classSets[cls];
+ }
+
+ @override
+ String dump([ClassEntity cls]) {
+ StringBuffer sb = new StringBuffer();
+ if (cls != null) {
+ sb.write("Classes in the closed world related to $cls:\n");
+ } else {
+ sb.write("Instantiated classes in the closed world:\n");
+ }
+ getClassHierarchyNode(_commonElements.objectClass)
+ .printOn(sb, ' ', instantiatedOnly: cls == null, withRespectTo: cls);
+ return sb.toString();
+ }
}
class ClassHierarchyBuilder {
@@ -335,7 +536,6 @@
}
ClassHierarchyNode _ensureClassHierarchyNode(ClassEntity cls) {
- assert(_classQueries.checkClass(cls));
return classHierarchyNodes.putIfAbsent(cls, () {
ClassHierarchyNode parentNode;
ClassEntity superclass = _classQueries.getSuperClass(cls);
@@ -348,7 +548,6 @@
}
ClassSet _ensureClassSet(ClassEntity cls) {
- assert(_classQueries.checkClass(cls));
return classSets.putIfAbsent(cls, () {
ClassHierarchyNode node = _ensureClassHierarchyNode(cls);
ClassSet classSet = new ClassSet(node);
@@ -460,9 +659,6 @@
}
abstract class ClassQueries {
- bool checkClass(covariant ClassEntity cls);
- bool validateClass(covariant ClassEntity cls);
-
/// Returns the declaration of [cls].
ClassEntity getDeclaration(covariant ClassEntity cls);
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder.dart b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
index b472c00..d3f30e2 100644
--- a/pkg/compiler/lib/src/universe/resolution_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
@@ -912,11 +912,6 @@
if (!info.hasInstantiation) {
return;
}
- assert(_classQueries.checkClass(cls));
- if (!_classQueries.validateClass(cls)) {
- failedAt(cls, 'Class "${cls.name}" is not resolved.');
- }
-
_classHierarchyBuilder.updateClassHierarchyNodeForClass(cls,
directlyInstantiated: info.isDirectlyInstantiated,
abstractlyInstantiated: info.isAbstractlyInstantiated);
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index d440deb..652cde7 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -71,97 +71,9 @@
ClassHierarchy get classHierarchy;
- /// Returns `true` if [cls] is either directly or indirectly instantiated.
- bool isInstantiated(ClassEntity cls);
-
- /// Returns `true` if [cls] is directly instantiated. This means that at
- /// runtime instances of exactly [cls] are assumed to exist.
- bool isDirectlyInstantiated(ClassEntity 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(ClassEntity cls);
-
- /// Returns `true` if [cls] is either directly or abstractly instantiated.
- ///
- /// See [isDirectlyInstantiated] and [isAbstractlyInstantiated].
- bool isExplicitlyInstantiated(ClassEntity cls);
-
- /// Returns `true` if [cls] is indirectly instantiated, that is through a
- /// subclass.
- bool isIndirectlyInstantiated(ClassEntity cls);
-
/// Returns `true` if [cls] is implemented by an instantiated class.
bool isImplemented(ClassEntity cls);
- /// Return `true` if [x] is a subclass of [y].
- bool isSubclassOf(ClassEntity x, ClassEntity y);
-
- /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an
- /// instance of [y].
- bool isSubtypeOf(ClassEntity x, ClassEntity y);
-
- /// Returns an iterable over the live classes that extend [cls] including
- /// [cls] itself.
- Iterable<ClassEntity> subclassesOf(ClassEntity cls);
-
- /// Returns an iterable over the live classes that extend [cls] _not_
- /// including [cls] itself.
- Iterable<ClassEntity> strictSubclassesOf(ClassEntity cls);
-
- /// Returns the number of live classes that extend [cls] _not_
- /// including [cls] itself.
- int strictSubclassCount(ClassEntity cls);
-
- /// Applies [f] to each live class that extend [cls] _not_ including [cls]
- /// itself.
- void forEachStrictSubclassOf(
- ClassEntity cls, IterationStep f(ClassEntity cls));
-
- /// Returns `true` if [predicate] applies to any live class that extend [cls]
- /// _not_ including [cls] itself.
- bool anyStrictSubclassOf(ClassEntity cls, bool predicate(ClassEntity cls));
-
- /// Returns an iterable over the directly instantiated that implement [cls]
- /// possibly including [cls] itself, if it is live.
- Iterable<ClassEntity> subtypesOf(ClassEntity cls);
-
- /// Returns an iterable over the live classes that implement [cls] _not_
- /// including [cls] if it is live.
- Iterable<ClassEntity> strictSubtypesOf(ClassEntity cls);
-
- /// Returns the number of live classes that implement [cls] _not_
- /// including [cls] itself.
- int strictSubtypeCount(ClassEntity cls);
-
- /// Applies [f] to each live class that implements [cls] _not_ including [cls]
- /// itself.
- void forEachStrictSubtypeOf(
- ClassEntity cls, IterationStep f(ClassEntity cls));
-
- /// Returns `true` if [predicate] applies to any live class that implements
- /// [cls] _not_ including [cls] itself.
- bool anyStrictSubtypeOf(ClassEntity cls, bool predicate(ClassEntity cls));
-
- /// Returns `true` if [a] and [b] have any known common subtypes.
- bool haveAnyCommonSubtypes(ClassEntity a, ClassEntity b);
-
- /// Returns `true` if any live class other than [cls] extends [cls].
- bool hasAnyStrictSubclass(ClassEntity cls);
-
- /// Returns `true` if any live class other than [cls] implements [cls].
- bool hasAnyStrictSubtype(ClassEntity cls);
-
- /// Returns `true` if all live classes that implement [cls] extend it.
- bool hasOnlySubclasses(ClassEntity cls);
-
/// 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.
@@ -246,20 +158,6 @@
bool hasElementIn(
covariant ClassEntity cls, Selector selector, covariant Entity element);
- /// 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 [JClosedWorld].
- ClassHierarchyNode getClassHierarchyNode(ClassEntity 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 [JClosedWorld].
- ClassSet getClassSet(ClassEntity cls);
-
/// Returns `true` if the field [element] is known to be effectively final.
bool fieldNeverChanges(MemberEntity element);
@@ -300,17 +198,6 @@
/// [receiver]. If multiple targets exist or the single target is not a field,
/// `null` is returned.
FieldEntity locateSingleField(Selector selector, AbstractValue receiver);
-
- /// Returns a string representation of the closed world.
- ///
- /// If [cls] is provided, the dump will contain only classes related to [cls].
- String dump([ClassEntity cls]);
-
- /// Adds the closure class [cls] to the inference world. The class is
- /// considered directly instantiated. If [fromInstanceMember] is true, this
- /// closure class represents a closure that is inside an instance member, thus
- /// has access to `this`.
- void registerClosureClass(ClassEntity cls);
}
abstract class OpenWorld implements World {
@@ -400,11 +287,6 @@
classHierarchy = new ClassHierarchyImpl(
commonElements, classHierarchyNodes, classSets) {}
- bool checkEntity(covariant Entity element);
-
- bool checkInvariants(covariant ClassEntity cls,
- {bool mustBeInstantiated: true});
-
OrderedTypeSet getOrderedTypeSet(covariant ClassEntity cls);
int getHierarchyDepth(covariant ClassEntity cls);
@@ -417,207 +299,11 @@
bool isNamedMixinApplication(covariant ClassEntity cls);
- @override
- bool isInstantiated(ClassEntity cls) {
- ClassHierarchyNode node = _classHierarchyNodes[cls];
- return node != null && node.isInstantiated;
- }
-
- @override
- bool isDirectlyInstantiated(ClassEntity cls) {
- ClassHierarchyNode node = _classHierarchyNodes[cls];
- return node != null && node.isDirectlyInstantiated;
- }
-
- @override
- bool isAbstractlyInstantiated(ClassEntity cls) {
- ClassHierarchyNode node = _classHierarchyNodes[cls];
- return node != null && node.isAbstractlyInstantiated;
- }
-
- @override
- bool isExplicitlyInstantiated(ClassEntity cls) {
- ClassHierarchyNode node = _classHierarchyNodes[cls];
- return node != null && node.isExplicitlyInstantiated;
- }
-
- @override
- bool isIndirectlyInstantiated(ClassEntity cls) {
- ClassHierarchyNode node = _classHierarchyNodes[cls];
- return node != null && node.isIndirectlyInstantiated;
- }
-
/// Returns `true` if [cls] is implemented by an instantiated class.
bool isImplemented(ClassEntity cls) {
return _implementedClasses.contains(cls);
}
- /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an
- /// instance of [y].
- bool isSubtypeOf(ClassEntity x, ClassEntity y) {
- assert(checkInvariants(x));
- assert(checkInvariants(y, mustBeInstantiated: false));
- ClassSet classSet = _classSets[y];
- assert(
- classSet != null,
- failedAt(
- y,
- "No ClassSet for $y (${y.runtimeType}): "
- "${dump(y)} : ${_classSets}"));
- ClassHierarchyNode classHierarchyNode = _classHierarchyNodes[x];
- assert(classHierarchyNode != null,
- failedAt(x, "No ClassHierarchyNode for $x: ${dump(x)}"));
- return classSet.hasSubtype(classHierarchyNode);
- }
-
- /// Return `true` if [x] is a (non-strict) subclass of [y].
- bool isSubclassOf(ClassEntity x, ClassEntity y) {
- assert(checkInvariants(x));
- assert(checkInvariants(y));
- return _classHierarchyNodes[y].hasSubclass(_classHierarchyNodes[x]);
- }
-
- /// Returns an iterable over the directly instantiated classes that extend
- /// [cls] possibly including [cls] itself, if it is live.
- Iterable<ClassEntity> subclassesOf(ClassEntity cls) {
- ClassHierarchyNode hierarchy = _classHierarchyNodes[cls];
- if (hierarchy == null) return const <ClassEntity>[];
- return hierarchy
- .subclassesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED);
- }
-
- /// Returns an iterable over the directly instantiated classes that extend
- /// [cls] _not_ including [cls] itself.
- Iterable<ClassEntity> strictSubclassesOf(ClassEntity cls) {
- ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
- if (subclasses == null) return const <ClassEntity>[];
- return subclasses.subclassesByMask(
- ClassHierarchyNode.EXPLICITLY_INSTANTIATED,
- strict: true);
- }
-
- /// Returns the number of live classes that extend [cls] _not_
- /// including [cls] itself.
- int strictSubclassCount(ClassEntity cls) {
- ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
- if (subclasses == null) return 0;
- return subclasses.instantiatedSubclassCount;
- }
-
- /// Applies [f] to each live class that extend [cls] _not_ including [cls]
- /// itself.
- void forEachStrictSubclassOf(
- ClassEntity cls, IterationStep f(ClassEntity cls)) {
- ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
- if (subclasses == null) return;
- subclasses.forEachSubclass(f, ClassHierarchyNode.EXPLICITLY_INSTANTIATED,
- strict: true);
- }
-
- /// Returns `true` if [predicate] applies to any live class that extend [cls]
- /// _not_ including [cls] itself.
- bool anyStrictSubclassOf(ClassEntity cls, bool predicate(ClassEntity cls)) {
- ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
- if (subclasses == null) return false;
- return subclasses.anySubclass(
- predicate, ClassHierarchyNode.EXPLICITLY_INSTANTIATED,
- strict: true);
- }
-
- /// Returns an iterable over the directly instantiated that implement [cls]
- /// possibly including [cls] itself, if it is live.
- Iterable<ClassEntity> subtypesOf(ClassEntity cls) {
- ClassSet classSet = _classSets[cls];
- if (classSet == null) {
- return const <ClassEntity>[];
- } else {
- return classSet
- .subtypesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED);
- }
- }
-
- /// Returns an iterable over the directly instantiated that implement [cls]
- /// _not_ including [cls].
- Iterable<ClassEntity> strictSubtypesOf(ClassEntity cls) {
- ClassSet classSet = _classSets[cls];
- if (classSet == null) {
- return const <ClassEntity>[];
- } else {
- return classSet.subtypesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED,
- strict: true);
- }
- }
-
- /// Returns the number of live classes that implement [cls] _not_
- /// including [cls] itself.
- int strictSubtypeCount(ClassEntity cls) {
- ClassSet classSet = _classSets[cls];
- if (classSet == null) return 0;
- return classSet.instantiatedSubtypeCount;
- }
-
- /// Applies [f] to each live class that implements [cls] _not_ including [cls]
- /// itself.
- void forEachStrictSubtypeOf(
- ClassEntity cls, IterationStep f(ClassEntity cls)) {
- ClassSet classSet = _classSets[cls];
- if (classSet == null) return;
- classSet.forEachSubtype(f, ClassHierarchyNode.EXPLICITLY_INSTANTIATED,
- strict: true);
- }
-
- /// Returns `true` if [predicate] applies to any live class that extend [cls]
- /// _not_ including [cls] itself.
- bool anyStrictSubtypeOf(ClassEntity cls, bool predicate(ClassEntity cls)) {
- ClassSet classSet = _classSets[cls];
- if (classSet == null) return false;
- return classSet.anySubtype(
- predicate, ClassHierarchyNode.EXPLICITLY_INSTANTIATED,
- strict: true);
- }
-
- /// Returns `true` if [a] and [b] have any known common subtypes.
- bool haveAnyCommonSubtypes(ClassEntity a, ClassEntity b) {
- ClassSet classSetA = _classSets[a];
- ClassSet classSetB = _classSets[b];
- if (classSetA == null || classSetB == null) return false;
- // TODO(johnniwinther): Implement an optimized query on [ClassSet].
- Set<ClassEntity> subtypesOfB = classSetB.subtypes().toSet();
- for (ClassEntity subtypeOfA in classSetA.subtypes()) {
- if (subtypesOfB.contains(subtypeOfA)) {
- return true;
- }
- }
- return false;
- }
-
- /// Returns `true` if any directly instantiated class other than [cls] extends
- /// [cls].
- bool hasAnyStrictSubclass(ClassEntity cls) {
- ClassHierarchyNode subclasses = _classHierarchyNodes[cls];
- if (subclasses == null) return false;
- return subclasses.isIndirectlyInstantiated;
- }
-
- /// Returns `true` if any directly instantiated class other than [cls]
- /// implements [cls].
- bool hasAnyStrictSubtype(ClassEntity cls) {
- return strictSubtypeCount(cls) > 0;
- }
-
- /// Returns `true` if all directly instantiated classes that implement [cls]
- /// extend it.
- bool hasOnlySubclasses(ClassEntity cls) {
- // TODO(johnniwinther): move this to ClassSet?
- if (cls == commonElements.objectClass) return true;
- ClassSet classSet = _classSets[cls];
- if (classSet == null) {
- // Vacuously true.
- return true;
- }
- return classSet.hasOnlyInstantiatedSubclasses;
- }
-
@override
ClassEntity getLubOfInstantiatedSubclasses(ClassEntity cls) {
if (nativeData.isJsInteropClass(cls)) {
@@ -655,8 +341,10 @@
bool everySubtypeIsSubclassOfOrMixinUseOf(ClassEntity x, ClassEntity y) {
Map<ClassEntity, bool> secondMap =
_subtypeCoveredByCache[x] ??= <ClassEntity, bool>{};
- return secondMap[y] ??= subtypesOf(x).every((ClassEntity cls) =>
- isSubclassOf(cls, y) || isSubclassOfMixinUseOf(cls, y));
+ return secondMap[y] ??= classHierarchy.subtypesOf(x).every(
+ (ClassEntity cls) =>
+ classHierarchy.isSubclassOf(cls, y) ||
+ isSubclassOfMixinUseOf(cls, y));
}
/// Returns `true` if any subclass of [superclass] implements [type].
@@ -726,7 +414,6 @@
if (!iterator.moveNext()) return const <ClassEntity>[];
ClassEntity cls = iterator.current;
- assert(checkInvariants(cls));
OrderedTypeSet typeSet = getOrderedTypeSet(cls);
if (!iterator.moveNext()) return typeSet.types.map((type) => type.element);
@@ -734,7 +421,6 @@
Link<OrderedTypeSet> otherTypeSets = const Link<OrderedTypeSet>();
do {
ClassEntity otherClass = iterator.current;
- assert(checkInvariants(otherClass));
OrderedTypeSet otherTypeSet = getOrderedTypeSet(otherClass);
otherTypeSets = otherTypeSets.prepend(otherTypeSet);
if (otherTypeSet.maxDepth < depth) {
@@ -769,7 +455,7 @@
List<ClassEntity> uses = <ClassEntity>[];
void addLiveUse(ClassEntity mixinApplication) {
- if (isInstantiated(mixinApplication)) {
+ if (classHierarchy.isInstantiated(mixinApplication)) {
uses.add(mixinApplication);
} else if (isNamedMixinApplication(mixinApplication)) {
Set<ClassEntity> next = mixinUses[mixinApplication];
@@ -793,7 +479,7 @@
/// of [superclass].
bool hasAnySubclassThatMixes(ClassEntity superclass, ClassEntity mixin) {
return mixinUsesOf(mixin).any((ClassEntity each) {
- return isSubclassOf(each, superclass);
+ return classHierarchy.isSubclassOf(each, superclass);
});
}
@@ -913,19 +599,6 @@
return false;
}
- @override
- String dump([ClassEntity cls]) {
- StringBuffer sb = new StringBuffer();
- if (cls != null) {
- sb.write("Classes in the closed world related to $cls:\n");
- } else {
- sb.write("Instantiated classes in the closed world:\n");
- }
- getClassHierarchyNode(commonElements.objectClass)
- .printOn(sb, ' ', instantiatedOnly: cls == null, withRespectTo: cls);
- return sb.toString();
- }
-
/// Should only be called by subclasses.
void addClassHierarchyNode(ClassEntity cls, ClassHierarchyNode node) {
_classHierarchyNodes[cls] = node;
diff --git a/tests/compiler/dart2js/inference/type_mask2_test.dart b/tests/compiler/dart2js/inference/type_mask2_test.dart
index 200f245..904a4c4 100644
--- a/tests/compiler/dart2js/inference/type_mask2_test.dart
+++ b/tests/compiler/dart2js/inference/type_mask2_test.dart
@@ -222,17 +222,17 @@
ClassEntity String_ = env.getElement("String");
ClassEntity JSString = closedWorld.commonElements.jsStringClass;
- Expect.isFalse(closedWorld.isDirectlyInstantiated(Object_));
- Expect.isTrue(closedWorld.isIndirectlyInstantiated(Object_));
- Expect.isTrue(closedWorld.isInstantiated(Object_));
+ Expect.isFalse(closedWorld.classHierarchy.isDirectlyInstantiated(Object_));
+ Expect.isTrue(closedWorld.classHierarchy.isIndirectlyInstantiated(Object_));
+ Expect.isTrue(closedWorld.classHierarchy.isInstantiated(Object_));
- Expect.isFalse(closedWorld.isDirectlyInstantiated(String_));
- Expect.isFalse(closedWorld.isIndirectlyInstantiated(String_));
- Expect.isFalse(closedWorld.isInstantiated(String_));
+ Expect.isFalse(closedWorld.classHierarchy.isDirectlyInstantiated(String_));
+ Expect.isFalse(closedWorld.classHierarchy.isIndirectlyInstantiated(String_));
+ Expect.isFalse(closedWorld.classHierarchy.isInstantiated(String_));
- Expect.isTrue(closedWorld.isDirectlyInstantiated(JSString));
- Expect.isFalse(closedWorld.isIndirectlyInstantiated(JSString));
- Expect.isTrue(closedWorld.isInstantiated(JSString));
+ Expect.isTrue(closedWorld.classHierarchy.isDirectlyInstantiated(JSString));
+ Expect.isFalse(closedWorld.classHierarchy.isIndirectlyInstantiated(JSString));
+ Expect.isTrue(closedWorld.classHierarchy.isInstantiated(JSString));
TypeMask subtypeString = new TypeMask.nonNullSubtype(String_, closedWorld);
TypeMask exactJSString = new TypeMask.nonNullExact(JSString, closedWorld);
diff --git a/tests/compiler/dart2js/jsinterop/world_test.dart b/tests/compiler/dart2js/jsinterop/world_test.dart
index 25377d5..8233d0b 100644
--- a/tests/compiler/dart2js/jsinterop/world_test.dart
+++ b/tests/compiler/dart2js/jsinterop/world_test.dart
@@ -150,16 +150,16 @@
if (directlyInstantiated.contains(name)) {
isInstantiated = true;
Expect.isTrue(
- world.isDirectlyInstantiated(cls),
+ world.classHierarchy.isDirectlyInstantiated(cls),
"Expected $name to be directly instantiated in `${mainSource}`:"
- "\n${world.dump(cls)}");
+ "\n${world.classHierarchy.dump(cls)}");
}
if (abstractlyInstantiated.contains(name)) {
isInstantiated = true;
Expect.isTrue(
- world.isAbstractlyInstantiated(cls),
+ world.classHierarchy.isAbstractlyInstantiated(cls),
"Expected $name to be abstractly instantiated in `${mainSource}`:"
- "\n${world.dump(cls)}");
+ "\n${world.classHierarchy.dump(cls)}");
Expect.isTrue(
world.needsNoSuchMethod(cls, nonExisting, ClassQuery.EXACT),
"Expected $name to need noSuchMethod for $nonExisting.");
@@ -173,15 +173,15 @@
if (indirectlyInstantiated.contains(name)) {
isInstantiated = true;
Expect.isTrue(
- world.isIndirectlyInstantiated(cls),
+ world.classHierarchy.isIndirectlyInstantiated(cls),
"Expected $name to be indirectly instantiated in `${mainSource}`:"
- "\n${world.dump(cls)}");
+ "\n${world.classHierarchy.dump(cls)}");
}
if (!isInstantiated && (name != 'Object' && name != 'Interceptor')) {
Expect.isFalse(
- world.isInstantiated(cls),
+ world.classHierarchy.isInstantiated(cls),
"Expected $name to be uninstantiated in `${mainSource}`:"
- "\n${world.dump(cls)}");
+ "\n${world.classHierarchy.dump(cls)}");
}
}
}
diff --git a/tests/compiler/dart2js/model/class_set_test.dart b/tests/compiler/dart2js/model/class_set_test.dart
index 833334f..70b8807 100644
--- a/tests/compiler/dart2js/model/class_set_test.dart
+++ b/tests/compiler/dart2js/model/class_set_test.dart
@@ -612,12 +612,12 @@
checkIsFunction(ClassEntity cls, {bool expected: true}) {
Expect.equals(
expected,
- world.isSubtypeOf(cls, functionClass),
+ world.classHierarchy.isSubtypeOf(cls, functionClass),
"Expected $cls ${expected ? '' : 'not '}to be a subtype "
"of $functionClass.");
}
checkIsFunction(A, expected: !strongMode);
- world.forEachStrictSubtypeOf(closureClass, checkIsFunction);
+ world.classHierarchy.forEachStrictSubtypeOf(closureClass, checkIsFunction);
}
diff --git a/tests/compiler/dart2js/model/world_test.dart b/tests/compiler/dart2js/model/world_test.dart
index 8975dba..e4599ef 100644
--- a/tests/compiler/dart2js/model/world_test.dart
+++ b/tests/compiler/dart2js/model/world_test.dart
@@ -74,7 +74,7 @@
foundClasses.contains(expectedClass),
"Expect $expectedClass in '$property' on $cls. "
"Found:\n ${foundClasses.join('\n ')}\n"
- "${closedWorld.dump(cls)}");
+ "${closedWorld.classHierarchy.dump(cls)}");
}
if (exact) {
Expect.equals(
@@ -83,7 +83,7 @@
"Unexpected classes "
"${foundClasses.where((c) => !expectedClasses.contains(c))} "
"in '$property' on $cls.\n"
- "${closedWorld.dump(cls)}");
+ "${closedWorld.classHierarchy.dump(cls)}");
}
}
@@ -109,32 +109,33 @@
expectedClasses.length,
count,
"Unexpected class count in '$property' on $cls.\n"
- "${closedWorld.dump(cls)}");
+ "${closedWorld.classHierarchy.dump(cls)}");
}
}
void testSubclasses(ClassEntity cls, List<ClassEntity> expectedClasses,
{bool exact: true}) {
- check('subclassesOf', cls, closedWorld.subclassesOf(cls), expectedClasses,
+ check('subclassesOf', cls, closedWorld.classHierarchy.subclassesOf(cls),
+ expectedClasses,
exact: exact);
}
void testStrictSubclasses(ClassEntity cls, List<ClassEntity> expectedClasses,
{bool exact: true}) {
- check('strictSubclassesOf', cls, closedWorld.strictSubclassesOf(cls),
- expectedClasses,
+ check('strictSubclassesOf', cls,
+ closedWorld.classHierarchy.strictSubclassesOf(cls), expectedClasses,
exact: exact,
- forEach: closedWorld.forEachStrictSubclassOf,
- getCount: closedWorld.strictSubclassCount);
+ forEach: closedWorld.classHierarchy.forEachStrictSubclassOf,
+ getCount: closedWorld.classHierarchy.strictSubclassCount);
}
void testStrictSubtypes(ClassEntity cls, List<ClassEntity> expectedClasses,
{bool exact: true}) {
- check('strictSubtypesOf', cls, closedWorld.strictSubtypesOf(cls),
- expectedClasses,
+ check('strictSubtypesOf', cls,
+ closedWorld.classHierarchy.strictSubtypesOf(cls), expectedClasses,
exact: exact,
- forEach: closedWorld.forEachStrictSubtypeOf,
- getCount: closedWorld.strictSubtypeCount);
+ forEach: closedWorld.classHierarchy.forEachStrictSubtypeOf,
+ getCount: closedWorld.classHierarchy.strictSubtypeCount);
}
void testMixinUses(ClassEntity cls, List<ClassEntity> expectedClasses,
@@ -248,9 +249,13 @@
check(String name, {bool hasStrictSubtype, bool hasOnlySubclasses}) {
ClassEntity cls = env.getElement(name);
- Expect.equals(hasStrictSubtype, closedWorld.hasAnyStrictSubtype(cls),
+ Expect.equals(
+ hasStrictSubtype,
+ closedWorld.classHierarchy.hasAnyStrictSubtype(cls),
"Unexpected hasAnyStrictSubtype property on $cls.");
- Expect.equals(hasOnlySubclasses, closedWorld.hasOnlySubclasses(cls),
+ Expect.equals(
+ hasOnlySubclasses,
+ closedWorld.classHierarchy.hasOnlySubclasses(cls),
"Unexpected hasOnlySubclasses property on $cls.");
}
@@ -360,26 +365,30 @@
int instantiatedSubtypeCount,
List<ClassEntity> subclasses: const <ClassEntity>[],
List<ClassEntity> subtypes: const <ClassEntity>[]}) {
- ClassSet classSet = closedWorld.getClassSet(cls);
+ ClassSet classSet = closedWorld.classHierarchy.getClassSet(cls);
ClassHierarchyNode node = classSet.node;
- String dumpText = '\n${closedWorld.dump(cls)}';
+ String dumpText = '\n${closedWorld.classHierarchy.dump(cls)}';
Expect.equals(
isDirectlyInstantiated,
- closedWorld.isDirectlyInstantiated(cls),
+ closedWorld.classHierarchy.isDirectlyInstantiated(cls),
"Unexpected isDirectlyInstantiated property on $cls.$dumpText");
Expect.equals(
isAbstractlyInstantiated,
- closedWorld.isAbstractlyInstantiated(cls),
+ closedWorld.classHierarchy.isAbstractlyInstantiated(cls),
"Unexpected isAbstractlyInstantiated property on $cls.$dumpText");
Expect.equals(
isIndirectlyInstantiated,
- closedWorld.isIndirectlyInstantiated(cls),
+ closedWorld.classHierarchy.isIndirectlyInstantiated(cls),
"Unexpected isIndirectlyInstantiated property on $cls.$dumpText");
- Expect.equals(hasStrictSubtype, closedWorld.hasAnyStrictSubtype(cls),
+ Expect.equals(
+ hasStrictSubtype,
+ closedWorld.classHierarchy.hasAnyStrictSubtype(cls),
"Unexpected hasAnyStrictSubtype property on $cls.$dumpText");
- Expect.equals(hasOnlySubclasses, closedWorld.hasOnlySubclasses(cls),
+ Expect.equals(
+ hasOnlySubclasses,
+ closedWorld.classHierarchy.hasOnlySubclasses(cls),
"Unexpected hasOnlySubclasses property on $cls.$dumpText");
Expect.equals(
lubOfInstantiatedSubclasses,
@@ -399,19 +408,20 @@
}
for (ClassEntity other in allClasses) {
if (other == cls) continue;
- if (!closedWorld.isExplicitlyInstantiated(other)) continue;
+ if (!closedWorld.classHierarchy.isExplicitlyInstantiated(other)) continue;
Expect.equals(
subclasses.contains(other),
- closedWorld.isSubclassOf(other, cls),
+ closedWorld.classHierarchy.isSubclassOf(other, cls),
"Unexpected subclass relation between $other and $cls.");
Expect.equals(
subtypes.contains(other),
- closedWorld.isSubtypeOf(other, cls),
+ closedWorld.classHierarchy.isSubtypeOf(other, cls),
"Unexpected subtype relation between $other and $cls.");
}
Set<ClassEntity> strictSubclasses = new Set<ClassEntity>();
- closedWorld.forEachStrictSubclassOf(cls, (ClassEntity other) {
+ closedWorld.classHierarchy.forEachStrictSubclassOf(cls,
+ (ClassEntity other) {
if (allClasses.contains(other)) {
strictSubclasses.add(other);
}
@@ -420,7 +430,7 @@
"Unexpected strict subclasses of $cls: ${strictSubclasses}.");
Set<ClassEntity> strictSubtypes = new Set<ClassEntity>();
- closedWorld.forEachStrictSubtypeOf(cls, (ClassEntity other) {
+ closedWorld.classHierarchy.forEachStrictSubtypeOf(cls, (ClassEntity other) {
if (allClasses.contains(other)) {
strictSubtypes.add(other);
}
diff --git a/tests/compiler/dart2js/needs_no_such_method_test.dart b/tests/compiler/dart2js/needs_no_such_method_test.dart
index 735e390..db958ac 100644
--- a/tests/compiler/dart2js/needs_no_such_method_test.dart
+++ b/tests/compiler/dart2js/needs_no_such_method_test.dart
@@ -65,7 +65,7 @@
void check(ClassEntity cls, ClassQuery query, Selector selector,
bool expectedResult) {
bool result;
- if (closedWorld.getClassSet(cls) == null) {
+ if (closedWorld.classHierarchy.getClassSet(cls) == null) {
// The class isn't live, so it can't need a noSuchMethod for [selector].
result = false;
} else {
@@ -80,16 +80,17 @@
await run([]);
- Expect.isFalse(closedWorld.isDirectlyInstantiated(superclass));
- Expect.isFalse(closedWorld.isIndirectlyInstantiated(superclass));
+ Expect.isFalse(closedWorld.classHierarchy.isDirectlyInstantiated(superclass));
+ Expect.isFalse(
+ closedWorld.classHierarchy.isIndirectlyInstantiated(superclass));
Expect.isFalse(closedWorld.isImplemented(superclass));
- Expect.isFalse(closedWorld.isDirectlyInstantiated(subclass));
- Expect.isFalse(closedWorld.isIndirectlyInstantiated(subclass));
+ Expect.isFalse(closedWorld.classHierarchy.isDirectlyInstantiated(subclass));
+ Expect.isFalse(closedWorld.classHierarchy.isIndirectlyInstantiated(subclass));
Expect.isFalse(closedWorld.isImplemented(subclass));
- Expect.isFalse(closedWorld.isDirectlyInstantiated(subtype));
- Expect.isFalse(closedWorld.isIndirectlyInstantiated(subtype));
+ Expect.isFalse(closedWorld.classHierarchy.isDirectlyInstantiated(subtype));
+ Expect.isFalse(closedWorld.classHierarchy.isIndirectlyInstantiated(subtype));
Expect.isFalse(closedWorld.isImplemented(subtype));
check(superclass, ClassQuery.EXACT, foo, false);
@@ -124,16 +125,17 @@
await run(['Superclass']);
- Expect.isTrue(closedWorld.isDirectlyInstantiated(superclass));
- Expect.isFalse(closedWorld.isIndirectlyInstantiated(superclass));
+ Expect.isTrue(closedWorld.classHierarchy.isDirectlyInstantiated(superclass));
+ Expect.isFalse(
+ closedWorld.classHierarchy.isIndirectlyInstantiated(superclass));
Expect.isTrue(closedWorld.isImplemented(superclass));
- Expect.isFalse(closedWorld.isDirectlyInstantiated(subclass));
- Expect.isFalse(closedWorld.isIndirectlyInstantiated(subclass));
+ Expect.isFalse(closedWorld.classHierarchy.isDirectlyInstantiated(subclass));
+ Expect.isFalse(closedWorld.classHierarchy.isIndirectlyInstantiated(subclass));
Expect.isFalse(closedWorld.isImplemented(subclass));
- Expect.isFalse(closedWorld.isDirectlyInstantiated(subtype));
- Expect.isFalse(closedWorld.isIndirectlyInstantiated(subtype));
+ Expect.isFalse(closedWorld.classHierarchy.isDirectlyInstantiated(subtype));
+ Expect.isFalse(closedWorld.classHierarchy.isIndirectlyInstantiated(subtype));
Expect.isFalse(closedWorld.isImplemented(subtype));
check(superclass, ClassQuery.EXACT, foo, false);
@@ -168,16 +170,17 @@
await run(['Subclass']);
- Expect.isFalse(closedWorld.isDirectlyInstantiated(superclass));
- Expect.isTrue(closedWorld.isIndirectlyInstantiated(superclass));
+ Expect.isFalse(closedWorld.classHierarchy.isDirectlyInstantiated(superclass));
+ Expect.isTrue(
+ closedWorld.classHierarchy.isIndirectlyInstantiated(superclass));
Expect.isTrue(closedWorld.isImplemented(superclass));
- Expect.isTrue(closedWorld.isDirectlyInstantiated(subclass));
- Expect.isFalse(closedWorld.isIndirectlyInstantiated(subclass));
+ Expect.isTrue(closedWorld.classHierarchy.isDirectlyInstantiated(subclass));
+ Expect.isFalse(closedWorld.classHierarchy.isIndirectlyInstantiated(subclass));
Expect.isTrue(closedWorld.isImplemented(subclass));
- Expect.isFalse(closedWorld.isDirectlyInstantiated(subtype));
- Expect.isFalse(closedWorld.isIndirectlyInstantiated(subtype));
+ Expect.isFalse(closedWorld.classHierarchy.isDirectlyInstantiated(subtype));
+ Expect.isFalse(closedWorld.classHierarchy.isIndirectlyInstantiated(subtype));
Expect.isFalse(closedWorld.isImplemented(subtype));
check(superclass, ClassQuery.EXACT, foo, false);
@@ -212,16 +215,17 @@
await run(['Subtype']);
- Expect.isFalse(closedWorld.isDirectlyInstantiated(superclass));
- Expect.isFalse(closedWorld.isIndirectlyInstantiated(superclass));
+ Expect.isFalse(closedWorld.classHierarchy.isDirectlyInstantiated(superclass));
+ Expect.isFalse(
+ closedWorld.classHierarchy.isIndirectlyInstantiated(superclass));
Expect.isTrue(closedWorld.isImplemented(superclass));
- Expect.isFalse(closedWorld.isDirectlyInstantiated(subclass));
- Expect.isFalse(closedWorld.isIndirectlyInstantiated(subclass));
+ Expect.isFalse(closedWorld.classHierarchy.isDirectlyInstantiated(subclass));
+ Expect.isFalse(closedWorld.classHierarchy.isIndirectlyInstantiated(subclass));
Expect.isFalse(closedWorld.isImplemented(subclass));
- Expect.isTrue(closedWorld.isDirectlyInstantiated(subtype));
- Expect.isFalse(closedWorld.isIndirectlyInstantiated(subtype));
+ Expect.isTrue(closedWorld.classHierarchy.isDirectlyInstantiated(subtype));
+ Expect.isFalse(closedWorld.classHierarchy.isIndirectlyInstantiated(subtype));
Expect.isTrue(closedWorld.isImplemented(subtype));
check(superclass, ClassQuery.EXACT, foo, false);
@@ -256,16 +260,17 @@
await run(['Subclass', 'Subtype']);
- Expect.isFalse(closedWorld.isDirectlyInstantiated(superclass));
- Expect.isTrue(closedWorld.isIndirectlyInstantiated(superclass));
+ Expect.isFalse(closedWorld.classHierarchy.isDirectlyInstantiated(superclass));
+ Expect.isTrue(
+ closedWorld.classHierarchy.isIndirectlyInstantiated(superclass));
Expect.isTrue(closedWorld.isImplemented(superclass));
- Expect.isTrue(closedWorld.isDirectlyInstantiated(subclass));
- Expect.isFalse(closedWorld.isIndirectlyInstantiated(subclass));
+ Expect.isTrue(closedWorld.classHierarchy.isDirectlyInstantiated(subclass));
+ Expect.isFalse(closedWorld.classHierarchy.isIndirectlyInstantiated(subclass));
Expect.isTrue(closedWorld.isImplemented(subclass));
- Expect.isTrue(closedWorld.isDirectlyInstantiated(subtype));
- Expect.isFalse(closedWorld.isIndirectlyInstantiated(subtype));
+ Expect.isTrue(closedWorld.classHierarchy.isDirectlyInstantiated(subtype));
+ Expect.isFalse(closedWorld.classHierarchy.isIndirectlyInstantiated(subtype));
Expect.isTrue(closedWorld.isImplemented(subtype));
check(superclass, ClassQuery.EXACT, foo, false);
diff --git a/tests/compiler/dart2js/receiver_type_test.dart b/tests/compiler/dart2js/receiver_type_test.dart
index 50b8fc3..c158073 100644
--- a/tests/compiler/dart2js/receiver_type_test.dart
+++ b/tests/compiler/dart2js/receiver_type_test.dart
@@ -47,8 +47,8 @@
JClosedWorld closedWorld = env.jClosedWorld;
int closureCount = 0;
Selector callSelector = new Selector.callClosure(0);
- closedWorld.forEachStrictSubclassOf(closedWorld.commonElements.objectClass,
- (ClassEntity cls) {
+ closedWorld.classHierarchy.forEachStrictSubclassOf(
+ closedWorld.commonElements.objectClass, (ClassEntity cls) {
if (cls.library.canonicalUri.scheme != 'memory') return;
TypeMask mask = new TypeMask.nonNullSubclass(cls, closedWorld);