Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(285)

Side by Side Diff: src/objects.h

Issue 289503002: ES6 Map/Set iterators/forEach improvements (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: git rebase to fix merge conflict Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/collection.js ('k') | src/objects.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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..(3 + NumberOfBuckets() - 1)]: "hash table", where each item is an
4157 // [4..(NumberOfBuckets() - 1)]: "hash table", where each item is an offset 4157 // offset into the data table (see below) where the
4158 // into the data table (see below) where the 4158 // first item in this bucket is stored.
4159 // first item in this bucket is stored. 4159 // [3 + NumberOfBuckets()..length]: "data table", an array of length
4160 // [4 + NumberOfBuckets()..length]: "data table", an array of length
4161 // Capacity() * kEntrySize, where the first entrysize 4160 // Capacity() * kEntrySize, where the first entrysize
4162 // items are handled by the derived class and the 4161 // items are handled by the derived class and the
4163 // item at kChainOffset is another entry into the 4162 // item at kChainOffset is another entry into the
4164 // data table indicating the next entry in this hash 4163 // data table indicating the next entry in this hash
4165 // bucket. 4164 // bucket.
4165 //
4166 // When we transition the table to a new version we obsolete it and reuse parts
4167 // of the memory to store information how to transition an iterator to the new
4168 // table:
4169 //
4170 // Memory layout for obsolete table:
4171 // [0]: bucket count
4172 // [1]: Next newer table
4173 // [2]: Number of removed holes or -1 when the table was cleared.
4174 // [3..(3 + NumberOfRemovedHoles() - 1)]: The indexes of the removed holes.
4175 // [3 + NumberOfRemovedHoles()..length]: Not used
4176 //
4166 template<class Derived, class Iterator, int entrysize> 4177 template<class Derived, class Iterator, int entrysize>
4167 class OrderedHashTable: public FixedArray { 4178 class OrderedHashTable: public FixedArray {
4168 public: 4179 public:
4169 // Returns an OrderedHashTable with a capacity of at least |capacity|. 4180 // Returns an OrderedHashTable with a capacity of at least |capacity|.
4170 static Handle<Derived> Allocate( 4181 static Handle<Derived> Allocate(
4171 Isolate* isolate, int capacity, PretenureFlag pretenure = NOT_TENURED); 4182 Isolate* isolate, int capacity, PretenureFlag pretenure = NOT_TENURED);
4172 4183
4173 // Returns an OrderedHashTable (possibly |table|) with enough space 4184 // Returns an OrderedHashTable (possibly |table|) with enough space
4174 // to add at least one new element. 4185 // to add at least one new element.
4175 static Handle<Derived> EnsureGrowable(Handle<Derived> table); 4186 static Handle<Derived> EnsureGrowable(Handle<Derived> table);
(...skipping 16 matching lines...) Expand all
4192 int NumberOfDeletedElements() { 4203 int NumberOfDeletedElements() {
4193 return Smi::cast(get(kNumberOfDeletedElementsIndex))->value(); 4204 return Smi::cast(get(kNumberOfDeletedElementsIndex))->value();
4194 } 4205 }
4195 4206
4196 int UsedCapacity() { return NumberOfElements() + NumberOfDeletedElements(); } 4207 int UsedCapacity() { return NumberOfElements() + NumberOfDeletedElements(); }
4197 4208
4198 int NumberOfBuckets() { 4209 int NumberOfBuckets() {
4199 return Smi::cast(get(kNumberOfBucketsIndex))->value(); 4210 return Smi::cast(get(kNumberOfBucketsIndex))->value();
4200 } 4211 }
4201 4212
4202 Object* iterators() { return get(kIteratorsIndex); }
4203
4204 void set_iterators(Object* value) { set(kIteratorsIndex, value); }
4205
4206 // Returns the index into the data table where the new entry 4213 // Returns the index into the data table where the new entry
4207 // should be placed. The table is assumed to have enough space 4214 // should be placed. The table is assumed to have enough space
4208 // for a new entry. 4215 // for a new entry.
4209 int AddEntry(int hash); 4216 int AddEntry(int hash);
4210 4217
4211 // Removes the entry, and puts the_hole in entrysize pointers 4218 // Removes the entry, and puts the_hole in entrysize pointers
4212 // (leaving the hash table chain intact). 4219 // (leaving the hash table chain intact).
4213 void RemoveEntry(int entry); 4220 void RemoveEntry(int entry);
4214 4221
4215 // Returns an index into |this| for the given entry. 4222 // Returns an index into |this| for the given entry.
4216 int EntryToIndex(int entry) { 4223 int EntryToIndex(int entry) {
4217 return kHashTableStartIndex + NumberOfBuckets() + (entry * kEntrySize); 4224 return kHashTableStartIndex + NumberOfBuckets() + (entry * kEntrySize);
4218 } 4225 }
4219 4226
4220 Object* KeyAt(int entry) { return get(EntryToIndex(entry)); } 4227 Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
4221 4228
4229 bool IsObsolete() {
4230 return !get(kNextTableIndex)->IsSmi();
4231 }
4232
4233 // The next newer table. This is only valid if the table is obsolete.
4234 Derived* NextTable() {
4235 return Derived::cast(get(kNextTableIndex));
4236 }
4237
4238 // When the table is obsolete we store the indexes of the removed holes.
4239 int RemovedIndexAt(int index) {
4240 return Smi::cast(get(kRemovedHolesIndex + index))->value();
4241 }
4242
4222 static const int kNotFound = -1; 4243 static const int kNotFound = -1;
4223 static const int kMinCapacity = 4; 4244 static const int kMinCapacity = 4;
4224 4245
4225 private: 4246 private:
4226 static Handle<Derived> Rehash(Handle<Derived> table, int new_capacity); 4247 static Handle<Derived> Rehash(Handle<Derived> table, int new_capacity);
4227 4248
4228 void SetNumberOfBuckets(int num) { 4249 void SetNumberOfBuckets(int num) {
4229 set(kNumberOfBucketsIndex, Smi::FromInt(num)); 4250 set(kNumberOfBucketsIndex, Smi::FromInt(num));
4230 } 4251 }
4231 4252
(...skipping 16 matching lines...) Expand all
4248 4269
4249 int HashToBucket(int hash) { 4270 int HashToBucket(int hash) {
4250 return hash & (NumberOfBuckets() - 1); 4271 return hash & (NumberOfBuckets() - 1);
4251 } 4272 }
4252 4273
4253 int HashToEntry(int hash) { 4274 int HashToEntry(int hash) {
4254 int bucket = HashToBucket(hash); 4275 int bucket = HashToBucket(hash);
4255 return Smi::cast(get(kHashTableStartIndex + bucket))->value(); 4276 return Smi::cast(get(kHashTableStartIndex + bucket))->value();
4256 } 4277 }
4257 4278
4279 void SetNextTable(Derived* next_table) {
4280 set(kNextTableIndex, next_table);
4281 }
4282
4283 void SetRemovedIndexAt(int index, int removed_index) {
4284 return set(kRemovedHolesIndex + index, Smi::FromInt(removed_index));
4285 }
4286
4258 static const int kNumberOfBucketsIndex = 0; 4287 static const int kNumberOfBucketsIndex = 0;
4259 static const int kNumberOfElementsIndex = kNumberOfBucketsIndex + 1; 4288 static const int kNumberOfElementsIndex = kNumberOfBucketsIndex + 1;
4260 static const int kNumberOfDeletedElementsIndex = kNumberOfElementsIndex + 1; 4289 static const int kNumberOfDeletedElementsIndex = kNumberOfElementsIndex + 1;
4261 static const int kIteratorsIndex = kNumberOfDeletedElementsIndex + 1; 4290 static const int kHashTableStartIndex = kNumberOfDeletedElementsIndex + 1;
4262 static const int kHashTableStartIndex = kIteratorsIndex + 1; 4291
4292 static const int kNextTableIndex = kNumberOfElementsIndex;
4293 static const int kRemovedHolesIndex = kHashTableStartIndex;
4263 4294
4264 static const int kEntrySize = entrysize + 1; 4295 static const int kEntrySize = entrysize + 1;
4265 static const int kChainOffset = entrysize; 4296 static const int kChainOffset = entrysize;
4266 4297
4267 static const int kLoadFactor = 2; 4298 static const int kLoadFactor = 2;
4268 static const int kMaxCapacity = 4299 static const int kMaxCapacity =
4269 (FixedArray::kMaxLength - kHashTableStartIndex) 4300 (FixedArray::kMaxLength - kHashTableStartIndex)
4270 / (1 + (kEntrySize * kLoadFactor)); 4301 / (1 + (kEntrySize * kLoadFactor));
4271 }; 4302 };
4272 4303
(...skipping 5676 matching lines...) Expand 10 before | Expand all | Expand 10 after
9949 static const int kSize = kTableOffset + kPointerSize; 9980 static const int kSize = kTableOffset + kPointerSize;
9950 9981
9951 private: 9982 private:
9952 DISALLOW_IMPLICIT_CONSTRUCTORS(JSMap); 9983 DISALLOW_IMPLICIT_CONSTRUCTORS(JSMap);
9953 }; 9984 };
9954 9985
9955 9986
9956 // OrderedHashTableIterator is an iterator that iterates over the keys and 9987 // OrderedHashTableIterator is an iterator that iterates over the keys and
9957 // values of an OrderedHashTable. 9988 // values of an OrderedHashTable.
9958 // 9989 //
9959 // The hash table has a reference to the iterator and the iterators themselves 9990 // The iterator has a reference to the underlying OrderedHashTable data,
9960 // have references to the [next_iterator] and [previous_iterator], thus creating 9991 // [table], as well as the current [index] the iterator is at.
9961 // a double linked list.
9962 // 9992 //
9963 // When the hash table changes the iterators are called to update their [index] 9993 // When the OrderedHashTable is rehashed it adds a reference from the old table
9964 // and [count]. The hash table calls [EntryRemoved], [TableCompacted] as well 9994 // to the new table as well as storing enough data about the changes so that the
9965 // as [TableCleared]. 9995 // iterator [index] can be adjusted accordingly.
9966 // 9996 //
9967 // When an iterator is done it closes itself. It removes itself from the double 9997 // 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 9998 // there is a newer table that it needs to transition to.
9969 // [table] alive.
9970 template<class Derived, class TableType> 9999 template<class Derived, class TableType>
9971 class OrderedHashTableIterator: public JSObject { 10000 class OrderedHashTableIterator: public JSObject {
9972 public: 10001 public:
9973 // [table]: the backing hash table mapping keys to values. 10002 // [table]: the backing hash table mapping keys to values.
9974 DECL_ACCESSORS(table, Object) 10003 DECL_ACCESSORS(table, Object)
9975 10004
9976 // [index]: The index into the data table. 10005 // [index]: The index into the data table.
9977 DECL_ACCESSORS(index, Smi) 10006 DECL_ACCESSORS(index, Smi)
9978 10007
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. 10008 // [kind]: The kind of iteration this is. One of the [Kind] enum values.
9983 DECL_ACCESSORS(kind, Smi) 10009 DECL_ACCESSORS(kind, Smi)
9984 10010
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 10011 #ifdef OBJECT_PRINT
9992 void OrderedHashTableIteratorPrint(FILE* out); 10012 void OrderedHashTableIteratorPrint(FILE* out);
9993 #endif 10013 #endif
9994 10014
9995 static const int kTableOffset = JSObject::kHeaderSize; 10015 static const int kTableOffset = JSObject::kHeaderSize;
9996 static const int kIndexOffset = kTableOffset + kPointerSize; 10016 static const int kIndexOffset = kTableOffset + kPointerSize;
9997 static const int kCountOffset = kIndexOffset + kPointerSize; 10017 static const int kKindOffset = kIndexOffset + kPointerSize;
9998 static const int kKindOffset = kCountOffset + kPointerSize; 10018 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 10019
10003 enum Kind { 10020 enum Kind {
10004 kKindKeys = 1, 10021 kKindKeys = 1,
10005 kKindValues = 2, 10022 kKindValues = 2,
10006 kKindEntries = 3 10023 kKindEntries = 3
10007 }; 10024 };
10008 10025
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 10026 // 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 10027 // the index to the next valid entry. Closes the iterator if moving past the
10030 // end. 10028 // end.
10031 static Handle<JSObject> Next(Handle<Derived> iterator); 10029 static Handle<JSObject> Next(Handle<Derived> iterator);
10032 10030
10033 protected: 10031 protected:
10034 static Handle<Derived> CreateInternal( 10032 static Handle<Derived> CreateInternal(
10035 Handle<Map> map, Handle<TableType> table, int kind); 10033 Handle<Map> map, Handle<TableType> table, int kind);
10036 10034
10037 private: 10035 private:
10038 // Ensures [index] is not pointing to a hole. 10036 // Transitions the iterator to the non obsolote backing store. This is a NOP
10039 void Seek(); 10037 // if the [table] is not obsolete.
10040 10038 void Transition();
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 10039
10049 DISALLOW_IMPLICIT_CONSTRUCTORS(OrderedHashTableIterator); 10040 DISALLOW_IMPLICIT_CONSTRUCTORS(OrderedHashTableIterator);
10050 }; 10041 };
10051 10042
10052 10043
10053 class JSSetIterator: public OrderedHashTableIterator<JSSetIterator, 10044 class JSSetIterator: public OrderedHashTableIterator<JSSetIterator,
10054 OrderedHashSet> { 10045 OrderedHashSet> {
10055 public: 10046 public:
10056 // Creates a new iterator associated with [table]. 10047 // Creates a new iterator associated with [table].
10057 // [kind] needs to be one of the OrderedHashTableIterator Kind enum values. 10048 // [kind] needs to be one of the OrderedHashTableIterator Kind enum values.
10058 static inline Handle<JSSetIterator> Create( 10049 static inline Handle<JSSetIterator> Create(
10059 Handle<OrderedHashSet> table, int kind); 10050 Handle<OrderedHashSet> table, int kind);
10060 10051
10061 // Dispatched behavior. 10052 // Dispatched behavior.
10062 DECLARE_PRINTER(JSSetIterator) 10053 DECLARE_PRINTER(JSSetIterator)
10063 DECLARE_VERIFIER(JSSetIterator) 10054 DECLARE_VERIFIER(JSSetIterator)
10064 10055
10065 // Casting. 10056 // Casting.
10066 static inline JSSetIterator* cast(Object* obj); 10057 static inline JSSetIterator* cast(Object* obj);
10067 10058
10068 static Handle<Object> ValueForKind( 10059 static Handle<Object> ValueForKind(
10069 Handle<JSSetIterator> iterator, int entry_index); 10060 Handle<JSSetIterator> iterator,
10061 int entry_index);
10070 10062
10071 private: 10063 private:
10072 DISALLOW_IMPLICIT_CONSTRUCTORS(JSSetIterator); 10064 DISALLOW_IMPLICIT_CONSTRUCTORS(JSSetIterator);
10073 }; 10065 };
10074 10066
10075 10067
10076 class JSMapIterator: public OrderedHashTableIterator<JSMapIterator, 10068 class JSMapIterator: public OrderedHashTableIterator<JSMapIterator,
10077 OrderedHashMap> { 10069 OrderedHashMap> {
10078 public: 10070 public:
10079 // Creates a new iterator associated with [table]. 10071 // Creates a new iterator associated with [table].
10080 // [kind] needs to be one of the OrderedHashTableIterator Kind enum values. 10072 // [kind] needs to be one of the OrderedHashTableIterator Kind enum values.
10081 static inline Handle<JSMapIterator> Create( 10073 static inline Handle<JSMapIterator> Create(
10082 Handle<OrderedHashMap> table, int kind); 10074 Handle<OrderedHashMap> table, int kind);
10083 10075
10084 // Dispatched behavior. 10076 // Dispatched behavior.
10085 DECLARE_PRINTER(JSMapIterator) 10077 DECLARE_PRINTER(JSMapIterator)
10086 DECLARE_VERIFIER(JSMapIterator) 10078 DECLARE_VERIFIER(JSMapIterator)
10087 10079
10088 // Casting. 10080 // Casting.
10089 static inline JSMapIterator* cast(Object* obj); 10081 static inline JSMapIterator* cast(Object* obj);
10090 10082
10091 static Handle<Object> ValueForKind( 10083 static Handle<Object> ValueForKind(
10092 Handle<JSMapIterator> iterator, int entry_index); 10084 Handle<JSMapIterator> iterator,
10085 int entry_index);
10093 10086
10094 private: 10087 private:
10095 DISALLOW_IMPLICIT_CONSTRUCTORS(JSMapIterator); 10088 DISALLOW_IMPLICIT_CONSTRUCTORS(JSMapIterator);
10096 }; 10089 };
10097 10090
10098 10091
10099 // Base class for both JSWeakMap and JSWeakSet 10092 // Base class for both JSWeakMap and JSWeakSet
10100 class JSWeakCollection: public JSObject { 10093 class JSWeakCollection: public JSObject {
10101 public: 10094 public:
10102 // [table]: the backing hash table mapping keys to values. 10095 // [table]: the backing hash table mapping keys to values.
(...skipping 1014 matching lines...) Expand 10 before | Expand all | Expand 10 after
11117 } else { 11110 } else {
11118 value &= ~(1 << bit_position); 11111 value &= ~(1 << bit_position);
11119 } 11112 }
11120 return value; 11113 return value;
11121 } 11114 }
11122 }; 11115 };
11123 11116
11124 } } // namespace v8::internal 11117 } } // namespace v8::internal
11125 11118
11126 #endif // V8_OBJECTS_H_ 11119 #endif // V8_OBJECTS_H_
OLDNEW
« no previous file with comments | « src/collection.js ('k') | src/objects.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698