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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | runtime/vm/raw_object.h » ('j') | runtime/vm/raw_object.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/object.h" 5 #include "vm/object.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 #include "platform/assert.h" 8 #include "platform/assert.h"
9 #include "vm/assembler.h" 9 #include "vm/assembler.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 1872 matching lines...) Expand 10 before | Expand all | Expand 10 after
1883 for (intptr_t i = 0; i < field_array.Length(); ++i) { 1883 for (intptr_t i = 0; i < field_array.Length(); ++i) {
1884 field ^= field_array.At(i); 1884 field ^= field_array.At(i);
1885 if (!field.is_static()) { 1885 if (!field.is_static()) {
1886 return true; 1886 return true;
1887 } 1887 }
1888 } 1888 }
1889 return false; 1889 return false;
1890 } 1890 }
1891 1891
1892 1892
1893 class FunctionName {
1894 public:
1895 FunctionName(const String& name, String* tmp_string)
1896 : name_(name), tmp_string_(tmp_string) {}
1897 bool Matches(const Function& function) const {
1898 if (name_.IsSymbol()) {
1899 return name_.raw() == function.name();
1900 } else {
1901 *tmp_string_ = function.name();
1902 return name_.Equals(*tmp_string_);
1903 }
1904 }
1905 intptr_t Hash() const { return name_.Hash(); }
1906 private:
1907 const String& name_;
1908 String* tmp_string_;
1909 };
1910
1911
1912 // Traits for looking up Functions by name.
1913 class ClassFunctionsTraits {
1914 public:
1915 // Called when growing the table.
1916 static bool IsMatch(const Object& a, const Object& b) {
1917 ASSERT(a.IsFunction() && b.IsFunction());
1918 // Function objects are always canonical.
1919 return a.raw() == b.raw();
1920 }
1921 static bool IsMatch(const FunctionName& name, const Object& obj) {
1922 return name.Matches(Function::Cast(obj));
1923 }
1924 static uword Hash(const Object& key) {
1925 return String::HashRawSymbol(Function::Cast(key).name());
1926 }
1927 static uword Hash(const FunctionName& name) {
1928 return name.Hash();
1929 }
1930 };
1931 typedef UnorderedHashSet<ClassFunctionsTraits> ClassFunctionsSet;
1932
1933
1893 void Class::SetFunctions(const Array& value) const { 1934 void Class::SetFunctions(const Array& value) const {
1894 ASSERT(!value.IsNull()); 1935 ASSERT(!value.IsNull());
1895 #if defined(DEBUG) 1936 StorePointer(&raw_ptr()->functions_, value.raw());
1896 // Verify that all the functions in the array have this class as owner. 1937 const intptr_t len = value.Length();
1938 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.
1897 Function& func = Function::Handle(); 1939 Function& func = Function::Handle();
1898 intptr_t len = value.Length(); 1940 for (intptr_t i = 0; i < len; ++i) {
1899 for (intptr_t i = 0; i < len; i++) {
1900 func ^= value.At(i); 1941 func ^= value.At(i);
1942 // Verify that all the functions in the array have this class as owner.
1901 ASSERT(func.Owner() == raw()); 1943 ASSERT(func.Owner() == raw());
1944 set.Insert(func);
1902 } 1945 }
1903 #endif 1946 StorePointer(&raw_ptr()->functions_hash_table_, set.Release().raw());
1904 StorePointer(&raw_ptr()->functions_, value.raw());
1905 } 1947 }
1906 1948
1907 1949
1908 void Class::AddFunction(const Function& function) const { 1950 void Class::AddFunction(const Function& function) const {
1909 const Array& arr = Array::Handle(functions()); 1951 const Array& arr = Array::Handle(functions());
1910 const Array& new_arr = Array::Handle(Array::Grow(arr, arr.Length() + 1)); 1952 const Array& new_arr = Array::Handle(Array::Grow(arr, arr.Length() + 1));
1911 new_arr.SetAt(arr.Length(), function); 1953 new_arr.SetAt(arr.Length(), function);
1912 SetFunctions(new_arr); 1954 SetFunctions(new_arr);
1913 } 1955 }
1914 1956
(...skipping 1908 matching lines...) Expand 10 before | Expand all | Expand 10 after
3823 if (EnsureIsFinalized(isolate) != Error::null()) { 3865 if (EnsureIsFinalized(isolate) != Error::null()) {
3824 return Function::null(); 3866 return Function::null();
3825 } 3867 }
3826 REUSABLE_ARRAY_HANDLESCOPE(isolate); 3868 REUSABLE_ARRAY_HANDLESCOPE(isolate);
3827 REUSABLE_FUNCTION_HANDLESCOPE(isolate); 3869 REUSABLE_FUNCTION_HANDLESCOPE(isolate);
3828 Array& funcs = isolate->ArrayHandle(); 3870 Array& funcs = isolate->ArrayHandle();
3829 funcs ^= functions(); 3871 funcs ^= functions();
3830 ASSERT(!funcs.IsNull()); 3872 ASSERT(!funcs.IsNull());
3831 const intptr_t len = funcs.Length(); 3873 const intptr_t len = funcs.Length();
3832 Function& function = isolate->FunctionHandle(); 3874 Function& function = isolate->FunctionHandle();
3875 static const intptr_t kFunctionLookupHashTreshold = 16;
3876 if (len >= kFunctionLookupHashTreshold) {
3877 ClassFunctionsSet set(raw_ptr()->functions_hash_table_);
3878 REUSABLE_STRING_HANDLESCOPE(isolate);
3879 function ^= set.GetOrNull(FunctionName(name, &(isolate->StringHandle())));
3880 // No mutations.
3881 ASSERT(set.Release().raw() == raw_ptr()->functions_hash_table_);
3882 return function.IsNull() ? Function::null()
3883 : CheckFunctionType(function, kind);
3884 }
3833 if (name.IsSymbol()) { 3885 if (name.IsSymbol()) {
3834 // Quick Symbol compare. 3886 // Quick Symbol compare.
3835 NoGCScope no_gc; 3887 NoGCScope no_gc;
3836 for (intptr_t i = 0; i < len; i++) { 3888 for (intptr_t i = 0; i < len; i++) {
3837 function ^= funcs.At(i); 3889 function ^= funcs.At(i);
3838 if (function.name() == name.raw()) { 3890 if (function.name() == name.raw()) {
3839 return CheckFunctionType(function, kind); 3891 return CheckFunctionType(function, kind);
3840 } 3892 }
3841 } 3893 }
3842 } else { 3894 } else {
(...skipping 15559 matching lines...) Expand 10 before | Expand all | Expand 10 after
19402 return tag_label.ToCString(); 19454 return tag_label.ToCString();
19403 } 19455 }
19404 19456
19405 19457
19406 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { 19458 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const {
19407 Instance::PrintJSONImpl(stream, ref); 19459 Instance::PrintJSONImpl(stream, ref);
19408 } 19460 }
19409 19461
19410 19462
19411 } // namespace dart 19463 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/raw_object.h » ('j') | runtime/vm/raw_object.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698