| Index: runtime/vm/cha.cc
|
| ===================================================================
|
| --- runtime/vm/cha.cc (revision 39070)
|
| +++ runtime/vm/cha.cc (working copy)
|
| @@ -12,81 +12,82 @@
|
|
|
| namespace dart {
|
|
|
| -bool CHA::HasSubclasses(intptr_t cid) {
|
| - Isolate* isolate = Isolate::Current();
|
| - const bool has_subclasses = HasSubclassesSafe(cid);
|
| - if (!has_subclasses) {
|
| - isolate->set_cha_used(true);
|
| +// Return true if the class is private to our internal libraries (not extendable
|
| +// or implementable after startup). Therefore, we don't need to register
|
| +// optimized code for invalidation for those classes.
|
| +// TODO(fschneider): Allow more libraries.
|
| +static bool IsKnownPrivateClass(const Class& type_class) {
|
| + if (!Library::IsPrivate(String::Handle(type_class.Name()))) return false;
|
| + const Library& library = Library::Handle(type_class.library());
|
| + if (library.raw() == Library::CoreLibrary()) return true;
|
| + if (library.raw() == Library::CollectionLibrary()) return true;
|
| + if (library.raw() == Library::TypedDataLibrary()) return true;
|
| + if (library.raw() == Library::MathLibrary()) return true;
|
| + return false;
|
| +}
|
| +
|
| +
|
| +void CHA::AddToLeafClasses(const Class& cls) {
|
| + if (IsKnownPrivateClass(cls)) return;
|
| +
|
| + for (intptr_t i = 0; i < leaf_classes_.length(); i++) {
|
| + if (leaf_classes_[i]->raw() == cls.raw()) {
|
| + return;
|
| + }
|
| }
|
| - return has_subclasses;
|
| + leaf_classes_.Add(&Class::ZoneHandle(isolate_, cls.raw()));
|
| }
|
|
|
|
|
| -bool CHA::HasSubclassesSafe(intptr_t cid) {
|
| - ASSERT(cid >= kInstanceCid);
|
| - Isolate* isolate = Isolate::Current();
|
| - const ClassTable& class_table = *isolate->class_table();
|
| - const Class& cls = Class::Handle(isolate, class_table.At(cid));
|
| +bool CHA::HasSubclasses(const Class& cls) {
|
| ASSERT(!cls.IsNull());
|
| + ASSERT(cls.id() >= kInstanceCid);
|
| + // 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
|
| + // classes.
|
| + if (cls.InVMHeap()) return true;
|
| +
|
| if (cls.IsObjectClass()) {
|
| // Class Object has subclasses, although we do not keep track of them.
|
| return true;
|
| }
|
| - const GrowableObjectArray& cls_direct_subclasses =
|
| - GrowableObjectArray::Handle(isolate, cls.direct_subclasses());
|
| - return
|
| - !cls_direct_subclasses.IsNull() && (cls_direct_subclasses.Length() > 0);
|
| + const GrowableObjectArray& direct_subclasses =
|
| + GrowableObjectArray::Handle(isolate_, cls.direct_subclasses());
|
| + bool result =
|
| + !direct_subclasses.IsNull() && (direct_subclasses.Length() > 0);
|
| + if (!result) {
|
| + AddToLeafClasses(cls);
|
| + }
|
| + return result;
|
| }
|
|
|
|
|
| -// Returns true if the given array of cids contains the given cid.
|
| -static bool ContainsCid(ZoneGrowableArray<intptr_t>* cids, intptr_t cid) {
|
| - for (intptr_t i = 0; i < cids->length(); i++) {
|
| - if ((*cids)[i] == cid) {
|
| - return true;
|
| - }
|
| - }
|
| - return false;
|
| +bool CHA::HasSubclasses(intptr_t cid) {
|
| + const ClassTable& class_table = *isolate_->class_table();
|
| + Class& cls = Class::Handle(isolate_, class_table.At(cid));
|
| + return HasSubclasses(cls);
|
| }
|
|
|
|
|
| -// Recursively collect direct and indirect subclass ids of cls.
|
| -static void CollectSubclassIds(ZoneGrowableArray<intptr_t>* cids,
|
| - const Class& cls) {
|
| - const GrowableObjectArray& cls_direct_subclasses =
|
| - GrowableObjectArray::Handle(cls.direct_subclasses());
|
| - if (cls_direct_subclasses.IsNull()) {
|
| - return;
|
| +bool CHA::IsImplemented(const Class& cls) {
|
| + // 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
|
| + // classes.
|
| + if (cls.InVMHeap()) return true;
|
| +
|
| + bool result = cls.is_implemented();
|
| + if (!result) {
|
| + AddToLeafClasses(cls);
|
| }
|
| - Class& direct_subclass = Class::Handle();
|
| - for (intptr_t i = 0; i < cls_direct_subclasses.Length(); i++) {
|
| - direct_subclass ^= cls_direct_subclasses.At(i);
|
| - intptr_t direct_subclass_id = direct_subclass.id();
|
| - if (!ContainsCid(cids, direct_subclass_id)) {
|
| - cids->Add(direct_subclass_id);
|
| - CollectSubclassIds(cids, direct_subclass);
|
| - }
|
| - }
|
| + return result;
|
| }
|
|
|
|
|
| -ZoneGrowableArray<intptr_t>* CHA::GetSubclassIdsOf(intptr_t cid) {
|
| - ASSERT(cid > kInstanceCid);
|
| - Isolate* isolate = Isolate::Current();
|
| - const ClassTable& class_table = *isolate->class_table();
|
| - const Class& cls = Class::Handle(isolate, class_table.At(cid));
|
| - ASSERT(!cls.IsNull());
|
| - ZoneGrowableArray<intptr_t>* ids = new ZoneGrowableArray<intptr_t>();
|
| - CollectSubclassIds(ids, cls);
|
| - isolate->set_cha_used(true);
|
| - return ids;
|
| -}
|
| -
|
| -
|
| bool CHA::HasOverride(const Class& cls, const String& function_name) {
|
| - Isolate* isolate = Isolate::Current();
|
| const GrowableObjectArray& cls_direct_subclasses =
|
| - GrowableObjectArray::Handle(isolate, cls.direct_subclasses());
|
| + GrowableObjectArray::Handle(isolate_, cls.direct_subclasses());
|
| // Subclasses of Object are not tracked by CHA. Safely assume that overrides
|
| // exist.
|
| if (cls.IsObjectClass()) {
|
| @@ -94,10 +95,10 @@
|
| }
|
|
|
| if (cls_direct_subclasses.IsNull()) {
|
| - isolate->set_cha_used(true);
|
| + AddToLeafClasses(cls);
|
| return false;
|
| }
|
| - Class& direct_subclass = Class::Handle(isolate);
|
| + Class& direct_subclass = Class::Handle(isolate_);
|
| 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,
|
| @@ -111,44 +112,8 @@
|
| return true;
|
| }
|
| }
|
| - isolate->set_cha_used(true);
|
| + AddToLeafClasses(cls);
|
| return false;
|
| }
|
|
|
| -
|
| -ZoneGrowableArray<Function*>* CHA::GetNamedInstanceFunctionsOf(
|
| - const ZoneGrowableArray<intptr_t>& cids,
|
| - const String& function_name) {
|
| - Isolate* isolate = Isolate::Current();
|
| - ASSERT(!function_name.IsNull());
|
| - const ClassTable& class_table = *isolate->class_table();
|
| - ZoneGrowableArray<Function*>* functions = new ZoneGrowableArray<Function*>();
|
| - Class& cls = Class::Handle(isolate);
|
| - Function& cls_function = Function::Handle(isolate);
|
| - for (intptr_t i = 0; i < cids.length(); i++) {
|
| - const intptr_t cid = cids[i];
|
| - ASSERT(cid > kInstanceCid);
|
| - cls = class_table.At(cid);
|
| - cls_function = cls.LookupDynamicFunction(function_name);
|
| - if (!cls_function.IsNull()) {
|
| - functions->Add(&Function::ZoneHandle(isolate, cls_function.raw()));
|
| - }
|
| - }
|
| - isolate->set_cha_used(true);
|
| - return functions;
|
| -}
|
| -
|
| -
|
| -ZoneGrowableArray<Function*>* CHA::GetOverridesOf(const Function& function) {
|
| - ASSERT(!function.IsNull());
|
| - ASSERT(function.IsDynamicFunction());
|
| - Isolate* isolate = Isolate::Current();
|
| - const Class& function_owner = Class::Handle(isolate, function.Owner());
|
| - const String& function_name = String::Handle(isolate, function.name());
|
| - ZoneGrowableArray<intptr_t>* cids = new ZoneGrowableArray<intptr_t>();
|
| - CollectSubclassIds(cids, function_owner);
|
| - isolate->set_cha_used(true);
|
| - return GetNamedInstanceFunctionsOf(*cids, function_name);
|
| -}
|
| -
|
| } // namespace dart
|
|
|