Chromium Code Reviews| Index: src/objects.cc |
| =================================================================== |
| --- src/objects.cc (revision 2321) |
| +++ src/objects.cc (working copy) |
| @@ -41,6 +41,7 @@ |
| #include "disassembler.h" |
| #endif |
| + |
| namespace v8 { |
| namespace internal { |
| @@ -428,17 +429,17 @@ |
| Object* value, |
| PropertyDetails details) { |
| ASSERT(!HasFastProperties()); |
| - int entry = property_dictionary()->FindStringEntry(name); |
| - if (entry == Dictionary::kNotFound) { |
| + int entry = property_dictionary()->FindEntry(name); |
| + if (entry == StringDictionary::kNotFound) { |
| Object* store_value = value; |
| if (IsGlobalObject()) { |
| store_value = Heap::AllocateJSGlobalPropertyCell(value); |
| if (store_value->IsFailure()) return store_value; |
| } |
| Object* dict = |
| - property_dictionary()->AddStringEntry(name, store_value, details); |
| + property_dictionary()->Add(name, store_value, details); |
| if (dict->IsFailure()) return dict; |
| - set_properties(Dictionary::cast(dict)); |
| + set_properties(StringDictionary::cast(dict)); |
| return value; |
| } |
| // Preserve enumeration index. |
| @@ -452,7 +453,7 @@ |
| // Please note we have to update the property details. |
| property_dictionary()->DetailsAtPut(entry, details); |
| } else { |
| - property_dictionary()->SetStringEntry(entry, name, value, details); |
| + property_dictionary()->SetEntry(entry, name, value, details); |
| } |
| return value; |
| } |
| @@ -460,9 +461,9 @@ |
| Object* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) { |
| ASSERT(!HasFastProperties()); |
| - Dictionary* dictionary = property_dictionary(); |
| - int entry = dictionary->FindStringEntry(name); |
| - if (entry != Dictionary::kNotFound) { |
| + StringDictionary* dictionary = property_dictionary(); |
| + int entry = dictionary->FindEntry(name); |
| + if (entry != StringDictionary::kNotFound) { |
| // If we have a global object set the cell to the hole. |
| if (IsGlobalObject()) { |
| PropertyDetails details = dictionary->DetailsAt(entry); |
| @@ -1340,16 +1341,16 @@ |
| Object* value, |
| PropertyAttributes attributes) { |
| ASSERT(!HasFastProperties()); |
| - Dictionary* dict = property_dictionary(); |
| + StringDictionary* dict = property_dictionary(); |
| Object* store_value = value; |
| if (IsGlobalObject()) { |
| // In case name is an orphaned property reuse the cell. |
| - int entry = dict->FindStringEntry(name); |
| - if (entry != Dictionary::kNotFound) { |
| + int entry = dict->FindEntry(name); |
| + if (entry != StringDictionary::kNotFound) { |
| store_value = dict->ValueAt(entry); |
| JSGlobalPropertyCell::cast(store_value)->set_value(value); |
| PropertyDetails details = PropertyDetails(attributes, NORMAL); |
| - dict->SetStringEntry(entry, name, store_value, details); |
| + dict->SetEntry(entry, name, store_value, details); |
| return value; |
| } |
| store_value = Heap::AllocateJSGlobalPropertyCell(value); |
| @@ -1357,9 +1358,9 @@ |
| JSGlobalPropertyCell::cast(store_value)->set_value(value); |
| } |
| PropertyDetails details = PropertyDetails(attributes, NORMAL); |
| - Object* result = dict->AddStringEntry(name, store_value, details); |
| + Object* result = dict->Add(name, store_value, details); |
| if (result->IsFailure()) return result; |
| - if (dict != result) set_properties(Dictionary::cast(result)); |
| + if (dict != result) set_properties(StringDictionary::cast(result)); |
| return value; |
| } |
| @@ -1405,8 +1406,8 @@ |
| Object* JSObject::ReplaceSlowProperty(String* name, |
| Object* value, |
| PropertyAttributes attributes) { |
| - Dictionary* dictionary = property_dictionary(); |
| - int old_index = dictionary->FindStringEntry(name); |
| + StringDictionary* dictionary = property_dictionary(); |
| + int old_index = dictionary->FindEntry(name); |
| int new_enumeration_index = 0; // 0 means "Use the next available index." |
| if (old_index != -1) { |
| // All calls to ReplaceSlowProperty have had all transitions removed. |
| @@ -1646,9 +1647,9 @@ |
| pt != Heap::null_value(); |
| pt = pt->GetPrototype()) { |
| if (JSObject::cast(pt)->HasFastElements()) continue; |
| - Dictionary* dictionary = JSObject::cast(pt)->element_dictionary(); |
| - int entry = dictionary->FindNumberEntry(index); |
| - if (entry != Dictionary::kNotFound) { |
| + NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary(); |
| + int entry = dictionary->FindEntry(index); |
| + if (entry != StringDictionary::kNotFound) { |
| Object* element = dictionary->ValueAt(entry); |
| PropertyDetails details = dictionary->DetailsAt(entry); |
| if (details.type() == CALLBACKS) { |
| @@ -1698,8 +1699,8 @@ |
| return; |
| } |
| } else { |
| - int entry = property_dictionary()->FindStringEntry(name); |
| - if (entry != Dictionary::kNotFound) { |
| + int entry = property_dictionary()->FindEntry(name); |
| + if (entry != StringDictionary::kNotFound) { |
| // Make sure to disallow caching for uninitialized constants |
| // found in the dictionary-mode objects. |
| Object* value = property_dictionary()->ValueAt(entry); |
| @@ -2101,9 +2102,9 @@ |
| // Allocate new content |
| Object* obj = |
| - Dictionary::Allocate(map()->NumberOfDescribedProperties() * 2 + 4); |
| + StringDictionary::Allocate(map()->NumberOfDescribedProperties() * 2 + 4); |
| if (obj->IsFailure()) return obj; |
| - Dictionary* dictionary = Dictionary::cast(obj); |
| + StringDictionary* dictionary = StringDictionary::cast(obj); |
| for (DescriptorReader r(map()->instance_descriptors()); |
| !r.eos(); |
| @@ -2118,9 +2119,9 @@ |
| value = Heap::AllocateJSGlobalPropertyCell(value); |
| if (value->IsFailure()) return value; |
| } |
| - Object* result = dictionary->AddStringEntry(r.GetKey(), value, d); |
| + Object* result = dictionary->Add(r.GetKey(), value, d); |
| if (result->IsFailure()) return result; |
| - dictionary = Dictionary::cast(result); |
| + dictionary = StringDictionary::cast(result); |
| break; |
| } |
| case FIELD: { |
| @@ -2131,9 +2132,9 @@ |
| value = Heap::AllocateJSGlobalPropertyCell(value); |
| if (value->IsFailure()) return value; |
| } |
| - Object* result = dictionary->AddStringEntry(r.GetKey(), value, d); |
| + Object* result = dictionary->Add(r.GetKey(), value, d); |
| if (result->IsFailure()) return result; |
| - dictionary = Dictionary::cast(result); |
| + dictionary = StringDictionary::cast(result); |
| break; |
| } |
| case CALLBACKS: { |
| @@ -2144,9 +2145,9 @@ |
| value = Heap::AllocateJSGlobalPropertyCell(value); |
| if (value->IsFailure()) return value; |
| } |
| - Object* result = dictionary->AddStringEntry(r.GetKey(), value, d); |
| + Object* result = dictionary->Add(r.GetKey(), value, d); |
| if (result->IsFailure()) return result; |
| - dictionary = Dictionary::cast(result); |
| + dictionary = StringDictionary::cast(result); |
| break; |
| } |
| case MAP_TRANSITION: |
| @@ -2219,9 +2220,9 @@ |
| int length = IsJSArray() ? |
| Smi::cast(JSArray::cast(this)->length())->value() : |
| array->length(); |
| - Object* obj = Dictionary::Allocate(length); |
| + Object* obj = NumberDictionary::Allocate(length); |
| if (obj->IsFailure()) return obj; |
| - Dictionary* dictionary = Dictionary::cast(obj); |
| + NumberDictionary* dictionary = NumberDictionary::cast(obj); |
| // Copy entries. |
| for (int i = 0; i < length; i++) { |
| Object* value = array->get(i); |
| @@ -2229,7 +2230,7 @@ |
| PropertyDetails details = PropertyDetails(NONE, NORMAL); |
| Object* result = dictionary->AddNumberEntry(i, array->get(i), details); |
| if (result->IsFailure()) return result; |
| - dictionary = Dictionary::cast(result); |
| + dictionary = NumberDictionary::cast(result); |
| } |
| } |
| // Switch to using the dictionary as the backing storage for elements. |
| @@ -2306,9 +2307,9 @@ |
| return Heap::true_value(); |
| } |
| ASSERT(!HasFastElements()); |
| - Dictionary* dictionary = element_dictionary(); |
| - int entry = dictionary->FindNumberEntry(index); |
| - if (entry != Dictionary::kNotFound) { |
| + NumberDictionary* dictionary = element_dictionary(); |
| + int entry = dictionary->FindEntry(index); |
| + if (entry != StringDictionary::kNotFound) { |
|
Mads Ager (chromium)
2009/07/01 15:32:49
NumberDictionary::kNotFound
|
| return dictionary->DeleteProperty(entry, mode); |
| } |
| return Heap::true_value(); |
| @@ -2380,9 +2381,9 @@ |
| } |
| return Heap::true_value(); |
| } else { |
| - Dictionary* dictionary = element_dictionary(); |
| - int entry = dictionary->FindNumberEntry(index); |
| - if (entry != Dictionary::kNotFound) { |
| + NumberDictionary* dictionary = element_dictionary(); |
| + int entry = dictionary->FindEntry(index); |
| + if (entry != NumberDictionary::kNotFound) { |
| return dictionary->DeleteProperty(entry, mode); |
| } |
| } |
| @@ -2687,9 +2688,9 @@ |
| if (is_element) { |
| // Lookup the index. |
| if (!HasFastElements()) { |
| - Dictionary* dictionary = element_dictionary(); |
| - int entry = dictionary->FindNumberEntry(index); |
| - if (entry != Dictionary::kNotFound) { |
| + NumberDictionary* dictionary = element_dictionary(); |
| + int entry = dictionary->FindEntry(index); |
| + if (entry != NumberDictionary::kNotFound) { |
| Object* result = dictionary->ValueAt(entry); |
| PropertyDetails details = dictionary->DetailsAt(entry); |
| if (details.IsReadOnly()) return Heap::undefined_value(); |
| @@ -2725,14 +2726,14 @@ |
| // Update the dictionary with the new CALLBACKS property. |
| Object* dict = |
| - element_dictionary()->SetOrAddNumberEntry(index, structure, details); |
| + element_dictionary()->Set(index, structure, details); |
| if (dict->IsFailure()) return dict; |
| // If name is an index we need to stay in slow case. |
| - Dictionary* elements = Dictionary::cast(dict); |
| + NumberDictionary* elements = NumberDictionary::cast(dict); |
| elements->set_requires_slow_elements(); |
| // Set the potential new dictionary on the object. |
| - set_elements(Dictionary::cast(dict)); |
| + set_elements(NumberDictionary::cast(dict)); |
| } else { |
| // Normalize object to make this operation simple. |
| Object* ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES); |
| @@ -2799,9 +2800,9 @@ |
| obj = JSObject::cast(obj)->GetPrototype()) { |
| JSObject* jsObject = JSObject::cast(obj); |
| if (!jsObject->HasFastElements()) { |
| - Dictionary* dictionary = jsObject->element_dictionary(); |
| - int entry = dictionary->FindNumberEntry(index); |
| - if (entry != Dictionary::kNotFound) { |
| + NumberDictionary* dictionary = jsObject->element_dictionary(); |
| + int entry = dictionary->FindEntry(index); |
| + if (entry != NumberDictionary::kNotFound) { |
| Object* element = dictionary->ValueAt(entry); |
| PropertyDetails details = dictionary->DetailsAt(entry); |
| if (details.type() == CALLBACKS) { |
| @@ -3004,7 +3005,7 @@ |
| return UnionOfKeys(array->elements()); |
| } |
| ASSERT(!array->HasFastElements()); |
| - Dictionary* dict = array->element_dictionary(); |
| + NumberDictionary* dict = array->element_dictionary(); |
| int size = dict->NumberOfElements(); |
| // Allocate a temporary fixed array. |
| @@ -5075,7 +5076,7 @@ |
| elems->set(i, old_elements->get(i), mode); |
| } |
| } else { |
| - Dictionary* dictionary = Dictionary::cast(elements()); |
| + NumberDictionary* dictionary = NumberDictionary::cast(elements()); |
| for (int i = 0; i < dictionary->Capacity(); i++) { |
| Object* key = dictionary->KeyAt(i); |
| if (key->IsNumber()) { |
| @@ -5240,7 +5241,8 @@ |
| return true; |
| } |
| } else { |
| - if (element_dictionary()->FindNumberEntry(index) != Dictionary::kNotFound) { |
| + if (element_dictionary()->FindEntry(index) |
| + != NumberDictionary::kNotFound) { |
| return true; |
| } |
| } |
| @@ -5317,8 +5319,8 @@ |
| return (index < length) && |
| !FixedArray::cast(elements())->get(index)->IsTheHole(); |
| } else { |
| - return element_dictionary()->FindNumberEntry(index) |
| - != Dictionary::kNotFound; |
| + return element_dictionary()->FindEntry(index) |
| + != NumberDictionary::kNotFound; |
| } |
| } |
| @@ -5344,7 +5346,8 @@ |
| if ((index < length) && |
| !FixedArray::cast(elements())->get(index)->IsTheHole()) return true; |
| } else { |
| - if (element_dictionary()->FindNumberEntry(index) != Dictionary::kNotFound) { |
| + if (element_dictionary()->FindEntry(index) |
| + != NumberDictionary::kNotFound) { |
| return true; |
| } |
| } |
| @@ -5479,10 +5482,10 @@ |
| // Insert element in the dictionary. |
| FixedArray* elms = FixedArray::cast(elements()); |
| - Dictionary* dictionary = Dictionary::cast(elms); |
| + NumberDictionary* dictionary = NumberDictionary::cast(elms); |
| - int entry = dictionary->FindNumberEntry(index); |
| - if (entry != Dictionary::kNotFound) { |
| + int entry = dictionary->FindEntry(index); |
| + if (entry != NumberDictionary::kNotFound) { |
| Object* element = dictionary->ValueAt(entry); |
| PropertyDetails details = dictionary->DetailsAt(entry); |
| if (details.type() == CALLBACKS) { |
| @@ -5531,7 +5534,7 @@ |
| CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), &new_length)); |
| JSArray::cast(this)->set_length(Smi::FromInt(new_length)); |
| } else { |
| - new_length = Dictionary::cast(elements())->max_number_key() + 1; |
| + new_length = NumberDictionary::cast(elements())->max_number_key() + 1; |
| } |
| Object* obj = Heap::AllocateFixedArrayWithHoles(new_length); |
| if (obj->IsFailure()) return obj; |
| @@ -5574,9 +5577,9 @@ |
| if (!value->IsTheHole()) return value; |
| } |
| } else { |
| - Dictionary* dictionary = element_dictionary(); |
| - int entry = dictionary->FindNumberEntry(index); |
| - if (entry != Dictionary::kNotFound) { |
| + NumberDictionary* dictionary = element_dictionary(); |
| + int entry = dictionary->FindEntry(index); |
| + if (entry != NumberDictionary::kNotFound) { |
| Object* element = dictionary->ValueAt(entry); |
| PropertyDetails details = dictionary->DetailsAt(entry); |
| if (details.type() == CALLBACKS) { |
| @@ -5658,9 +5661,9 @@ |
| if (!value->IsTheHole()) return value; |
| } |
| } else { |
| - Dictionary* dictionary = element_dictionary(); |
| - int entry = dictionary->FindNumberEntry(index); |
| - if (entry != Dictionary::kNotFound) { |
| + NumberDictionary* dictionary = element_dictionary(); |
| + int entry = dictionary->FindEntry(index); |
| + if (entry != NumberDictionary::kNotFound) { |
| Object* element = dictionary->ValueAt(entry); |
| PropertyDetails details = dictionary->DetailsAt(entry); |
| if (details.type() == CALLBACKS) { |
| @@ -5696,7 +5699,7 @@ |
| if (!elms->get(i)->IsTheHole()) number_of_elements++; |
| } |
| } else { |
| - Dictionary* dictionary = Dictionary::cast(elements()); |
| + NumberDictionary* dictionary = NumberDictionary::cast(elements()); |
| capacity = dictionary->Capacity(); |
| number_of_elements = dictionary->NumberOfElements(); |
| } |
| @@ -5718,7 +5721,7 @@ |
| bool JSObject::ShouldConvertToFastElements() { |
| ASSERT(!HasFastElements()); |
| - Dictionary* dictionary = Dictionary::cast(elements()); |
| + NumberDictionary* dictionary = NumberDictionary::cast(elements()); |
| // If the elements are sparse, we should not go back to fast case. |
| if (!HasDenseElements()) return false; |
| // If an element has been added at a very high index in the elements |
| @@ -5737,17 +5740,19 @@ |
| length = dictionary->max_number_key(); |
| } |
| return static_cast<uint32_t>(dictionary->Capacity()) >= |
| - (length / (2 * Dictionary::kElementSize)); |
| + (length / (2 * NumberDictionary::kEntrySize)); |
| } |
| - |
| -void Dictionary::CopyValuesTo(FixedArray* elements) { |
| +template<typename Shape, typename Key> |
| +void Dictionary<Shape, Key>::CopyValuesTo(FixedArray* elements) { |
| int pos = 0; |
| - int capacity = Capacity(); |
| + int capacity = HashTable<Shape, Key>::Capacity(); |
| WriteBarrierMode mode = elements->GetWriteBarrierMode(); |
| for (int i = 0; i < capacity; i++) { |
| - Object* k = KeyAt(i); |
| - if (IsKey(k)) elements->set(pos++, ValueAt(i), mode); |
| + Object* k = Dictionary<Shape, Key>::KeyAt(i); |
| + if (Dictionary<Shape, Key>::IsKey(k)) { |
| + elements->set(pos++, ValueAt(i), mode); |
| + } |
| } |
| ASSERT(pos == elements->length()); |
| } |
| @@ -5953,8 +5958,8 @@ |
| return (index < length) && |
| !FixedArray::cast(elements())->get(index)->IsTheHole(); |
| } |
| - return element_dictionary()->FindNumberEntry(index) |
| - != Dictionary::kNotFound; |
| + return element_dictionary()->FindEntry(index) |
| + != NumberDictionary::kNotFound; |
| } |
| @@ -6187,51 +6192,62 @@ |
| } |
| -// The NumberKey uses carries the uint32_t as key. |
| -// This avoids allocation in HasProperty. |
| -class NumberKey : public HashTableKey { |
| - public: |
| - explicit NumberKey(uint32_t number) : number_(number) { } |
| +bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) { |
| + ASSERT(other->IsNumber()); |
| + return key == static_cast<uint32_t>(other->Number()); |
| +} |
| - bool IsMatch(Object* number) { |
| - return number_ == ToUint32(number); |
| - } |
| - uint32_t Hash() { return ComputeIntegerHash(number_); } |
| +uint32_t NumberDictionaryShape::Hash(uint32_t key) { |
| + return ComputeIntegerHash(key); |
| +} |
| - HashFunction GetHashFunction() { return NumberHash; } |
| - Object* GetObject() { |
| - return Heap::NumberFromDouble(number_); |
| - } |
| +uint32_t NumberDictionaryShape::HashForObject(uint32_t key, Object* other) { |
| + ASSERT(other->IsNumber()); |
| + return ComputeIntegerHash(static_cast<uint32_t>(other->Number())); |
| +} |
| - bool IsStringKey() { return false; } |
| - private: |
| - static uint32_t NumberHash(Object* obj) { |
| - return ComputeIntegerHash(ToUint32(obj)); |
| - } |
| +Object* NumberDictionaryShape::AsObject(uint32_t key) { |
| + return Heap::NumberFromUint32(key); |
| +} |
| - static uint32_t ToUint32(Object* obj) { |
| - ASSERT(obj->IsNumber()); |
| - return static_cast<uint32_t>(obj->Number()); |
| - } |
| - uint32_t number_; |
| -}; |
| +bool StringDictionaryShape::IsMatch(String* key, Object* other) { |
| + // We know that all entries in a hash table had their hash keys created. |
| + // Use that knowledge to have fast failure. |
| + if (key->Hash() != String::cast(other)->Hash()) return false; |
| + return key->Equals(String::cast(other)); |
| +} |
| +uint32_t StringDictionaryShape::Hash(String* key) { |
| + return key->Hash(); |
| +} |
| + |
| + |
| +uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) { |
| + return String::cast(other)->Hash(); |
| +} |
| + |
| + |
| +Object* StringDictionaryShape::AsObject(String* key) { |
| + return key; |
| +} |
| + |
| + |
| // StringKey simply carries a string object as key. |
| class StringKey : public HashTableKey { |
| public: |
| explicit StringKey(String* string) : |
| string_(string), |
| - hash_(StringHash(string)) { } |
| + hash_(HashForObject(string)) { } |
| bool IsMatch(Object* string) { |
| // We know that all entries in a hash table had their hash keys created. |
| // Use that knowledge to have fast failure. |
| - if (hash_ != StringHash(string)) { |
| + if (hash_ != HashForObject(string)) { |
| return false; |
| } |
| return string_->Equals(String::cast(string)); |
| @@ -6239,16 +6255,10 @@ |
| uint32_t Hash() { return hash_; } |
| - HashFunction GetHashFunction() { return StringHash; } |
| + uint32_t HashForObject(Object* other) { return String::cast(other)->Hash(); } |
| - Object* GetObject() { return string_; } |
| + Object* AsObject() { return string_; } |
| - static uint32_t StringHash(Object* obj) { |
| - return String::cast(obj)->Hash(); |
| - } |
| - |
| - bool IsStringKey() { return true; } |
| - |
| String* string_; |
| uint32_t hash_; |
| }; |
| @@ -6269,10 +6279,6 @@ |
| return source->Equals(source_); |
| } |
| - typedef uint32_t (*HashFunction)(Object* obj); |
| - |
| - virtual HashFunction GetHashFunction() { return StringSharedHash; } |
| - |
| static uint32_t StringSharedHashHelper(String* source, |
| SharedFunctionInfo* shared) { |
| uint32_t hash = source->Hash(); |
| @@ -6289,18 +6295,18 @@ |
| return hash; |
| } |
| - static uint32_t StringSharedHash(Object* obj) { |
| + uint32_t Hash() { |
| + return StringSharedHashHelper(source_, shared_); |
| + } |
| + |
| + uint32_t HashForObject(Object* obj) { |
| FixedArray* pair = FixedArray::cast(obj); |
| SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0)); |
| String* source = String::cast(pair->get(1)); |
| return StringSharedHashHelper(source, shared); |
| } |
| - virtual uint32_t Hash() { |
| - return StringSharedHashHelper(source_, shared_); |
| - } |
| - |
| - virtual Object* GetObject() { |
| + Object* AsObject() { |
| Object* obj = Heap::AllocateFixedArray(2); |
| if (obj->IsFailure()) return obj; |
| FixedArray* pair = FixedArray::cast(obj); |
| @@ -6309,8 +6315,6 @@ |
| return pair; |
| } |
| - virtual bool IsStringKey() { return false; } |
| - |
| private: |
| String* source_; |
| SharedFunctionInfo* shared_; |
| @@ -6332,16 +6336,14 @@ |
| uint32_t Hash() { return RegExpHash(string_, flags_); } |
| - HashFunction GetHashFunction() { return RegExpObjectHash; } |
| - |
| - Object* GetObject() { |
| + Object* AsObject() { |
| // Plain hash maps, which is where regexp keys are used, don't |
| // use this function. |
| UNREACHABLE(); |
| return NULL; |
| } |
| - static uint32_t RegExpObjectHash(Object* obj) { |
| + uint32_t HashForObject(Object* obj) { |
| FixedArray* val = FixedArray::cast(obj); |
| return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)), |
| Smi::cast(val->get(JSRegExp::kFlagsIndex))); |
| @@ -6351,8 +6353,6 @@ |
| return string->Hash() + flags->value(); |
| } |
| - bool IsStringKey() { return false; } |
| - |
| String* string_; |
| Smi* flags_; |
| }; |
| @@ -6367,10 +6367,6 @@ |
| return String::cast(string)->IsEqualTo(string_); |
| } |
| - HashFunction GetHashFunction() { |
| - return StringHash; |
| - } |
| - |
| uint32_t Hash() { |
| if (length_field_ != 0) return length_field_ >> String::kHashShift; |
| unibrow::Utf8InputBuffer<> buffer(string_.start(), |
| @@ -6382,17 +6378,15 @@ |
| return result; |
| } |
| - Object* GetObject() { |
| + uint32_t HashForObject(Object* other) { |
| + return String::cast(other)->Hash(); |
| + } |
| + |
| + Object* AsObject() { |
| if (length_field_ == 0) Hash(); |
| return Heap::AllocateSymbol(string_, chars_, length_field_); |
| } |
| - static uint32_t StringHash(Object* obj) { |
| - return String::cast(obj)->Hash(); |
| - } |
| - |
| - bool IsStringKey() { return true; } |
| - |
| Vector<const char> string_; |
| uint32_t length_field_; |
| int chars_; // Caches the number of characters when computing the hash code. |
| @@ -6404,17 +6398,17 @@ |
| public: |
| explicit SymbolKey(String* string) : string_(string) { } |
| - HashFunction GetHashFunction() { |
| - return StringHash; |
| - } |
| - |
| bool IsMatch(Object* string) { |
| return String::cast(string)->Equals(string_); |
| } |
| uint32_t Hash() { return string_->Hash(); } |
| - Object* GetObject() { |
| + uint32_t HashForObject(Object* other) { |
| + return String::cast(other)->Hash(); |
| + } |
| + |
| + Object* AsObject() { |
| // If the string is a cons string, attempt to flatten it so that |
| // symbols will most often be flat strings. |
| if (StringShape(string_).IsCons()) { |
| @@ -6442,28 +6436,27 @@ |
| return String::cast(obj)->Hash(); |
| } |
| - bool IsStringKey() { return true; } |
| - |
| String* string_; |
| }; |
| -template<int prefix_size, int element_size> |
| -void HashTable<prefix_size, element_size>::IteratePrefix(ObjectVisitor* v) { |
| +template<typename Shape, typename Key> |
| +void HashTable<Shape, Key>::IteratePrefix(ObjectVisitor* v) { |
| IteratePointers(v, 0, kElementsStartOffset); |
| } |
| -template<int prefix_size, int element_size> |
| -void HashTable<prefix_size, element_size>::IterateElements(ObjectVisitor* v) { |
| +template<typename Shape, typename Key> |
| +void HashTable<Shape, Key>::IterateElements(ObjectVisitor* v) { |
| IteratePointers(v, |
| kElementsStartOffset, |
| kHeaderSize + length() * kPointerSize); |
| } |
| -template<int prefix_size, int element_size> |
| -Object* HashTable<prefix_size, element_size>::Allocate(int at_least_space_for) { |
| +template<typename Shape, typename Key> |
| +Object* HashTable<Shape, Key>::Allocate( |
| + int at_least_space_for) { |
| int capacity = RoundUpToPowerOf2(at_least_space_for); |
| if (capacity < 4) capacity = 4; // Guarantee min capacity. |
| Object* obj = Heap::AllocateHashTable(EntryToIndex(capacity)); |
| @@ -6475,27 +6468,28 @@ |
| } |
| + |
| // Find entry for key otherwise return -1. |
| -template <int prefix_size, int element_size> |
| -int HashTable<prefix_size, element_size>::FindEntry(HashTableKey* key) { |
| +template<typename Shape, typename Key> |
| +int HashTable<Shape, Key>::FindEntry(Key key) { |
| uint32_t nof = NumberOfElements(); |
| if (nof == 0) return kNotFound; // Bail out if empty. |
| uint32_t capacity = Capacity(); |
| - uint32_t hash = key->Hash(); |
| + uint32_t hash = Shape::Hash(key); |
| uint32_t entry = GetProbe(hash, 0, capacity); |
| Object* element = KeyAt(entry); |
| uint32_t passed_elements = 0; |
| if (!element->IsNull()) { |
| - if (!element->IsUndefined() && key->IsMatch(element)) return entry; |
| + if (!element->IsUndefined() && Shape::IsMatch(key, element)) return entry; |
| if (++passed_elements == nof) return kNotFound; |
| } |
| for (uint32_t i = 1; !element->IsUndefined(); i++) { |
| entry = GetProbe(hash, i, capacity); |
| element = KeyAt(entry); |
| if (!element->IsNull()) { |
| - if (!element->IsUndefined() && key->IsMatch(element)) return entry; |
| + if (!element->IsUndefined() && Shape::IsMatch(key, element)) return entry; |
| if (++passed_elements == nof) return kNotFound; |
| } |
| } |
| @@ -6503,9 +6497,8 @@ |
| } |
| -template<int prefix_size, int element_size> |
| -Object* HashTable<prefix_size, element_size>::EnsureCapacity( |
| - int n, HashTableKey* key) { |
| +template<typename Shape, typename Key> |
| +Object* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) { |
| int capacity = Capacity(); |
| int nof = NumberOfElements() + n; |
| // Make sure 50% is free |
| @@ -6517,18 +6510,20 @@ |
| WriteBarrierMode mode = table->GetWriteBarrierMode(); |
| // Copy prefix to new array. |
| - for (int i = kPrefixStartIndex; i < kPrefixStartIndex + prefix_size; i++) { |
| + for (int i = kPrefixStartIndex; |
| + i < kPrefixStartIndex + Shape::kPrefixSize; |
| + i++) { |
| table->set(i, get(i), mode); |
| } |
| // Rehash the elements. |
| - uint32_t (*Hash)(Object* key) = key->GetHashFunction(); |
| for (int i = 0; i < capacity; i++) { |
| uint32_t from_index = EntryToIndex(i); |
| - Object* key = get(from_index); |
| - if (IsKey(key)) { |
| + Object* k = get(from_index); |
| + if (IsKey(k)) { |
| + uint32_t hash = Shape::HashForObject(key, k); |
| uint32_t insertion_index = |
| - EntryToIndex(table->FindInsertionEntry(key, Hash(key))); |
| - for (int j = 0; j < element_size; j++) { |
| + EntryToIndex(table->FindInsertionEntry(hash)); |
| + for (int j = 0; j < Shape::kEntrySize; j++) { |
| table->set(insertion_index + j, get(from_index + j), mode); |
| } |
| } |
| @@ -6538,10 +6533,8 @@ |
| } |
| -template<int prefix_size, int element_size> |
| -uint32_t HashTable<prefix_size, element_size>::FindInsertionEntry( |
| - Object* key, |
| - uint32_t hash) { |
| +template<typename Shape, typename Key> |
| +uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) { |
| uint32_t capacity = Capacity(); |
| uint32_t entry = GetProbe(hash, 0, capacity); |
| Object* element = KeyAt(entry); |
| @@ -6554,19 +6547,24 @@ |
| return entry; |
| } |
| +// Force instantiation of template instances class |
| +template class HashTable<SymbolTableShape, HashTableKey*>; |
| -// Force instantiation of SymbolTable's base class |
| -template class HashTable<0, 1>; |
| +template class HashTable<CompilationCacheShape, HashTableKey*>; |
| +template class HashTable<MapCacheShape, HashTableKey*>; |
| -// Force instantiation of Dictionary's base class |
| -template class HashTable<2, 3>; |
| +template class Dictionary<StringDictionaryShape, String*>; |
| +template class Dictionary<NumberDictionaryShape, uint32_t>; |
| -// Force instantiation of EvalCache's base class |
| -template class HashTable<0, 2>; |
| +template Object* Dictionary<NumberDictionaryShape, uint32_t>::Allocate( |
| + int at_least_space_for); |
| +template Object* Dictionary<StringDictionaryShape, String*>::Allocate( |
| + int at_least_space_for); |
| + |
| // Collates undefined and unexisting elements below limit from position |
| // zero of the elements. The object stays in Dictionary mode. |
| Object* JSObject::PrepareSlowElementsForSort(uint32_t limit) { |
| @@ -6574,7 +6572,7 @@ |
| // Must stay in dictionary mode, either because of requires_slow_elements, |
| // or because we are not going to sort (and therefore compact) all of the |
| // elements. |
| - Dictionary* dict = element_dictionary(); |
| + NumberDictionary* dict = element_dictionary(); |
| HeapNumber* result_double = NULL; |
| if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { |
| // Allocate space for result before we start mutating the object. |
| @@ -6584,9 +6582,9 @@ |
| } |
| int capacity = dict->Capacity(); |
| - Object* obj = Dictionary::Allocate(dict->Capacity()); |
| + Object* obj = NumberDictionary::Allocate(dict->Capacity()); |
| if (obj->IsFailure()) return obj; |
| - Dictionary* new_dict = Dictionary::cast(obj); |
| + NumberDictionary* new_dict = NumberDictionary::cast(obj); |
| AssertNoAllocation no_alloc; |
| @@ -6647,7 +6645,7 @@ |
| if (!HasFastElements()) { |
| // Convert to fast elements containing only the existing properties. |
| // Ordering is irrelevant, since we are going to sort anyway. |
| - Dictionary* dict = element_dictionary(); |
| + NumberDictionary* dict = element_dictionary(); |
| if (IsJSArray() || dict->requires_slow_elements() || |
| dict->max_number_key() >= limit) { |
| return PrepareSlowElementsForSort(limit); |
| @@ -6787,7 +6785,7 @@ |
| if (obj->IsFailure()) return obj; |
| // Create symbol object. |
| - Object* symbol = key->GetObject(); |
| + Object* symbol = key->AsObject(); |
| if (symbol->IsFailure()) return symbol; |
| // If the symbol table grew as part of EnsureCapacity, obj is not |
| @@ -6796,7 +6794,7 @@ |
| SymbolTable* table = reinterpret_cast<SymbolTable*>(obj); |
| // Add the new symbol and return it along with the symbol table. |
| - entry = table->FindInsertionEntry(symbol, key->Hash()); |
| + entry = table->FindInsertionEntry(key->Hash()); |
| table->set(EntryToIndex(entry), symbol); |
| table->ElementAdded(); |
| *s = symbol; |
| @@ -6836,7 +6834,7 @@ |
| CompilationCacheTable* cache = |
| reinterpret_cast<CompilationCacheTable*>(obj); |
| - int entry = cache->FindInsertionEntry(src, key.Hash()); |
| + int entry = cache->FindInsertionEntry(key.Hash()); |
| cache->set(EntryToIndex(entry), src); |
| cache->set(EntryToIndex(entry) + 1, value); |
| cache->ElementAdded(); |
| @@ -6853,9 +6851,9 @@ |
| CompilationCacheTable* cache = |
| reinterpret_cast<CompilationCacheTable*>(obj); |
| - int entry = cache->FindInsertionEntry(src, key.Hash()); |
| + int entry = cache->FindInsertionEntry(key.Hash()); |
| - Object* k = key.GetObject(); |
| + Object* k = key.AsObject(); |
| if (k->IsFailure()) return k; |
| cache->set(EntryToIndex(entry), k); |
| @@ -6874,7 +6872,7 @@ |
| CompilationCacheTable* cache = |
| reinterpret_cast<CompilationCacheTable*>(obj); |
| - int entry = cache->FindInsertionEntry(value, key.Hash()); |
| + int entry = cache->FindInsertionEntry(key.Hash()); |
| cache->set(EntryToIndex(entry), value); |
| cache->set(EntryToIndex(entry) + 1, value); |
| cache->ElementAdded(); |
| @@ -6897,13 +6895,9 @@ |
| return true; |
| } |
| - uint32_t Hash() { return SymbolsHash(symbols_); } |
| + uint32_t Hash() { return HashForObject(symbols_); } |
| - HashFunction GetHashFunction() { return SymbolsHash; } |
| - |
| - Object* GetObject() { return symbols_; } |
| - |
| - static uint32_t SymbolsHash(Object* obj) { |
| + uint32_t HashForObject(Object* obj) { |
| FixedArray* symbols = FixedArray::cast(obj); |
| int len = symbols->length(); |
| uint32_t hash = 0; |
| @@ -6913,7 +6907,7 @@ |
| return hash; |
| } |
| - bool IsStringKey() { return false; } |
| + Object* AsObject() { return symbols_; } |
| private: |
| FixedArray* symbols_; |
| @@ -6934,7 +6928,7 @@ |
| if (obj->IsFailure()) return obj; |
| MapCache* cache = reinterpret_cast<MapCache*>(obj); |
| - int entry = cache->FindInsertionEntry(array, key.Hash()); |
| + int entry = cache->FindInsertionEntry(key.Hash()); |
| cache->set(EntryToIndex(entry), array); |
| cache->set(EntryToIndex(entry) + 1, value); |
| cache->ElementAdded(); |
| @@ -6942,19 +6936,21 @@ |
| } |
| -Object* Dictionary::Allocate(int at_least_space_for) { |
| - Object* obj = DictionaryBase::Allocate(at_least_space_for); |
| +template<typename Shape, typename Key> |
| +Object* Dictionary<Shape, Key>::Allocate(int at_least_space_for) { |
| + Object* obj = HashTable<Shape, Key>::Allocate(at_least_space_for); |
| // Initialize the next enumeration index. |
| if (!obj->IsFailure()) { |
| - Dictionary::cast(obj)-> |
| + Dictionary<Shape, Key>::cast(obj)-> |
| SetNextEnumerationIndex(PropertyDetails::kInitialIndex); |
| } |
| return obj; |
| } |
| -Object* Dictionary::GenerateNewEnumerationIndices() { |
| - int length = NumberOfElements(); |
| +template<typename Shape, typename Key> |
| +Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() { |
| + int length = HashTable<Shape, Key>::NumberOfElements(); |
| // Allocate and initialize iteration order array. |
| Object* obj = Heap::AllocateFixedArray(length); |
| @@ -6970,10 +6966,10 @@ |
| FixedArray* enumeration_order = FixedArray::cast(obj); |
| // Fill the enumeration order array with property details. |
| - int capacity = Capacity(); |
| + int capacity = HashTable<Shape, Key>::Capacity(); |
| int pos = 0; |
| for (int i = 0; i < capacity; i++) { |
| - if (IsKey(KeyAt(i))) { |
| + if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { |
| enumeration_order->set(pos++, |
| Smi::FromInt(DetailsAt(i).index()), |
| SKIP_WRITE_BARRIER); |
| @@ -6993,10 +6989,10 @@ |
| } |
| // Update the dictionary with new indices. |
| - capacity = Capacity(); |
| + capacity = HashTable<Shape, Key>::Capacity(); |
| pos = 0; |
| for (int i = 0; i < capacity; i++) { |
| - if (IsKey(KeyAt(i))) { |
| + if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { |
| int enum_index = Smi::cast(enumeration_order->get(pos++))->value(); |
| PropertyDetails details = DetailsAt(i); |
| PropertyDetails new_details = |
| @@ -7010,20 +7006,20 @@ |
| return this; |
| } |
| - |
| -Object* Dictionary::EnsureCapacity(int n, HashTableKey* key) { |
| +template<typename Shape, typename Key> |
| +Object* Dictionary<Shape, Key>::EnsureCapacity(int n, Key key) { |
| // Check whether there are enough enumeration indices to add n elements. |
| - if (key->IsStringKey() && |
| + if (Shape::kIsEnumerable && |
| !PropertyDetails::IsValidIndex(NextEnumerationIndex() + n)) { |
| // If not, we generate new indices for the properties. |
| Object* result = GenerateNewEnumerationIndices(); |
| if (result->IsFailure()) return result; |
| } |
| - return DictionaryBase::EnsureCapacity(n, key); |
| + return HashTable<Shape, Key>::EnsureCapacity(n, key); |
| } |
| -void Dictionary::RemoveNumberEntries(uint32_t from, uint32_t to) { |
| +void NumberDictionary::RemoveNumberEntries(uint32_t from, uint32_t to) { |
| // Do nothing if the interval [from, to) is empty. |
| if (from >= to) return; |
| @@ -7045,36 +7041,26 @@ |
| SetNumberOfElements(NumberOfElements() - removed_entries); |
| } |
| - |
| -Object* Dictionary::DeleteProperty(int entry, JSObject::DeleteMode mode) { |
| +template<typename Shape, typename Key> |
| +Object* Dictionary<Shape, Key>::DeleteProperty(int entry, |
| + JSObject::DeleteMode mode) { |
| PropertyDetails details = DetailsAt(entry); |
| // Ignore attributes if forcing a deletion. |
| if (details.IsDontDelete() && mode == JSObject::NORMAL_DELETION) { |
| return Heap::false_value(); |
| } |
| SetEntry(entry, Heap::null_value(), Heap::null_value(), Smi::FromInt(0)); |
| - ElementRemoved(); |
| + HashTable<Shape, Key>::ElementRemoved(); |
| return Heap::true_value(); |
| } |
| -int Dictionary::FindStringEntry(String* key) { |
| - StringKey k(key); |
| - return FindEntry(&k); |
| -} |
| - |
| - |
| -int Dictionary::FindNumberEntry(uint32_t index) { |
| - NumberKey k(index); |
| - return FindEntry(&k); |
| -} |
| - |
| - |
| -Object* Dictionary::AtPut(HashTableKey* key, Object* value) { |
| +template<typename Shape, typename Key> |
| +Object* Dictionary<Shape, Key>::AtPut(Key key, Object* value) { |
| int entry = FindEntry(key); |
| // If the entry is present set the value; |
| - if (entry != kNotFound) { |
| + if (entry != Dictionary<Shape, Key>::kNotFound) { |
| ValueAtPut(entry, value); |
| return this; |
| } |
| @@ -7082,48 +7068,57 @@ |
| // Check whether the dictionary should be extended. |
| Object* obj = EnsureCapacity(1, key); |
| if (obj->IsFailure()) return obj; |
| - Object* k = key->GetObject(); |
| + |
| + Object* k = Shape::AsObject(key); |
| if (k->IsFailure()) return k; |
| PropertyDetails details = PropertyDetails(NONE, NORMAL); |
| - Dictionary::cast(obj)->AddEntry(k, value, details, key->Hash()); |
| - return obj; |
| + return Dictionary<Shape, Key>::cast(obj)-> |
| + AddEntry(key, value, details, Shape::Hash(key)); |
| } |
| -Object* Dictionary::Add(HashTableKey* key, Object* value, |
| - PropertyDetails details) { |
| +template<typename Shape, typename Key> |
| +Object* Dictionary<Shape, Key>::Add(Key key, |
| + Object* value, |
| + PropertyDetails details) { |
| + // Valdate key is absent. |
| + SLOW_ASSERT((FindEntry(key) == Dictionary<Shape, Key>::kNotFound)); |
| // Check whether the dictionary should be extended. |
| Object* obj = EnsureCapacity(1, key); |
| if (obj->IsFailure()) return obj; |
| - // Compute the key object. |
| - Object* k = key->GetObject(); |
| - if (k->IsFailure()) return k; |
| - Dictionary::cast(obj)->AddEntry(k, value, details, key->Hash()); |
| - return obj; |
| + return Dictionary<Shape, Key>::cast(obj)-> |
| + AddEntry(key, value, details, Shape::Hash(key)); |
| } |
| // Add a key, value pair to the dictionary. |
| -void Dictionary::AddEntry(Object* key, |
| - Object* value, |
| - PropertyDetails details, |
| - uint32_t hash) { |
| - uint32_t entry = FindInsertionEntry(key, hash); |
| +template<typename Shape, typename Key> |
| +Object* Dictionary<Shape, Key>::AddEntry(Key key, |
| + Object* value, |
| + PropertyDetails details, |
| + uint32_t hash) { |
| + // Compute the key object. |
| + Object* k = Shape::AsObject(key); |
| + if (k->IsFailure()) return k; |
| + |
| + uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash); |
| // Insert element at empty or deleted entry |
| - if (details.index() == 0 && key->IsString()) { |
| + if (details.index() == 0 && Shape::kIsEnumerable) { |
| // Assign an enumeration index to the property and update |
| // SetNextEnumerationIndex. |
| int index = NextEnumerationIndex(); |
| details = PropertyDetails(details.attributes(), details.type(), index); |
| SetNextEnumerationIndex(index + 1); |
| } |
| - SetEntry(entry, key, value, details); |
| - ASSERT(KeyAt(entry)->IsNumber() || KeyAt(entry)->IsString()); |
| - ElementAdded(); |
| + SetEntry(entry, k, value, details); |
| + ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber() |
| + || Dictionary<Shape, Key>::KeyAt(entry)->IsString())); |
| + HashTable<Shape, Key>::ElementAdded(); |
| + return this; |
| } |
| -void Dictionary::UpdateMaxNumberKey(uint32_t key) { |
| +void NumberDictionary::UpdateMaxNumberKey(uint32_t key) { |
| // If the dictionary requires slow elements an element has already |
| // been added at a high index. |
| if (requires_slow_elements()) return; |
| @@ -7136,73 +7131,51 @@ |
| // Update max key value. |
| Object* max_index_object = get(kMaxNumberKeyIndex); |
| if (!max_index_object->IsSmi() || max_number_key() < key) { |
| - set(kMaxNumberKeyIndex, |
| - Smi::FromInt(key << kRequiresSlowElementsTagSize), |
| - SKIP_WRITE_BARRIER); |
| + FixedArray::set(kMaxNumberKeyIndex, |
| + Smi::FromInt(key << kRequiresSlowElementsTagSize), |
| + SKIP_WRITE_BARRIER); |
| } |
| } |
| -Object* Dictionary::AddStringEntry(String* key, |
| - Object* value, |
| - PropertyDetails details) { |
| - StringKey k(key); |
| - SLOW_ASSERT(FindEntry(&k) == kNotFound); |
| - return Add(&k, value, details); |
| -} |
| - |
| - |
| -Object* Dictionary::AddNumberEntry(uint32_t key, |
| - Object* value, |
| - PropertyDetails details) { |
| - NumberKey k(key); |
| +Object* NumberDictionary::AddNumberEntry(uint32_t key, |
| + Object* value, |
| + PropertyDetails details) { |
| UpdateMaxNumberKey(key); |
| - SLOW_ASSERT(FindEntry(&k) == kNotFound); |
| - return Add(&k, value, details); |
| + SLOW_ASSERT(FindEntry(key) == kNotFound); |
| + return Add(key, value, details); |
| } |
| -Object* Dictionary::AtNumberPut(uint32_t key, Object* value) { |
| - NumberKey k(key); |
| +Object* NumberDictionary::AtNumberPut(uint32_t key, Object* value) { |
| UpdateMaxNumberKey(key); |
| - return AtPut(&k, value); |
| + return AtPut(key, value); |
| } |
| -Object* Dictionary::SetStringEntry(int entry, |
| - String* key, |
| - Object* value, |
| - PropertyDetails details) { |
| +Object* NumberDictionary::Set(uint32_t key, |
| + Object* value, |
| + PropertyDetails details) { |
| + int entry = FindEntry(key); |
| + if (entry == kNotFound) return AddNumberEntry(key, value, details); |
| // Preserve enumeration index. |
| details = PropertyDetails(details.attributes(), |
| details.type(), |
| DetailsAt(entry).index()); |
| - SetEntry(entry, key, value, details); |
| + SetEntry(entry, NumberDictionaryShape::AsObject(key), value, details); |
| return this; |
| } |
| -Object* Dictionary::SetOrAddNumberEntry(uint32_t key, |
| - Object* value, |
| - PropertyDetails details) { |
| - NumberKey k(key); |
| - int entry = FindEntry(&k); |
| - if (entry == -1) return AddNumberEntry(key, value, details); |
| - // Preserve enumeration index. |
| - details = PropertyDetails(details.attributes(), |
| - details.type(), |
| - DetailsAt(entry).index()); |
| - SetEntry(entry, k.GetObject(), value, details); |
| - return this; |
| -} |
| - |
| -int Dictionary::NumberOfElementsFilterAttributes(PropertyAttributes filter) { |
| - int capacity = Capacity(); |
| +template<typename Shape, typename Key> |
| +int Dictionary<Shape, Key>::NumberOfElementsFilterAttributes( |
| + PropertyAttributes filter) { |
| + int capacity = HashTable<Shape, Key>::Capacity(); |
| int result = 0; |
| for (int i = 0; i < capacity; i++) { |
| - Object* k = KeyAt(i); |
| - if (IsKey(k)) { |
| + Object* k = HashTable<Shape, Key>::KeyAt(i); |
| + if (HashTable<Shape, Key>::IsKey(k)) { |
| PropertyAttributes attr = DetailsAt(i).attributes(); |
| if ((attr & filter) == 0) result++; |
| } |
| @@ -7211,19 +7184,22 @@ |
| } |
| -int Dictionary::NumberOfEnumElements() { |
| +template<typename Shape, typename Key> |
| +int Dictionary<Shape, Key>::NumberOfEnumElements() { |
| return NumberOfElementsFilterAttributes( |
| static_cast<PropertyAttributes>(DONT_ENUM)); |
| } |
| -void Dictionary::CopyKeysTo(FixedArray* storage, PropertyAttributes filter) { |
| +template<typename Shape, typename Key> |
| +void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage, |
| + PropertyAttributes filter) { |
| ASSERT(storage->length() >= NumberOfEnumElements()); |
| - int capacity = Capacity(); |
| + int capacity = HashTable<Shape, Key>::Capacity(); |
| int index = 0; |
| for (int i = 0; i < capacity; i++) { |
| - Object* k = KeyAt(i); |
| - if (IsKey(k)) { |
| + Object* k = HashTable<Shape, Key>::KeyAt(i); |
| + if (HashTable<Shape, Key>::IsKey(k)) { |
| PropertyAttributes attr = DetailsAt(i).attributes(); |
| if ((attr & filter) == 0) storage->set(index++, k); |
| } |
| @@ -7233,7 +7209,8 @@ |
| } |
| -void Dictionary::CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array) { |
| +void StringDictionary::CopyEnumKeysTo(FixedArray* storage, |
| + FixedArray* sort_array) { |
| ASSERT(storage->length() >= NumberOfEnumElements()); |
| int capacity = Capacity(); |
| int index = 0; |
| @@ -7255,14 +7232,15 @@ |
| } |
| -void Dictionary::CopyKeysTo(FixedArray* storage) { |
| +template<typename Shape, typename Key> |
| +void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage) { |
| ASSERT(storage->length() >= NumberOfElementsFilterAttributes( |
| static_cast<PropertyAttributes>(NONE))); |
| - int capacity = Capacity(); |
| + int capacity = HashTable<Shape, Key>::Capacity(); |
| int index = 0; |
| for (int i = 0; i < capacity; i++) { |
| - Object* k = KeyAt(i); |
| - if (IsKey(k)) { |
| + Object* k = HashTable<Shape, Key>::KeyAt(i); |
| + if (HashTable<Shape, Key>::IsKey(k)) { |
| storage->set(index++, k); |
| } |
| } |
| @@ -7271,11 +7249,12 @@ |
| // Backwards lookup (slow). |
| -Object* Dictionary::SlowReverseLookup(Object* value) { |
| - int capacity = Capacity(); |
| +template<typename Shape, typename Key> |
| +Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) { |
| + int capacity = HashTable<Shape, Key>::Capacity(); |
| for (int i = 0; i < capacity; i++) { |
| - Object* k = KeyAt(i); |
| - if (IsKey(k)) { |
| + Object* k = HashTable<Shape, Key>::KeyAt(i); |
| + if (Dictionary<Shape, Key>::IsKey(k)) { |
| Object* e = ValueAt(i); |
| if (e->IsJSGlobalPropertyCell()) { |
| e = JSGlobalPropertyCell::cast(e)->value(); |
| @@ -7287,8 +7266,8 @@ |
| } |
| -Object* Dictionary::TransformPropertiesToFastFor(JSObject* obj, |
| - int unused_property_fields) { |
| +Object* StringDictionary::TransformPropertiesToFastFor( |
| + JSObject* obj, int unused_property_fields) { |
| // Make sure we preserve dictionary representation if there are too many |
| // descriptors. |
| if (NumberOfElements() > DescriptorArray::kMaxNumberOfDescriptors) return obj; |
| @@ -7296,7 +7275,8 @@ |
| // Figure out if it is necessary to generate new enumeration indices. |
| int max_enumeration_index = |
| NextEnumerationIndex() + |
| - (DescriptorArray::kMaxNumberOfDescriptors - NumberOfElements()); |
| + (DescriptorArray::kMaxNumberOfDescriptors - |
| + NumberOfElements()); |
| if (!PropertyDetails::IsValidIndex(max_enumeration_index)) { |
| Object* result = GenerateNewEnumerationIndices(); |
| if (result->IsFailure()) return result; |
| @@ -7645,4 +7625,5 @@ |
| } |
| #endif |
| + |
| } } // namespace v8::internal |