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); |