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

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 | « runtime/vm/object.h ('k') | runtime/vm/raw_object.h » ('j') | no next file with comments »
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();
1897 Function& func = Function::Handle(); 1938 ClassFunctionsSet set(HashTables::New<ClassFunctionsSet>(len));
1898 intptr_t len = value.Length(); 1939 if (len >= kFunctionLookupHashTreshold) {
1899 for (intptr_t i = 0; i < len; i++) { 1940 Function& func = Function::Handle();
1900 func ^= value.At(i); 1941 for (intptr_t i = 0; i < len; ++i) {
1901 ASSERT(func.Owner() == raw()); 1942 func ^= value.At(i);
1943 // Verify that all the functions in the array have this class as owner.
1944 ASSERT(func.Owner() == raw());
1945 set.Insert(func);
1946 }
1902 } 1947 }
1903 #endif 1948 StorePointer(&raw_ptr()->functions_hash_table_, set.Release().raw());
1904 StorePointer(&raw_ptr()->functions_, value.raw());
1905 } 1949 }
1906 1950
1907 1951
1908 void Class::AddFunction(const Function& function) const { 1952 void Class::AddFunction(const Function& function) const {
1909 const Array& arr = Array::Handle(functions()); 1953 const Array& arr = Array::Handle(functions());
1910 const Array& new_arr = Array::Handle(Array::Grow(arr, arr.Length() + 1)); 1954 const Array& new_arr = Array::Handle(Array::Grow(arr, arr.Length() + 1));
1911 new_arr.SetAt(arr.Length(), function); 1955 new_arr.SetAt(arr.Length(), function);
1912 SetFunctions(new_arr); 1956 StorePointer(&raw_ptr()->functions_, new_arr.raw());
1957 // Add to hash table, if any.
1958 const intptr_t new_len = new_arr.Length();
1959 if (new_len == kFunctionLookupHashTreshold) {
1960 // Transition to using hash table.
1961 SetFunctions(new_arr);
1962 } else if (new_len > kFunctionLookupHashTreshold) {
1963 ClassFunctionsSet set(raw_ptr()->functions_hash_table_);
1964 set.Insert(function);
1965 StorePointer(&raw_ptr()->functions_hash_table_, set.Release().raw());
1966 }
1913 } 1967 }
1914 1968
1915 1969
1916 intptr_t Class::FindFunctionIndex(const Function& needle) const { 1970 intptr_t Class::FindFunctionIndex(const Function& needle) const {
1917 Isolate* isolate = Isolate::Current(); 1971 Isolate* isolate = Isolate::Current();
1918 if (EnsureIsFinalized(isolate) != Error::null()) { 1972 if (EnsureIsFinalized(isolate) != Error::null()) {
1919 return -1; 1973 return -1;
1920 } 1974 }
1921 REUSABLE_ARRAY_HANDLESCOPE(isolate); 1975 REUSABLE_ARRAY_HANDLESCOPE(isolate);
1922 REUSABLE_FUNCTION_HANDLESCOPE(isolate); 1976 REUSABLE_FUNCTION_HANDLESCOPE(isolate);
(...skipping 1900 matching lines...) Expand 10 before | Expand all | Expand 10 after
3823 if (EnsureIsFinalized(isolate) != Error::null()) { 3877 if (EnsureIsFinalized(isolate) != Error::null()) {
3824 return Function::null(); 3878 return Function::null();
3825 } 3879 }
3826 REUSABLE_ARRAY_HANDLESCOPE(isolate); 3880 REUSABLE_ARRAY_HANDLESCOPE(isolate);
3827 REUSABLE_FUNCTION_HANDLESCOPE(isolate); 3881 REUSABLE_FUNCTION_HANDLESCOPE(isolate);
3828 Array& funcs = isolate->ArrayHandle(); 3882 Array& funcs = isolate->ArrayHandle();
3829 funcs ^= functions(); 3883 funcs ^= functions();
3830 ASSERT(!funcs.IsNull()); 3884 ASSERT(!funcs.IsNull());
3831 const intptr_t len = funcs.Length(); 3885 const intptr_t len = funcs.Length();
3832 Function& function = isolate->FunctionHandle(); 3886 Function& function = isolate->FunctionHandle();
3887 if (len >= kFunctionLookupHashTreshold) {
3888 ClassFunctionsSet set(raw_ptr()->functions_hash_table_);
3889 REUSABLE_STRING_HANDLESCOPE(isolate);
3890 function ^= set.GetOrNull(FunctionName(name, &(isolate->StringHandle())));
3891 // No mutations.
3892 ASSERT(set.Release().raw() == raw_ptr()->functions_hash_table_);
3893 return function.IsNull() ? Function::null()
3894 : CheckFunctionType(function, kind);
3895 }
3833 if (name.IsSymbol()) { 3896 if (name.IsSymbol()) {
3834 // Quick Symbol compare. 3897 // Quick Symbol compare.
3835 NoGCScope no_gc; 3898 NoGCScope no_gc;
3836 for (intptr_t i = 0; i < len; i++) { 3899 for (intptr_t i = 0; i < len; i++) {
3837 function ^= funcs.At(i); 3900 function ^= funcs.At(i);
3838 if (function.name() == name.raw()) { 3901 if (function.name() == name.raw()) {
3839 return CheckFunctionType(function, kind); 3902 return CheckFunctionType(function, kind);
3840 } 3903 }
3841 } 3904 }
3842 } else { 3905 } else {
(...skipping 15559 matching lines...) Expand 10 before | Expand all | Expand 10 after
19402 return tag_label.ToCString(); 19465 return tag_label.ToCString();
19403 } 19466 }
19404 19467
19405 19468
19406 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { 19469 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const {
19407 Instance::PrintJSONImpl(stream, ref); 19470 Instance::PrintJSONImpl(stream, ref);
19408 } 19471 }
19409 19472
19410 19473
19411 } // namespace dart 19474 } // namespace dart
OLDNEW
« 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