| Index: runtime/vm/cha.cc
|
| diff --git a/runtime/vm/cha.cc b/runtime/vm/cha.cc
|
| index ed5255e664bd9f5d425346fb7753093fe124e65d..57214bb10fe32e6562bc4dea38da5d956cbe972c 100644
|
| --- a/runtime/vm/cha.cc
|
| +++ b/runtime/vm/cha.cc
|
| @@ -48,6 +48,31 @@ bool CHA::HasSubclasses(intptr_t cid) const {
|
| }
|
|
|
|
|
| +bool CHA::ConcreteSubclasses(const Class& cls,
|
| + GrowableArray<intptr_t> *class_ids) {
|
| + if (cls.InVMHeap()) return false;
|
| + if (cls.IsObjectClass()) return false;
|
| +
|
| + if (!cls.is_abstract()) {
|
| + class_ids->Add(cls.id());
|
| + }
|
| +
|
| + const GrowableObjectArray& direct_subclasses =
|
| + GrowableObjectArray::Handle(cls.direct_subclasses());
|
| + if (direct_subclasses.IsNull()) {
|
| + return true;
|
| + }
|
| + Class& subclass = Class::Handle();
|
| + for (intptr_t i = 0; i < direct_subclasses.Length(); i++) {
|
| + subclass ^= direct_subclasses.At(i);
|
| + if (!ConcreteSubclasses(subclass, class_ids)) {
|
| + return false;
|
| + }
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +
|
| bool CHA::IsImplemented(const Class& cls) {
|
| // Function type aliases have different type checking rules.
|
| ASSERT(!cls.IsTypedefClass());
|
|
|