| 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 |