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

Side by Side Diff: src/objects.cc

Issue 1375003002: Teach JSReceiver::GetKeys() how to include symbols (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebased Created 5 years, 2 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
« no previous file with comments | « src/objects.h ('k') | src/runtime/runtime-array.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 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/objects.h" 5 #include "src/objects.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 #include <iomanip> 8 #include <iomanip>
9 #include <sstream> 9 #include <sstream>
10 10
(...skipping 6741 matching lines...) Expand 10 before | Expand all | Expand 10 after
6752 for (int i = 0; i < check_limit; i++) { 6752 for (int i = 0; i < check_limit; i++) {
6753 Object* current = keys_->get(i); 6753 Object* current = keys_->get(i);
6754 if (current->KeyEquals(*key)) return; 6754 if (current->KeyEquals(*key)) return;
6755 } 6755 }
6756 EnsureCapacity(length_); 6756 EnsureCapacity(length_);
6757 keys_->set(length_, *key); 6757 keys_->set(length_, *key);
6758 length_++; 6758 length_++;
6759 } 6759 }
6760 6760
6761 6761
6762 void KeyAccumulator::AddKeys(Handle<FixedArray> array, 6762 void KeyAccumulator::AddKeys(Handle<FixedArray> array, KeyFilter filter) {
6763 FixedArray::KeyFilter filter) {
6764 int add_length = array->length(); 6763 int add_length = array->length();
6765 if (add_length == 0) return; 6764 if (add_length == 0) return;
6766 if (keys_.is_null() && filter == FixedArray::ALL_KEYS) { 6765 if (keys_.is_null() && filter == INCLUDE_SYMBOLS) {
6767 keys_ = array; 6766 keys_ = array;
6768 length_ = keys_->length(); 6767 length_ = keys_->length();
6769 return; 6768 return;
6770 } 6769 }
6771 PrepareForComparisons(add_length); 6770 PrepareForComparisons(add_length);
6772 int previous_key_count = length_; 6771 int previous_key_count = length_;
6773 for (int i = 0; i < add_length; i++) { 6772 for (int i = 0; i < add_length; i++) {
6774 Handle<Object> current(array->get(i), isolate_); 6773 Handle<Object> current(array->get(i), isolate_);
6775 if (filter == FixedArray::NON_SYMBOL_KEYS && current->IsSymbol()) continue; 6774 if (filter == SKIP_SYMBOLS && current->IsSymbol()) continue;
6776 AddKey(current, previous_key_count); 6775 AddKey(current, previous_key_count);
6777 } 6776 }
6778 } 6777 }
6779 6778
6780 6779
6781 void KeyAccumulator::AddKeys(Handle<JSObject> array_like, 6780 void KeyAccumulator::AddKeys(Handle<JSObject> array_like, KeyFilter filter) {
6782 FixedArray::KeyFilter filter) {
6783 DCHECK(array_like->IsJSArray() || array_like->HasSloppyArgumentsElements()); 6781 DCHECK(array_like->IsJSArray() || array_like->HasSloppyArgumentsElements());
6784 ElementsAccessor* accessor = array_like->GetElementsAccessor(); 6782 ElementsAccessor* accessor = array_like->GetElementsAccessor();
6785 accessor->AddElementsToKeyAccumulator(array_like, this, filter); 6783 accessor->AddElementsToKeyAccumulator(array_like, this, filter);
6786 } 6784 }
6787 6785
6788 6786
6789 void KeyAccumulator::PrepareForComparisons(int count) { 6787 void KeyAccumulator::PrepareForComparisons(int count) {
6790 // Depending on how many comparisons we do we should switch to the 6788 // Depending on how many comparisons we do we should switch to the
6791 // hash-table-based checks which have a one-time overhead for 6789 // hash-table-based checks which have a one-time overhead for
6792 // initializing but O(1) for HasKey checks. 6790 // initializing but O(1) for HasKey checks.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
6824 WriteBarrierMode mode = new_keys->GetWriteBarrierMode(no_gc); 6822 WriteBarrierMode mode = new_keys->GetWriteBarrierMode(no_gc);
6825 for (int i = 0; i < buffer_length; i++) { 6823 for (int i = 0; i < buffer_length; i++) {
6826 new_keys->set(i, keys_->get(i), mode); 6824 new_keys->set(i, keys_->get(i), mode);
6827 } 6825 }
6828 } 6826 }
6829 keys_ = new_keys; 6827 keys_ = new_keys;
6830 } 6828 }
6831 6829
6832 6830
6833 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, 6831 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
6834 KeyCollectionType type) { 6832 KeyCollectionType type,
6833 KeyFilter filter) {
6835 USE(ContainsOnlyValidKeys); 6834 USE(ContainsOnlyValidKeys);
6836 Isolate* isolate = object->GetIsolate(); 6835 Isolate* isolate = object->GetIsolate();
6837 KeyAccumulator accumulator(isolate); 6836 KeyAccumulator accumulator(isolate);
6838 Handle<JSFunction> arguments_function( 6837 Handle<JSFunction> arguments_function(
6839 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); 6838 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
6840 6839
6841 PrototypeIterator::WhereToEnd end = type == OWN_ONLY 6840 PrototypeIterator::WhereToEnd end = type == OWN_ONLY
6842 ? PrototypeIterator::END_AT_NON_HIDDEN 6841 ? PrototypeIterator::END_AT_NON_HIDDEN
6843 : PrototypeIterator::END_AT_NULL; 6842 : PrototypeIterator::END_AT_NULL;
6844 // Only collect keys if access is permitted. 6843 // Only collect keys if access is permitted.
6845 for (PrototypeIterator iter(isolate, object, 6844 for (PrototypeIterator iter(isolate, object,
6846 PrototypeIterator::START_AT_RECEIVER); 6845 PrototypeIterator::START_AT_RECEIVER);
6847 !iter.IsAtEnd(end); iter.Advance()) { 6846 !iter.IsAtEnd(end); iter.Advance()) {
6848 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { 6847 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
6849 Handle<JSProxy> proxy = PrototypeIterator::GetCurrent<JSProxy>(iter); 6848 Handle<JSProxy> proxy = PrototypeIterator::GetCurrent<JSProxy>(iter);
6850 Handle<Object> args[] = { proxy }; 6849 Handle<Object> args[] = { proxy };
6851 Handle<Object> names; 6850 Handle<Object> names;
6852 ASSIGN_RETURN_ON_EXCEPTION( 6851 ASSIGN_RETURN_ON_EXCEPTION(
6853 isolate, names, 6852 isolate, names,
6854 Execution::Call(isolate, 6853 Execution::Call(isolate,
6855 isolate->proxy_enumerate(), 6854 isolate->proxy_enumerate(),
6856 object, 6855 object,
6857 arraysize(args), 6856 arraysize(args),
6858 args), 6857 args),
6859 FixedArray); 6858 FixedArray);
6860 accumulator.AddKeys(Handle<JSObject>::cast(names), FixedArray::ALL_KEYS); 6859 accumulator.AddKeys(Handle<JSObject>::cast(names), filter);
6861 break; 6860 break;
6862 } 6861 }
6863 6862
6864 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter); 6863 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter);
6865 6864
6866 // Check access rights if required. 6865 // Check access rights if required.
6867 if (current->IsAccessCheckNeeded() && !isolate->MayAccess(current)) { 6866 if (current->IsAccessCheckNeeded() && !isolate->MayAccess(current)) {
6868 if (iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { 6867 if (iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
6869 isolate->ReportFailedAccessCheck(current); 6868 isolate->ReportFailedAccessCheck(current);
6870 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray); 6869 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
6871 } 6870 }
6872 break; 6871 break;
6873 } 6872 }
6874 6873
6875 // Compute the element keys. 6874 // Compute the element keys.
6876 Handle<FixedArray> element_keys = 6875 Handle<FixedArray> element_keys =
6877 isolate->factory()->NewFixedArray(current->NumberOfEnumElements()); 6876 isolate->factory()->NewFixedArray(current->NumberOfEnumElements());
6878 current->GetEnumElementKeys(*element_keys); 6877 current->GetEnumElementKeys(*element_keys);
6879 accumulator.AddKeys(element_keys, FixedArray::ALL_KEYS); 6878 accumulator.AddKeys(element_keys, filter);
6880 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); 6879 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
6881 6880
6882 // Add the element keys from the interceptor. 6881 // Add the element keys from the interceptor.
6883 if (current->HasIndexedInterceptor()) { 6882 if (current->HasIndexedInterceptor()) {
6884 Handle<JSObject> result; 6883 Handle<JSObject> result;
6885 if (JSObject::GetKeysForIndexedInterceptor( 6884 if (JSObject::GetKeysForIndexedInterceptor(
6886 current, object).ToHandle(&result)) { 6885 current, object).ToHandle(&result)) {
6887 accumulator.AddKeys(result, FixedArray::ALL_KEYS); 6886 accumulator.AddKeys(result, filter);
6888 } 6887 }
6889 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); 6888 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
6890 } 6889 }
6891 6890
6892 // We can cache the computed property keys if access checks are 6891 if (filter == SKIP_SYMBOLS) {
6893 // not needed and no interceptors are involved. 6892 // We can cache the computed property keys if access checks are
6894 // 6893 // not needed and no interceptors are involved.
6895 // We do not use the cache if the object has elements and 6894 //
6896 // therefore it does not make sense to cache the property names 6895 // We do not use the cache if the object has elements and
6897 // for arguments objects. Arguments objects will always have 6896 // therefore it does not make sense to cache the property names
6898 // elements. 6897 // for arguments objects. Arguments objects will always have
6899 // Wrapped strings have elements, but don't have an elements 6898 // elements.
6900 // array or dictionary. So the fast inline test for whether to 6899 // Wrapped strings have elements, but don't have an elements
6901 // use the cache says yes, so we should not create a cache. 6900 // array or dictionary. So the fast inline test for whether to
6902 bool cache_enum_length = 6901 // use the cache says yes, so we should not create a cache.
6903 ((current->map()->GetConstructor() != *arguments_function) && 6902 bool cache_enum_length =
6904 !current->IsJSValue() && !current->IsAccessCheckNeeded() && 6903 ((current->map()->GetConstructor() != *arguments_function) &&
6905 !current->HasNamedInterceptor() && !current->HasIndexedInterceptor()); 6904 !current->IsJSValue() && !current->IsAccessCheckNeeded() &&
6906 // Compute the property keys and cache them if possible. 6905 !current->HasNamedInterceptor() &&
6906 !current->HasIndexedInterceptor());
6907 // Compute the property keys and cache them if possible.
6907 6908
6908 Handle<FixedArray> enum_keys = 6909 Handle<FixedArray> enum_keys =
6909 JSObject::GetEnumPropertyKeys(current, cache_enum_length); 6910 JSObject::GetEnumPropertyKeys(current, cache_enum_length);
6910 accumulator.AddKeys(enum_keys, FixedArray::ALL_KEYS); 6911 accumulator.AddKeys(enum_keys, filter);
6912 } else {
6913 DCHECK(filter == INCLUDE_SYMBOLS);
6914 PropertyAttributes attr_filter =
6915 static_cast<PropertyAttributes>(DONT_ENUM | PRIVATE_SYMBOL);
6916 Handle<FixedArray> property_keys = isolate->factory()->NewFixedArray(
6917 current->NumberOfOwnProperties(attr_filter));
6918 current->GetOwnPropertyNames(*property_keys, 0, attr_filter);
6919 accumulator.AddKeys(property_keys, filter);
6920 }
6911 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); 6921 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
6912 6922
6913 // Add the non-symbol property keys from the interceptor. 6923 // Add the property keys from the interceptor.
6914 if (current->HasNamedInterceptor()) { 6924 if (current->HasNamedInterceptor()) {
6915 Handle<JSObject> result; 6925 Handle<JSObject> result;
6916 if (JSObject::GetKeysForNamedInterceptor( 6926 if (JSObject::GetKeysForNamedInterceptor(
6917 current, object).ToHandle(&result)) { 6927 current, object).ToHandle(&result)) {
6918 accumulator.AddKeys(result, FixedArray::NON_SYMBOL_KEYS); 6928 accumulator.AddKeys(result, filter);
6919 } 6929 }
6920 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); 6930 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
6921 } 6931 }
6922 } 6932 }
6923 6933
6924 Handle<FixedArray> keys = accumulator.GetKeys(); 6934 Handle<FixedArray> keys = accumulator.GetKeys();
6925 DCHECK(ContainsOnlyValidKeys(keys)); 6935 DCHECK(ContainsOnlyValidKeys(keys));
6926 return keys; 6936 return keys;
6927 } 6937 }
6928 6938
(...skipping 6897 matching lines...) Expand 10 before | Expand all | Expand 10 after
13826 return global_dictionary()->CopyKeysTo(storage, index, filter, 13836 return global_dictionary()->CopyKeysTo(storage, index, filter,
13827 GlobalDictionary::UNSORTED); 13837 GlobalDictionary::UNSORTED);
13828 } else { 13838 } else {
13829 return property_dictionary()->CopyKeysTo(storage, index, filter, 13839 return property_dictionary()->CopyKeysTo(storage, index, filter,
13830 NameDictionary::UNSORTED); 13840 NameDictionary::UNSORTED);
13831 } 13841 }
13832 } 13842 }
13833 13843
13834 13844
13835 int JSObject::NumberOfOwnElements(PropertyAttributes filter) { 13845 int JSObject::NumberOfOwnElements(PropertyAttributes filter) {
13836 return GetOwnElementKeys(NULL, filter);
13837 }
13838
13839
13840 int JSObject::NumberOfEnumElements() {
13841 // Fast case for objects with no elements. 13846 // Fast case for objects with no elements.
13842 if (!IsJSValue() && HasFastObjectElements()) { 13847 if (!IsJSValue() && HasFastElements()) {
13843 uint32_t length = IsJSArray() ? 13848 uint32_t length = IsJSArray() ?
13844 static_cast<uint32_t>( 13849 static_cast<uint32_t>(
13845 Smi::cast(JSArray::cast(this)->length())->value()) : 13850 Smi::cast(JSArray::cast(this)->length())->value()) :
13846 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 13851 static_cast<uint32_t>(FixedArray::cast(elements())->length());
13847 if (length == 0) return 0; 13852 if (length == 0) return 0;
13848 } 13853 }
13849 // Compute the number of enumerable elements. 13854 // Compute the number of enumerable elements.
13855 return GetOwnElementKeys(NULL, filter);
13856 }
13857
13858
13859 int JSObject::NumberOfEnumElements() {
13850 return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM)); 13860 return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM));
13851 } 13861 }
13852 13862
13853 13863
13854 int JSObject::GetOwnElementKeys(FixedArray* storage, 13864 int JSObject::GetOwnElementKeys(FixedArray* storage,
13855 PropertyAttributes filter) { 13865 PropertyAttributes filter) {
13856 int counter = 0; 13866 int counter = 0;
13857 13867
13858 // If this is a String wrapper, add the string indices first, 13868 // If this is a String wrapper, add the string indices first,
13859 // as they're guaranteed to preced the elements in numerical order 13869 // as they're guaranteed to preced the elements in numerical order
(...skipping 2942 matching lines...) Expand 10 before | Expand all | Expand 10 after
16802 if (cell->value() != *new_value) { 16812 if (cell->value() != *new_value) {
16803 cell->set_value(*new_value); 16813 cell->set_value(*new_value);
16804 Isolate* isolate = cell->GetIsolate(); 16814 Isolate* isolate = cell->GetIsolate();
16805 cell->dependent_code()->DeoptimizeDependentCodeGroup( 16815 cell->dependent_code()->DeoptimizeDependentCodeGroup(
16806 isolate, DependentCode::kPropertyCellChangedGroup); 16816 isolate, DependentCode::kPropertyCellChangedGroup);
16807 } 16817 }
16808 } 16818 }
16809 16819
16810 } // namespace internal 16820 } // namespace internal
16811 } // namespace v8 16821 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/runtime/runtime-array.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698