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 |