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()); |