Chromium Code Reviews| Index: runtime/vm/object.cc |
| =================================================================== |
| --- runtime/vm/object.cc (revision 38949) |
| +++ runtime/vm/object.cc (working copy) |
| @@ -1890,18 +1890,60 @@ |
| } |
| +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. |
| + StorePointer(&raw_ptr()->functions_, value.raw()); |
| + const intptr_t len = value.Length(); |
| + ClassFunctionsSet set(HashTables::New<ClassFunctionsSet>(len)); |
|
Ivan Posva
2014/08/06 23:37:39
As discussed it seems a bit wasteful to be recreat
koda
2014/08/11 19:26:51
Done.
|
| Function& func = Function::Handle(); |
| - intptr_t len = value.Length(); |
| - for (intptr_t i = 0; i < len; i++) { |
| + 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()); |
| } |
| @@ -3830,6 +3872,16 @@ |
| ASSERT(!funcs.IsNull()); |
| const intptr_t len = funcs.Length(); |
| Function& function = isolate->FunctionHandle(); |
| + static const intptr_t kFunctionLookupHashTreshold = 16; |
| + 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; |