OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 #include "src/keys.h" | 5 #include "src/keys.h" |
6 | 6 |
7 #include "src/api-arguments.h" | 7 #include "src/api-arguments.h" |
8 #include "src/elements.h" | 8 #include "src/elements.h" |
9 #include "src/factory.h" | 9 #include "src/factory.h" |
10 #include "src/identity-map.h" | 10 #include "src/identity-map.h" |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 for (int i = 0; i < keys->length(); ++i) { | 110 for (int i = 0; i < keys->length(); ++i) { |
111 Handle<Name> key(Name::cast(keys->get(i)), isolate); | 111 Handle<Name> key(Name::cast(keys->get(i)), isolate); |
112 if (key->FilterKey(filter)) continue; // Skip this key. | 112 if (key->FilterKey(filter)) continue; // Skip this key. |
113 if (filter & ONLY_ENUMERABLE) { | 113 if (filter & ONLY_ENUMERABLE) { |
114 PropertyDescriptor desc; | 114 PropertyDescriptor desc; |
115 Maybe<bool> found = | 115 Maybe<bool> found = |
116 JSProxy::GetOwnPropertyDescriptor(isolate, owner, key, &desc); | 116 JSProxy::GetOwnPropertyDescriptor(isolate, owner, key, &desc); |
117 MAYBE_RETURN(found, MaybeHandle<FixedArray>()); | 117 MAYBE_RETURN(found, MaybeHandle<FixedArray>()); |
118 if (!found.FromJust()) continue; | 118 if (!found.FromJust()) continue; |
119 if (!desc.enumerable()) { | 119 if (!desc.enumerable()) { |
120 accumulator->AddShadowKey(key); | 120 accumulator->AddShadowingKey(key); |
121 continue; | 121 continue; |
122 } | 122 } |
123 } | 123 } |
124 // Keep this key. | 124 // Keep this key. |
125 if (store_position != i) { | 125 if (store_position != i) { |
126 keys->set(store_position, *key); | 126 keys->set(store_position, *key); |
127 } | 127 } |
128 store_position++; | 128 store_position++; |
129 } | 129 } |
130 if (store_position == 0) return isolate->factory()->empty_fixed_array(); | 130 if (store_position == 0) return isolate->factory()->empty_fixed_array(); |
(...skipping 28 matching lines...) Expand all Loading... |
159 MAYBE_RETURN(CollectOwnJSProxyKeys(receiver, Handle<JSProxy>::cast(object)), | 159 MAYBE_RETURN(CollectOwnJSProxyKeys(receiver, Handle<JSProxy>::cast(object)), |
160 Nothing<bool>()); | 160 Nothing<bool>()); |
161 return Just(true); | 161 return Just(true); |
162 } | 162 } |
163 | 163 |
164 PrototypeIterator::WhereToEnd end = mode_ == KeyCollectionMode::kOwnOnly | 164 PrototypeIterator::WhereToEnd end = mode_ == KeyCollectionMode::kOwnOnly |
165 ? PrototypeIterator::END_AT_NON_HIDDEN | 165 ? PrototypeIterator::END_AT_NON_HIDDEN |
166 : PrototypeIterator::END_AT_NULL; | 166 : PrototypeIterator::END_AT_NULL; |
167 for (PrototypeIterator iter(isolate_, object, kStartAtReceiver, end); | 167 for (PrototypeIterator iter(isolate_, object, kStartAtReceiver, end); |
168 !iter.IsAtEnd();) { | 168 !iter.IsAtEnd();) { |
| 169 // Start the shadow checks only after the first prototype has added |
| 170 // shadowing keys. |
| 171 if (HasShadowingKeys()) skip_shadow_check_ = false; |
169 Handle<JSReceiver> current = | 172 Handle<JSReceiver> current = |
170 PrototypeIterator::GetCurrent<JSReceiver>(iter); | 173 PrototypeIterator::GetCurrent<JSReceiver>(iter); |
171 Maybe<bool> result = Just(false); // Dummy initialization. | 174 Maybe<bool> result = Just(false); // Dummy initialization. |
172 if (current->IsJSProxy()) { | 175 if (current->IsJSProxy()) { |
173 result = CollectOwnJSProxyKeys(receiver, Handle<JSProxy>::cast(current)); | 176 result = CollectOwnJSProxyKeys(receiver, Handle<JSProxy>::cast(current)); |
174 } else { | 177 } else { |
175 DCHECK(current->IsJSObject()); | 178 DCHECK(current->IsJSObject()); |
176 result = CollectOwnKeys(receiver, Handle<JSObject>::cast(current)); | 179 result = CollectOwnKeys(receiver, Handle<JSObject>::cast(current)); |
177 } | 180 } |
178 MAYBE_RETURN(result, Nothing<bool>()); | 181 MAYBE_RETURN(result, Nothing<bool>()); |
179 if (!result.FromJust()) break; // |false| means "stop iterating". | 182 if (!result.FromJust()) break; // |false| means "stop iterating". |
180 // Iterate through proxies but ignore access checks for the ALL_CAN_READ | 183 // Iterate through proxies but ignore access checks for the ALL_CAN_READ |
181 // case on API objects for OWN_ONLY keys handled in CollectOwnKeys. | 184 // case on API objects for OWN_ONLY keys handled in CollectOwnKeys. |
182 if (!iter.AdvanceFollowingProxiesIgnoringAccessChecks()) { | 185 if (!iter.AdvanceFollowingProxiesIgnoringAccessChecks()) { |
183 return Nothing<bool>(); | 186 return Nothing<bool>(); |
184 } | 187 } |
185 if (!last_non_empty_prototype_.is_null() && | 188 if (!last_non_empty_prototype_.is_null() && |
186 *last_non_empty_prototype_ == *current) { | 189 *last_non_empty_prototype_ == *current) { |
187 break; | 190 break; |
188 } | 191 } |
189 } | 192 } |
190 return Just(true); | 193 return Just(true); |
191 } | 194 } |
192 | 195 |
| 196 bool KeyAccumulator::HasShadowingKeys() { return !shadowing_keys_.is_null(); } |
| 197 |
193 bool KeyAccumulator::IsShadowed(Handle<Object> key) { | 198 bool KeyAccumulator::IsShadowed(Handle<Object> key) { |
194 if (shadowed_keys_.is_null()) return false; | 199 if (!HasShadowingKeys() || skip_shadow_check_) return false; |
195 return shadowed_keys_->Has(isolate_, key); | 200 return shadowing_keys_->Has(isolate_, key); |
196 } | 201 } |
197 | 202 |
198 void KeyAccumulator::AddShadowKey(Object* key) { | 203 void KeyAccumulator::AddShadowingKey(Object* key) { |
199 if (mode_ == KeyCollectionMode::kOwnOnly) return; | 204 if (mode_ == KeyCollectionMode::kOwnOnly) return; |
200 AddShadowKey(handle(key, isolate_)); | 205 AddShadowingKey(handle(key, isolate_)); |
201 } | 206 } |
202 void KeyAccumulator::AddShadowKey(Handle<Object> key) { | 207 void KeyAccumulator::AddShadowingKey(Handle<Object> key) { |
203 if (mode_ == KeyCollectionMode::kOwnOnly) return; | 208 if (mode_ == KeyCollectionMode::kOwnOnly) return; |
204 if (shadowed_keys_.is_null()) { | 209 if (shadowing_keys_.is_null()) { |
205 shadowed_keys_ = ObjectHashSet::New(isolate_, 16); | 210 shadowing_keys_ = ObjectHashSet::New(isolate_, 16); |
206 } | 211 } |
207 shadowed_keys_ = ObjectHashSet::Add(shadowed_keys_, key); | 212 shadowing_keys_ = ObjectHashSet::Add(shadowing_keys_, key); |
208 } | 213 } |
209 | 214 |
210 namespace { | 215 namespace { |
211 | 216 |
212 void TrySettingEmptyEnumCache(JSReceiver* object) { | 217 void TrySettingEmptyEnumCache(JSReceiver* object) { |
213 Map* map = object->map(); | 218 Map* map = object->map(); |
214 DCHECK_EQ(kInvalidEnumCacheSentinel, map->EnumLength()); | 219 DCHECK_EQ(kInvalidEnumCacheSentinel, map->EnumLength()); |
215 if (!map->OnlyHasSimpleProperties()) return; | 220 if (!map->OnlyHasSimpleProperties()) return; |
216 if (map->IsJSProxyMap()) return; | 221 if (map->IsJSProxyMap()) return; |
217 if (map->NumberOfOwnDescriptors() > 0) { | 222 if (map->NumberOfOwnDescriptors() > 0) { |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
541 } | 546 } |
542 | 547 |
543 Name* key = descs->GetKey(i); | 548 Name* key = descs->GetKey(i); |
544 if (skip_symbols == key->IsSymbol()) { | 549 if (skip_symbols == key->IsSymbol()) { |
545 if (first_skipped == -1) first_skipped = i; | 550 if (first_skipped == -1) first_skipped = i; |
546 continue; | 551 continue; |
547 } | 552 } |
548 if (key->FilterKey(keys->filter())) continue; | 553 if (key->FilterKey(keys->filter())) continue; |
549 | 554 |
550 if (is_shadowing_key) { | 555 if (is_shadowing_key) { |
551 keys->AddShadowKey(key); | 556 keys->AddShadowingKey(key); |
552 } else { | 557 } else { |
553 keys->AddKey(key, DO_NOT_CONVERT); | 558 keys->AddKey(key, DO_NOT_CONVERT); |
554 } | 559 } |
555 } | 560 } |
556 return first_skipped; | 561 return first_skipped; |
557 } | 562 } |
558 | 563 |
559 template <class T> | 564 template <class T> |
560 Handle<FixedArray> GetOwnEnumPropertyDictionaryKeys(Isolate* isolate, | 565 Handle<FixedArray> GetOwnEnumPropertyDictionaryKeys(Isolate* isolate, |
561 KeyCollectionMode mode, | 566 KeyCollectionMode mode, |
(...skipping 21 matching lines...) Expand all Loading... |
583 // we do not have to filter out non-enumerable ones | 588 // we do not have to filter out non-enumerable ones |
584 Map* map = object->map(); | 589 Map* map = object->map(); |
585 int nof_descriptors = map->NumberOfOwnDescriptors(); | 590 int nof_descriptors = map->NumberOfOwnDescriptors(); |
586 if (enum_keys->length() != nof_descriptors) { | 591 if (enum_keys->length() != nof_descriptors) { |
587 Handle<DescriptorArray> descs = | 592 Handle<DescriptorArray> descs = |
588 Handle<DescriptorArray>(map->instance_descriptors(), isolate_); | 593 Handle<DescriptorArray>(map->instance_descriptors(), isolate_); |
589 for (int i = 0; i < nof_descriptors; i++) { | 594 for (int i = 0; i < nof_descriptors; i++) { |
590 PropertyDetails details = descs->GetDetails(i); | 595 PropertyDetails details = descs->GetDetails(i); |
591 if (!details.IsDontEnum()) continue; | 596 if (!details.IsDontEnum()) continue; |
592 Object* key = descs->GetKey(i); | 597 Object* key = descs->GetKey(i); |
593 this->AddShadowKey(key); | 598 this->AddShadowingKey(key); |
594 } | 599 } |
595 } | 600 } |
596 } else if (object->IsJSGlobalObject()) { | 601 } else if (object->IsJSGlobalObject()) { |
597 enum_keys = GetOwnEnumPropertyDictionaryKeys( | 602 enum_keys = GetOwnEnumPropertyDictionaryKeys( |
598 isolate_, mode_, this, object, object->global_dictionary()); | 603 isolate_, mode_, this, object, object->global_dictionary()); |
599 } else { | 604 } else { |
600 enum_keys = GetOwnEnumPropertyDictionaryKeys( | 605 enum_keys = GetOwnEnumPropertyDictionaryKeys( |
601 isolate_, mode_, this, object, object->property_dictionary()); | 606 isolate_, mode_, this, object, object->property_dictionary()); |
602 } | 607 } |
603 AddKeys(enum_keys, DO_NOT_CONVERT); | 608 AddKeys(enum_keys, DO_NOT_CONVERT); |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
860 Nothing<bool>()); | 865 Nothing<bool>()); |
861 bool prev_filter_proxy_keys_ = filter_proxy_keys_; | 866 bool prev_filter_proxy_keys_ = filter_proxy_keys_; |
862 filter_proxy_keys_ = false; | 867 filter_proxy_keys_ = false; |
863 Maybe<bool> result = AddKeysFromJSProxy(proxy, keys); | 868 Maybe<bool> result = AddKeysFromJSProxy(proxy, keys); |
864 filter_proxy_keys_ = prev_filter_proxy_keys_; | 869 filter_proxy_keys_ = prev_filter_proxy_keys_; |
865 return result; | 870 return result; |
866 } | 871 } |
867 | 872 |
868 } // namespace internal | 873 } // namespace internal |
869 } // namespace v8 | 874 } // namespace v8 |
OLD | NEW |