| Index: src/objects.h
|
| diff --git a/src/objects.h b/src/objects.h
|
| index d642e1e7da88b4f57bf49f79b485031f771a1ef3..910c25200ee3ec808f632a107078702138ea5d76 100644
|
| --- a/src/objects.h
|
| +++ b/src/objects.h
|
| @@ -4153,16 +4153,27 @@ class ObjectHashTable: public HashTable<ObjectHashTable,
|
| // [0]: bucket count
|
| // [1]: element count
|
| // [2]: deleted element count
|
| -// [3]: live iterators (doubly-linked list)
|
| -// [4..(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.
|
| -// [4 + NumberOfBuckets()..length]: "data table", an array of length
|
| +// [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.
|
| +//
|
| +// 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
|
| +//
|
| template<class Derived, class Iterator, int entrysize>
|
| class OrderedHashTable: public FixedArray {
|
| public:
|
| @@ -4199,10 +4210,6 @@ class OrderedHashTable: public FixedArray {
|
| return Smi::cast(get(kNumberOfBucketsIndex))->value();
|
| }
|
|
|
| - Object* iterators() { return get(kIteratorsIndex); }
|
| -
|
| - void set_iterators(Object* value) { set(kIteratorsIndex, value); }
|
| -
|
| // Returns the index into the data table where the new entry
|
| // should be placed. The table is assumed to have enough space
|
| // for a new entry.
|
| @@ -4219,6 +4226,20 @@ class OrderedHashTable: public FixedArray {
|
|
|
| Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
|
|
|
| + bool IsObsolete() {
|
| + return !get(kNextTableIndex)->IsSmi();
|
| + }
|
| +
|
| + // The next newer table. This is only valid if the table is obsolete.
|
| + Derived* NextTable() {
|
| + return Derived::cast(get(kNextTableIndex));
|
| + }
|
| +
|
| + // When the table is obsolete we store the indexes of the removed holes.
|
| + int RemovedIndexAt(int index) {
|
| + return Smi::cast(get(kRemovedHolesIndex + index))->value();
|
| + }
|
| +
|
| static const int kNotFound = -1;
|
| static const int kMinCapacity = 4;
|
|
|
| @@ -4255,11 +4276,21 @@ class OrderedHashTable: public FixedArray {
|
| return Smi::cast(get(kHashTableStartIndex + bucket))->value();
|
| }
|
|
|
| + void SetNextTable(Derived* next_table) {
|
| + set(kNextTableIndex, next_table);
|
| + }
|
| +
|
| + void SetRemovedIndexAt(int index, int removed_index) {
|
| + return set(kRemovedHolesIndex + index, Smi::FromInt(removed_index));
|
| + }
|
| +
|
| static const int kNumberOfBucketsIndex = 0;
|
| static const int kNumberOfElementsIndex = kNumberOfBucketsIndex + 1;
|
| static const int kNumberOfDeletedElementsIndex = kNumberOfElementsIndex + 1;
|
| - static const int kIteratorsIndex = kNumberOfDeletedElementsIndex + 1;
|
| - static const int kHashTableStartIndex = kIteratorsIndex + 1;
|
| + static const int kHashTableStartIndex = kNumberOfDeletedElementsIndex + 1;
|
| +
|
| + static const int kNextTableIndex = kNumberOfElementsIndex;
|
| + static const int kRemovedHolesIndex = kHashTableStartIndex;
|
|
|
| static const int kEntrySize = entrysize + 1;
|
| static const int kChainOffset = entrysize;
|
| @@ -9956,17 +9987,15 @@ class JSMap: public JSObject {
|
| // OrderedHashTableIterator is an iterator that iterates over the keys and
|
| // values of an OrderedHashTable.
|
| //
|
| -// The hash table has a reference to the iterator and the iterators themselves
|
| -// have references to the [next_iterator] and [previous_iterator], thus creating
|
| -// a double linked list.
|
| +// The iterator has a reference to the underlying OrderedHashTable data,
|
| +// [table], as well as the current [index] the iterator is at.
|
| //
|
| -// When the hash table changes the iterators are called to update their [index]
|
| -// and [count]. The hash table calls [EntryRemoved], [TableCompacted] as well
|
| -// as [TableCleared].
|
| +// When the OrderedHashTable is rehashed it adds a reference from the old table
|
| +// to the new table as well as storing enough data about the changes so that the
|
| +// iterator [index] can be adjusted accordingly.
|
| //
|
| -// When an iterator is done it closes itself. It removes itself from the double
|
| -// linked list and it sets its [table] to undefined, no longer keeping the
|
| -// [table] alive.
|
| +// When the [Next] result from the iterator is requested, the iterator checks if
|
| +// there is a newer table that it needs to transition to.
|
| template<class Derived, class TableType>
|
| class OrderedHashTableIterator: public JSObject {
|
| public:
|
| @@ -9976,29 +10005,17 @@ class OrderedHashTableIterator: public JSObject {
|
| // [index]: The index into the data table.
|
| DECL_ACCESSORS(index, Smi)
|
|
|
| - // [count]: The logical index into the data table, ignoring the holes.
|
| - DECL_ACCESSORS(count, Smi)
|
| -
|
| // [kind]: The kind of iteration this is. One of the [Kind] enum values.
|
| DECL_ACCESSORS(kind, Smi)
|
|
|
| - // [next_iterator]: Used as a double linked list for the live iterators.
|
| - DECL_ACCESSORS(next_iterator, Object)
|
| -
|
| - // [previous_iterator]: Used as a double linked list for the live iterators.
|
| - DECL_ACCESSORS(previous_iterator, Object)
|
| -
|
| #ifdef OBJECT_PRINT
|
| void OrderedHashTableIteratorPrint(FILE* out);
|
| #endif
|
|
|
| static const int kTableOffset = JSObject::kHeaderSize;
|
| static const int kIndexOffset = kTableOffset + kPointerSize;
|
| - static const int kCountOffset = kIndexOffset + kPointerSize;
|
| - static const int kKindOffset = kCountOffset + kPointerSize;
|
| - static const int kNextIteratorOffset = kKindOffset + kPointerSize;
|
| - static const int kPreviousIteratorOffset = kNextIteratorOffset + kPointerSize;
|
| - static const int kSize = kPreviousIteratorOffset + kPointerSize;
|
| + static const int kKindOffset = kIndexOffset + kPointerSize;
|
| + static const int kSize = kKindOffset + kPointerSize;
|
|
|
| enum Kind {
|
| kKindKeys = 1,
|
| @@ -10006,25 +10023,6 @@ class OrderedHashTableIterator: public JSObject {
|
| kKindEntries = 3
|
| };
|
|
|
| - // Called by the underlying [table] when an entry is removed.
|
| - void EntryRemoved(int index);
|
| -
|
| - // Called by the underlying [table] when it is compacted/rehashed.
|
| - void TableCompacted() {
|
| - // All holes have been removed so index is now same as count.
|
| - set_index(count());
|
| - }
|
| -
|
| - // Called by the underlying [table] when it is cleared.
|
| - void TableCleared() {
|
| - set_index(Smi::FromInt(0));
|
| - set_count(Smi::FromInt(0));
|
| - }
|
| -
|
| - // Removes the iterator from the double linked list and removes its reference
|
| - // back to the [table].
|
| - void Close();
|
| -
|
| // Returns an iterator result object: {value: any, done: boolean} and moves
|
| // the index to the next valid entry. Closes the iterator if moving past the
|
| // end.
|
| @@ -10035,16 +10033,9 @@ class OrderedHashTableIterator: public JSObject {
|
| Handle<Map> map, Handle<TableType> table, int kind);
|
|
|
| private:
|
| - // Ensures [index] is not pointing to a hole.
|
| - void Seek();
|
| -
|
| - // Moves [index] to next valid entry. Closes the iterator if moving past the
|
| - // end.
|
| - void MoveNext();
|
| -
|
| - bool Closed() {
|
| - return table()->IsUndefined();
|
| - }
|
| + // Transitions the iterator to the non obsolote backing store. This is a NOP
|
| + // if the [table] is not obsolete.
|
| + void Transition();
|
|
|
| DISALLOW_IMPLICIT_CONSTRUCTORS(OrderedHashTableIterator);
|
| };
|
| @@ -10066,7 +10057,8 @@ class JSSetIterator: public OrderedHashTableIterator<JSSetIterator,
|
| static inline JSSetIterator* cast(Object* obj);
|
|
|
| static Handle<Object> ValueForKind(
|
| - Handle<JSSetIterator> iterator, int entry_index);
|
| + Handle<JSSetIterator> iterator,
|
| + int entry_index);
|
|
|
| private:
|
| DISALLOW_IMPLICIT_CONSTRUCTORS(JSSetIterator);
|
| @@ -10089,7 +10081,8 @@ class JSMapIterator: public OrderedHashTableIterator<JSMapIterator,
|
| static inline JSMapIterator* cast(Object* obj);
|
|
|
| static Handle<Object> ValueForKind(
|
| - Handle<JSMapIterator> iterator, int entry_index);
|
| + Handle<JSMapIterator> iterator,
|
| + int entry_index);
|
|
|
| private:
|
| DISALLOW_IMPLICIT_CONSTRUCTORS(JSMapIterator);
|
|
|