| Index: src/objects.h
|
| diff --git a/src/objects.h b/src/objects.h
|
| index 5bfa60423a0e0d3c355be1d4535729baa57fc1b3..081237840774039f245e9e447bd9b3b854782b48 100644
|
| --- a/src/objects.h
|
| +++ b/src/objects.h
|
| @@ -854,6 +854,7 @@ class FixedArrayBase;
|
| class FunctionLiteral;
|
| class GlobalObject;
|
| class JSBuiltinsObject;
|
| +class KeyAccumulator;
|
| class LayoutDescriptor;
|
| class LiteralsArray;
|
| class LookupIterator;
|
| @@ -1089,6 +1090,8 @@ class Object {
|
| // 1 all refer to the same property, so this helper will return true.
|
| inline bool KeyEquals(Object* other);
|
|
|
| + inline bool FilterKey(PropertyAttributes filter);
|
| +
|
| Handle<HeapType> OptimalType(Isolate* isolate, Representation representation);
|
|
|
| inline static Handle<Object> NewStorageFor(Isolate* isolate,
|
| @@ -1791,6 +1794,9 @@ enum AccessorComponent {
|
| enum KeyFilter { SKIP_SYMBOLS, INCLUDE_SYMBOLS };
|
|
|
|
|
| +enum GetKeysConversion { KEEP_NUMBERS, CONVERT_TO_STRING };
|
| +
|
| +
|
| enum ShouldThrow { THROW_ON_ERROR, DONT_THROW };
|
|
|
|
|
| @@ -1903,7 +1909,8 @@ class JSReceiver: public HeapObject {
|
| // "for (n in object) { }".
|
| MUST_USE_RESULT static MaybeHandle<FixedArray> GetKeys(
|
| Handle<JSReceiver> object, KeyCollectionType type,
|
| - KeyFilter filter = SKIP_SYMBOLS);
|
| + KeyFilter filter = SKIP_SYMBOLS,
|
| + GetKeysConversion getConversion = KEEP_NUMBERS);
|
|
|
| private:
|
| DISALLOW_IMPLICIT_CONSTRUCTORS(JSReceiver);
|
| @@ -2233,6 +2240,9 @@ class JSObject: public JSReceiver {
|
| // Returns the number of elements on this object filtering out elements
|
| // with the specified attributes (ignoring interceptors).
|
| int GetOwnElementKeys(FixedArray* storage, PropertyAttributes filter);
|
| + static void CollectOwnElementKeys(Handle<JSObject> object,
|
| + KeyAccumulator* keys,
|
| + PropertyAttributes filter);
|
| // Count and fill in the enumerable elements into storage.
|
| // (storage->length() == NumberOfEnumElements()).
|
| // If storage is NULL, will count the elements without adding
|
| @@ -10712,26 +10722,62 @@ class BooleanBit : public AllStatic {
|
| };
|
|
|
|
|
| +enum AddKeyConversion { DO_NOT_CONVERT, CONVERT_TO_ARRAY_INDEX, PROXY_MAGIC };
|
| +
|
| +// This is a helper class for JSReceiver::GetKeys which collects and sorts keys.
|
| +// GetKeys needs to sort keys per prototype level, first showing the integer
|
| +// indices from elements then the strings from the properties. However, this
|
| +// does not apply to proxies which are in full control of how the keys are
|
| +// sorted.
|
| +//
|
| +// For performance reasons the KeyAccumulator internally separates integer
|
| +// keys in |elements_| into sorted lists per prototype level. String keys are
|
| +// collected in |properties_|, a single OrderedHashSet. To separate the keys per
|
| +// level later when assembling the final list, |levelLengths_| keeps track of
|
| +// the total number of keys (integers + strings) per level.
|
| +//
|
| +// Only unique keys are kept by the KeyAccumulator, strings are stored in a
|
| +// HashSet for inexpensive lookups. Integer keys are kept in sorted lists which
|
| +// are more compact and allow for reasonably fast includes check.
|
| class KeyAccumulator final BASE_EMBEDDED {
|
| public:
|
| - explicit KeyAccumulator(Isolate* isolate) : isolate_(isolate), length_(0) {}
|
| -
|
| - void AddKey(Handle<Object> key, int check_limit);
|
| - void AddKeys(Handle<FixedArray> array, KeyFilter filter);
|
| - void AddKeys(Handle<JSObject> array, KeyFilter filter);
|
| - void PrepareForComparisons(int count);
|
| - Handle<FixedArray> GetKeys();
|
| + explicit KeyAccumulator(Isolate* isolate,
|
| + KeyFilter filter = KeyFilter::SKIP_SYMBOLS)
|
| + : isolate_(isolate), filter_(filter), length_(0), levelLength_(0) {}
|
| + ~KeyAccumulator();
|
| +
|
| + bool AddKey(uint32_t key);
|
| + bool AddKey(Object* key, AddKeyConversion convert = DO_NOT_CONVERT);
|
| + bool AddKey(Handle<Object> key, AddKeyConversion convert = DO_NOT_CONVERT);
|
| + void AddKeys(Handle<FixedArray> array,
|
| + AddKeyConversion convert = DO_NOT_CONVERT);
|
| + void AddKeys(Handle<JSObject> array,
|
| + AddKeyConversion convert = DO_NOT_CONVERT);
|
| + void AddKeysFromProxy(Handle<JSObject> array);
|
| + // Jump to the next level, pushing the current |levelLength_| to
|
| + // |levelLengths_| and adding a new list to |elements_|.
|
| + void NextPrototype();
|
| + // Sort the integer indices in the last list in |elements_|
|
| + void SortCurrentElementsList();
|
| + Handle<FixedArray> GetKeys(GetKeysConversion convert = KEEP_NUMBERS);
|
|
|
| - int GetLength() { return length_; }
|
|
|
| private:
|
| - void EnsureCapacity(int capacity);
|
| - void Grow();
|
| -
|
| Isolate* isolate_;
|
| - Handle<FixedArray> keys_;
|
| - Handle<OrderedHashSet> set_;
|
| + KeyFilter filter_;
|
| + // |elements_| contains the sorted element keys (indices) per level.
|
| + List<List<uint32_t>*> elements_;
|
| + // |protoLengths_| contains the total number of keys (elements + properties)
|
| + // per level. Negative values mark counts for a level with keys from a proxy.
|
| + List<int> levelLengths_;
|
| + // |properties_| contains the property keys per level in insertion order.
|
| + Handle<OrderedHashSet> properties_;
|
| + // |length_| keeps track of the total number of all element and property keys.
|
| int length_;
|
| + // |levelLength_| keeps track of the total number of keys
|
| + // (elements + properties) in the current level.
|
| + int levelLength_;
|
| +
|
| DISALLOW_COPY_AND_ASSIGN(KeyAccumulator);
|
| };
|
|
|
|
|