| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_OBJECTS_H_ | 5 #ifndef V8_OBJECTS_H_ |
| 6 #define V8_OBJECTS_H_ | 6 #define V8_OBJECTS_H_ |
| 7 | 7 |
| 8 #include "allocation.h" | 8 #include "allocation.h" |
| 9 #include "assert-scope.h" | 9 #include "assert-scope.h" |
| 10 #include "builtins.h" | 10 #include "builtins.h" |
| (...skipping 4135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4146 // equality operator and Object::GetHash() for the hash function. | 4146 // equality operator and Object::GetHash() for the hash function. |
| 4147 // | 4147 // |
| 4148 // Based on the "Deterministic Hash Table" as described by Jason Orendorff at | 4148 // Based on the "Deterministic Hash Table" as described by Jason Orendorff at |
| 4149 // https://wiki.mozilla.org/User:Jorend/Deterministic_hash_tables | 4149 // https://wiki.mozilla.org/User:Jorend/Deterministic_hash_tables |
| 4150 // Originally attributed to Tyler Close. | 4150 // Originally attributed to Tyler Close. |
| 4151 // | 4151 // |
| 4152 // Memory layout: | 4152 // Memory layout: |
| 4153 // [0]: bucket count | 4153 // [0]: bucket count |
| 4154 // [1]: element count | 4154 // [1]: element count |
| 4155 // [2]: deleted element count | 4155 // [2]: deleted element count |
| 4156 // [3]: live iterators (doubly-linked list) | 4156 // [3]: "next table". When the table is rehashed the old table points to the |
| 4157 // [4..(NumberOfBuckets() - 1)]: "hash table", where each item is an offset | 4157 // next newer table. The changes between the two tables are described by |
| 4158 // [changes]. |
| 4159 // [4]: "changes". This contains the information needed to transition an |
| 4160 // iterator to the next table. |
| 4161 // [5..(NumberOfBuckets() - 1)]: "hash table", where each item is an offset |
| 4158 // into the data table (see below) where the | 4162 // into the data table (see below) where the |
| 4159 // first item in this bucket is stored. | 4163 // first item in this bucket is stored. |
| 4160 // [4 + NumberOfBuckets()..length]: "data table", an array of length | 4164 // [5 + NumberOfBuckets()..length]: "data table", an array of length |
| 4161 // Capacity() * kEntrySize, where the first entrysize | 4165 // Capacity() * kEntrySize, where the first entrysize |
| 4162 // items are handled by the derived class and the | 4166 // items are handled by the derived class and the |
| 4163 // item at kChainOffset is another entry into the | 4167 // item at kChainOffset is another entry into the |
| 4164 // data table indicating the next entry in this hash | 4168 // data table indicating the next entry in this hash |
| 4165 // bucket. | 4169 // bucket. |
| 4166 template<class Derived, class Iterator, int entrysize> | 4170 template<class Derived, class Iterator, int entrysize> |
| 4167 class OrderedHashTable: public FixedArray { | 4171 class OrderedHashTable: public FixedArray { |
| 4168 public: | 4172 public: |
| 4169 // Returns an OrderedHashTable with a capacity of at least |capacity|. | 4173 // Returns an OrderedHashTable with a capacity of at least |capacity|. |
| 4170 static Handle<Derived> Allocate( | 4174 static Handle<Derived> Allocate( |
| (...skipping 21 matching lines...) Expand all Loading... |
| 4192 int NumberOfDeletedElements() { | 4196 int NumberOfDeletedElements() { |
| 4193 return Smi::cast(get(kNumberOfDeletedElementsIndex))->value(); | 4197 return Smi::cast(get(kNumberOfDeletedElementsIndex))->value(); |
| 4194 } | 4198 } |
| 4195 | 4199 |
| 4196 int UsedCapacity() { return NumberOfElements() + NumberOfDeletedElements(); } | 4200 int UsedCapacity() { return NumberOfElements() + NumberOfDeletedElements(); } |
| 4197 | 4201 |
| 4198 int NumberOfBuckets() { | 4202 int NumberOfBuckets() { |
| 4199 return Smi::cast(get(kNumberOfBucketsIndex))->value(); | 4203 return Smi::cast(get(kNumberOfBucketsIndex))->value(); |
| 4200 } | 4204 } |
| 4201 | 4205 |
| 4202 Object* iterators() { return get(kIteratorsIndex); } | 4206 // The next newer table or |undefined| if no newer table exists. |
| 4207 Object* next_table() { |
| 4208 return get(kNextTableIndex); |
| 4209 } |
| 4203 | 4210 |
| 4204 void set_iterators(Object* value) { set(kIteratorsIndex, value); } | 4211 // The changes describing how to transition an iterator to the [next_table]. |
| 4212 // This is an array of the removed holes during a Rehash. In case the table |
| 4213 // was cleared, this stays as |undefined|. |
| 4214 Object* changes() { |
| 4215 return get(kChangesIndex); |
| 4216 } |
| 4205 | 4217 |
| 4206 // Returns the index into the data table where the new entry | 4218 // Returns the index into the data table where the new entry |
| 4207 // should be placed. The table is assumed to have enough space | 4219 // should be placed. The table is assumed to have enough space |
| 4208 // for a new entry. | 4220 // for a new entry. |
| 4209 int AddEntry(int hash); | 4221 int AddEntry(int hash); |
| 4210 | 4222 |
| 4211 // Removes the entry, and puts the_hole in entrysize pointers | 4223 // Removes the entry, and puts the_hole in entrysize pointers |
| 4212 // (leaving the hash table chain intact). | 4224 // (leaving the hash table chain intact). |
| 4213 void RemoveEntry(int entry); | 4225 void RemoveEntry(int entry); |
| 4214 | 4226 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4248 | 4260 |
| 4249 int HashToBucket(int hash) { | 4261 int HashToBucket(int hash) { |
| 4250 return hash & (NumberOfBuckets() - 1); | 4262 return hash & (NumberOfBuckets() - 1); |
| 4251 } | 4263 } |
| 4252 | 4264 |
| 4253 int HashToEntry(int hash) { | 4265 int HashToEntry(int hash) { |
| 4254 int bucket = HashToBucket(hash); | 4266 int bucket = HashToBucket(hash); |
| 4255 return Smi::cast(get(kHashTableStartIndex + bucket))->value(); | 4267 return Smi::cast(get(kHashTableStartIndex + bucket))->value(); |
| 4256 } | 4268 } |
| 4257 | 4269 |
| 4270 void set_next_table(Object* next_table) { |
| 4271 set(kNextTableIndex, next_table); |
| 4272 } |
| 4273 |
| 4274 void set_changes(Object* changes) { |
| 4275 set(kChangesIndex, changes); |
| 4276 } |
| 4277 |
| 4258 static const int kNumberOfBucketsIndex = 0; | 4278 static const int kNumberOfBucketsIndex = 0; |
| 4259 static const int kNumberOfElementsIndex = kNumberOfBucketsIndex + 1; | 4279 static const int kNumberOfElementsIndex = kNumberOfBucketsIndex + 1; |
| 4260 static const int kNumberOfDeletedElementsIndex = kNumberOfElementsIndex + 1; | 4280 static const int kNumberOfDeletedElementsIndex = kNumberOfElementsIndex + 1; |
| 4261 static const int kIteratorsIndex = kNumberOfDeletedElementsIndex + 1; | 4281 static const int kNextTableIndex = kNumberOfDeletedElementsIndex + 1; |
| 4262 static const int kHashTableStartIndex = kIteratorsIndex + 1; | 4282 static const int kChangesIndex = kNextTableIndex + 1; |
| 4283 static const int kHashTableStartIndex = kChangesIndex + 1; |
| 4263 | 4284 |
| 4264 static const int kEntrySize = entrysize + 1; | 4285 static const int kEntrySize = entrysize + 1; |
| 4265 static const int kChainOffset = entrysize; | 4286 static const int kChainOffset = entrysize; |
| 4266 | 4287 |
| 4267 static const int kLoadFactor = 2; | 4288 static const int kLoadFactor = 2; |
| 4268 static const int kMaxCapacity = | 4289 static const int kMaxCapacity = |
| 4269 (FixedArray::kMaxLength - kHashTableStartIndex) | 4290 (FixedArray::kMaxLength - kHashTableStartIndex) |
| 4270 / (1 + (kEntrySize * kLoadFactor)); | 4291 / (1 + (kEntrySize * kLoadFactor)); |
| 4271 }; | 4292 }; |
| 4272 | 4293 |
| (...skipping 5676 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9949 static const int kSize = kTableOffset + kPointerSize; | 9970 static const int kSize = kTableOffset + kPointerSize; |
| 9950 | 9971 |
| 9951 private: | 9972 private: |
| 9952 DISALLOW_IMPLICIT_CONSTRUCTORS(JSMap); | 9973 DISALLOW_IMPLICIT_CONSTRUCTORS(JSMap); |
| 9953 }; | 9974 }; |
| 9954 | 9975 |
| 9955 | 9976 |
| 9956 // OrderedHashTableIterator is an iterator that iterates over the keys and | 9977 // OrderedHashTableIterator is an iterator that iterates over the keys and |
| 9957 // values of an OrderedHashTable. | 9978 // values of an OrderedHashTable. |
| 9958 // | 9979 // |
| 9959 // The hash table has a reference to the iterator and the iterators themselves | 9980 // The iterator has a reference to the underlying OrderedHashTable data, |
| 9960 // have references to the [next_iterator] and [previous_iterator], thus creating | 9981 // [table], as well as the current [index] the iterator is at. |
| 9961 // a double linked list. | |
| 9962 // | 9982 // |
| 9963 // When the hash table changes the iterators are called to update their [index] | 9983 // When the OrderedHashTable is rehashed it adds a reference from the old table |
| 9964 // and [count]. The hash table calls [EntryRemoved], [TableCompacted] as well | 9984 // to the new table as well as storing enough data about the changes so that the |
| 9965 // as [TableCleared]. | 9985 // iterator [index] can be adjusted accordingly. |
| 9966 // | 9986 // |
| 9967 // When an iterator is done it closes itself. It removes itself from the double | 9987 // When the [Next] result from the iterator is requested, the iterator checks if |
| 9968 // linked list and it sets its [table] to undefined, no longer keeping the | 9988 // there is a newer table that it needs to transition to. |
| 9969 // [table] alive. | |
| 9970 template<class Derived, class TableType> | 9989 template<class Derived, class TableType> |
| 9971 class OrderedHashTableIterator: public JSObject { | 9990 class OrderedHashTableIterator: public JSObject { |
| 9972 public: | 9991 public: |
| 9973 // [table]: the backing hash table mapping keys to values. | 9992 // [table]: the backing hash table mapping keys to values. |
| 9974 DECL_ACCESSORS(table, Object) | 9993 DECL_ACCESSORS(table, Object) |
| 9975 | 9994 |
| 9976 // [index]: The index into the data table. | 9995 // [index]: The index into the data table. |
| 9977 DECL_ACCESSORS(index, Smi) | 9996 DECL_ACCESSORS(index, Smi) |
| 9978 | 9997 |
| 9979 // [count]: The logical index into the data table, ignoring the holes. | |
| 9980 DECL_ACCESSORS(count, Smi) | |
| 9981 | |
| 9982 // [kind]: The kind of iteration this is. One of the [Kind] enum values. | 9998 // [kind]: The kind of iteration this is. One of the [Kind] enum values. |
| 9983 DECL_ACCESSORS(kind, Smi) | 9999 DECL_ACCESSORS(kind, Smi) |
| 9984 | 10000 |
| 9985 // [next_iterator]: Used as a double linked list for the live iterators. | |
| 9986 DECL_ACCESSORS(next_iterator, Object) | |
| 9987 | |
| 9988 // [previous_iterator]: Used as a double linked list for the live iterators. | |
| 9989 DECL_ACCESSORS(previous_iterator, Object) | |
| 9990 | |
| 9991 #ifdef OBJECT_PRINT | 10001 #ifdef OBJECT_PRINT |
| 9992 void OrderedHashTableIteratorPrint(FILE* out); | 10002 void OrderedHashTableIteratorPrint(FILE* out); |
| 9993 #endif | 10003 #endif |
| 9994 | 10004 |
| 9995 static const int kTableOffset = JSObject::kHeaderSize; | 10005 static const int kTableOffset = JSObject::kHeaderSize; |
| 9996 static const int kIndexOffset = kTableOffset + kPointerSize; | 10006 static const int kIndexOffset = kTableOffset + kPointerSize; |
| 9997 static const int kCountOffset = kIndexOffset + kPointerSize; | 10007 static const int kKindOffset = kIndexOffset + kPointerSize; |
| 9998 static const int kKindOffset = kCountOffset + kPointerSize; | 10008 static const int kSize = kKindOffset + kPointerSize; |
| 9999 static const int kNextIteratorOffset = kKindOffset + kPointerSize; | |
| 10000 static const int kPreviousIteratorOffset = kNextIteratorOffset + kPointerSize; | |
| 10001 static const int kSize = kPreviousIteratorOffset + kPointerSize; | |
| 10002 | 10009 |
| 10003 enum Kind { | 10010 enum Kind { |
| 10004 kKindKeys = 1, | 10011 kKindKeys = 1, |
| 10005 kKindValues = 2, | 10012 kKindValues = 2, |
| 10006 kKindEntries = 3 | 10013 kKindEntries = 3 |
| 10007 }; | 10014 }; |
| 10008 | 10015 |
| 10009 // Called by the underlying [table] when an entry is removed. | |
| 10010 void EntryRemoved(int index); | |
| 10011 | |
| 10012 // Called by the underlying [table] when it is compacted/rehashed. | |
| 10013 void TableCompacted() { | |
| 10014 // All holes have been removed so index is now same as count. | |
| 10015 set_index(count()); | |
| 10016 } | |
| 10017 | |
| 10018 // Called by the underlying [table] when it is cleared. | |
| 10019 void TableCleared() { | |
| 10020 set_index(Smi::FromInt(0)); | |
| 10021 set_count(Smi::FromInt(0)); | |
| 10022 } | |
| 10023 | |
| 10024 // Removes the iterator from the double linked list and removes its reference | |
| 10025 // back to the [table]. | |
| 10026 void Close(); | |
| 10027 | |
| 10028 // Returns an iterator result object: {value: any, done: boolean} and moves | 10016 // Returns an iterator result object: {value: any, done: boolean} and moves |
| 10029 // the index to the next valid entry. Closes the iterator if moving past the | 10017 // the index to the next valid entry. Closes the iterator if moving past the |
| 10030 // end. | 10018 // end. |
| 10031 static Handle<JSObject> Next(Handle<Derived> iterator); | 10019 static Handle<JSObject> Next(Handle<Derived> iterator); |
| 10032 | 10020 |
| 10033 protected: | 10021 protected: |
| 10034 static Handle<Derived> CreateInternal( | 10022 static Handle<Derived> CreateInternal( |
| 10035 Handle<Map> map, Handle<TableType> table, int kind); | 10023 Handle<Map> map, Handle<TableType> table, int kind); |
| 10036 | 10024 |
| 10037 private: | 10025 private: |
| 10038 // Ensures [index] is not pointing to a hole. | 10026 void Transition(); |
| 10039 void Seek(); | |
| 10040 | |
| 10041 // Moves [index] to next valid entry. Closes the iterator if moving past the | |
| 10042 // end. | |
| 10043 void MoveNext(); | |
| 10044 | |
| 10045 bool Closed() { | |
| 10046 return table()->IsUndefined(); | |
| 10047 } | |
| 10048 | 10027 |
| 10049 DISALLOW_IMPLICIT_CONSTRUCTORS(OrderedHashTableIterator); | 10028 DISALLOW_IMPLICIT_CONSTRUCTORS(OrderedHashTableIterator); |
| 10050 }; | 10029 }; |
| 10051 | 10030 |
| 10052 | 10031 |
| 10053 class JSSetIterator: public OrderedHashTableIterator<JSSetIterator, | 10032 class JSSetIterator: public OrderedHashTableIterator<JSSetIterator, |
| 10054 OrderedHashSet> { | 10033 OrderedHashSet> { |
| 10055 public: | 10034 public: |
| 10056 // Creates a new iterator associated with [table]. | 10035 // Creates a new iterator associated with [table]. |
| 10057 // [kind] needs to be one of the OrderedHashTableIterator Kind enum values. | 10036 // [kind] needs to be one of the OrderedHashTableIterator Kind enum values. |
| 10058 static inline Handle<JSSetIterator> Create( | 10037 static inline Handle<JSSetIterator> Create( |
| 10059 Handle<OrderedHashSet> table, int kind); | 10038 Handle<OrderedHashSet> table, int kind); |
| 10060 | 10039 |
| 10061 // Dispatched behavior. | 10040 // Dispatched behavior. |
| 10062 DECLARE_PRINTER(JSSetIterator) | 10041 DECLARE_PRINTER(JSSetIterator) |
| 10063 DECLARE_VERIFIER(JSSetIterator) | 10042 DECLARE_VERIFIER(JSSetIterator) |
| 10064 | 10043 |
| 10065 // Casting. | 10044 // Casting. |
| 10066 static inline JSSetIterator* cast(Object* obj); | 10045 static inline JSSetIterator* cast(Object* obj); |
| 10067 | 10046 |
| 10068 static Handle<Object> ValueForKind( | 10047 static Handle<Object> ValueForKind( |
| 10069 Handle<JSSetIterator> iterator, int entry_index); | 10048 Handle<JSSetIterator> iterator, |
| 10049 int entry_index); |
| 10070 | 10050 |
| 10071 private: | 10051 private: |
| 10072 DISALLOW_IMPLICIT_CONSTRUCTORS(JSSetIterator); | 10052 DISALLOW_IMPLICIT_CONSTRUCTORS(JSSetIterator); |
| 10073 }; | 10053 }; |
| 10074 | 10054 |
| 10075 | 10055 |
| 10076 class JSMapIterator: public OrderedHashTableIterator<JSMapIterator, | 10056 class JSMapIterator: public OrderedHashTableIterator<JSMapIterator, |
| 10077 OrderedHashMap> { | 10057 OrderedHashMap> { |
| 10078 public: | 10058 public: |
| 10079 // Creates a new iterator associated with [table]. | 10059 // Creates a new iterator associated with [table]. |
| 10080 // [kind] needs to be one of the OrderedHashTableIterator Kind enum values. | 10060 // [kind] needs to be one of the OrderedHashTableIterator Kind enum values. |
| 10081 static inline Handle<JSMapIterator> Create( | 10061 static inline Handle<JSMapIterator> Create( |
| 10082 Handle<OrderedHashMap> table, int kind); | 10062 Handle<OrderedHashMap> table, int kind); |
| 10083 | 10063 |
| 10084 // Dispatched behavior. | 10064 // Dispatched behavior. |
| 10085 DECLARE_PRINTER(JSMapIterator) | 10065 DECLARE_PRINTER(JSMapIterator) |
| 10086 DECLARE_VERIFIER(JSMapIterator) | 10066 DECLARE_VERIFIER(JSMapIterator) |
| 10087 | 10067 |
| 10088 // Casting. | 10068 // Casting. |
| 10089 static inline JSMapIterator* cast(Object* obj); | 10069 static inline JSMapIterator* cast(Object* obj); |
| 10090 | 10070 |
| 10091 static Handle<Object> ValueForKind( | 10071 static Handle<Object> ValueForKind( |
| 10092 Handle<JSMapIterator> iterator, int entry_index); | 10072 Handle<JSMapIterator> iterator, |
| 10073 int entry_index); |
| 10093 | 10074 |
| 10094 private: | 10075 private: |
| 10095 DISALLOW_IMPLICIT_CONSTRUCTORS(JSMapIterator); | 10076 DISALLOW_IMPLICIT_CONSTRUCTORS(JSMapIterator); |
| 10096 }; | 10077 }; |
| 10097 | 10078 |
| 10098 | 10079 |
| 10099 // Base class for both JSWeakMap and JSWeakSet | 10080 // Base class for both JSWeakMap and JSWeakSet |
| 10100 class JSWeakCollection: public JSObject { | 10081 class JSWeakCollection: public JSObject { |
| 10101 public: | 10082 public: |
| 10102 // [table]: the backing hash table mapping keys to values. | 10083 // [table]: the backing hash table mapping keys to values. |
| (...skipping 1014 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11117 } else { | 11098 } else { |
| 11118 value &= ~(1 << bit_position); | 11099 value &= ~(1 << bit_position); |
| 11119 } | 11100 } |
| 11120 return value; | 11101 return value; |
| 11121 } | 11102 } |
| 11122 }; | 11103 }; |
| 11123 | 11104 |
| 11124 } } // namespace v8::internal | 11105 } } // namespace v8::internal |
| 11125 | 11106 |
| 11126 #endif // V8_OBJECTS_H_ | 11107 #endif // V8_OBJECTS_H_ |
| OLD | NEW |