| Index: src/objects.cc
|
| ===================================================================
|
| --- src/objects.cc (revision 2326)
|
| +++ 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,20 @@
|
| 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);
|
| + // Assign an enumeration index to the property and update
|
| + // SetNextEnumerationIndex.
|
| + int index = dict->NextEnumerationIndex();
|
| + PropertyDetails details = PropertyDetails(attributes, NORMAL, index);
|
| + dict->SetNextEnumerationIndex(index + 1);
|
| + dict->SetEntry(entry, name, store_value, details);
|
| return value;
|
| }
|
| store_value = Heap::AllocateJSGlobalPropertyCell(value);
|
| @@ -1357,9 +1362,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 +1410,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 +1651,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 +1703,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 +2106,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 +2123,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 +2136,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 +2149,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 +2224,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 +2234,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 +2311,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 != NumberDictionary::kNotFound) {
|
| return dictionary->DeleteProperty(entry, mode);
|
| }
|
| return Heap::true_value();
|
| @@ -2380,9 +2385,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 +2692,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 +2730,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 +2804,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 +3009,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 +5080,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 +5245,8 @@
|
| return true;
|
| }
|
| } else {
|
| - if (element_dictionary()->FindNumberEntry(index) != Dictionary::kNotFound) {
|
| + if (element_dictionary()->FindEntry(index)
|
| + != NumberDictionary::kNotFound) {
|
| return true;
|
| }
|
| }
|
| @@ -5317,8 +5323,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 +5350,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 +5486,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 +5538,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 +5581,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 +5665,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 +5703,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 +5725,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 +5744,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 +5962,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 +6196,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 +6259,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 +6283,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 +6299,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 +6319,6 @@
|
| return pair;
|
| }
|
|
|
| - virtual bool IsStringKey() { return false; }
|
| -
|
| private:
|
| String* source_;
|
| SharedFunctionInfo* shared_;
|
| @@ -6332,16 +6340,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 +6357,6 @@
|
| return string->Hash() + flags->value();
|
| }
|
|
|
| - bool IsStringKey() { return false; }
|
| -
|
| String* string_;
|
| Smi* flags_;
|
| };
|
| @@ -6367,10 +6371,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 +6382,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 +6402,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 +6440,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 +6472,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 +6501,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 +6514,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 +6537,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 +6551,81 @@
|
| return entry;
|
| }
|
|
|
| +// Force instantiation of template instances class.
|
| +// Please note this list is compiler dependent.
|
|
|
| -// Force instantiation of SymbolTable's base class
|
| -template class HashTable<0, 1>;
|
| +template class HashTable<SymbolTableShape, HashTableKey*>;
|
|
|
| +template class HashTable<CompilationCacheShape, HashTableKey*>;
|
|
|
| -// Force instantiation of Dictionary's base class
|
| -template class HashTable<2, 3>;
|
| +template class HashTable<MapCacheShape, HashTableKey*>;
|
|
|
| +template class Dictionary<StringDictionaryShape, String*>;
|
|
|
| -// Force instantiation of EvalCache's base class
|
| -template class HashTable<0, 2>;
|
| +template class Dictionary<NumberDictionaryShape, uint32_t>;
|
|
|
| +template Object* Dictionary<NumberDictionaryShape, uint32_t>::Allocate(
|
| + int);
|
|
|
| +template Object* Dictionary<StringDictionaryShape, String*>::Allocate(
|
| + int);
|
| +
|
| +template Object* Dictionary<NumberDictionaryShape, uint32_t>::AtPut(
|
| + uint32_t, Object*);
|
| +
|
| +template Object* Dictionary<NumberDictionaryShape, uint32_t>::SlowReverseLookup(
|
| + Object*);
|
| +
|
| +template Object* Dictionary<StringDictionaryShape, String*>::SlowReverseLookup(
|
| + Object*);
|
| +
|
| +template void Dictionary<NumberDictionaryShape, uint32_t>::CopyKeysTo(
|
| + FixedArray*, PropertyAttributes);
|
| +
|
| +template Object* Dictionary<StringDictionaryShape, String*>::DeleteProperty(
|
| + int, JSObject::DeleteMode);
|
| +
|
| +template Object* Dictionary<NumberDictionaryShape, uint32_t>::DeleteProperty(
|
| + int, JSObject::DeleteMode);
|
| +
|
| +template void Dictionary<StringDictionaryShape, String*>::CopyKeysTo(
|
| + FixedArray*);
|
| +
|
| +template int
|
| +Dictionary<StringDictionaryShape, String*>::NumberOfElementsFilterAttributes(
|
| + PropertyAttributes);
|
| +
|
| +template Object* Dictionary<StringDictionaryShape, String*>::Add(
|
| + String*, Object*, PropertyDetails);
|
| +
|
| +template Object*
|
| +Dictionary<StringDictionaryShape, String*>::GenerateNewEnumerationIndices();
|
| +
|
| +template int
|
| +Dictionary<NumberDictionaryShape, uint32_t>::NumberOfElementsFilterAttributes(
|
| + PropertyAttributes);
|
| +
|
| +template Object* Dictionary<NumberDictionaryShape, uint32_t>::Add(
|
| + uint32_t, Object*, PropertyDetails);
|
| +
|
| +template Object* Dictionary<NumberDictionaryShape, uint32_t>::EnsureCapacity(
|
| + int, uint32_t);
|
| +
|
| +template Object* Dictionary<StringDictionaryShape, String*>::EnsureCapacity(
|
| + int, String*);
|
| +
|
| +template Object* Dictionary<NumberDictionaryShape, uint32_t>::AddEntry(
|
| + uint32_t, Object*, PropertyDetails, uint32_t);
|
| +
|
| +template Object* Dictionary<StringDictionaryShape, String*>::AddEntry(
|
| + String*, Object*, PropertyDetails, uint32_t);
|
| +
|
| +template
|
| +int Dictionary<NumberDictionaryShape, uint32_t>::NumberOfEnumElements();
|
| +
|
| +template
|
| +int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements();
|
| +
|
| // 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 +6633,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 +6643,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 +6706,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 +6846,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 +6855,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 +6895,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 +6912,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 +6933,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 +6956,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 +6968,7 @@
|
| return hash;
|
| }
|
|
|
| - bool IsStringKey() { return false; }
|
| + Object* AsObject() { return symbols_; }
|
|
|
| private:
|
| FixedArray* symbols_;
|
| @@ -6934,7 +6989,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 +6997,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 +7027,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 +7050,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 +7067,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;
|
|
|
| @@ -7046,35 +7103,26 @@
|
| }
|
|
|
|
|
| -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 +7130,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 +7193,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 +7246,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 +7271,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 +7294,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 +7311,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 +7328,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 +7337,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 +7687,5 @@
|
| }
|
| #endif
|
|
|
| +
|
| } } // namespace v8::internal
|
|
|