Revert r39246 which reverted r39101
R=koda@google.com Review URL: https://codereview.chromium.org//474073002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@39272 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
+73
-10
@@ -1890,18 +1890,62 @@ bool Class::HasInstanceFields() const {
|
||||
}
|
||||
|
||||
|
||||
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());
|
||||
}
|
||||
#endif
|
||||
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);
|
||||
}
|
||||
}
|
||||
StorePointer(&raw_ptr()->functions_hash_table_, set.Release().raw());
|
||||
}
|
||||
|
||||
|
||||
@@ -1909,7 +1953,17 @@ void Class::AddFunction(const Function& function) const {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3831,6 +3885,15 @@ RawFunction* Class::LookupFunction(const String& name, MemberKind kind) const {
|
||||
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;
|
||||
|
||||
@@ -949,6 +949,7 @@ class Class : public Object {
|
||||
// Returns true if non-static fields are defined.
|
||||
bool HasInstanceFields() const;
|
||||
|
||||
// TODO(koda): Unite w/ hash table.
|
||||
RawArray* functions() const { return raw_ptr()->functions_; }
|
||||
void SetFunctions(const Array& value) const;
|
||||
void AddFunction(const Function& function) const;
|
||||
@@ -1211,6 +1212,9 @@ class Class : public Object {
|
||||
|
||||
void CalculateFieldOffsets() const;
|
||||
|
||||
// functions_hash_table is in use iff there are at least this many functions.
|
||||
static const intptr_t kFunctionLookupHashTreshold = 16;
|
||||
|
||||
// Initial value for the cached number of type arguments.
|
||||
static const intptr_t kUnknownNumTypeArguments = -1;
|
||||
|
||||
|
||||
@@ -499,6 +499,7 @@ class RawClass : public RawObject {
|
||||
RawString* name_;
|
||||
RawString* user_name_;
|
||||
RawArray* functions_;
|
||||
RawArray* functions_hash_table_;
|
||||
RawArray* fields_;
|
||||
RawArray* offset_in_words_to_field_;
|
||||
RawGrowableObjectArray* closure_functions_; // Local functions and literals.
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user