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/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 6769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6780 DisallowHeapAllocation no_gc; | 6780 DisallowHeapAllocation no_gc; |
6781 WriteBarrierMode mode = new_keys->GetWriteBarrierMode(no_gc); | 6781 WriteBarrierMode mode = new_keys->GetWriteBarrierMode(no_gc); |
6782 for (int i = 0; i < buffer_length; i++) { | 6782 for (int i = 0; i < buffer_length; i++) { |
6783 new_keys->set(i, keys_->get(i), mode); | 6783 new_keys->set(i, keys_->get(i), mode); |
6784 } | 6784 } |
6785 } | 6785 } |
6786 keys_ = new_keys; | 6786 keys_ = new_keys; |
6787 } | 6787 } |
6788 | 6788 |
6789 | 6789 |
6790 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, | 6790 MaybeHandle<FixedArray> JSReceiver::GetKeys( |
6791 KeyCollectionType type) { | 6791 Handle<JSReceiver> object, KeyCollectionType type, |
| 6792 IncludeSymbolNamedProperties include_symbols) { |
6792 USE(ContainsOnlyValidKeys); | 6793 USE(ContainsOnlyValidKeys); |
6793 Isolate* isolate = object->GetIsolate(); | 6794 Isolate* isolate = object->GetIsolate(); |
6794 KeyAccumulator accumulator(isolate); | 6795 KeyAccumulator accumulator(isolate); |
6795 Handle<JSFunction> arguments_function( | 6796 Handle<JSFunction> arguments_function( |
6796 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); | 6797 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); |
6797 | 6798 |
6798 PrototypeIterator::WhereToEnd end = type == OWN_ONLY | 6799 PrototypeIterator::WhereToEnd end = type == OWN_ONLY |
6799 ? PrototypeIterator::END_AT_NON_HIDDEN | 6800 ? PrototypeIterator::END_AT_NON_HIDDEN |
6800 : PrototypeIterator::END_AT_NULL; | 6801 : PrototypeIterator::END_AT_NULL; |
6801 // Only collect keys if access is permitted. | 6802 // Only collect keys if access is permitted. |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6839 // Add the element keys from the interceptor. | 6840 // Add the element keys from the interceptor. |
6840 if (current->HasIndexedInterceptor()) { | 6841 if (current->HasIndexedInterceptor()) { |
6841 Handle<JSObject> result; | 6842 Handle<JSObject> result; |
6842 if (JSObject::GetKeysForIndexedInterceptor( | 6843 if (JSObject::GetKeysForIndexedInterceptor( |
6843 current, object).ToHandle(&result)) { | 6844 current, object).ToHandle(&result)) { |
6844 accumulator.AddKeys(result, FixedArray::ALL_KEYS); | 6845 accumulator.AddKeys(result, FixedArray::ALL_KEYS); |
6845 } | 6846 } |
6846 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); | 6847 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); |
6847 } | 6848 } |
6848 | 6849 |
6849 // We can cache the computed property keys if access checks are | 6850 if (include_symbols == SKIP_SYMBOLS) { |
6850 // not needed and no interceptors are involved. | 6851 // We can cache the computed property keys if access checks are |
6851 // | 6852 // not needed and no interceptors are involved. |
6852 // We do not use the cache if the object has elements and | 6853 // |
6853 // therefore it does not make sense to cache the property names | 6854 // We do not use the cache if the object has elements and |
6854 // for arguments objects. Arguments objects will always have | 6855 // therefore it does not make sense to cache the property names |
6855 // elements. | 6856 // for arguments objects. Arguments objects will always have |
6856 // Wrapped strings have elements, but don't have an elements | 6857 // elements. |
6857 // array or dictionary. So the fast inline test for whether to | 6858 // Wrapped strings have elements, but don't have an elements |
6858 // use the cache says yes, so we should not create a cache. | 6859 // array or dictionary. So the fast inline test for whether to |
6859 bool cache_enum_keys = | 6860 // use the cache says yes, so we should not create a cache. |
6860 ((current->map()->GetConstructor() != *arguments_function) && | 6861 bool cache_enum_keys = |
6861 !current->IsJSValue() && !current->IsAccessCheckNeeded() && | 6862 ((current->map()->GetConstructor() != *arguments_function) && |
6862 !current->HasNamedInterceptor() && !current->HasIndexedInterceptor()); | 6863 !current->IsJSValue() && !current->IsAccessCheckNeeded() && |
6863 // Compute the property keys and cache them if possible. | 6864 !current->HasNamedInterceptor() && |
6864 | 6865 !current->HasIndexedInterceptor()); |
6865 Handle<FixedArray> enum_keys = | 6866 // Compute the property keys and cache them if possible. |
6866 JSObject::GetEnumPropertyKeys(current, cache_enum_keys); | 6867 Handle<FixedArray> enum_keys = |
6867 accumulator.AddKeys(enum_keys, FixedArray::ALL_KEYS); | 6868 JSObject::GetEnumPropertyKeys(current, cache_enum_keys); |
| 6869 accumulator.AddKeys(enum_keys, FixedArray::ALL_KEYS); |
| 6870 } else { |
| 6871 DCHECK(include_symbols == INCLUDE_SYMBOLS); |
| 6872 PropertyAttributes filter = |
| 6873 static_cast<PropertyAttributes>(DONT_ENUM | PRIVATE_SYMBOL); |
| 6874 Handle<FixedArray> property_keys = isolate->factory()->NewFixedArray( |
| 6875 current->NumberOfOwnProperties(filter)); |
| 6876 current->GetOwnPropertyNames(*property_keys, 0, filter); |
| 6877 accumulator.AddKeys(property_keys, FixedArray::ALL_KEYS); |
| 6878 } |
6868 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); | 6879 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); |
6869 | 6880 |
6870 // Add the non-symbol property keys from the interceptor. | 6881 // Add the property keys from the interceptor. |
6871 if (current->HasNamedInterceptor()) { | 6882 if (current->HasNamedInterceptor()) { |
6872 Handle<JSObject> result; | 6883 Handle<JSObject> result; |
6873 if (JSObject::GetKeysForNamedInterceptor( | 6884 if (JSObject::GetKeysForNamedInterceptor( |
6874 current, object).ToHandle(&result)) { | 6885 current, object).ToHandle(&result)) { |
6875 accumulator.AddKeys(result, FixedArray::NON_SYMBOL_KEYS); | 6886 FixedArray::KeyFilter filter = include_symbols == SKIP_SYMBOLS |
| 6887 ? FixedArray::NON_SYMBOL_KEYS |
| 6888 : FixedArray::ALL_KEYS; |
| 6889 accumulator.AddKeys(result, filter); |
6876 } | 6890 } |
6877 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); | 6891 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); |
6878 } | 6892 } |
6879 } | 6893 } |
6880 | 6894 |
6881 Handle<FixedArray> keys = accumulator.GetKeys(); | 6895 Handle<FixedArray> keys = accumulator.GetKeys(); |
6882 DCHECK(ContainsOnlyValidKeys(keys)); | 6896 DCHECK(ContainsOnlyValidKeys(keys)); |
6883 return keys; | 6897 return keys; |
6884 } | 6898 } |
6885 | 6899 |
(...skipping 22 matching lines...) Expand all Loading... |
6908 return true; | 6922 return true; |
6909 } | 6923 } |
6910 } | 6924 } |
6911 } | 6925 } |
6912 | 6926 |
6913 return false; | 6927 return false; |
6914 } | 6928 } |
6915 | 6929 |
6916 | 6930 |
6917 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object, | 6931 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object, |
6918 Handle<Name> name, | 6932 Handle<Object> name, |
6919 Handle<Object> getter, | 6933 Handle<Object> getter, |
6920 Handle<Object> setter, | 6934 Handle<Object> setter, |
6921 PropertyAttributes attributes) { | 6935 PropertyAttributes attributes) { |
6922 Isolate* isolate = object->GetIsolate(); | 6936 Isolate* isolate = object->GetIsolate(); |
6923 | 6937 |
6924 LookupIterator it = LookupIterator::PropertyOrElement( | 6938 LookupIterator it = LookupIterator::PropertyOrElement( |
6925 isolate, object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR); | 6939 isolate, object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR); |
6926 | 6940 |
6927 if (it.state() == LookupIterator::ACCESS_CHECK) { | 6941 if (it.state() == LookupIterator::ACCESS_CHECK) { |
6928 if (!it.HasAccess()) { | 6942 if (!it.HasAccess()) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6960 } | 6974 } |
6961 if (!setter->IsNull()) { | 6975 if (!setter->IsNull()) { |
6962 it.TransitionToAccessorProperty(ACCESSOR_SETTER, setter, attributes); | 6976 it.TransitionToAccessorProperty(ACCESSOR_SETTER, setter, attributes); |
6963 } | 6977 } |
6964 | 6978 |
6965 if (is_observed) { | 6979 if (is_observed) { |
6966 // Make sure the top context isn't changed. | 6980 // Make sure the top context isn't changed. |
6967 AssertNoContextChange ncc(isolate); | 6981 AssertNoContextChange ncc(isolate); |
6968 const char* type = preexists ? "reconfigure" : "add"; | 6982 const char* type = preexists ? "reconfigure" : "add"; |
6969 RETURN_ON_EXCEPTION( | 6983 RETURN_ON_EXCEPTION( |
6970 isolate, EnqueueChangeRecord(object, type, name, old_value), Object); | 6984 isolate, EnqueueChangeRecord(object, type, it.GetName(), old_value), |
| 6985 Object); |
6971 } | 6986 } |
6972 | 6987 |
6973 return isolate->factory()->undefined_value(); | 6988 return isolate->factory()->undefined_value(); |
6974 } | 6989 } |
6975 | 6990 |
6976 | 6991 |
6977 MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object, | 6992 MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object, |
6978 Handle<AccessorInfo> info) { | 6993 Handle<AccessorInfo> info) { |
6979 Isolate* isolate = object->GetIsolate(); | 6994 Isolate* isolate = object->GetIsolate(); |
6980 Handle<Name> name(Name::cast(info->name()), isolate); | 6995 Handle<Name> name(Name::cast(info->name()), isolate); |
(...skipping 6787 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13768 return global_dictionary()->CopyKeysTo(storage, index, filter, | 13783 return global_dictionary()->CopyKeysTo(storage, index, filter, |
13769 GlobalDictionary::UNSORTED); | 13784 GlobalDictionary::UNSORTED); |
13770 } else { | 13785 } else { |
13771 return property_dictionary()->CopyKeysTo(storage, index, filter, | 13786 return property_dictionary()->CopyKeysTo(storage, index, filter, |
13772 NameDictionary::UNSORTED); | 13787 NameDictionary::UNSORTED); |
13773 } | 13788 } |
13774 } | 13789 } |
13775 | 13790 |
13776 | 13791 |
13777 int JSObject::NumberOfOwnElements(PropertyAttributes filter) { | 13792 int JSObject::NumberOfOwnElements(PropertyAttributes filter) { |
13778 return GetOwnElementKeys(NULL, filter); | |
13779 } | |
13780 | |
13781 | |
13782 int JSObject::NumberOfEnumElements() { | |
13783 // Fast case for objects with no elements. | 13793 // Fast case for objects with no elements. |
13784 if (!IsJSValue() && HasFastObjectElements()) { | 13794 if (!IsJSValue() && HasFastElements()) { |
13785 uint32_t length = IsJSArray() ? | 13795 uint32_t length = IsJSArray() ? |
13786 static_cast<uint32_t>( | 13796 static_cast<uint32_t>( |
13787 Smi::cast(JSArray::cast(this)->length())->value()) : | 13797 Smi::cast(JSArray::cast(this)->length())->value()) : |
13788 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 13798 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
13789 if (length == 0) return 0; | 13799 if (length == 0) return 0; |
13790 } | 13800 } |
13791 // Compute the number of enumerable elements. | 13801 // Compute the number of enumerable elements. |
| 13802 return GetOwnElementKeys(NULL, filter); |
| 13803 } |
| 13804 |
| 13805 |
| 13806 int JSObject::NumberOfEnumElements() { |
13792 return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM)); | 13807 return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM)); |
13793 } | 13808 } |
13794 | 13809 |
13795 | 13810 |
13796 int JSObject::GetOwnElementKeys(FixedArray* storage, | 13811 int JSObject::GetOwnElementKeys(FixedArray* storage, |
13797 PropertyAttributes filter) { | 13812 PropertyAttributes filter) { |
13798 int counter = 0; | 13813 int counter = 0; |
13799 | 13814 |
13800 // If this is a String wrapper, add the string indices first, | 13815 // If this is a String wrapper, add the string indices first, |
13801 // as they're guaranteed to preced the elements in numerical order | 13816 // as they're guaranteed to preced the elements in numerical order |
(...skipping 2943 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16745 if (cell->value() != *new_value) { | 16760 if (cell->value() != *new_value) { |
16746 cell->set_value(*new_value); | 16761 cell->set_value(*new_value); |
16747 Isolate* isolate = cell->GetIsolate(); | 16762 Isolate* isolate = cell->GetIsolate(); |
16748 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 16763 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
16749 isolate, DependentCode::kPropertyCellChangedGroup); | 16764 isolate, DependentCode::kPropertyCellChangedGroup); |
16750 } | 16765 } |
16751 } | 16766 } |
16752 | 16767 |
16753 } // namespace internal | 16768 } // namespace internal |
16754 } // namespace v8 | 16769 } // namespace v8 |
OLD | NEW |