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

Unified Diff: runtime/vm/object.cc

Issue 421913010: Avoid linear search for function lookup. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 4 months 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
===================================================================
--- runtime/vm/object.cc (revision 39092)
+++ runtime/vm/object.cc (working copy)
@@ -1890,18 +1890,62 @@
}
+class FunctionName {
+ public:
+ FunctionName(const String& name, String* tmp_string)
+ : name_(name), tmp_string_(tmp_string) {}
+ bool Matches(const Function& function) const {
+ if (name_.IsSymbol()) {
+ return name_.raw() == function.name();
+ } else {
+ *tmp_string_ = function.name();
+ return name_.Equals(*tmp_string_);
+ }
+ }
+ intptr_t Hash() const { return name_.Hash(); }
+ private:
+ const String& name_;
+ String* tmp_string_;
+};
+
+
+// Traits for looking up Functions by name.
+class ClassFunctionsTraits {
+ public:
+ // Called when growing the table.
+ static bool IsMatch(const Object& a, const Object& b) {
+ ASSERT(a.IsFunction() && b.IsFunction());
+ // Function objects are always canonical.
+ return a.raw() == b.raw();
+ }
+ static bool IsMatch(const FunctionName& name, const Object& obj) {
+ return name.Matches(Function::Cast(obj));
+ }
+ static uword Hash(const Object& key) {
+ return String::HashRawSymbol(Function::Cast(key).name());
+ }
+ static uword Hash(const FunctionName& name) {
+ return name.Hash();
+ }
+};
+typedef UnorderedHashSet<ClassFunctionsTraits> ClassFunctionsSet;
+
+
void Class::SetFunctions(const Array& value) const {
ASSERT(!value.IsNull());
-#if defined(DEBUG)
- // Verify that all the functions in the array have this class as owner.
- Function& func = Function::Handle();
- intptr_t len = value.Length();
- for (intptr_t i = 0; i < len; i++) {
- func ^= value.At(i);
- ASSERT(func.Owner() == raw());
+ StorePointer(&raw_ptr()->functions_, value.raw());
+ const intptr_t len = value.Length();
+ ClassFunctionsSet set(HashTables::New<ClassFunctionsSet>(len));
+ if (len >= kFunctionLookupHashTreshold) {
+ Function& func = Function::Handle();
+ for (intptr_t i = 0; i < len; ++i) {
+ func ^= value.At(i);
+ // Verify that all the functions in the array have this class as owner.
+ ASSERT(func.Owner() == raw());
+ set.Insert(func);
+ }
}
-#endif
- StorePointer(&raw_ptr()->functions_, value.raw());
+ StorePointer(&raw_ptr()->functions_hash_table_, set.Release().raw());
}
@@ -1909,7 +1953,17 @@
const Array& arr = Array::Handle(functions());
const Array& new_arr = Array::Handle(Array::Grow(arr, arr.Length() + 1));
new_arr.SetAt(arr.Length(), function);
- SetFunctions(new_arr);
+ StorePointer(&raw_ptr()->functions_, new_arr.raw());
+ // Add to hash table, if any.
+ const intptr_t new_len = new_arr.Length();
+ if (new_len == kFunctionLookupHashTreshold) {
+ // Transition to using hash table.
+ SetFunctions(new_arr);
+ } else if (new_len > kFunctionLookupHashTreshold) {
+ ClassFunctionsSet set(raw_ptr()->functions_hash_table_);
+ set.Insert(function);
+ StorePointer(&raw_ptr()->functions_hash_table_, set.Release().raw());
+ }
}
@@ -3830,6 +3884,15 @@
ASSERT(!funcs.IsNull());
const intptr_t len = funcs.Length();
Function& function = isolate->FunctionHandle();
+ if (len >= kFunctionLookupHashTreshold) {
+ ClassFunctionsSet set(raw_ptr()->functions_hash_table_);
+ REUSABLE_STRING_HANDLESCOPE(isolate);
+ function ^= set.GetOrNull(FunctionName(name, &(isolate->StringHandle())));
+ // No mutations.
+ ASSERT(set.Release().raw() == raw_ptr()->functions_hash_table_);
+ return function.IsNull() ? Function::null()
+ : CheckFunctionType(function, kind);
+ }
if (name.IsSymbol()) {
// Quick Symbol compare.
NoGCScope no_gc;
« 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