Index: runtime/vm/cha.cc |
diff --git a/runtime/vm/cha.cc b/runtime/vm/cha.cc |
index 57214bb10fe32e6562bc4dea38da5d956cbe972c..6a0a16d32f59ce375b6503949dfeae6b372e46f2 100644 |
--- a/runtime/vm/cha.cc |
+++ b/runtime/vm/cha.cc |
@@ -12,13 +12,26 @@ |
namespace dart { |
-void CHA::AddToLeafClasses(const Class& cls) { |
- for (intptr_t i = 0; i < leaf_classes_.length(); i++) { |
- if (leaf_classes_[i]->raw() == cls.raw()) { |
+void CHA::AddToGuardedClasses(const Class& cls, intptr_t subclass_count) { |
+ for (intptr_t i = 0; i < guarded_classes_.length(); i++) { |
+ if (guarded_classes_[i].cls->raw() == cls.raw()) { |
return; |
} |
} |
- leaf_classes_.Add(&Class::ZoneHandle(thread_->zone(), cls.raw())); |
+ GuardedClassInfo info = { |
+ &Class::ZoneHandle(thread_->zone(), cls.raw()), |
+ subclass_count |
+ }; |
+ guarded_classes_.Add(info); |
+ return; |
+} |
+ |
+ |
+bool CHA::IsGuardedClass(intptr_t cid) const { |
+ for (intptr_t i = 0; i < guarded_classes_.length(); ++i) { |
+ if (guarded_classes_[i].cls->id() == cid) return true; |
+ } |
+ return false; |
} |
@@ -86,7 +99,41 @@ bool CHA::IsImplemented(const Class& cls) { |
} |
-bool CHA::HasOverride(const Class& cls, const String& function_name) { |
+static intptr_t CountFinalizedSubclasses(Thread* thread, const Class& cls) { |
+ intptr_t count = 0; |
+ const GrowableObjectArray& cls_direct_subclasses = |
+ GrowableObjectArray::Handle(thread->zone(), cls.direct_subclasses()); |
+ if (cls_direct_subclasses.IsNull()) return count; |
+ Class& direct_subclass = Class::Handle(thread->zone()); |
+ for (intptr_t i = 0; i < cls_direct_subclasses.Length(); i++) { |
+ direct_subclass ^= cls_direct_subclasses.At(i); |
+ // Unfinalized classes are treated as non-existent for CHA purposes, |
+ // as that means that no instance of that class exists at runtime. |
+ if (!direct_subclass.is_finalized()) { |
+ continue; |
+ } |
+ |
+ count += 1 + CountFinalizedSubclasses(thread, direct_subclass); |
+ } |
+ return count; |
+} |
+ |
+ |
+bool CHA::IsConsistentWithCurrentHierarchy() const { |
+ for (intptr_t i = 0; i < guarded_classes_.length(); i++) { |
+ const intptr_t subclass_count = |
+ CountFinalizedSubclasses(thread_, *guarded_classes_[i].cls); |
+ if (guarded_classes_[i].subclass_count != subclass_count) { |
+ return false; |
+ } |
+ } |
+ return true; |
+} |
+ |
+ |
+bool CHA::HasOverride(const Class& cls, |
+ const String& function_name, |
+ intptr_t* subclasses_count) { |
// Can't track dependencies for classes on the VM heap since those are |
// read-only. |
// TODO(fschneider): Enable tracking of CHA dependent code for VM heap |
@@ -109,16 +156,31 @@ bool CHA::HasOverride(const Class& cls, const String& function_name) { |
direct_subclass ^= cls_direct_subclasses.At(i); |
// Unfinalized classes are treated as non-existent for CHA purposes, |
// as that means that no instance of that class exists at runtime. |
- if (direct_subclass.is_finalized() && |
- (direct_subclass.LookupDynamicFunction(function_name) != |
- Function::null())) { |
+ if (!direct_subclass.is_finalized()) { |
+ continue; |
+ } |
+ |
+ if (direct_subclass.LookupDynamicFunction(function_name) != |
+ Function::null()) { |
return true; |
} |
- if (HasOverride(direct_subclass, function_name)) { |
+ |
+ if (HasOverride(direct_subclass, function_name, subclasses_count)) { |
return true; |
} |
+ |
+ (*subclasses_count)++; |
} |
+ |
return false; |
} |
+ |
+void CHA::RegisterDependencies(const Code& code) const { |
+ for (intptr_t i = 0; i < guarded_classes_.length(); ++i) { |
+ guarded_classes_[i].cls->RegisterCHACode(code); |
+ } |
+} |
+ |
+ |
} // namespace dart |