aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/objects/ordered-hash-table.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/objects/ordered-hash-table.h')
-rw-r--r--deps/v8/src/objects/ordered-hash-table.h534
1 files changed, 368 insertions, 166 deletions
diff --git a/deps/v8/src/objects/ordered-hash-table.h b/deps/v8/src/objects/ordered-hash-table.h
index 6c606efc75..6e938d53b2 100644
--- a/deps/v8/src/objects/ordered-hash-table.h
+++ b/deps/v8/src/objects/ordered-hash-table.h
@@ -8,6 +8,8 @@
#include "src/globals.h"
#include "src/objects/fixed-array.h"
#include "src/objects/js-objects.h"
+#include "src/objects/smi.h"
+#include "src/roots.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
@@ -15,45 +17,11 @@
namespace v8 {
namespace internal {
-// Non-templatized base class for {OrderedHashTable}s.
-// TODO(hash): Unify this with the HashTableBase above.
-class OrderedHashTableBase : public FixedArray {
- public:
- static const int kNotFound = -1;
- static const int kMinCapacity = 4;
-
- static const int kNumberOfElementsIndex = 0;
- // The next table is stored at the same index as the nof elements.
- static const int kNextTableIndex = kNumberOfElementsIndex;
- static const int kNumberOfDeletedElementsIndex = kNumberOfElementsIndex + 1;
- static const int kNumberOfBucketsIndex = kNumberOfDeletedElementsIndex + 1;
- static const int kHashTableStartIndex = kNumberOfBucketsIndex + 1;
- static const int kRemovedHolesIndex = kHashTableStartIndex;
-
- static constexpr const int kNumberOfElementsOffset =
- FixedArray::OffsetOfElementAt(kNumberOfElementsIndex);
- static constexpr const int kNextTableOffset =
- FixedArray::OffsetOfElementAt(kNextTableIndex);
- static constexpr const int kNumberOfDeletedElementsOffset =
- FixedArray::OffsetOfElementAt(kNumberOfDeletedElementsIndex);
- static constexpr const int kNumberOfBucketsOffset =
- FixedArray::OffsetOfElementAt(kNumberOfBucketsIndex);
- static constexpr const int kHashTableStartOffset =
- FixedArray::OffsetOfElementAt(kHashTableStartIndex);
-
- static const int kLoadFactor = 2;
-
- // NumberOfDeletedElements is set to kClearedTableSentinel when
- // the table is cleared, which allows iterator transitions to
- // optimize that case.
- static const int kClearedTableSentinel = -1;
-};
-
// OrderedHashTable is a HashTable with Object keys that preserves
// insertion order. There are Map and Set interfaces (OrderedHashMap
// and OrderedHashTable, below). It is meant to be used by JSMap/JSSet.
//
-// Only Object* keys are supported, with Object::SameValueZero() used as the
+// Only Object keys are supported, with Object::SameValueZero() used as the
// equality operator and Object::GetHash() for the hash function.
//
// Based on the "Deterministic Hash Table" as described by Jason Orendorff at
@@ -61,37 +29,38 @@ class OrderedHashTableBase : public FixedArray {
// Originally attributed to Tyler Close.
//
// Memory layout:
-// [0]: element count
-// [1]: deleted element count
-// [2]: bucket count
-// [3..(3 + NumberOfBuckets() - 1)]: "hash table", where each item is an
-// offset into the data table (see below) where the
-// first item in this bucket is stored.
-// [3 + NumberOfBuckets()..length]: "data table", an array of length
-// Capacity() * kEntrySize, where the first entrysize
-// items are handled by the derived class and the
-// item at kChainOffset is another entry into the
-// data table indicating the next entry in this hash
-// bucket.
+// [0] : Prefix
+// [kPrefixSize]: element count
+// [kPrefixSize + 1]: deleted element count
+// [kPrefixSize + 2]: bucket count
+// [kPrefixSize + 3..(3 + NumberOfBuckets() - 1)]: "hash table",
+// where each item is an offset into the
+// data table (see below) where the first
+// item in this bucket is stored.
+// [kPrefixSize + 3 + NumberOfBuckets()..length]: "data table", an
+// array of length Capacity() * kEntrySize,
+// where the first entrysize items are
+// handled by the derived class and the
+// item at kChainOffset is another entry
+// into the data table indicating the next
+// entry in this hash bucket.
//
// When we transition the table to a new version we obsolete it and reuse parts
// of the memory to store information how to transition an iterator to the new
// table:
//
// Memory layout for obsolete table:
-// [0]: bucket count
-// [1]: Next newer table
-// [2]: Number of removed holes or -1 when the table was cleared.
-// [3..(3 + NumberOfRemovedHoles() - 1)]: The indexes of the removed holes.
-// [3 + NumberOfRemovedHoles()..length]: Not used
-//
+// [0] : Prefix
+// [kPrefixSize + 0]: bucket count
+// [kPrefixSize + 1]: Next newer table
+// [kPrefixSize + 2]: Number of removed holes or -1 when the table was
+// cleared.
+// [kPrefixSize + 3..(3 + NumberOfRemovedHoles() - 1)]: The indexes
+// of the removed holes.
+// [kPrefixSize + 3 + NumberOfRemovedHoles()..length]: Not used
template <class Derived, int entrysize>
-class OrderedHashTable : public OrderedHashTableBase {
+class OrderedHashTable : public FixedArray {
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
// to add at least one new element.
static Handle<Derived> EnsureGrowable(Isolate* isolate,
@@ -106,18 +75,20 @@ class OrderedHashTable : public OrderedHashTableBase {
static Handle<Derived> Clear(Isolate* isolate, Handle<Derived> table);
// Returns true if the OrderedHashTable contains the key
- static bool HasKey(Isolate* isolate, Derived* table, Object* key);
+ static bool HasKey(Isolate* isolate, Derived table, Object key);
// Returns a true value if the OrderedHashTable contains the key and
// the key has been deleted. This does not shrink the table.
- static bool Delete(Isolate* isolate, Derived* table, Object* key);
+ static bool Delete(Isolate* isolate, Derived table, Object key);
+
+ int FindEntry(Isolate* isolate, Object key);
int NumberOfElements() const {
- return Smi::ToInt(get(kNumberOfElementsIndex));
+ return Smi::ToInt(get(NumberOfElementsIndex()));
}
int NumberOfDeletedElements() const {
- return Smi::ToInt(get(kNumberOfDeletedElementsIndex));
+ return Smi::ToInt(get(NumberOfDeletedElementsIndex()));
}
// Returns the number of contiguous entries in the data table, starting at 0,
@@ -126,99 +97,135 @@ class OrderedHashTable : public OrderedHashTableBase {
return NumberOfElements() + NumberOfDeletedElements();
}
- int NumberOfBuckets() const { return Smi::ToInt(get(kNumberOfBucketsIndex)); }
+ int NumberOfBuckets() const {
+ return Smi::ToInt(get(NumberOfBucketsIndex()));
+ }
// Returns an index into |this| for the given entry.
int EntryToIndex(int entry) {
- return kHashTableStartIndex + NumberOfBuckets() + (entry * kEntrySize);
+ return HashTableStartIndex() + NumberOfBuckets() + (entry * kEntrySize);
}
int HashToBucket(int hash) { return hash & (NumberOfBuckets() - 1); }
int HashToEntry(int hash) {
int bucket = HashToBucket(hash);
- Object* entry = this->get(kHashTableStartIndex + bucket);
+ Object entry = this->get(HashTableStartIndex() + bucket);
return Smi::ToInt(entry);
}
- int KeyToFirstEntry(Isolate* isolate, Object* key) {
- // This special cases for Smi, so that we avoid the HandleScope
- // creation below.
- if (key->IsSmi()) {
- uint32_t hash = ComputeUnseededHash(Smi::ToInt(key));
- return HashToEntry(hash & Smi::kMaxValue);
- }
- HandleScope scope(isolate);
- Object* hash = key->GetHash();
- // If the object does not have an identity hash, it was never used as a key
- if (hash->IsUndefined(isolate)) return kNotFound;
- return HashToEntry(Smi::ToInt(hash));
- }
-
- int FindEntry(Isolate* isolate, Object* key) {
- int entry = KeyToFirstEntry(isolate, key);
- // Walk the chain in the bucket to find the key.
- while (entry != kNotFound) {
- Object* candidate_key = KeyAt(entry);
- if (candidate_key->SameValueZero(key)) break;
- entry = NextChainEntry(entry);
- }
-
- return entry;
- }
-
int NextChainEntry(int entry) {
- Object* next_entry = get(EntryToIndex(entry) + kChainOffset);
+ Object next_entry = get(EntryToIndex(entry) + kChainOffset);
return Smi::ToInt(next_entry);
}
// use KeyAt(i)->IsTheHole(isolate) to determine if this is a deleted entry.
- Object* KeyAt(int entry) {
+ Object KeyAt(int entry) {
DCHECK_LT(entry, this->UsedCapacity());
return get(EntryToIndex(entry));
}
- bool IsObsolete() { return !get(kNextTableIndex)->IsSmi(); }
+ bool IsObsolete() { return !get(NextTableIndex())->IsSmi(); }
// The next newer table. This is only valid if the table is obsolete.
- Derived* NextTable() { return Derived::cast(get(kNextTableIndex)); }
+ Derived NextTable() { return Derived::cast(get(NextTableIndex())); }
// When the table is obsolete we store the indexes of the removed holes.
int RemovedIndexAt(int index) {
- return Smi::ToInt(get(kRemovedHolesIndex + 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 kChainOffset = entrysize;
- static const int kMaxCapacity =
- (FixedArray::kMaxLength - kHashTableStartIndex) /
- (1 + (kEntrySize * kLoadFactor));
+ static const int kNotFound = -1;
+ static const int kMinCapacity = 4;
+
+ static constexpr int PrefixIndex() { return 0; }
+
+ static constexpr int NumberOfElementsIndex() { return Derived::kPrefixSize; }
+
+ // The next table is stored at the same index as the nof elements.
+ static constexpr int NextTableIndex() { return NumberOfElementsIndex(); }
+
+ static constexpr int NumberOfDeletedElementsIndex() {
+ return NumberOfElementsIndex() + 1;
+ }
+
+ static constexpr int NumberOfBucketsIndex() {
+ return NumberOfDeletedElementsIndex() + 1;
+ }
+
+ static constexpr int HashTableStartIndex() {
+ return NumberOfBucketsIndex() + 1;
+ }
+
+ static constexpr int RemovedHolesIndex() { return HashTableStartIndex(); }
+
+ static constexpr int NumberOfElementsOffset() {
+ return FixedArray::OffsetOfElementAt(NumberOfElementsIndex());
+ }
+
+ static constexpr int NextTableOffset() {
+ return FixedArray::OffsetOfElementAt(NextTableIndex());
+ }
+
+ static constexpr int NumberOfDeletedElementsOffset() {
+ return FixedArray::OffsetOfElementAt(NumberOfDeletedElementsIndex());
+ }
+
+ static constexpr int NumberOfBucketsOffset() {
+ return FixedArray::OffsetOfElementAt(NumberOfBucketsIndex());
+ }
+
+ static constexpr int HashTableStartOffset() {
+ return FixedArray::OffsetOfElementAt(HashTableStartIndex());
+ }
+
+ static const int kLoadFactor = 2;
+
+ // NumberOfDeletedElements is set to kClearedTableSentinel when
+ // the table is cleared, which allows iterator transitions to
+ // optimize that case.
+ static const int kClearedTableSentinel = -1;
+ static constexpr int MaxCapacity() {
+ return (FixedArray::kMaxLength - HashTableStartIndex()) /
+ (1 + (kEntrySize * kLoadFactor));
+ }
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,
int new_capacity);
void SetNumberOfBuckets(int num) {
- set(kNumberOfBucketsIndex, Smi::FromInt(num));
+ set(NumberOfBucketsIndex(), Smi::FromInt(num));
}
void SetNumberOfElements(int num) {
- set(kNumberOfElementsIndex, Smi::FromInt(num));
+ set(NumberOfElementsIndex(), Smi::FromInt(num));
}
void SetNumberOfDeletedElements(int num) {
- set(kNumberOfDeletedElementsIndex, Smi::FromInt(num));
+ set(NumberOfDeletedElementsIndex(), Smi::FromInt(num));
}
// Returns the number elements that can fit into the allocated buffer.
int Capacity() { return NumberOfBuckets() * kLoadFactor; }
- void SetNextTable(Derived* next_table) { set(kNextTableIndex, next_table); }
+ void SetNextTable(Derived next_table) { set(NextTableIndex(), next_table); }
void SetRemovedIndexAt(int index, int removed_index) {
- return set(kRemovedHolesIndex + index, Smi::FromInt(removed_index));
+ return set(RemovedHolesIndex() + index, Smi::FromInt(removed_index));
}
+
+ OBJECT_CONSTRUCTORS(OrderedHashTable, FixedArray)
+
+ private:
+ friend class OrderedNameDictionaryHandler;
};
class OrderedHashSet : public OrderedHashTable<OrderedHashSet, 1> {
@@ -231,9 +238,17 @@ class OrderedHashSet : public OrderedHashTable<OrderedHashSet, 1> {
static Handle<FixedArray> ConvertToKeysArray(Isolate* isolate,
Handle<OrderedHashSet> table,
GetKeysConversion convert);
- static HeapObject* GetEmpty(ReadOnlyRoots ro_roots);
+ 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 inline RootIndex GetMapRootIndex();
static inline bool Is(Handle<HeapObject> table);
+ static const int kPrefixSize = 0;
+
+ OBJECT_CONSTRUCTORS(OrderedHashSet, OrderedHashTable<OrderedHashSet, 1>)
};
class OrderedHashMap : public OrderedHashTable<OrderedHashMap, 2> {
@@ -245,15 +260,26 @@ class OrderedHashMap : public OrderedHashTable<OrderedHashMap, 2> {
static Handle<OrderedHashMap> Add(Isolate* isolate,
Handle<OrderedHashMap> table,
Handle<Object> key, Handle<Object> value);
- Object* ValueAt(int entry);
- static Object* GetHash(Isolate* isolate, Object* key);
+ 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);
+
+ // This takes and returns raw Address values containing tagged Object
+ // pointers because it is called via ExternalReference.
+ static Address GetHash(Isolate* isolate, Address raw_key);
- static HeapObject* GetEmpty(ReadOnlyRoots ro_roots);
+ static HeapObject GetEmpty(ReadOnlyRoots ro_roots);
static inline RootIndex GetMapRootIndex();
static inline bool Is(Handle<HeapObject> table);
static const int kValueOffset = 1;
+ static const int kPrefixSize = 0;
+
+ OBJECT_CONSTRUCTORS(OrderedHashMap, OrderedHashTable<OrderedHashMap, 2>)
};
// This is similar to the OrderedHashTable, except for the memory
@@ -265,11 +291,20 @@ class OrderedHashMap : public OrderedHashTable<OrderedHashMap, 2> {
// that the DataTable entries start aligned. A bucket or chain value
// of 255 is used to denote an unknown entry.
//
-// Memory layout: [ Header ] [ Padding ] [ DataTable ] [ HashTable ] [ Chains ]
+// The prefix size is calculated as the kPrefixSize * kTaggedSize.
+//
+// Memory layout: [ Prefix ] [ Header ] [ Padding ] [ DataTable ] [ HashTable ]
+// [ Chains ]
//
// The index are represented as bytes, on a 64 bit machine with
// kEntrySize = 1, capacity = 4 and entries = 2:
//
+// [ 0 ] : Prefix
+//
+// Note: For the sake of brevity, the following start with index 0
+// but, they actually start from kPrefixSize * kTaggedSize to
+// account for the the prefix.
+//
// [ Header ] :
// [0] : Number of elements
// [1] : Number of deleted elements
@@ -314,15 +349,15 @@ class SmallOrderedHashTable : public HeapObject {
// Returns a true value if the table contains the key and
// the key has been deleted. This does not shrink the table.
- static bool Delete(Isolate* isolate, Derived* table, Object* key);
+ static bool Delete(Isolate* isolate, Derived table, Object key);
// Returns an SmallOrderedHashTable (possibly |table|) with enough
// space to add at least one new element. Returns empty handle if
// we've already reached MaxCapacity.
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);
+ static Handle<Derived> Shrink(Isolate* isolate, Handle<Derived> table);
// Iterates only fields in the DataTable.
class BodyDescriptor;
@@ -336,10 +371,10 @@ class SmallOrderedHashTable : public HeapObject {
int data_table_size = DataTableSizeFor(capacity);
int hash_table_size = capacity / kLoadFactor;
int chain_table_size = capacity;
- int total_size = kDataTableStartOffset + data_table_size + hash_table_size +
- chain_table_size;
+ int total_size = DataTableStartOffset() + data_table_size +
+ hash_table_size + chain_table_size;
- return RoundUp(total_size, kPointerSize);
+ return RoundUp(total_size, kTaggedSize);
}
// Returns the number elements that can fit into the allocated table.
@@ -353,20 +388,26 @@ class SmallOrderedHashTable : public HeapObject {
// Returns the number elements that are present in the table.
int NumberOfElements() const {
- int nof_elements = getByte(kNumberOfElementsOffset, 0);
+ int nof_elements = getByte(NumberOfElementsOffset(), 0);
DCHECK_LE(nof_elements, Capacity());
return nof_elements;
}
int NumberOfDeletedElements() const {
- int nof_deleted_elements = getByte(kNumberOfDeletedElementsOffset, 0);
+ int nof_deleted_elements = getByte(NumberOfDeletedElementsOffset(), 0);
DCHECK_LE(nof_deleted_elements, Capacity());
return nof_deleted_elements;
}
- int NumberOfBuckets() const { return getByte(kNumberOfBucketsOffset, 0); }
+ int NumberOfBuckets() const { return getByte(NumberOfBucketsOffset(), 0); }
+
+ Object KeyAt(int entry) const {
+ DCHECK_LT(entry, Capacity());
+ Offset entry_offset = GetDataEntryOffset(entry, Derived::kKeyIndex);
+ return READ_FIELD(this, entry_offset);
+ }
DECL_VERIFIER(SmallOrderedHashTable)
@@ -394,18 +435,22 @@ class SmallOrderedHashTable : public HeapObject {
static const int kGrowthHack = 256;
protected:
- void SetDataEntry(int entry, int relative_index, Object* value);
+ static Handle<Derived> Rehash(Isolate* isolate, Handle<Derived> table,
+ int new_capacity);
+
+ void SetDataEntry(int entry, int relative_index, Object value);
// TODO(gsathya): Calculate all the various possible values for this
// at compile time since capacity can only be 4 different values.
Offset GetBucketsStartOffset() const {
int capacity = Capacity();
int data_table_size = DataTableSizeFor(capacity);
- return kDataTableStartOffset + data_table_size;
+ return DataTableStartOffset() + data_table_size;
}
Address GetHashTableStartAddress(int capacity) const {
- return FIELD_ADDR(this, kDataTableStartOffset + DataTableSizeFor(capacity));
+ return FIELD_ADDR(this,
+ DataTableStartOffset() + DataTableSizeFor(capacity));
}
void SetFirstEntry(int bucket, byte value) {
@@ -427,7 +472,7 @@ class SmallOrderedHashTable : public HeapObject {
int data_table_size = DataTableSizeFor(capacity);
int hash_table_size = nof_buckets;
- return kDataTableStartOffset + data_table_size + hash_table_size;
+ return DataTableStartOffset() + data_table_size + hash_table_size;
}
void SetNextEntry(int entry, int next_entry) {
@@ -442,19 +487,13 @@ class SmallOrderedHashTable : public HeapObject {
return getByte(GetChainTableOffset(), entry);
}
- Object* GetDataEntry(int entry, int relative_index) {
+ Object GetDataEntry(int entry, int relative_index) {
DCHECK_LT(entry, Capacity());
DCHECK_LE(static_cast<unsigned>(relative_index), Derived::kEntrySize);
Offset entry_offset = GetDataEntryOffset(entry, relative_index);
return READ_FIELD(this, entry_offset);
}
- Object* KeyAt(int entry) const {
- DCHECK_LT(entry, Capacity());
- Offset entry_offset = GetDataEntryOffset(entry, Derived::kKeyIndex);
- return READ_FIELD(this, entry_offset);
- }
-
int HashToBucket(int hash) const { return hash & (NumberOfBuckets() - 1); }
int HashToFirstEntry(int hash) const {
@@ -464,63 +503,59 @@ class SmallOrderedHashTable : public HeapObject {
return entry;
}
- void SetNumberOfBuckets(int num) { setByte(kNumberOfBucketsOffset, 0, num); }
+ void SetNumberOfBuckets(int num) { setByte(NumberOfBucketsOffset(), 0, num); }
void SetNumberOfElements(int num) {
DCHECK_LE(static_cast<unsigned>(num), Capacity());
- setByte(kNumberOfElementsOffset, 0, num);
+ setByte(NumberOfElementsOffset(), 0, num);
}
void SetNumberOfDeletedElements(int num) {
DCHECK_LE(static_cast<unsigned>(num), Capacity());
- setByte(kNumberOfDeletedElementsOffset, 0, num);
+ setByte(NumberOfDeletedElementsOffset(), 0, num);
}
- int FindEntry(Isolate* isolate, Object* key) {
- DisallowHeapAllocation no_gc;
- Object* hash = key->GetHash();
+ static constexpr Offset PrefixOffset() { return kHeaderSize; }
- if (hash->IsUndefined(isolate)) return kNotFound;
- int entry = HashToFirstEntry(Smi::ToInt(hash));
+ static constexpr Offset NumberOfElementsOffset() {
+ return PrefixOffset() + (Derived::kPrefixSize * kTaggedSize);
+ }
- // Walk the chain in the bucket to find the key.
- while (entry != kNotFound) {
- Object* candidate_key = KeyAt(entry);
- if (candidate_key->SameValueZero(key)) return entry;
- entry = GetNextEntry(entry);
- }
- return kNotFound;
+ static constexpr Offset NumberOfDeletedElementsOffset() {
+ return NumberOfElementsOffset() + kOneByteSize;
}
- static const Offset kNumberOfElementsOffset = kHeaderSize;
- static const Offset kNumberOfDeletedElementsOffset =
- kNumberOfElementsOffset + kOneByteSize;
- static const Offset kNumberOfBucketsOffset =
- kNumberOfDeletedElementsOffset + kOneByteSize;
- static const constexpr Offset kDataTableStartOffset =
- RoundUp<kPointerSize>(kNumberOfBucketsOffset);
+ static constexpr Offset NumberOfBucketsOffset() {
+ return NumberOfDeletedElementsOffset() + kOneByteSize;
+ }
+
+ static constexpr Offset DataTableStartOffset() {
+ return RoundUp<kTaggedSize>(NumberOfBucketsOffset());
+ }
static constexpr int DataTableSizeFor(int capacity) {
- return capacity * Derived::kEntrySize * kPointerSize;
+ return capacity * Derived::kEntrySize * kTaggedSize;
}
// This is used for accessing the non |DataTable| part of the
// structure.
byte getByte(Offset offset, ByteIndex index) const {
- DCHECK(offset < kDataTableStartOffset || offset >= GetBucketsStartOffset());
+ DCHECK(offset < DataTableStartOffset() ||
+ offset >= GetBucketsStartOffset());
return READ_BYTE_FIELD(this, offset + (index * kOneByteSize));
}
void setByte(Offset offset, ByteIndex index, byte value) {
- DCHECK(offset < kDataTableStartOffset || offset >= GetBucketsStartOffset());
+ DCHECK(offset < DataTableStartOffset() ||
+ offset >= GetBucketsStartOffset());
WRITE_BYTE_FIELD(this, offset + (index * kOneByteSize), value);
}
Offset GetDataEntryOffset(int entry, int relative_index) const {
DCHECK_LT(entry, Capacity());
- int offset_in_datatable = entry * Derived::kEntrySize * kPointerSize;
- int offset_in_entry = relative_index * kPointerSize;
- return kDataTableStartOffset + offset_in_datatable + offset_in_entry;
+ int offset_in_datatable = entry * Derived::kEntrySize * kTaggedSize;
+ int offset_in_entry = relative_index * kTaggedSize;
+ return DataTableStartOffset() + offset_in_datatable + offset_in_entry;
}
int UsedCapacity() const {
@@ -533,7 +568,10 @@ class SmallOrderedHashTable : public HeapObject {
private:
friend class OrderedHashMapHandler;
friend class OrderedHashSetHandler;
+ friend class OrderedNameDictionaryHandler;
friend class CodeStubAssembler;
+
+ OBJECT_CONSTRUCTORS(SmallOrderedHashTable, HeapObject)
};
class SmallOrderedHashSet : public SmallOrderedHashTable<SmallOrderedHashSet> {
@@ -541,9 +579,11 @@ class SmallOrderedHashSet : public SmallOrderedHashTable<SmallOrderedHashSet> {
DECL_CAST(SmallOrderedHashSet)
DECL_PRINTER(SmallOrderedHashSet)
+ DECL_VERIFIER(SmallOrderedHashSet)
static const int kKeyIndex = 0;
static const int kEntrySize = 1;
+ static const int kPrefixSize = 0;
// Adds |value| to |table|, if the capacity isn't enough, a new
// table is created. The original |table| is returned if there is
@@ -553,6 +593,11 @@ class SmallOrderedHashSet : public SmallOrderedHashTable<SmallOrderedHashSet> {
Handle<Object> key);
static inline bool Is(Handle<HeapObject> table);
static inline RootIndex GetMapRootIndex();
+ static Handle<SmallOrderedHashSet> Rehash(Isolate* isolate,
+ Handle<SmallOrderedHashSet> table,
+ int new_capacity);
+ OBJECT_CONSTRUCTORS(SmallOrderedHashSet,
+ SmallOrderedHashTable<SmallOrderedHashSet>)
};
class SmallOrderedHashMap : public SmallOrderedHashTable<SmallOrderedHashMap> {
@@ -560,10 +605,12 @@ class SmallOrderedHashMap : public SmallOrderedHashTable<SmallOrderedHashMap> {
DECL_CAST(SmallOrderedHashMap)
DECL_PRINTER(SmallOrderedHashMap)
+ DECL_VERIFIER(SmallOrderedHashMap)
static const int kKeyIndex = 0;
static const int kValueIndex = 1;
static const int kEntrySize = 2;
+ static const int kPrefixSize = 0;
// Adds |value| to |table|, if the capacity isn't enough, a new
// table is created. The original |table| is returned if there is
@@ -574,6 +621,13 @@ class SmallOrderedHashMap : public SmallOrderedHashTable<SmallOrderedHashMap> {
Handle<Object> value);
static inline bool Is(Handle<HeapObject> table);
static inline RootIndex GetMapRootIndex();
+
+ static Handle<SmallOrderedHashMap> Rehash(Isolate* isolate,
+ Handle<SmallOrderedHashMap> table,
+ int new_capacity);
+
+ OBJECT_CONSTRUCTORS(SmallOrderedHashMap,
+ SmallOrderedHashTable<SmallOrderedHashMap>)
};
// TODO(gsathya): Rename this to OrderedHashTable, after we rename
@@ -613,6 +667,149 @@ class OrderedHashSetHandler
Isolate* isolate, Handle<SmallOrderedHashSet> table);
};
+class OrderedNameDictionary
+ : public OrderedHashTable<OrderedNameDictionary, 3> {
+ public:
+ DECL_CAST(OrderedNameDictionary)
+
+ static Handle<OrderedNameDictionary> Add(Isolate* isolate,
+ Handle<OrderedNameDictionary> table,
+ Handle<Name> key,
+ Handle<Object> value,
+ PropertyDetails details);
+
+ void SetEntry(Isolate* isolate, int entry, Object key, Object value,
+ PropertyDetails details);
+
+ static Handle<OrderedNameDictionary> DeleteEntry(
+ Isolate* isolate, Handle<OrderedNameDictionary> table, int entry);
+
+ 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.
+ inline Object ValueAt(int entry);
+
+ // Set the value for entry.
+ inline void ValueAtPut(int entry, Object value);
+
+ // Returns the property details for the property at entry.
+ inline PropertyDetails DetailsAt(int entry);
+
+ // Set the details for entry.
+ inline void DetailsAtPut(int entry, PropertyDetails value);
+
+ inline void SetHash(int hash);
+ inline int Hash();
+
+ static HeapObject GetEmpty(ReadOnlyRoots ro_roots);
+ static inline RootIndex GetMapRootIndex();
+
+ static const int kValueOffset = 1;
+ static const int kPropertyDetailsOffset = 2;
+ static const int kPrefixSize = 1;
+
+ OBJECT_CONSTRUCTORS(OrderedNameDictionary,
+ OrderedHashTable<OrderedNameDictionary, 3>)
+};
+
+class OrderedNameDictionaryHandler
+ : public OrderedHashTableHandler<SmallOrderedNameDictionary,
+ OrderedNameDictionary> {
+ public:
+ static Handle<HeapObject> Add(Isolate* isolate, Handle<HeapObject> table,
+ Handle<Name> key, Handle<Object> value,
+ PropertyDetails details);
+ static Handle<HeapObject> Shrink(Isolate* isolate, Handle<HeapObject> table);
+
+ static Handle<HeapObject> DeleteEntry(Isolate* isolate,
+ Handle<HeapObject> table, int entry);
+ static int FindEntry(Isolate* isolate, HeapObject table, Name key);
+ static void SetEntry(Isolate* isolate, HeapObject table, int entry,
+ Object key, Object value, PropertyDetails details);
+
+ // Returns the value for entry.
+ static Object ValueAt(HeapObject table, int entry);
+
+ // Set the value for entry.
+ static void ValueAtPut(HeapObject table, int entry, Object value);
+
+ // Returns the property details for the property at entry.
+ static PropertyDetails DetailsAt(HeapObject table, int entry);
+
+ // Set the details for entry.
+ static void DetailsAtPut(HeapObject table, int entry, PropertyDetails value);
+
+ static Name KeyAt(HeapObject table, int entry);
+
+ static void SetHash(HeapObject table, int hash);
+ static int Hash(HeapObject table);
+
+ static int NumberOfElements(HeapObject table);
+ static int Capacity(HeapObject table);
+
+ static const int kNotFound = -1;
+
+ protected:
+ static Handle<OrderedNameDictionary> AdjustRepresentation(
+ Isolate* isolate, Handle<SmallOrderedNameDictionary> table);
+};
+
+class SmallOrderedNameDictionary
+ : public SmallOrderedHashTable<SmallOrderedNameDictionary> {
+ public:
+ DECL_CAST(SmallOrderedNameDictionary)
+
+ DECL_PRINTER(SmallOrderedNameDictionary)
+ DECL_VERIFIER(SmallOrderedNameDictionary)
+
+ // Returns the value for entry.
+ inline Object ValueAt(int entry);
+
+ static Handle<SmallOrderedNameDictionary> Rehash(
+ Isolate* isolate, Handle<SmallOrderedNameDictionary> table,
+ int new_capacity);
+
+ static Handle<SmallOrderedNameDictionary> DeleteEntry(
+ Isolate* isolate, Handle<SmallOrderedNameDictionary> table, int entry);
+
+ // Set the value for entry.
+ inline void ValueAtPut(int entry, Object value);
+
+ // Returns the property details for the property at entry.
+ inline PropertyDetails DetailsAt(int entry);
+
+ // Set the details for entry.
+ inline void DetailsAtPut(int entry, PropertyDetails value);
+
+ inline void SetHash(int hash);
+ inline int Hash();
+
+ static const int kKeyIndex = 0;
+ static const int kValueIndex = 1;
+ static const int kPropertyDetailsIndex = 2;
+ static const int kEntrySize = 3;
+ static const int kPrefixSize = 1;
+
+ // Adds |value| to |table|, if the capacity isn't enough, a new
+ // table is created. The original |table| is returned if there is
+ // capacity to store |value| otherwise the new table is returned.
+ static MaybeHandle<SmallOrderedNameDictionary> Add(
+ Isolate* isolate, Handle<SmallOrderedNameDictionary> table,
+ Handle<Name> key, Handle<Object> value, PropertyDetails details);
+
+ void SetEntry(Isolate* isolate, int entry, Object key, Object value,
+ PropertyDetails details);
+
+ static inline RootIndex GetMapRootIndex();
+
+ OBJECT_CONSTRUCTORS(SmallOrderedNameDictionary,
+ SmallOrderedHashTable<SmallOrderedNameDictionary>)
+};
+
class JSCollectionIterator : public JSObject {
public:
// [table]: the backing hash table mapping keys to values.
@@ -621,15 +818,20 @@ class JSCollectionIterator : public JSObject {
// [index]: The index into the data table.
DECL_ACCESSORS(index, Object)
- // Dispatched behavior.
- DECL_PRINTER(JSCollectionIterator)
+ void JSCollectionIteratorPrint(std::ostream& os, const char* name);
- static const int kTableOffset = JSObject::kHeaderSize;
- static const int kIndexOffset = kTableOffset + kPointerSize;
- static const int kSize = kIndexOffset + kPointerSize;
+// Layout description.
+#define JS_COLLECTION_ITERATOR_FIELDS(V) \
+ V(kTableOffset, kTaggedSize) \
+ V(kIndexOffset, kTaggedSize) \
+ /* Header size. */ \
+ V(kSize, 0)
- private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(JSCollectionIterator);
+ DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
+ JS_COLLECTION_ITERATOR_FIELDS)
+#undef JS_COLLECTION_ITERATOR_FIELDS
+
+ OBJECT_CONSTRUCTORS(JSCollectionIterator, JSObject);
};
// OrderedHashTableIterator is an iterator that iterates over the keys and
@@ -656,14 +858,14 @@ class OrderedHashTableIterator : public JSCollectionIterator {
// Returns the current key of the iterator. This should only be called when
// |HasMore| returns true.
- inline Object* CurrentKey();
+ inline Object CurrentKey();
private:
// Transitions the iterator to the non obsolete backing store. This is a NOP
// if the [table] is not obsolete.
void Transition();
- DISALLOW_IMPLICIT_CONSTRUCTORS(OrderedHashTableIterator);
+ OBJECT_CONSTRUCTORS(OrderedHashTableIterator, JSCollectionIterator);
};
} // namespace internal