5 #include "src/arguments-inl.h" 6 #include "src/code-stubs.h" 7 #include "src/conversions-inl.h" 8 #include "src/counters.h" 9 #include "src/debug/debug.h" 10 #include "src/elements.h" 11 #include "src/heap/factory.h" 12 #include "src/isolate-inl.h" 14 #include "src/objects/arguments-inl.h" 15 #include "src/objects/hash-table-inl.h" 16 #include "src/objects/js-array-inl.h" 17 #include "src/prototype.h" 18 #include "src/runtime/runtime-utils.h" 23 RUNTIME_FUNCTION(Runtime_TransitionElementsKind) {
24 HandleScope scope(isolate);
25 DCHECK_EQ(2, args.length());
26 CONVERT_ARG_HANDLE_CHECKED(JSObject,
object, 0);
27 CONVERT_ARG_HANDLE_CHECKED(Map, to_map, 1);
28 ElementsKind to_kind = to_map->elements_kind();
29 ElementsAccessor::ForKind(to_kind)->TransitionElementsKind(
object, to_map);
33 RUNTIME_FUNCTION(Runtime_TransitionElementsKindWithKind) {
34 HandleScope scope(isolate);
35 DCHECK_EQ(2, args.length());
36 CONVERT_ARG_HANDLE_CHECKED(JSObject,
object, 0);
37 CONVERT_ARG_HANDLE_CHECKED(Smi, elements_kind_smi, 1);
38 ElementsKind to_kind =
static_cast<ElementsKind
>(elements_kind_smi->value());
39 JSObject::TransitionElementsKind(
object, to_kind);
47 Maybe<uint32_t> FindNextFreePosition(Isolate* isolate,
48 Handle<JSReceiver> receiver,
50 for (
uint32_t position = current_pos;; ++position) {
51 Maybe<bool> has_element = JSReceiver::HasElement(receiver, position);
52 MAYBE_RETURN(has_element, Nothing<uint32_t>());
53 if (!has_element.FromJust())
return Just(position);
55 Handle<Object> element;
56 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
57 isolate, element, JSReceiver::GetElement(isolate, receiver, position),
59 if (element->IsUndefined(isolate))
return Just(position);
67 Object* RemoveArrayHolesGeneric(Isolate* isolate, Handle<JSReceiver> receiver,
69 HandleScope scope(isolate);
73 Handle<FixedArray> keys;
74 if (!receiver->IsJSProxy()) {
75 keys = JSReceiver::GetOwnElementIndices(isolate, receiver,
76 Handle<JSObject>::cast(receiver));
81 int num_indices = keys.is_null() ? limit : keys->length();
92 for (
int i = 0;
i < num_indices; ++
i) {
93 uint32_t key = keys.is_null() ?
i : NumberToUint32(keys->get(
i));
97 if (key >= limit)
break;
99 Maybe<bool> has_element = JSReceiver::HasElement(receiver, key);
100 MAYBE_RETURN(has_element, ReadOnlyRoots(isolate).exception());
101 if (!has_element.FromJust()) {
105 Handle<Object> element;
106 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
107 isolate, element, JSReceiver::GetElement(isolate, receiver, key));
109 if (element->IsUndefined(isolate)) {
113 Maybe<uint32_t> free_position =
114 FindNextFreePosition(isolate, receiver, current_pos);
115 MAYBE_RETURN(free_position, ReadOnlyRoots(isolate).exception());
116 current_pos = free_position.FromJust();
119 if (key <= current_pos)
continue;
128 RETURN_FAILURE_ON_EXCEPTION(
129 isolate, JSReceiver::SetElement(isolate, receiver, current_pos,
130 element, LanguageMode::kStrict));
138 RETURN_FAILURE_ON_EXCEPTION(
139 isolate, JSReceiver::SetElement(isolate, receiver, current_pos++,
140 isolate->factory()->undefined_value(),
141 LanguageMode::kStrict));
149 for (
int i = num_indices - 1;
i >= 0; --
i) {
150 uint32_t key = keys.is_null() ?
i : NumberToUint32(keys->get(
i));
151 if (key < current_pos)
break;
152 if (key >= limit)
continue;
154 Maybe<bool> delete_result = JSReceiver::DeleteElement(receiver, key);
155 MAYBE_RETURN(delete_result, ReadOnlyRoots(isolate).exception());
163 const uint32_t number_of_non_undefined_elements = std::min(limit, result);
165 return *isolate->factory()->NewNumberFromUint(
166 number_of_non_undefined_elements);
173 V8_WARN_UNUSED_RESULT
174 Object* RemoveArrayHoles(Isolate* isolate, Handle<JSReceiver> receiver,
176 if (receiver->IsJSProxy()) {
177 return RemoveArrayHolesGeneric(isolate, receiver, limit);
180 Handle<JSObject>
object = Handle<JSObject>::cast(receiver);
181 if (object->HasStringWrapperElements()) {
182 int len = String::cast(Handle<JSValue>::cast(
object)->value())->length();
183 DCHECK_LE(len, limit);
184 return Smi::FromInt(len);
187 if (object->HasSloppyArgumentsElements() || !
object->map()->is_extensible()) {
188 return RemoveArrayHolesGeneric(isolate, receiver, limit);
191 JSObject::ValidateElements(*
object);
192 if (object->HasDictionaryElements()) {
195 Handle<NumberDictionary> dict(object->element_dictionary(), isolate);
196 if (object->IsJSArray() || dict->requires_slow_elements() ||
197 dict->max_number_key() >= limit) {
198 return RemoveArrayHolesGeneric(isolate, receiver, limit);
201 Handle<Map> new_map =
202 JSObject::GetElementsTransitionMap(
object, HOLEY_ELEMENTS);
204 PretenureFlag tenure = Heap::InNewSpace(*
object) ? NOT_TENURED : TENURED;
205 Handle<FixedArray> fast_elements =
206 isolate->factory()->NewFixedArray(dict->NumberOfElements(), tenure);
207 dict->CopyValuesTo(*fast_elements);
209 JSObject::SetMapAndElements(
object, new_map, fast_elements);
210 JSObject::ValidateElements(*
object);
211 }
else if (object->HasFixedTypedArrayElements()) {
213 int array_length = FixedArrayBase::cast(object->elements())->length();
214 return Smi::FromInt(Min(limit, static_cast<uint32_t>(array_length)));
215 }
else if (!object->HasDoubleElements()) {
216 JSObject::EnsureWritableFastElements(
object);
218 DCHECK(object->HasSmiOrObjectElements() ||
object->HasDoubleElements());
223 Handle<FixedArrayBase> elements_base(object->elements(), isolate);
225 if (limit > elements_length) {
226 limit = elements_length;
233 if (elements_base->map() == ReadOnlyRoots(isolate).fixed_double_array_map()) {
234 FixedDoubleArray elements = FixedDoubleArray::cast(*elements_base);
236 unsigned int holes = limit;
239 for (
unsigned int i = 0;
i < holes;
i++) {
240 if (elements->is_the_hole(
i)) {
247 if (elements->is_the_hole(holes)) {
250 elements->set(
i, elements->get_scalar(holes));
256 while (holes < limit) {
257 elements->set_the_hole(holes);
261 FixedArray elements = FixedArray::cast(*elements_base);
262 DisallowHeapAllocation no_gc;
266 WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_gc);
267 unsigned int undefs = limit;
268 unsigned int holes = limit;
271 for (
unsigned int i = 0;
i < undefs;
i++) {
272 Object* current = elements->get(
i);
273 if (current->IsTheHole(isolate)) {
276 }
else if (current->IsUndefined(isolate)) {
283 current = elements->get(undefs);
284 if (current->IsTheHole(isolate)) {
287 }
else if (current->IsUndefined(isolate)) {
290 elements->set(
i, current, write_barrier);
296 while (undefs < holes) {
297 elements->set_undefined(isolate, undefs);
300 while (holes < limit) {
301 elements->set_the_hole(isolate, holes);
306 DCHECK_LE(result, limit);
307 return *isolate->factory()->NewNumberFromUint(result);
313 V8_WARN_UNUSED_RESULT
314 Maybe<bool> ConditionalCopy(Isolate* isolate, Handle<JSReceiver> source,
315 Handle<JSReceiver> target,
uint32_t index) {
316 Maybe<bool> source_has_prop = JSReceiver::HasOwnProperty(source, index);
317 MAYBE_RETURN(source_has_prop, Nothing<bool>());
318 if (!source_has_prop.FromJust())
return Just(
false);
320 Maybe<bool> target_has_prop = JSReceiver::HasOwnProperty(target, index);
321 MAYBE_RETURN(target_has_prop, Nothing<bool>());
322 if (target_has_prop.FromJust())
return Just(
false);
324 Handle<Object> source_element;
325 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
326 isolate, source_element, JSReceiver::GetElement(isolate, target, index),
329 Handle<Object> set_result;
330 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
332 JSReceiver::SetElement(isolate, target, index, source_element,
333 LanguageMode::kStrict),
342 V8_WARN_UNUSED_RESULT
343 MaybeHandle<Object> CopyFromPrototype(Isolate* isolate,
344 Handle<JSReceiver>
object,
346 for (PrototypeIterator iter(isolate,
object, kStartAtPrototype);
347 !iter.IsAtEnd(); iter.Advance()) {
348 Handle<JSReceiver> current(PrototypeIterator::GetCurrent<JSReceiver>(iter));
350 if (current->IsJSProxy()) {
352 MAYBE_RETURN_NULL(ConditionalCopy(isolate, current,
object,
i));
355 Handle<FixedArray> keys = JSReceiver::GetOwnElementIndices(
356 isolate,
object, Handle<JSObject>::cast(current));
358 uint32_t num_indices = keys->length();
360 uint32_t idx = NumberToUint32(keys->get(
i));
364 if (idx >= length)
break;
366 MAYBE_RETURN_NULL(ConditionalCopy(isolate, current,
object, idx));
370 return isolate->factory()->undefined_value();
375 RUNTIME_FUNCTION(Runtime_PrepareElementsForSort) {
376 HandleScope scope(isolate);
377 DCHECK_EQ(2, args.length());
378 CONVERT_ARG_HANDLE_CHECKED(JSReceiver,
object, 0);
379 CONVERT_NUMBER_CHECKED(
uint32_t, length, Uint32, args[1]);
381 if (isolate->debug_execution_mode() == DebugInfo::kSideEffects) {
382 if (!isolate->debug()->PerformSideEffectCheckForObject(
object)) {
383 return ReadOnlyRoots(isolate).exception();
390 if (object->IsJSArray() &&
391 !Handle<JSArray>::cast(
object)->HasFastPackedElements()) {
392 JSObject* initial_array_proto = JSObject::cast(
393 isolate->native_context()->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX));
394 if (!isolate->IsNoElementsProtectorIntact() ||
395 object->map()->prototype() != initial_array_proto) {
397 v8::Isolate::kArrayPrototypeSortJSArrayModifiedPrototype);
401 if (!object->IsJSArray()) {
402 RETURN_FAILURE_ON_EXCEPTION(isolate,
403 CopyFromPrototype(isolate,
object, length));
405 return RemoveArrayHoles(isolate,
object, length);
409 RUNTIME_FUNCTION(Runtime_EstimateNumberOfElements) {
410 DisallowHeapAllocation no_gc;
411 HandleScope scope(isolate);
412 DCHECK_EQ(1, args.length());
413 CONVERT_ARG_CHECKED(JSArray, array, 0);
414 FixedArrayBase elements = array->elements();
415 SealHandleScope shs(isolate);
416 if (elements->IsNumberDictionary()) {
417 int result = NumberDictionary::cast(elements)->NumberOfElements();
418 return Smi::FromInt(result);
420 DCHECK(array->length()->IsSmi());
422 int length = elements->length();
423 ElementsKind kind = array->GetElementsKind();
424 if (IsFastPackedElementsKind(kind)) {
425 return Smi::FromInt(length);
429 const int kNumberOfHoleCheckSamples = 97;
430 int increment = (length < kNumberOfHoleCheckSamples)
432 : static_cast<int>(length / kNumberOfHoleCheckSamples);
433 ElementsAccessor* accessor = array->GetElementsAccessor();
435 for (
int i = 0;
i < length;
i += increment) {
436 if (!accessor->HasElement(array,
i, elements)) {
440 int estimate =
static_cast<int>((kNumberOfHoleCheckSamples - holes) /
441 kNumberOfHoleCheckSamples * length);
442 return Smi::FromInt(estimate);
452 RUNTIME_FUNCTION(Runtime_GetArrayKeys) {
453 HandleScope scope(isolate);
454 DCHECK_EQ(2, args.length());
455 CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
456 CONVERT_NUMBER_CHECKED(
uint32_t, length, Uint32, args[1]);
457 ElementsKind kind = array->GetElementsKind();
459 if (IsFastElementsKind(kind) || IsFixedTypedArrayElementsKind(kind)) {
460 uint32_t actual_length =
static_cast<uint32_t>(array->elements()->length());
461 return *isolate->factory()->NewNumberFromUint(Min(actual_length, length));
464 if (kind == FAST_STRING_WRAPPER_ELEMENTS) {
466 String::cast(Handle<JSValue>::cast(array)->value())->length();
467 int backing_store_length = array->elements()->length();
468 return *isolate->factory()->NewNumberFromUint(
470 static_cast<uint32_t>(Max(string_length, backing_store_length))));
473 KeyAccumulator accumulator(isolate, KeyCollectionMode::kOwnOnly,
475 for (PrototypeIterator iter(isolate, array, kStartAtReceiver);
476 !iter.IsAtEnd(); iter.Advance()) {
477 Handle<JSReceiver> current(PrototypeIterator::GetCurrent<JSReceiver>(iter));
478 if (current->HasComplexElements()) {
479 return *isolate->factory()->NewNumberFromUint(length);
481 accumulator.CollectOwnElementIndices(array,
482 Handle<JSObject>::cast(current));
485 Handle<FixedArray> keys =
486 accumulator.GetKeys(GetKeysConversion::kKeepNumbers);
488 for (
int i = 0;
i < keys->length();
i++) {
489 if (NumberToUint32(keys->get(
i)) >= length)
continue;
490 if (
i != j) keys->set(j, keys->get(
i));
494 keys = FixedArray::ShrinkOrEmpty(isolate, keys, j);
495 return *isolate->factory()->NewJSArrayWithElements(keys);
498 RUNTIME_FUNCTION(Runtime_TrySliceSimpleNonFastElements) {
499 HandleScope scope(isolate);
500 DCHECK_EQ(3, args.length());
501 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
502 CONVERT_SMI_ARG_CHECKED(first, 1);
503 CONVERT_SMI_ARG_CHECKED(count, 2);
508 if (receiver->IsJSArray()) {
510 if (!isolate->IsArraySpeciesLookupChainIntact() ||
511 !JSArray::cast(*receiver)->HasArrayPrototype(isolate)) {
512 return Smi::FromInt(0);
516 if (!receiver->IsJSObject() ||
517 !JSSloppyArgumentsObject::GetSloppyArgumentsLength(
518 isolate, Handle<JSObject>::cast(receiver), &len) ||
519 (length >
static_cast<uint32_t>(len))) {
520 return Smi::FromInt(0);
526 Handle<JSObject> object(Handle<JSObject>::cast(receiver));
527 if (!JSObject::PrototypeHasNoElements(isolate, *
object) ||
528 object->HasComplexElements()) {
529 return Smi::FromInt(0);
532 ElementsAccessor* accessor =
object->GetElementsAccessor();
533 return *accessor->Slice(
object, first, length);
536 RUNTIME_FUNCTION(Runtime_NewArray) {
537 HandleScope scope(isolate);
538 DCHECK_LE(3, args.length());
539 int const argc = args.length() - 3;
541 Arguments argv(argc, args.address_of_arg_at(1));
542 CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
543 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, new_target, argc + 1);
544 CONVERT_ARG_HANDLE_CHECKED(HeapObject, type_info, argc + 2);
546 Handle<AllocationSite> site = type_info->IsAllocationSite()
547 ? Handle<AllocationSite>::cast(type_info)
548 : Handle<AllocationSite>::null();
550 Factory* factory = isolate->factory();
558 DCHECK(new_target->IsConstructor());
561 bool can_use_type_feedback = !site.is_null();
562 bool can_inline_array_constructor =
true;
563 if (argv.length() == 1) {
564 Handle<Object> argument_one = argv.at<Object>(0);
565 if (argument_one->IsSmi()) {
566 int value = Handle<Smi>::cast(argument_one)->value();
568 JSArray::SetLengthWouldNormalize(isolate->heap(), value)) {
570 can_use_type_feedback =
false;
571 }
else if (value != 0) {
573 if (value >= JSArray::kInitialMaxFastElementArray) {
574 can_inline_array_constructor =
false;
579 can_use_type_feedback =
false;
583 Handle<Map> initial_map;
584 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
585 isolate, initial_map,
586 JSFunction::GetDerivedMap(isolate, constructor, new_target));
588 ElementsKind to_kind = can_use_type_feedback ? site->GetElementsKind()
589 : initial_map->elements_kind();
590 if (holey && !IsHoleyElementsKind(to_kind)) {
591 to_kind = GetHoleyElementsKind(to_kind);
593 if (!site.is_null()) site->SetElementsKind(to_kind);
599 initial_map = Map::AsElementsKind(isolate, initial_map, to_kind);
603 Handle<AllocationSite> allocation_site;
604 if (AllocationSite::ShouldTrack(to_kind)) {
605 allocation_site = site;
608 Handle<JSArray> array = Handle<JSArray>::cast(
609 factory->NewJSObjectFromMap(initial_map, NOT_TENURED, allocation_site));
611 factory->NewJSArrayStorage(array, 0, 0, DONT_INITIALIZE_ARRAY_ELEMENTS);
613 ElementsKind old_kind = array->GetElementsKind();
614 RETURN_FAILURE_ON_EXCEPTION(isolate,
615 ArrayConstructInitializeElements(array, &argv));
616 if (!site.is_null()) {
617 if ((old_kind != array->GetElementsKind() || !can_use_type_feedback ||
618 !can_inline_array_constructor)) {
622 site->SetDoNotInlineCall();
625 if (old_kind != array->GetElementsKind() || !can_inline_array_constructor) {
631 if (isolate->IsArrayConstructorIntact()) {
632 isolate->InvalidateArrayConstructorProtector();
640 RUNTIME_FUNCTION(Runtime_NormalizeElements) {
641 HandleScope scope(isolate);
642 DCHECK_EQ(1, args.length());
643 CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
644 CHECK(!array->HasFixedTypedArrayElements());
645 CHECK(!array->IsJSGlobalProxy());
646 JSObject::NormalizeElements(array);
652 RUNTIME_FUNCTION(Runtime_GrowArrayElements) {
653 HandleScope scope(isolate);
654 DCHECK_EQ(2, args.length());
655 CONVERT_ARG_HANDLE_CHECKED(JSObject,
object, 0);
656 CONVERT_NUMBER_CHECKED(
int, key, Int32, args[1]);
658 if (key < 0)
return Smi::kZero;
663 if (index >= capacity) {
664 if (!object->GetElementsAccessor()->GrowCapacity(
object, index)) {
669 return object->elements();
673 RUNTIME_FUNCTION(Runtime_HasComplexElements) {
674 HandleScope scope(isolate);
675 DCHECK_EQ(1, args.length());
676 CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
677 for (PrototypeIterator iter(isolate, array, kStartAtReceiver);
678 !iter.IsAtEnd(); iter.Advance()) {
679 if (PrototypeIterator::GetCurrent<JSReceiver>(iter)->HasComplexElements()) {
680 return ReadOnlyRoots(isolate).true_value();
683 return ReadOnlyRoots(isolate).false_value();
687 RUNTIME_FUNCTION(Runtime_ArrayIsArray) {
688 HandleScope shs(isolate);
689 DCHECK_EQ(1, args.length());
690 CONVERT_ARG_HANDLE_CHECKED(Object,
object, 0);
691 Maybe<bool> result = Object::IsArray(
object);
692 MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
693 return isolate->heap()->ToBoolean(result.FromJust());
696 RUNTIME_FUNCTION(Runtime_IsArray) {
697 SealHandleScope shs(isolate);
698 DCHECK_EQ(1, args.length());
699 CONVERT_ARG_CHECKED(Object, obj, 0);
700 return isolate->heap()->ToBoolean(obj->IsJSArray());
703 RUNTIME_FUNCTION(Runtime_ArraySpeciesConstructor) {
704 HandleScope scope(isolate);
705 DCHECK_EQ(1, args.length());
706 CONVERT_ARG_HANDLE_CHECKED(Object, original_array, 0);
707 RETURN_RESULT_OR_FAILURE(
708 isolate, Object::ArraySpeciesConstructor(isolate, original_array));
712 RUNTIME_FUNCTION(Runtime_ArrayIncludes_Slow) {
713 HandleScope shs(isolate);
714 DCHECK_EQ(3, args.length());
715 CONVERT_ARG_HANDLE_CHECKED(Object, search_element, 1);
716 CONVERT_ARG_HANDLE_CHECKED(Object, from_index, 2);
719 Handle<JSReceiver> object;
720 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
722 Object::ToObject(isolate, Handle<Object>(args[0], isolate)));
727 if (object->map()->instance_type() == JS_ARRAY_TYPE) {
729 bool success = JSArray::cast(*object)->length()->ToArrayLength(&len32);
735 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
737 Object::GetProperty(isolate,
object,
738 isolate->factory()->length_string()));
740 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, len_,
741 Object::ToLength(isolate, len_));
742 len =
static_cast<int64_t>(len_->Number());
743 DCHECK_EQ(len, len_->Number());
747 if (len == 0)
return ReadOnlyRoots(isolate).false_value();
752 if (!from_index->IsUndefined(isolate)) {
753 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, from_index,
754 Object::ToInteger(isolate, from_index));
756 if (V8_LIKELY(from_index->IsSmi())) {
757 int start_from = Smi::ToInt(*from_index);
758 if (start_from < 0) {
759 index = std::max<int64_t>(len + start_from, 0);
764 DCHECK(from_index->IsHeapNumber());
765 double start_from = from_index->Number();
766 if (start_from >= len)
return ReadOnlyRoots(isolate).false_value();
767 if (V8_LIKELY(std::isfinite(start_from))) {
768 if (start_from < 0) {
769 index =
static_cast<int64_t>(std::max<double>(start_from + len, 0));
781 if (!object->map()->IsSpecialReceiverMap() && len < kMaxUInt32 &&
782 JSObject::PrototypeHasNoElements(isolate, JSObject::cast(*
object))) {
783 Handle<JSObject> obj = Handle<JSObject>::cast(
object);
784 ElementsAccessor* elements = obj->GetElementsAccessor();
785 Maybe<bool> result = elements->IncludesValue(isolate, obj, search_element,
786 static_cast<uint32_t>(index),
787 static_cast<uint32_t>(len));
788 MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
789 return *isolate->factory()->ToBoolean(result.FromJust());
793 for (; index < len; ++index) {
795 Handle<Object> element_k;
797 Handle<Object> index_obj = isolate->factory()->NewNumberFromInt64(index);
799 LookupIterator it = LookupIterator::PropertyOrElement(
800 isolate,
object, index_obj, &success);
802 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, element_k,
803 Object::GetProperty(&it));
807 if (search_element->SameValueZero(*element_k)) {
808 return ReadOnlyRoots(isolate).true_value();
811 return ReadOnlyRoots(isolate).false_value();
814 RUNTIME_FUNCTION(Runtime_ArrayIndexOf) {
815 HandleScope hs(isolate);
816 DCHECK_EQ(3, args.length());
817 CONVERT_ARG_HANDLE_CHECKED(Object, search_element, 1);
818 CONVERT_ARG_HANDLE_CHECKED(Object, from_index, 2);
821 Handle<JSReceiver> object;
822 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
824 Object::ToObject(isolate, args.at(0),
"Array.prototype.indexOf"));
829 if (object->IsJSArray()) {
831 bool success = JSArray::cast(*object)->length()->ToArrayLength(&len32);
837 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
839 Object::GetProperty(isolate,
object,
840 isolate->factory()->length_string()));
842 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, len_,
843 Object::ToLength(isolate, len_));
844 len =
static_cast<int64_t>(len_->Number());
845 DCHECK_EQ(len, len_->Number());
849 if (len == 0)
return Smi::FromInt(-1);
855 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, from_index,
856 Object::ToInteger(isolate, from_index));
857 double fp = from_index->Number();
858 if (fp > len)
return Smi::FromInt(-1);
860 static_cast<double>(std::numeric_limits<int64_t>::min()))) {
861 DCHECK(fp < std::numeric_limits<int64_t>::max());
862 start_from =
static_cast<int64_t>(fp);
864 start_from = std::numeric_limits<int64_t>::min();
869 if (start_from >= 0) {
872 index = len + start_from;
880 if (!object->map()->IsSpecialReceiverMap() && len <= kMaxUInt32 &&
881 JSObject::PrototypeHasNoElements(isolate, JSObject::cast(*
object))) {
882 Handle<JSObject> obj = Handle<JSObject>::cast(
object);
883 ElementsAccessor* elements = obj->GetElementsAccessor();
884 Maybe<int64_t> result = elements->IndexOfValue(isolate, obj, search_element,
885 static_cast<uint32_t>(index),
886 static_cast<uint32_t>(len));
887 MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
888 return *isolate->factory()->NewNumberFromInt64(result.FromJust());
892 for (; index < len; ++index) {
893 HandleScope iteration_hs(isolate);
895 Handle<Object> element_k;
897 Handle<Object> index_obj = isolate->factory()->NewNumberFromInt64(index);
899 LookupIterator it = LookupIterator::PropertyOrElement(
900 isolate,
object, index_obj, &success);
902 Maybe<bool> present = JSReceiver::HasProperty(&it);
903 MAYBE_RETURN(present, ReadOnlyRoots(isolate).exception());
904 if (!present.FromJust())
continue;
905 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, element_k,
906 Object::GetProperty(&it));
907 if (search_element->StrictEquals(*element_k)) {
912 return Smi::FromInt(-1);