Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1071)

Unified Diff: runtime/vm/object.cc

Issue 11299298: Cache lookups at megamorphic call sites in optimized code. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: One change I forgot. Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/raw_object.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/object.cc
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 15b3d58683c3eb1e671bb1d96f01a2b4f9aa8274..bf4b5fc87b85e962d8219c0e0903532a6c90b240 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -97,6 +97,8 @@ RawClass* Object::deopt_info_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::context_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::context_scope_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::icdata_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
+RawClass* Object::megamorphic_cache_class_ =
+ reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::subtypetestcache_class_ =
reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::api_error_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
@@ -382,6 +384,9 @@ void Object::InitOnce() {
cls = Class::New<ICData>();
icdata_class_ = cls.raw();
+ cls = Class::New<MegamorphicCache>();
+ megamorphic_cache_class_ = cls.raw();
+
cls = Class::New<SubtypeTestCache>();
subtypetestcache_class_ = cls.raw();
@@ -457,6 +462,7 @@ void Object::RegisterSingletonClassNames() {
SET_CLASS_NAME(context, Context);
SET_CLASS_NAME(context_scope, ContextScope);
SET_CLASS_NAME(icdata, ICData);
+ SET_CLASS_NAME(megamorphic_cache, MegamorphicCache);
SET_CLASS_NAME(subtypetestcache, SubtypeTestCache);
SET_CLASS_NAME(api_error, ApiError);
SET_CLASS_NAME(language_error, LanguageError);
@@ -7758,6 +7764,120 @@ RawICData* ICData::New(const Function& function,
}
+RawArray* MegamorphicCache::buckets() const {
+ return raw_ptr()->buckets_;
+}
+
+
+void MegamorphicCache::set_buckets(const Array& buckets) const {
+ StorePointer(&raw_ptr()->buckets_, buckets.raw());
+}
+
+
+// Class IDs in the table are smi-tagged, so we use a smi-tagged mask
+// and target class ID to avoid untagging (on each iteration of the
+// test loop) in generated code.
+intptr_t MegamorphicCache::mask() const {
+ return Smi::Value(raw_ptr()->mask_);
+}
+
+
+void MegamorphicCache::set_mask(intptr_t mask) const {
+ raw_ptr()->mask_ = Smi::New(mask);
+}
+
+
+intptr_t MegamorphicCache::filled_entry_count() const {
+ return raw_ptr()->filled_entry_count_;
+}
+
+
+void MegamorphicCache::set_filled_entry_count(intptr_t count) const {
+ raw_ptr()->filled_entry_count_ = count;
+}
+
+
+RawMegamorphicCache* MegamorphicCache::New() {
+ MegamorphicCache& result = MegamorphicCache::Handle();
+ { RawObject* raw = Object::Allocate(MegamorphicCache::kClassId,
+ MegamorphicCache::InstanceSize(),
+ Heap::kOld);
+ NoGCScope no_gc;
+ result ^= raw;
+ }
+ const intptr_t capacity = kInitialCapacity;
+ const Array& buckets = Array::Handle(Array::New(kEntryLength * capacity));
+ const Smi& illegal = Smi::Handle(Smi::New(kIllegalCid));
+ const Function& handler = Function::Handle(
+ Isolate::Current()->megamorphic_cache_table()->miss_handler());
+ for (intptr_t i = 0; i < capacity; ++i) {
+ SetEntry(buckets, i, illegal, handler);
+ }
+ result.set_buckets(buckets);
+ result.set_mask(capacity - 1);
+ result.set_filled_entry_count(0);
+ return result.raw();
+}
+
+
+void MegamorphicCache::EnsureCapacity() const {
+ intptr_t old_capacity = mask() + 1;
+ double load_limit = kLoadFactor * static_cast<double>(old_capacity);
+ if (static_cast<double>(filled_entry_count() + 1) > load_limit) {
+ const Array& old_buckets = Array::Handle(buckets());
+ intptr_t new_capacity = old_capacity * 2;
+ const Array& new_buckets =
+ Array::Handle(Array::New(kEntryLength * new_capacity));
+
+ Smi& class_id = Smi::Handle(Smi::New(kIllegalCid));
+ Function& target = Function::Handle(
+ Isolate::Current()->megamorphic_cache_table()->miss_handler());
+ for (intptr_t i = 0; i < new_capacity; ++i) {
+ SetEntry(new_buckets, i, class_id, target);
+ }
+ set_buckets(new_buckets);
+ set_mask(new_capacity - 1);
+ set_filled_entry_count(0);
+
+ // Rehash the valid entries.
+ for (intptr_t i = 0; i < old_capacity; ++i) {
+ class_id ^= GetClassId(old_buckets, i);
+ if (class_id.Value() != kIllegalCid) {
+ target ^= GetTargetFunction(old_buckets, i);
+ Insert(class_id, target);
+ }
+ }
+ }
+}
+
+
+void MegamorphicCache::Insert(const Smi& class_id,
+ const Function& target) const {
+ ASSERT(static_cast<double>(filled_entry_count() + 1) <=
+ (kLoadFactor * static_cast<double>(mask() + 1)));
+ const Array& backing_array = Array::Handle(buckets());
+ intptr_t id_mask = mask();
+ intptr_t index = class_id.Value() & id_mask;
+ Smi& probe = Smi::Handle();
+ intptr_t i = index;
+ do {
+ probe ^= GetClassId(backing_array, i);
+ if (probe.Value() == kIllegalCid) {
+ SetEntry(backing_array, i, class_id, target);
+ set_filled_entry_count(filled_entry_count() + 1);
+ return;
+ }
+ i = (i + 1) & id_mask;
+ } while (i != index);
+ UNREACHABLE();
+}
+
+
+const char* MegamorphicCache::ToCString() const {
+ return "";
+}
+
+
RawSubtypeTestCache* SubtypeTestCache::New() {
ASSERT(Object::subtypetestcache_class() != Class::null());
SubtypeTestCache& result = SubtypeTestCache::Handle();
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/raw_object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698