| 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
|
|
|