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

Unified Diff: src/objects.cc

Issue 150168: Removed virtual behavior from Dictionaries. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« src/objects.h ('K') | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« src/objects.h ('K') | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698