OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 } | 109 } |
110 constructor = handle( | 110 constructor = handle( |
111 JSFunction::cast(native_context->get(constructor_function_index)), | 111 JSFunction::cast(native_context->get(constructor_function_index)), |
112 isolate); | 112 isolate); |
113 } | 113 } |
114 Handle<JSObject> result = isolate->factory()->NewJSObject(constructor); | 114 Handle<JSObject> result = isolate->factory()->NewJSObject(constructor); |
115 Handle<JSValue>::cast(result)->set_value(*object); | 115 Handle<JSValue>::cast(result)->set_value(*object); |
116 return result; | 116 return result; |
117 } | 117 } |
118 | 118 |
119 // ES6 section 9.2.1.2, OrdinaryCallBindThis for sloppy callee. | |
120 // static | |
121 MaybeHandle<JSReceiver> Object::ConvertReceiver(Isolate* isolate, | |
122 Handle<Object> object) { | |
123 if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object); | |
124 if (*object == isolate->heap()->null_value() || | |
125 *object == isolate->heap()->undefined_value()) { | |
126 return isolate->global_proxy(); | |
127 } | |
128 return Object::ToObject(isolate, object); | |
129 } | |
130 | 119 |
131 // static | 120 // static |
132 MaybeHandle<Object> Object::ToNumber(Handle<Object> input) { | 121 MaybeHandle<Object> Object::ToNumber(Handle<Object> input) { |
133 while (true) { | 122 while (true) { |
134 if (input->IsNumber()) { | 123 if (input->IsNumber()) { |
135 return input; | 124 return input; |
136 } | 125 } |
137 if (input->IsString()) { | 126 if (input->IsString()) { |
138 return String::ToNumber(Handle<String>::cast(input)); | 127 return String::ToNumber(Handle<String>::cast(input)); |
139 } | 128 } |
(...skipping 5999 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6139 Maybe<bool> JSReceiver::DeletePropertyOrElement(Handle<JSReceiver> object, | 6128 Maybe<bool> JSReceiver::DeletePropertyOrElement(Handle<JSReceiver> object, |
6140 Handle<Name> name, | 6129 Handle<Name> name, |
6141 LanguageMode language_mode) { | 6130 LanguageMode language_mode) { |
6142 LookupIterator it = LookupIterator::PropertyOrElement( | 6131 LookupIterator it = LookupIterator::PropertyOrElement( |
6143 name->GetIsolate(), object, name, object, LookupIterator::HIDDEN); | 6132 name->GetIsolate(), object, name, object, LookupIterator::HIDDEN); |
6144 return DeleteProperty(&it, language_mode); | 6133 return DeleteProperty(&it, language_mode); |
6145 } | 6134 } |
6146 | 6135 |
6147 | 6136 |
6148 // ES6 7.1.14 | 6137 // ES6 7.1.14 |
6149 // static | 6138 MaybeHandle<Object> ToPropertyKey(Isolate* isolate, Handle<Object> value) { |
6150 MaybeHandle<Object> Object::ToPropertyKey(Isolate* isolate, | |
6151 Handle<Object> value) { | |
6152 // 1. Let key be ToPrimitive(argument, hint String). | 6139 // 1. Let key be ToPrimitive(argument, hint String). |
6153 MaybeHandle<Object> maybe_key = | 6140 MaybeHandle<Object> maybe_key = |
6154 Object::ToPrimitive(value, ToPrimitiveHint::kString); | 6141 Object::ToPrimitive(value, ToPrimitiveHint::kString); |
6155 // 2. ReturnIfAbrupt(key). | 6142 // 2. ReturnIfAbrupt(key). |
6156 Handle<Object> key; | 6143 Handle<Object> key; |
6157 if (!maybe_key.ToHandle(&key)) return key; | 6144 if (!maybe_key.ToHandle(&key)) return key; |
6158 // 3. If Type(key) is Symbol, then return key. | 6145 // 3. If Type(key) is Symbol, then return key. |
6159 if (key->IsSymbol()) return key; | 6146 if (key->IsSymbol()) return key; |
6160 // 4. Return ToString(key). | 6147 // 4. Return ToString(key). |
6161 // Extending spec'ed behavior, we'd be happy to return an element index. | 6148 // Extending spec'ed behavior, we'd be happy to return an element index. |
(...skipping 2763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8925 // configurable. See 8.6.1 (Table 5). | 8912 // configurable. See 8.6.1 (Table 5). |
8926 if (it.IsFound() && !it.IsConfigurable()) { | 8913 if (it.IsFound() && !it.IsConfigurable()) { |
8927 return it.factory()->undefined_value(); | 8914 return it.factory()->undefined_value(); |
8928 } | 8915 } |
8929 | 8916 |
8930 it.TransitionToAccessorPair(info, info->property_attributes()); | 8917 it.TransitionToAccessorPair(info, info->property_attributes()); |
8931 | 8918 |
8932 return object; | 8919 return object; |
8933 } | 8920 } |
8934 | 8921 |
| 8922 |
| 8923 MaybeHandle<Object> JSObject::GetAccessor(Handle<JSObject> object, |
| 8924 Handle<Name> name, |
| 8925 AccessorComponent component) { |
| 8926 Isolate* isolate = object->GetIsolate(); |
| 8927 |
| 8928 // Make sure that the top context does not change when doing callbacks or |
| 8929 // interceptor calls. |
| 8930 AssertNoContextChange ncc(isolate); |
| 8931 |
| 8932 LookupIterator it = LookupIterator::PropertyOrElement( |
| 8933 isolate, object, name, LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR); |
| 8934 |
| 8935 for (; it.IsFound(); it.Next()) { |
| 8936 switch (it.state()) { |
| 8937 case LookupIterator::INTERCEPTOR: |
| 8938 case LookupIterator::NOT_FOUND: |
| 8939 case LookupIterator::TRANSITION: |
| 8940 UNREACHABLE(); |
| 8941 |
| 8942 case LookupIterator::ACCESS_CHECK: |
| 8943 if (it.HasAccess()) continue; |
| 8944 isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>()); |
| 8945 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 8946 return isolate->factory()->undefined_value(); |
| 8947 |
| 8948 case LookupIterator::JSPROXY: |
| 8949 return isolate->factory()->undefined_value(); |
| 8950 |
| 8951 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
| 8952 return isolate->factory()->undefined_value(); |
| 8953 case LookupIterator::DATA: |
| 8954 continue; |
| 8955 case LookupIterator::ACCESSOR: { |
| 8956 Handle<Object> maybe_pair = it.GetAccessors(); |
| 8957 if (maybe_pair->IsAccessorPair()) { |
| 8958 return AccessorPair::GetComponent( |
| 8959 Handle<AccessorPair>::cast(maybe_pair), component); |
| 8960 } |
| 8961 } |
| 8962 } |
| 8963 } |
| 8964 |
| 8965 return isolate->factory()->undefined_value(); |
| 8966 } |
| 8967 |
| 8968 |
8935 Object* JSObject::SlowReverseLookup(Object* value) { | 8969 Object* JSObject::SlowReverseLookup(Object* value) { |
8936 if (HasFastProperties()) { | 8970 if (HasFastProperties()) { |
8937 int number_of_own_descriptors = map()->NumberOfOwnDescriptors(); | 8971 int number_of_own_descriptors = map()->NumberOfOwnDescriptors(); |
8938 DescriptorArray* descs = map()->instance_descriptors(); | 8972 DescriptorArray* descs = map()->instance_descriptors(); |
8939 bool value_is_number = value->IsNumber(); | 8973 bool value_is_number = value->IsNumber(); |
8940 for (int i = 0; i < number_of_own_descriptors; i++) { | 8974 for (int i = 0; i < number_of_own_descriptors; i++) { |
8941 if (descs->GetType(i) == DATA) { | 8975 if (descs->GetType(i) == DATA) { |
8942 FieldIndex field_index = FieldIndex::ForDescriptor(map(), i); | 8976 FieldIndex field_index = FieldIndex::ForDescriptor(map(), i); |
8943 if (IsUnboxedDoubleField(field_index)) { | 8977 if (IsUnboxedDoubleField(field_index)) { |
8944 if (value_is_number) { | 8978 if (value_is_number) { |
(...skipping 6796 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15741 if (constructor->shared()->IsApiFunction()) { | 15775 if (constructor->shared()->IsApiFunction()) { |
15742 DCHECK(is_api_object); | 15776 DCHECK(is_api_object); |
15743 } else { | 15777 } else { |
15744 DCHECK(!is_api_object); | 15778 DCHECK(!is_api_object); |
15745 } | 15779 } |
15746 } | 15780 } |
15747 #endif | 15781 #endif |
15748 return is_api_object; | 15782 return is_api_object; |
15749 } | 15783 } |
15750 | 15784 |
| 15785 int JSObject::NumberOfOwnElements(PropertyFilter filter) { |
| 15786 // Fast case for objects with no elements. |
| 15787 if (!IsJSValue() && HasFastElements()) { |
| 15788 uint32_t length = |
| 15789 IsJSArray() |
| 15790 ? static_cast<uint32_t>( |
| 15791 Smi::cast(JSArray::cast(this)->length())->value()) |
| 15792 : static_cast<uint32_t>(FixedArrayBase::cast(elements())->length()); |
| 15793 if (length == 0) return 0; |
| 15794 } |
| 15795 // Compute the number of enumerable elements. |
| 15796 return GetOwnElementKeys(NULL, filter); |
| 15797 } |
| 15798 |
15751 void JSObject::CollectOwnElementKeys(Handle<JSObject> object, | 15799 void JSObject::CollectOwnElementKeys(Handle<JSObject> object, |
15752 KeyAccumulator* keys, | 15800 KeyAccumulator* keys, |
15753 PropertyFilter filter) { | 15801 PropertyFilter filter) { |
15754 if (filter & SKIP_STRINGS) return; | 15802 if (filter & SKIP_STRINGS) return; |
15755 ElementsAccessor* accessor = object->GetElementsAccessor(); | 15803 ElementsAccessor* accessor = object->GetElementsAccessor(); |
15756 accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0); | 15804 accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0); |
15757 } | 15805 } |
15758 | 15806 |
15759 | 15807 |
| 15808 int JSObject::GetOwnElementKeys(FixedArray* storage, PropertyFilter filter) { |
| 15809 int counter = 0; |
| 15810 |
| 15811 // If this is a String wrapper, add the string indices first, |
| 15812 // as they're guaranteed to precede the elements in numerical order |
| 15813 // and ascending order is required by ECMA-262, 6th, 9.1.12. |
| 15814 if (IsJSValue()) { |
| 15815 Object* val = JSValue::cast(this)->value(); |
| 15816 if (val->IsString()) { |
| 15817 String* str = String::cast(val); |
| 15818 if (storage) { |
| 15819 for (int i = 0; i < str->length(); i++) { |
| 15820 storage->set(counter + i, Smi::FromInt(i)); |
| 15821 } |
| 15822 } |
| 15823 counter += str->length(); |
| 15824 } |
| 15825 } |
| 15826 |
| 15827 switch (GetElementsKind()) { |
| 15828 case FAST_SMI_ELEMENTS: |
| 15829 case FAST_ELEMENTS: |
| 15830 case FAST_HOLEY_SMI_ELEMENTS: |
| 15831 case FAST_HOLEY_ELEMENTS: |
| 15832 case FAST_STRING_WRAPPER_ELEMENTS: { |
| 15833 int length = IsJSArray() ? |
| 15834 Smi::cast(JSArray::cast(this)->length())->value() : |
| 15835 FixedArray::cast(elements())->length(); |
| 15836 for (int i = 0; i < length; i++) { |
| 15837 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { |
| 15838 if (storage != NULL) { |
| 15839 storage->set(counter, Smi::FromInt(i)); |
| 15840 } |
| 15841 counter++; |
| 15842 } |
| 15843 } |
| 15844 DCHECK(!storage || storage->length() >= counter); |
| 15845 break; |
| 15846 } |
| 15847 case FAST_DOUBLE_ELEMENTS: |
| 15848 case FAST_HOLEY_DOUBLE_ELEMENTS: { |
| 15849 int length = IsJSArray() ? |
| 15850 Smi::cast(JSArray::cast(this)->length())->value() : |
| 15851 FixedArrayBase::cast(elements())->length(); |
| 15852 for (int i = 0; i < length; i++) { |
| 15853 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) { |
| 15854 if (storage != NULL) { |
| 15855 storage->set(counter, Smi::FromInt(i)); |
| 15856 } |
| 15857 counter++; |
| 15858 } |
| 15859 } |
| 15860 DCHECK(!storage || storage->length() >= counter); |
| 15861 break; |
| 15862 } |
| 15863 |
| 15864 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
| 15865 case TYPE##_ELEMENTS: \ |
| 15866 |
| 15867 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 15868 #undef TYPED_ARRAY_CASE |
| 15869 { |
| 15870 int length = FixedArrayBase::cast(elements())->length(); |
| 15871 while (counter < length) { |
| 15872 if (storage != NULL) { |
| 15873 storage->set(counter, Smi::FromInt(counter)); |
| 15874 } |
| 15875 counter++; |
| 15876 } |
| 15877 DCHECK(!storage || storage->length() >= counter); |
| 15878 break; |
| 15879 } |
| 15880 |
| 15881 case DICTIONARY_ELEMENTS: |
| 15882 case SLOW_STRING_WRAPPER_ELEMENTS: { |
| 15883 if (storage != NULL) { |
| 15884 element_dictionary()->CopyKeysTo(storage, counter, filter, |
| 15885 SeededNumberDictionary::SORTED); |
| 15886 } |
| 15887 counter += element_dictionary()->NumberOfElementsFilterAttributes(filter); |
| 15888 break; |
| 15889 } |
| 15890 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
| 15891 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { |
| 15892 FixedArray* parameter_map = FixedArray::cast(elements()); |
| 15893 int mapped_length = parameter_map->length() - 2; |
| 15894 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 15895 if (arguments->IsDictionary()) { |
| 15896 // Copy the keys from arguments first, because Dictionary::CopyKeysTo |
| 15897 // will insert in storage starting at index 0. |
| 15898 SeededNumberDictionary* dictionary = |
| 15899 SeededNumberDictionary::cast(arguments); |
| 15900 if (storage != NULL) { |
| 15901 dictionary->CopyKeysTo(storage, counter, filter, |
| 15902 SeededNumberDictionary::UNSORTED); |
| 15903 } |
| 15904 counter += dictionary->NumberOfElementsFilterAttributes(filter); |
| 15905 for (int i = 0; i < mapped_length; ++i) { |
| 15906 if (!parameter_map->get(i + 2)->IsTheHole()) { |
| 15907 if (storage != NULL) storage->set(counter, Smi::FromInt(i)); |
| 15908 ++counter; |
| 15909 } |
| 15910 } |
| 15911 if (storage != NULL) storage->SortPairs(storage, counter); |
| 15912 |
| 15913 } else { |
| 15914 int backing_length = arguments->length(); |
| 15915 int i = 0; |
| 15916 for (; i < mapped_length; ++i) { |
| 15917 if (!parameter_map->get(i + 2)->IsTheHole()) { |
| 15918 if (storage != NULL) storage->set(counter, Smi::FromInt(i)); |
| 15919 ++counter; |
| 15920 } else if (i < backing_length && !arguments->get(i)->IsTheHole()) { |
| 15921 if (storage != NULL) storage->set(counter, Smi::FromInt(i)); |
| 15922 ++counter; |
| 15923 } |
| 15924 } |
| 15925 for (; i < backing_length; ++i) { |
| 15926 if (storage != NULL) storage->set(counter, Smi::FromInt(i)); |
| 15927 ++counter; |
| 15928 } |
| 15929 } |
| 15930 break; |
| 15931 } |
| 15932 case NO_ELEMENTS: |
| 15933 break; |
| 15934 } |
| 15935 |
| 15936 DCHECK(!storage || storage->length() == counter); |
| 15937 return counter; |
| 15938 } |
| 15939 |
| 15940 |
15760 MaybeHandle<String> Object::ObjectProtoToString(Isolate* isolate, | 15941 MaybeHandle<String> Object::ObjectProtoToString(Isolate* isolate, |
15761 Handle<Object> object) { | 15942 Handle<Object> object) { |
15762 if (object->IsUndefined()) return isolate->factory()->undefined_to_string(); | 15943 if (object->IsUndefined()) return isolate->factory()->undefined_to_string(); |
15763 if (object->IsNull()) return isolate->factory()->null_to_string(); | 15944 if (object->IsNull()) return isolate->factory()->null_to_string(); |
15764 | 15945 |
15765 Handle<JSReceiver> receiver = | 15946 Handle<JSReceiver> receiver = |
15766 Object::ToObject(isolate, object).ToHandleChecked(); | 15947 Object::ToObject(isolate, object).ToHandleChecked(); |
15767 | 15948 |
15768 Handle<String> tag; | 15949 Handle<String> tag; |
15769 Handle<Object> to_string_tag; | 15950 Handle<Object> to_string_tag; |
(...skipping 1823 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17593 CHECK_EQ(length, properties); | 17774 CHECK_EQ(length, properties); |
17594 EnumIndexComparator<Derived> cmp(static_cast<Derived*>(this)); | 17775 EnumIndexComparator<Derived> cmp(static_cast<Derived*>(this)); |
17595 Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress()); | 17776 Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress()); |
17596 std::sort(start, start + length, cmp); | 17777 std::sort(start, start + length, cmp); |
17597 for (int i = 0; i < length; i++) { | 17778 for (int i = 0; i < length; i++) { |
17598 int index = Smi::cast(storage->get(i))->value(); | 17779 int index = Smi::cast(storage->get(i))->value(); |
17599 storage->set(i, this->KeyAt(index)); | 17780 storage->set(i, this->KeyAt(index)); |
17600 } | 17781 } |
17601 } | 17782 } |
17602 | 17783 |
| 17784 |
| 17785 template <typename Derived, typename Shape, typename Key> |
| 17786 int Dictionary<Derived, Shape, Key>::CopyKeysTo( |
| 17787 FixedArray* storage, int index, PropertyFilter filter, |
| 17788 typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) { |
| 17789 DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter)); |
| 17790 int start_index = index; |
| 17791 int capacity = this->Capacity(); |
| 17792 for (int i = 0; i < capacity; i++) { |
| 17793 Object* k = this->KeyAt(i); |
| 17794 if (!this->IsKey(k) || k->FilterKey(filter)) continue; |
| 17795 if (this->IsDeleted(i)) continue; |
| 17796 PropertyDetails details = this->DetailsAt(i); |
| 17797 PropertyAttributes attr = details.attributes(); |
| 17798 if ((attr & filter) != 0) continue; |
| 17799 storage->set(index++, k); |
| 17800 } |
| 17801 if (sort_mode == Dictionary::SORTED) { |
| 17802 storage->SortPairs(storage, index); |
| 17803 } |
| 17804 DCHECK(storage->length() >= index); |
| 17805 return index - start_index; |
| 17806 } |
| 17807 |
17603 template <typename Derived, typename Shape, typename Key> | 17808 template <typename Derived, typename Shape, typename Key> |
17604 void Dictionary<Derived, Shape, Key>::CollectKeysTo( | 17809 void Dictionary<Derived, Shape, Key>::CollectKeysTo( |
17605 Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys, | 17810 Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys, |
17606 PropertyFilter filter) { | 17811 PropertyFilter filter) { |
17607 int capacity = dictionary->Capacity(); | 17812 int capacity = dictionary->Capacity(); |
17608 Handle<FixedArray> array = | 17813 Handle<FixedArray> array = |
17609 keys->isolate()->factory()->NewFixedArray(dictionary->NumberOfElements()); | 17814 keys->isolate()->factory()->NewFixedArray(dictionary->NumberOfElements()); |
17610 int array_size = 0; | 17815 int array_size = 0; |
17611 | 17816 |
17612 { | 17817 { |
(...skipping 1274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
18887 if (cell->value() != *new_value) { | 19092 if (cell->value() != *new_value) { |
18888 cell->set_value(*new_value); | 19093 cell->set_value(*new_value); |
18889 Isolate* isolate = cell->GetIsolate(); | 19094 Isolate* isolate = cell->GetIsolate(); |
18890 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 19095 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
18891 isolate, DependentCode::kPropertyCellChangedGroup); | 19096 isolate, DependentCode::kPropertyCellChangedGroup); |
18892 } | 19097 } |
18893 } | 19098 } |
18894 | 19099 |
18895 } // namespace internal | 19100 } // namespace internal |
18896 } // namespace v8 | 19101 } // namespace v8 |
OLD | NEW |