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 } |
119 | 130 |
120 // static | 131 // static |
121 MaybeHandle<Object> Object::ToNumber(Handle<Object> input) { | 132 MaybeHandle<Object> Object::ToNumber(Handle<Object> input) { |
122 while (true) { | 133 while (true) { |
123 if (input->IsNumber()) { | 134 if (input->IsNumber()) { |
124 return input; | 135 return input; |
125 } | 136 } |
126 if (input->IsString()) { | 137 if (input->IsString()) { |
127 return String::ToNumber(Handle<String>::cast(input)); | 138 return String::ToNumber(Handle<String>::cast(input)); |
128 } | 139 } |
(...skipping 5999 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6128 Maybe<bool> JSReceiver::DeletePropertyOrElement(Handle<JSReceiver> object, | 6139 Maybe<bool> JSReceiver::DeletePropertyOrElement(Handle<JSReceiver> object, |
6129 Handle<Name> name, | 6140 Handle<Name> name, |
6130 LanguageMode language_mode) { | 6141 LanguageMode language_mode) { |
6131 LookupIterator it = LookupIterator::PropertyOrElement( | 6142 LookupIterator it = LookupIterator::PropertyOrElement( |
6132 name->GetIsolate(), object, name, object, LookupIterator::HIDDEN); | 6143 name->GetIsolate(), object, name, object, LookupIterator::HIDDEN); |
6133 return DeleteProperty(&it, language_mode); | 6144 return DeleteProperty(&it, language_mode); |
6134 } | 6145 } |
6135 | 6146 |
6136 | 6147 |
6137 // ES6 7.1.14 | 6148 // ES6 7.1.14 |
6138 MaybeHandle<Object> ToPropertyKey(Isolate* isolate, Handle<Object> value) { | 6149 // static |
| 6150 MaybeHandle<Object> Object::ToPropertyKey(Isolate* isolate, |
| 6151 Handle<Object> value) { |
6139 // 1. Let key be ToPrimitive(argument, hint String). | 6152 // 1. Let key be ToPrimitive(argument, hint String). |
6140 MaybeHandle<Object> maybe_key = | 6153 MaybeHandle<Object> maybe_key = |
6141 Object::ToPrimitive(value, ToPrimitiveHint::kString); | 6154 Object::ToPrimitive(value, ToPrimitiveHint::kString); |
6142 // 2. ReturnIfAbrupt(key). | 6155 // 2. ReturnIfAbrupt(key). |
6143 Handle<Object> key; | 6156 Handle<Object> key; |
6144 if (!maybe_key.ToHandle(&key)) return key; | 6157 if (!maybe_key.ToHandle(&key)) return key; |
6145 // 3. If Type(key) is Symbol, then return key. | 6158 // 3. If Type(key) is Symbol, then return key. |
6146 if (key->IsSymbol()) return key; | 6159 if (key->IsSymbol()) return key; |
6147 // 4. Return ToString(key). | 6160 // 4. Return ToString(key). |
6148 // Extending spec'ed behavior, we'd be happy to return an element index. | 6161 // 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... |
8912 // configurable. See 8.6.1 (Table 5). | 8925 // configurable. See 8.6.1 (Table 5). |
8913 if (it.IsFound() && !it.IsConfigurable()) { | 8926 if (it.IsFound() && !it.IsConfigurable()) { |
8914 return it.factory()->undefined_value(); | 8927 return it.factory()->undefined_value(); |
8915 } | 8928 } |
8916 | 8929 |
8917 it.TransitionToAccessorPair(info, info->property_attributes()); | 8930 it.TransitionToAccessorPair(info, info->property_attributes()); |
8918 | 8931 |
8919 return object; | 8932 return object; |
8920 } | 8933 } |
8921 | 8934 |
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 | |
8969 Object* JSObject::SlowReverseLookup(Object* value) { | 8935 Object* JSObject::SlowReverseLookup(Object* value) { |
8970 if (HasFastProperties()) { | 8936 if (HasFastProperties()) { |
8971 int number_of_own_descriptors = map()->NumberOfOwnDescriptors(); | 8937 int number_of_own_descriptors = map()->NumberOfOwnDescriptors(); |
8972 DescriptorArray* descs = map()->instance_descriptors(); | 8938 DescriptorArray* descs = map()->instance_descriptors(); |
8973 bool value_is_number = value->IsNumber(); | 8939 bool value_is_number = value->IsNumber(); |
8974 for (int i = 0; i < number_of_own_descriptors; i++) { | 8940 for (int i = 0; i < number_of_own_descriptors; i++) { |
8975 if (descs->GetType(i) == DATA) { | 8941 if (descs->GetType(i) == DATA) { |
8976 FieldIndex field_index = FieldIndex::ForDescriptor(map(), i); | 8942 FieldIndex field_index = FieldIndex::ForDescriptor(map(), i); |
8977 if (IsUnboxedDoubleField(field_index)) { | 8943 if (IsUnboxedDoubleField(field_index)) { |
8978 if (value_is_number) { | 8944 if (value_is_number) { |
(...skipping 6796 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15775 if (constructor->shared()->IsApiFunction()) { | 15741 if (constructor->shared()->IsApiFunction()) { |
15776 DCHECK(is_api_object); | 15742 DCHECK(is_api_object); |
15777 } else { | 15743 } else { |
15778 DCHECK(!is_api_object); | 15744 DCHECK(!is_api_object); |
15779 } | 15745 } |
15780 } | 15746 } |
15781 #endif | 15747 #endif |
15782 return is_api_object; | 15748 return is_api_object; |
15783 } | 15749 } |
15784 | 15750 |
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 | |
15799 void JSObject::CollectOwnElementKeys(Handle<JSObject> object, | 15751 void JSObject::CollectOwnElementKeys(Handle<JSObject> object, |
15800 KeyAccumulator* keys, | 15752 KeyAccumulator* keys, |
15801 PropertyFilter filter) { | 15753 PropertyFilter filter) { |
15802 if (filter & SKIP_STRINGS) return; | 15754 if (filter & SKIP_STRINGS) return; |
15803 ElementsAccessor* accessor = object->GetElementsAccessor(); | 15755 ElementsAccessor* accessor = object->GetElementsAccessor(); |
15804 accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0); | 15756 accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0); |
15805 } | 15757 } |
15806 | 15758 |
15807 | 15759 |
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 | |
15941 MaybeHandle<String> Object::ObjectProtoToString(Isolate* isolate, | 15760 MaybeHandle<String> Object::ObjectProtoToString(Isolate* isolate, |
15942 Handle<Object> object) { | 15761 Handle<Object> object) { |
15943 if (object->IsUndefined()) return isolate->factory()->undefined_to_string(); | 15762 if (object->IsUndefined()) return isolate->factory()->undefined_to_string(); |
15944 if (object->IsNull()) return isolate->factory()->null_to_string(); | 15763 if (object->IsNull()) return isolate->factory()->null_to_string(); |
15945 | 15764 |
15946 Handle<JSReceiver> receiver = | 15765 Handle<JSReceiver> receiver = |
15947 Object::ToObject(isolate, object).ToHandleChecked(); | 15766 Object::ToObject(isolate, object).ToHandleChecked(); |
15948 | 15767 |
15949 Handle<String> tag; | 15768 Handle<String> tag; |
15950 Handle<Object> to_string_tag; | 15769 Handle<Object> to_string_tag; |
(...skipping 1823 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17774 CHECK_EQ(length, properties); | 17593 CHECK_EQ(length, properties); |
17775 EnumIndexComparator<Derived> cmp(static_cast<Derived*>(this)); | 17594 EnumIndexComparator<Derived> cmp(static_cast<Derived*>(this)); |
17776 Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress()); | 17595 Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress()); |
17777 std::sort(start, start + length, cmp); | 17596 std::sort(start, start + length, cmp); |
17778 for (int i = 0; i < length; i++) { | 17597 for (int i = 0; i < length; i++) { |
17779 int index = Smi::cast(storage->get(i))->value(); | 17598 int index = Smi::cast(storage->get(i))->value(); |
17780 storage->set(i, this->KeyAt(index)); | 17599 storage->set(i, this->KeyAt(index)); |
17781 } | 17600 } |
17782 } | 17601 } |
17783 | 17602 |
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 | |
17808 template <typename Derived, typename Shape, typename Key> | 17603 template <typename Derived, typename Shape, typename Key> |
17809 void Dictionary<Derived, Shape, Key>::CollectKeysTo( | 17604 void Dictionary<Derived, Shape, Key>::CollectKeysTo( |
17810 Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys, | 17605 Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys, |
17811 PropertyFilter filter) { | 17606 PropertyFilter filter) { |
17812 int capacity = dictionary->Capacity(); | 17607 int capacity = dictionary->Capacity(); |
17813 Handle<FixedArray> array = | 17608 Handle<FixedArray> array = |
17814 keys->isolate()->factory()->NewFixedArray(dictionary->NumberOfElements()); | 17609 keys->isolate()->factory()->NewFixedArray(dictionary->NumberOfElements()); |
17815 int array_size = 0; | 17610 int array_size = 0; |
17816 | 17611 |
17817 { | 17612 { |
(...skipping 1274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19092 if (cell->value() != *new_value) { | 18887 if (cell->value() != *new_value) { |
19093 cell->set_value(*new_value); | 18888 cell->set_value(*new_value); |
19094 Isolate* isolate = cell->GetIsolate(); | 18889 Isolate* isolate = cell->GetIsolate(); |
19095 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 18890 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
19096 isolate, DependentCode::kPropertyCellChangedGroup); | 18891 isolate, DependentCode::kPropertyCellChangedGroup); |
19097 } | 18892 } |
19098 } | 18893 } |
19099 | 18894 |
19100 } // namespace internal | 18895 } // namespace internal |
19101 } // namespace v8 | 18896 } // namespace v8 |
OLD | NEW |