Index: src/keys.h |
diff --git a/src/keys.h b/src/keys.h |
index 502c834527e65caf9e3cab6f5bb68e442f940a09..ecd3d97c550cf5a8aa80f2aa312c18d1001115ca 100644 |
--- a/src/keys.h |
+++ b/src/keys.h |
@@ -53,8 +53,8 @@ class KeyAccumulator final BASE_EMBEDDED { |
Handle<AccessCheckInfo> access_check_info, Handle<JSReceiver> receiver, |
Handle<JSObject> object); |
- static Handle<FixedArray> GetEnumPropertyKeys(Isolate* isolate, |
- Handle<JSObject> object); |
+ static Handle<FixedArray> GetOwnEnumPropertyKeys(Isolate* isolate, |
+ Handle<JSObject> object); |
void AddKey(Object* key, AddKeyConversion convert = DO_NOT_CONVERT); |
void AddKey(Handle<Object> key, AddKeyConversion convert = DO_NOT_CONVERT); |
@@ -64,13 +64,27 @@ class KeyAccumulator final BASE_EMBEDDED { |
// Jump to the next level, pushing the current |levelLength_| to |
// |levelLengths_| and adding a new list to |elements_|. |
Isolate* isolate() { return isolate_; } |
+ // Filter keys based on their property descriptors. |
PropertyFilter filter() { return filter_; } |
+ // The collection mode defines whether we collect the keys from the prototype |
+ // chain or only look at the receiver. |
+ KeyCollectionMode mode() { return mode_; } |
void set_filter_proxy_keys(bool filter) { filter_proxy_keys_ = filter; } |
+ // In case of for-in loops we have to treat JSProxy keys differently and |
+ // deduplicate them. Additionally we convert JSProxy keys back to array |
+ // indices. |
void set_is_for_in(bool value) { is_for_in_ = value; } |
void set_skip_indices(bool value) { skip_indices_ = value; } |
+ // The last_non_empty_prototype is used to limit the prototypes for which |
+ // we have to keep track of non-enumerable keys that can shadow keys |
+ // repeated on the prototype chain. |
void set_last_non_empty_prototype(Handle<JSReceiver> object) { |
last_non_empty_prototype_ = object; |
} |
+ // Shadowing keys are used to filter keys. This happens when non-enumerable |
+ // keys appear again on the prototype chain. |
+ void AddShadowKey(Object* key); |
+ void AddShadowKey(Handle<Object> key); |
private: |
Maybe<bool> CollectOwnKeys(Handle<JSReceiver> receiver, |
@@ -79,17 +93,18 @@ class KeyAccumulator final BASE_EMBEDDED { |
Handle<JSProxy> proxy); |
Maybe<bool> CollectOwnJSProxyTargetKeys(Handle<JSProxy> proxy, |
Handle<JSReceiver> target); |
- |
Maybe<bool> AddKeysFromJSProxy(Handle<JSProxy> proxy, |
Handle<FixedArray> keys); |
- |
+ bool IsShadowed(Handle<Object> key); |
Handle<OrderedHashSet> keys() { return Handle<OrderedHashSet>::cast(keys_); } |
Isolate* isolate_; |
// keys_ is either an Handle<OrderedHashSet> or in the case of own JSProxy |
- // keys a Handle<FixedArray>. |
+ // keys a Handle<FixedArray>. The OrderedHashSet is in-place converted to the |
+ // result list, a FixedArray containing all collected keys. |
Handle<FixedArray> keys_; |
Handle<JSReceiver> last_non_empty_prototype_; |
+ Handle<ObjectHashSet> shadowed_keys_; |
KeyCollectionMode mode_; |
PropertyFilter filter_; |
bool filter_proxy_keys_ = true; |
@@ -101,7 +116,8 @@ class KeyAccumulator final BASE_EMBEDDED { |
// The FastKeyAccumulator handles the cases where there are no elements on the |
// prototype chain and forwords the complex/slow cases to the normal |
-// KeyAccumulator. |
+// KeyAccumulator. This significantly speeds up the cases where the OWN_ONLY |
+// case where we do not have to walk the prototype chain. |
class FastKeyAccumulator { |
public: |
FastKeyAccumulator(Isolate* isolate, Handle<JSReceiver> receiver, |