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 |