Commit bef0d03c authored by Sathya Gunasekaran's avatar Sathya Gunasekaran Committed by Commit Bot

[dict] Store hash in prefix slot

Sets the hash default when dictionary is created.
Migrates the hash correctly when the dictionary grows.

Bug: v8:6443, v8:7569
Change-Id: I9195b557796b9bd3d040bd6f4f77d1f9ead4fc7d
Reviewed-on: https://chromium-review.googlesource.com/c/1337744Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58181}
parent 98bbb636
...@@ -564,8 +564,11 @@ Handle<SmallOrderedHashMap> Factory::NewSmallOrderedHashMap( ...@@ -564,8 +564,11 @@ Handle<SmallOrderedHashMap> Factory::NewSmallOrderedHashMap(
Handle<SmallOrderedNameDictionary> Factory::NewSmallOrderedNameDictionary( Handle<SmallOrderedNameDictionary> Factory::NewSmallOrderedNameDictionary(
int capacity, PretenureFlag pretenure) { int capacity, PretenureFlag pretenure) {
return AllocateSmallOrderedHashTable<SmallOrderedNameDictionary>( Handle<SmallOrderedNameDictionary> dict =
small_ordered_name_dictionary_map(), capacity, pretenure); AllocateSmallOrderedHashTable<SmallOrderedNameDictionary>(
small_ordered_name_dictionary_map(), capacity, pretenure);
dict->SetHash(PropertyArray::kNoHashSentinel);
return dict;
} }
Handle<OrderedHashSet> Factory::NewOrderedHashSet() { Handle<OrderedHashSet> Factory::NewOrderedHashSet() {
......
...@@ -170,6 +170,29 @@ Object* OrderedHashTableIterator<Derived, TableType>::CurrentKey() { ...@@ -170,6 +170,29 @@ Object* OrderedHashTableIterator<Derived, TableType>::CurrentKey() {
return key; return key;
} }
inline void SmallOrderedNameDictionary::SetHash(int hash) {
DCHECK(PropertyArray::HashField::is_valid(hash));
WRITE_INT_FIELD(this, PrefixOffset(), hash);
}
inline int SmallOrderedNameDictionary::Hash() {
int hash = READ_INT_FIELD(this, PrefixOffset());
DCHECK(PropertyArray::HashField::is_valid(hash));
return hash;
}
inline void OrderedNameDictionary::SetHash(int hash) {
DCHECK(PropertyArray::HashField::is_valid(hash));
this->set(PrefixIndex(), Smi::FromInt(hash));
}
inline int OrderedNameDictionary::Hash() {
Object* hash_obj = this->get(PrefixIndex());
int hash = Smi::ToInt(hash_obj);
DCHECK(PropertyArray::HashField::is_valid(hash));
return hash;
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -50,8 +50,8 @@ Handle<Derived> OrderedHashTable<Derived, entrysize>::EnsureGrowable( ...@@ -50,8 +50,8 @@ Handle<Derived> OrderedHashTable<Derived, entrysize>::EnsureGrowable(
// Don't need to grow if we can simply clear out deleted entries instead. // Don't need to grow if we can simply clear out deleted entries instead.
// Note that we can't compact in place, though, so we always allocate // Note that we can't compact in place, though, so we always allocate
// a new table. // a new table.
return Rehash(isolate, table, return Derived::Rehash(isolate, table,
(nod < (capacity >> 1)) ? capacity << 1 : capacity); (nod < (capacity >> 1)) ? capacity << 1 : capacity);
} }
template <class Derived, int entrysize> template <class Derived, int entrysize>
...@@ -62,7 +62,7 @@ Handle<Derived> OrderedHashTable<Derived, entrysize>::Shrink( ...@@ -62,7 +62,7 @@ Handle<Derived> OrderedHashTable<Derived, entrysize>::Shrink(
int nof = table->NumberOfElements(); int nof = table->NumberOfElements();
int capacity = table->Capacity(); int capacity = table->Capacity();
if (nof >= (capacity >> 2)) return table; if (nof >= (capacity >> 2)) return table;
return Rehash(isolate, table, capacity / 2); return Derived::Rehash(isolate, table, capacity / 2);
} }
template <class Derived, int entrysize> template <class Derived, int entrysize>
...@@ -187,7 +187,7 @@ Handle<Derived> OrderedHashTable<Derived, entrysize>::Rehash( ...@@ -187,7 +187,7 @@ Handle<Derived> OrderedHashTable<Derived, entrysize>::Rehash(
Isolate* isolate, Handle<Derived> table, int new_capacity) { Isolate* isolate, Handle<Derived> table, int new_capacity) {
DCHECK(!table->IsObsolete()); DCHECK(!table->IsObsolete());
Handle<Derived> new_table = Allocate( Handle<Derived> new_table = Derived::Allocate(
isolate, new_capacity, Heap::InNewSpace(*table) ? NOT_TENURED : TENURED); isolate, new_capacity, Heap::InNewSpace(*table) ? NOT_TENURED : TENURED);
int nof = table->NumberOfElements(); int nof = table->NumberOfElements();
int nod = table->NumberOfDeletedElements(); int nod = table->NumberOfDeletedElements();
...@@ -225,6 +225,29 @@ Handle<Derived> OrderedHashTable<Derived, entrysize>::Rehash( ...@@ -225,6 +225,29 @@ Handle<Derived> OrderedHashTable<Derived, entrysize>::Rehash(
return new_table; return new_table;
} }
Handle<OrderedHashSet> OrderedHashSet::Rehash(Isolate* isolate,
Handle<OrderedHashSet> table,
int new_capacity) {
return OrderedHashTable<OrderedHashSet, 1>::Rehash(isolate, table,
new_capacity);
}
Handle<OrderedHashMap> OrderedHashMap::Rehash(Isolate* isolate,
Handle<OrderedHashMap> table,
int new_capacity) {
return OrderedHashTable<OrderedHashMap, 2>::Rehash(isolate, table,
new_capacity);
}
Handle<OrderedNameDictionary> OrderedNameDictionary::Rehash(
Isolate* isolate, Handle<OrderedNameDictionary> table, int new_capacity) {
Handle<OrderedNameDictionary> new_table =
OrderedHashTable<OrderedNameDictionary, 3>::Rehash(isolate, table,
new_capacity);
new_table->SetHash(table->Hash());
return new_table;
}
template <class Derived, int entrysize> template <class Derived, int entrysize>
bool OrderedHashTable<Derived, entrysize>::Delete(Isolate* isolate, bool OrderedHashTable<Derived, entrysize>::Delete(Isolate* isolate,
Derived table, Object* key) { Derived table, Object* key) {
...@@ -361,9 +384,26 @@ int OrderedHashTable<OrderedNameDictionary, 3>::FindEntry(Isolate* isolate, ...@@ -361,9 +384,26 @@ int OrderedHashTable<OrderedNameDictionary, 3>::FindEntry(Isolate* isolate,
return kNotFound; return kNotFound;
} }
Handle<OrderedHashSet> OrderedHashSet::Allocate(Isolate* isolate, int capacity,
PretenureFlag pretenure) {
return OrderedHashTable<OrderedHashSet, 1>::Allocate(isolate, capacity,
pretenure);
}
template Handle<OrderedHashSet> OrderedHashTable<OrderedHashSet, 1>::Allocate( Handle<OrderedHashMap> OrderedHashMap::Allocate(Isolate* isolate, int capacity,
Isolate* isolate, int capacity, PretenureFlag pretenure); PretenureFlag pretenure) {
return OrderedHashTable<OrderedHashMap, 2>::Allocate(isolate, capacity,
pretenure);
}
Handle<OrderedNameDictionary> OrderedNameDictionary::Allocate(
Isolate* isolate, int capacity, PretenureFlag pretenure) {
Handle<OrderedNameDictionary> table =
OrderedHashTable<OrderedNameDictionary, 3>::Allocate(isolate, capacity,
pretenure);
table->SetHash(PropertyArray::kNoHashSentinel);
return table;
}
template Handle<OrderedHashSet> template Handle<OrderedHashSet>
OrderedHashTable<OrderedHashSet, 1>::EnsureGrowable( OrderedHashTable<OrderedHashSet, 1>::EnsureGrowable(
...@@ -386,9 +426,6 @@ template bool OrderedHashTable<OrderedHashSet, 1>::Delete(Isolate* isolate, ...@@ -386,9 +426,6 @@ template bool OrderedHashTable<OrderedHashSet, 1>::Delete(Isolate* isolate,
template int OrderedHashTable<OrderedHashSet, 1>::FindEntry(Isolate* isolate, template int OrderedHashTable<OrderedHashSet, 1>::FindEntry(Isolate* isolate,
Object* key); Object* key);
template Handle<OrderedHashMap> OrderedHashTable<OrderedHashMap, 2>::Allocate(
Isolate* isolate, int capacity, PretenureFlag pretenure);
template Handle<OrderedHashMap> template Handle<OrderedHashMap>
OrderedHashTable<OrderedHashMap, 2>::EnsureGrowable( OrderedHashTable<OrderedHashMap, 2>::EnsureGrowable(
Isolate* isolate, Handle<OrderedHashMap> table); Isolate* isolate, Handle<OrderedHashMap> table);
...@@ -410,10 +447,6 @@ template bool OrderedHashTable<OrderedHashMap, 2>::Delete(Isolate* isolate, ...@@ -410,10 +447,6 @@ template bool OrderedHashTable<OrderedHashMap, 2>::Delete(Isolate* isolate,
template int OrderedHashTable<OrderedHashMap, 2>::FindEntry(Isolate* isolate, template int OrderedHashTable<OrderedHashMap, 2>::FindEntry(Isolate* isolate,
Object* key); Object* key);
template Handle<OrderedNameDictionary>
OrderedHashTable<OrderedNameDictionary, 3>::Allocate(Isolate* isolate,
int capacity,
PretenureFlag pretenure);
template bool OrderedHashTable<OrderedNameDictionary, 3>::HasKey( template bool OrderedHashTable<OrderedNameDictionary, 3>::HasKey(
Isolate* isolate, OrderedNameDictionary table, Object* key); Isolate* isolate, OrderedNameDictionary table, Object* key);
...@@ -662,6 +695,28 @@ Handle<Derived> SmallOrderedHashTable<Derived>::Rehash(Isolate* isolate, ...@@ -662,6 +695,28 @@ Handle<Derived> SmallOrderedHashTable<Derived>::Rehash(Isolate* isolate,
return new_table; return new_table;
} }
Handle<SmallOrderedHashSet> SmallOrderedHashSet::Rehash(
Isolate* isolate, Handle<SmallOrderedHashSet> table, int new_capacity) {
return SmallOrderedHashTable<SmallOrderedHashSet>::Rehash(isolate, table,
new_capacity);
}
Handle<SmallOrderedHashMap> SmallOrderedHashMap::Rehash(
Isolate* isolate, Handle<SmallOrderedHashMap> table, int new_capacity) {
return SmallOrderedHashTable<SmallOrderedHashMap>::Rehash(isolate, table,
new_capacity);
}
Handle<SmallOrderedNameDictionary> SmallOrderedNameDictionary::Rehash(
Isolate* isolate, Handle<SmallOrderedNameDictionary> table,
int new_capacity) {
Handle<SmallOrderedNameDictionary> new_table =
SmallOrderedHashTable<SmallOrderedNameDictionary>::Rehash(isolate, table,
new_capacity);
new_table->SetHash(table->Hash());
return new_table;
}
template <class Derived> template <class Derived>
MaybeHandle<Derived> SmallOrderedHashTable<Derived>::Grow( MaybeHandle<Derived> SmallOrderedHashTable<Derived>::Grow(
Isolate* isolate, Handle<Derived> table) { Isolate* isolate, Handle<Derived> table) {
...@@ -686,7 +741,7 @@ MaybeHandle<Derived> SmallOrderedHashTable<Derived>::Grow( ...@@ -686,7 +741,7 @@ MaybeHandle<Derived> SmallOrderedHashTable<Derived>::Grow(
} }
} }
return Rehash(isolate, table, new_capacity); return Derived::Rehash(isolate, table, new_capacity);
} }
template <class Derived> template <class Derived>
......
...@@ -60,10 +60,6 @@ namespace internal { ...@@ -60,10 +60,6 @@ namespace internal {
template <class Derived, int entrysize> template <class Derived, int entrysize>
class OrderedHashTable : public FixedArray { class OrderedHashTable : public FixedArray {
public: public:
// Returns an OrderedHashTable with a capacity of at least |capacity|.
static Handle<Derived> Allocate(Isolate* isolate, int capacity,
PretenureFlag pretenure = NOT_TENURED);
// Returns an OrderedHashTable (possibly |table|) with enough space // Returns an OrderedHashTable (possibly |table|) with enough space
// to add at least one new element. // to add at least one new element.
static Handle<Derived> EnsureGrowable(Isolate* isolate, static Handle<Derived> EnsureGrowable(Isolate* isolate,
...@@ -138,6 +134,7 @@ class OrderedHashTable : public FixedArray { ...@@ -138,6 +134,7 @@ class OrderedHashTable : public FixedArray {
return Smi::ToInt(get(RemovedHolesIndex() + index)); return Smi::ToInt(get(RemovedHolesIndex() + index));
} }
// The extra +1 is for linking the bucket chains together.
static const int kEntrySize = entrysize + 1; static const int kEntrySize = entrysize + 1;
static const int kChainOffset = entrysize; static const int kChainOffset = entrysize;
...@@ -197,6 +194,9 @@ class OrderedHashTable : public FixedArray { ...@@ -197,6 +194,9 @@ class OrderedHashTable : public FixedArray {
} }
protected: protected:
// Returns an OrderedHashTable with a capacity of at least |capacity|.
static Handle<Derived> Allocate(Isolate* isolate, int capacity,
PretenureFlag pretenure = NOT_TENURED);
static Handle<Derived> Rehash(Isolate* isolate, Handle<Derived> table, static Handle<Derived> Rehash(Isolate* isolate, Handle<Derived> table,
int new_capacity); int new_capacity);
...@@ -234,6 +234,11 @@ class OrderedHashSet : public OrderedHashTable<OrderedHashSet, 1> { ...@@ -234,6 +234,11 @@ class OrderedHashSet : public OrderedHashTable<OrderedHashSet, 1> {
static Handle<FixedArray> ConvertToKeysArray(Isolate* isolate, static Handle<FixedArray> ConvertToKeysArray(Isolate* isolate,
Handle<OrderedHashSet> table, Handle<OrderedHashSet> table,
GetKeysConversion convert); GetKeysConversion convert);
static Handle<OrderedHashSet> Rehash(Isolate* isolate,
Handle<OrderedHashSet> table,
int new_capacity);
static Handle<OrderedHashSet> Allocate(Isolate* isolate, int capacity,
PretenureFlag pretenure = NOT_TENURED);
static HeapObject* GetEmpty(ReadOnlyRoots ro_roots); static HeapObject* GetEmpty(ReadOnlyRoots ro_roots);
static inline RootIndex GetMapRootIndex(); static inline RootIndex GetMapRootIndex();
static inline bool Is(Handle<HeapObject> table); static inline bool Is(Handle<HeapObject> table);
...@@ -251,6 +256,12 @@ class OrderedHashMap : public OrderedHashTable<OrderedHashMap, 2> { ...@@ -251,6 +256,12 @@ class OrderedHashMap : public OrderedHashTable<OrderedHashMap, 2> {
static Handle<OrderedHashMap> Add(Isolate* isolate, static Handle<OrderedHashMap> Add(Isolate* isolate,
Handle<OrderedHashMap> table, Handle<OrderedHashMap> table,
Handle<Object> key, Handle<Object> value); Handle<Object> key, Handle<Object> value);
static Handle<OrderedHashMap> Allocate(Isolate* isolate, int capacity,
PretenureFlag pretenure = NOT_TENURED);
static Handle<OrderedHashMap> Rehash(Isolate* isolate,
Handle<OrderedHashMap> table,
int new_capacity);
Object* ValueAt(int entry); Object* ValueAt(int entry);
static Object* GetHash(Isolate* isolate, Object* key); static Object* GetHash(Isolate* isolate, Object* key);
...@@ -339,9 +350,6 @@ class SmallOrderedHashTable : public HeapObjectPtr { ...@@ -339,9 +350,6 @@ class SmallOrderedHashTable : public HeapObjectPtr {
// we've already reached MaxCapacity. // we've already reached MaxCapacity.
static MaybeHandle<Derived> Grow(Isolate* isolate, Handle<Derived> table); static MaybeHandle<Derived> Grow(Isolate* isolate, Handle<Derived> table);
static Handle<Derived> Rehash(Isolate* isolate, Handle<Derived> table,
int new_capacity);
int FindEntry(Isolate* isolate, Object* key); int FindEntry(Isolate* isolate, Object* key);
// Iterates only fields in the DataTable. // Iterates only fields in the DataTable.
...@@ -414,6 +422,9 @@ class SmallOrderedHashTable : public HeapObjectPtr { ...@@ -414,6 +422,9 @@ class SmallOrderedHashTable : public HeapObjectPtr {
static const int kGrowthHack = 256; static const int kGrowthHack = 256;
protected: protected:
static Handle<Derived> Rehash(Isolate* isolate, Handle<Derived> table,
int new_capacity);
void SetDataEntry(int entry, int relative_index, Object* value); void SetDataEntry(int entry, int relative_index, Object* value);
// TODO(gsathya): Calculate all the various possible values for this // TODO(gsathya): Calculate all the various possible values for this
...@@ -573,7 +584,9 @@ class SmallOrderedHashSet : public SmallOrderedHashTable<SmallOrderedHashSet> { ...@@ -573,7 +584,9 @@ class SmallOrderedHashSet : public SmallOrderedHashTable<SmallOrderedHashSet> {
Handle<Object> key); Handle<Object> key);
static inline bool Is(Handle<HeapObject> table); static inline bool Is(Handle<HeapObject> table);
static inline RootIndex GetMapRootIndex(); static inline RootIndex GetMapRootIndex();
static Handle<SmallOrderedHashSet> Rehash(Isolate* isolate,
Handle<SmallOrderedHashSet> table,
int new_capacity);
OBJECT_CONSTRUCTORS(SmallOrderedHashSet, OBJECT_CONSTRUCTORS(SmallOrderedHashSet,
SmallOrderedHashTable<SmallOrderedHashSet>) SmallOrderedHashTable<SmallOrderedHashSet>)
}; };
...@@ -599,6 +612,10 @@ class SmallOrderedHashMap : public SmallOrderedHashTable<SmallOrderedHashMap> { ...@@ -599,6 +612,10 @@ class SmallOrderedHashMap : public SmallOrderedHashTable<SmallOrderedHashMap> {
static inline bool Is(Handle<HeapObject> table); static inline bool Is(Handle<HeapObject> table);
static inline RootIndex GetMapRootIndex(); static inline RootIndex GetMapRootIndex();
static Handle<SmallOrderedHashMap> Rehash(Isolate* isolate,
Handle<SmallOrderedHashMap> table,
int new_capacity);
OBJECT_CONSTRUCTORS(SmallOrderedHashMap, OBJECT_CONSTRUCTORS(SmallOrderedHashMap,
SmallOrderedHashTable<SmallOrderedHashMap>) SmallOrderedHashTable<SmallOrderedHashMap>)
}; };
...@@ -651,6 +668,12 @@ class OrderedNameDictionary ...@@ -651,6 +668,12 @@ class OrderedNameDictionary
Handle<Object> value, Handle<Object> value,
PropertyDetails details); PropertyDetails details);
static Handle<OrderedNameDictionary> Allocate(
Isolate* isolate, int capacity, PretenureFlag pretenure = NOT_TENURED);
static Handle<OrderedNameDictionary> Rehash(
Isolate* isolate, Handle<OrderedNameDictionary> table, int new_capacity);
// Returns the value for entry. // Returns the value for entry.
inline Object* ValueAt(int entry); inline Object* ValueAt(int entry);
...@@ -663,6 +686,9 @@ class OrderedNameDictionary ...@@ -663,6 +686,9 @@ class OrderedNameDictionary
// Set the details for entry. // Set the details for entry.
inline void DetailsAtPut(int entry, PropertyDetails value); inline void DetailsAtPut(int entry, PropertyDetails value);
inline void SetHash(int hash);
inline int Hash();
static HeapObject* GetEmpty(ReadOnlyRoots ro_roots); static HeapObject* GetEmpty(ReadOnlyRoots ro_roots);
static inline RootIndex GetMapRootIndex(); static inline RootIndex GetMapRootIndex();
...@@ -684,6 +710,10 @@ class SmallOrderedNameDictionary ...@@ -684,6 +710,10 @@ class SmallOrderedNameDictionary
// Returns the value for entry. // Returns the value for entry.
inline Object* ValueAt(int entry); inline Object* ValueAt(int entry);
static Handle<SmallOrderedNameDictionary> Rehash(
Isolate* isolate, Handle<SmallOrderedNameDictionary> table,
int new_capacity);
// Set the value for entry. // Set the value for entry.
inline void ValueAtPut(int entry, Object* value); inline void ValueAtPut(int entry, Object* value);
...@@ -693,6 +723,9 @@ class SmallOrderedNameDictionary ...@@ -693,6 +723,9 @@ class SmallOrderedNameDictionary
// Set the details for entry. // Set the details for entry.
inline void DetailsAtPut(int entry, PropertyDetails value); inline void DetailsAtPut(int entry, PropertyDetails value);
inline void SetHash(int hash);
inline int Hash();
static const int kKeyIndex = 0; static const int kKeyIndex = 0;
static const int kValueIndex = 1; static const int kValueIndex = 1;
static const int kPropertyDetailsIndex = 2; static const int kPropertyDetailsIndex = 2;
......
...@@ -1682,6 +1682,54 @@ TEST(SmallOrderedNameDictionaryDetailsAtAndDetailsAtPut) { ...@@ -1682,6 +1682,54 @@ TEST(SmallOrderedNameDictionaryDetailsAtAndDetailsAtPut) {
CHECK_EQ(other.AsSmi(), found.AsSmi()); CHECK_EQ(other.AsSmi(), found.AsSmi());
} }
TEST(SmallOrderedNameDictionarySetAndMigrateHash) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<SmallOrderedNameDictionary> dict =
factory->NewSmallOrderedNameDictionary();
Handle<String> value = isolate->factory()->InternalizeUtf8String("bar");
PropertyDetails details = PropertyDetails::Empty();
CHECK_EQ(PropertyArray::kNoHashSentinel, dict->Hash());
dict->SetHash(100);
CHECK_EQ(100, dict->Hash());
char buf[10];
for (int i = 0; i < SmallOrderedNameDictionary::kMaxCapacity; i++) {
CHECK_LT(0, snprintf(buf, sizeof(buf), "foo%d", i));
Handle<String> key = isolate->factory()->InternalizeUtf8String(buf);
dict = SmallOrderedNameDictionary::Add(isolate, dict, key, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(100, dict->Hash());
}
}
TEST(OrderedNameDictionarySetAndMigrateHash) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<OrderedNameDictionary> dict = factory->NewOrderedNameDictionary();
Handle<String> value = isolate->factory()->InternalizeUtf8String("bar");
PropertyDetails details = PropertyDetails::Empty();
CHECK_EQ(PropertyArray::kNoHashSentinel, dict->Hash());
dict->SetHash(100);
CHECK_EQ(100, dict->Hash());
char buf[10];
for (int i = 0; i <= 1024; i++) {
CHECK_LT(0, snprintf(buf, sizeof(buf), "foo%d", i));
Handle<String> key = isolate->factory()->InternalizeUtf8String(buf);
dict = OrderedNameDictionary::Add(isolate, dict, key, value, details);
Verify(isolate, dict);
CHECK_EQ(100, dict->Hash());
}
}
} // namespace test_orderedhashtable } // namespace test_orderedhashtable
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment