11cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/debug/debug.h"
61cb0ef41Sopenharmony_ci#include "src/execution/arguments-inl.h"
71cb0ef41Sopenharmony_ci#include "src/execution/isolate-inl.h"
81cb0ef41Sopenharmony_ci#include "src/execution/protectors-inl.h"
91cb0ef41Sopenharmony_ci#include "src/heap/factory.h"
101cb0ef41Sopenharmony_ci#include "src/heap/heap-inl.h"  // For ToBoolean. TODO(jkummerow): Drop.
111cb0ef41Sopenharmony_ci#include "src/heap/heap-write-barrier-inl.h"
121cb0ef41Sopenharmony_ci#include "src/logging/counters.h"
131cb0ef41Sopenharmony_ci#include "src/numbers/conversions-inl.h"
141cb0ef41Sopenharmony_ci#include "src/objects/allocation-site-inl.h"
151cb0ef41Sopenharmony_ci#include "src/objects/arguments-inl.h"
161cb0ef41Sopenharmony_ci#include "src/objects/elements.h"
171cb0ef41Sopenharmony_ci#include "src/objects/hash-table-inl.h"
181cb0ef41Sopenharmony_ci#include "src/objects/js-array-inl.h"
191cb0ef41Sopenharmony_ci#include "src/objects/prototype.h"
201cb0ef41Sopenharmony_ci#include "src/runtime/runtime-utils.h"
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_cinamespace v8 {
231cb0ef41Sopenharmony_cinamespace internal {
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_TransitionElementsKind) {
261cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
271cb0ef41Sopenharmony_ci  DCHECK_EQ(2, args.length());
281cb0ef41Sopenharmony_ci  Handle<JSObject> object = args.at<JSObject>(0);
291cb0ef41Sopenharmony_ci  Handle<Map> to_map = args.at<Map>(1);
301cb0ef41Sopenharmony_ci  ElementsKind to_kind = to_map->elements_kind();
311cb0ef41Sopenharmony_ci  if (ElementsAccessor::ForKind(to_kind)
321cb0ef41Sopenharmony_ci          ->TransitionElementsKind(object, to_map)
331cb0ef41Sopenharmony_ci          .IsNothing()) {
341cb0ef41Sopenharmony_ci    // TODO(victorgomes): EffectControlLinearizer::LowerTransitionElementsKind
351cb0ef41Sopenharmony_ci    // does not handle exceptions.
361cb0ef41Sopenharmony_ci    FATAL(
371cb0ef41Sopenharmony_ci        "Fatal JavaScript invalid size error when transitioning elements kind");
381cb0ef41Sopenharmony_ci    UNREACHABLE();
391cb0ef41Sopenharmony_ci  }
401cb0ef41Sopenharmony_ci  return *object;
411cb0ef41Sopenharmony_ci}
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_TransitionElementsKindWithKind) {
441cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
451cb0ef41Sopenharmony_ci  DCHECK_EQ(2, args.length());
461cb0ef41Sopenharmony_ci  Handle<JSObject> object = args.at<JSObject>(0);
471cb0ef41Sopenharmony_ci  ElementsKind to_kind = static_cast<ElementsKind>(args.smi_value_at(1));
481cb0ef41Sopenharmony_ci  JSObject::TransitionElementsKind(object, to_kind);
491cb0ef41Sopenharmony_ci  return *object;
501cb0ef41Sopenharmony_ci}
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_NewArray) {
531cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
541cb0ef41Sopenharmony_ci  DCHECK_LE(3, args.length());
551cb0ef41Sopenharmony_ci  int const argc = args.length() - 3;
561cb0ef41Sopenharmony_ci  // argv points to the arguments constructed by the JavaScript call.
571cb0ef41Sopenharmony_ci  JavaScriptArguments argv(argc, args.address_of_arg_at(0));
581cb0ef41Sopenharmony_ci  Handle<JSFunction> constructor = args.at<JSFunction>(argc);
591cb0ef41Sopenharmony_ci  Handle<JSReceiver> new_target = args.at<JSReceiver>(argc + 1);
601cb0ef41Sopenharmony_ci  Handle<HeapObject> type_info = args.at<HeapObject>(argc + 2);
611cb0ef41Sopenharmony_ci  // TODO(bmeurer): Use MaybeHandle to pass around the AllocationSite.
621cb0ef41Sopenharmony_ci  Handle<AllocationSite> site = type_info->IsAllocationSite()
631cb0ef41Sopenharmony_ci                                    ? Handle<AllocationSite>::cast(type_info)
641cb0ef41Sopenharmony_ci                                    : Handle<AllocationSite>::null();
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci  Factory* factory = isolate->factory();
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci  // If called through new, new.target can be:
691cb0ef41Sopenharmony_ci  // - a subclass of constructor,
701cb0ef41Sopenharmony_ci  // - a proxy wrapper around constructor, or
711cb0ef41Sopenharmony_ci  // - the constructor itself.
721cb0ef41Sopenharmony_ci  // If called through Reflect.construct, it's guaranteed to be a constructor by
731cb0ef41Sopenharmony_ci  // REFLECT_CONSTRUCT_PREPARE.
741cb0ef41Sopenharmony_ci  DCHECK(new_target->IsConstructor());
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  bool holey = false;
771cb0ef41Sopenharmony_ci  bool can_use_type_feedback = !site.is_null();
781cb0ef41Sopenharmony_ci  bool can_inline_array_constructor = true;
791cb0ef41Sopenharmony_ci  if (argv.length() == 1) {
801cb0ef41Sopenharmony_ci    Handle<Object> argument_one = argv.at<Object>(0);
811cb0ef41Sopenharmony_ci    if (argument_one->IsSmi()) {
821cb0ef41Sopenharmony_ci      int value = Handle<Smi>::cast(argument_one)->value();
831cb0ef41Sopenharmony_ci      if (value < 0 ||
841cb0ef41Sopenharmony_ci          JSArray::SetLengthWouldNormalize(isolate->heap(), value)) {
851cb0ef41Sopenharmony_ci        // the array is a dictionary in this case.
861cb0ef41Sopenharmony_ci        can_use_type_feedback = false;
871cb0ef41Sopenharmony_ci      } else if (value != 0) {
881cb0ef41Sopenharmony_ci        holey = true;
891cb0ef41Sopenharmony_ci        if (value >= JSArray::kInitialMaxFastElementArray) {
901cb0ef41Sopenharmony_ci          can_inline_array_constructor = false;
911cb0ef41Sopenharmony_ci        }
921cb0ef41Sopenharmony_ci      }
931cb0ef41Sopenharmony_ci    } else {
941cb0ef41Sopenharmony_ci      // Non-smi length argument produces a dictionary
951cb0ef41Sopenharmony_ci      can_use_type_feedback = false;
961cb0ef41Sopenharmony_ci    }
971cb0ef41Sopenharmony_ci  }
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci  Handle<Map> initial_map;
1001cb0ef41Sopenharmony_ci  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1011cb0ef41Sopenharmony_ci      isolate, initial_map,
1021cb0ef41Sopenharmony_ci      JSFunction::GetDerivedMap(isolate, constructor, new_target));
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci  ElementsKind to_kind = can_use_type_feedback ? site->GetElementsKind()
1051cb0ef41Sopenharmony_ci                                               : initial_map->elements_kind();
1061cb0ef41Sopenharmony_ci  if (holey && !IsHoleyElementsKind(to_kind)) {
1071cb0ef41Sopenharmony_ci    to_kind = GetHoleyElementsKind(to_kind);
1081cb0ef41Sopenharmony_ci    // Update the allocation site info to reflect the advice alteration.
1091cb0ef41Sopenharmony_ci    if (!site.is_null()) site->SetElementsKind(to_kind);
1101cb0ef41Sopenharmony_ci  }
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci  // We should allocate with an initial map that reflects the allocation site
1131cb0ef41Sopenharmony_ci  // advice. Therefore we use AllocateJSObjectFromMap instead of passing
1141cb0ef41Sopenharmony_ci  // the constructor.
1151cb0ef41Sopenharmony_ci  initial_map = Map::AsElementsKind(isolate, initial_map, to_kind);
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci  // If we don't care to track arrays of to_kind ElementsKind, then
1181cb0ef41Sopenharmony_ci  // don't emit a memento for them.
1191cb0ef41Sopenharmony_ci  Handle<AllocationSite> allocation_site;
1201cb0ef41Sopenharmony_ci  if (AllocationSite::ShouldTrack(to_kind)) {
1211cb0ef41Sopenharmony_ci    allocation_site = site;
1221cb0ef41Sopenharmony_ci  }
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ci  Handle<JSArray> array = Handle<JSArray>::cast(factory->NewJSObjectFromMap(
1251cb0ef41Sopenharmony_ci      initial_map, AllocationType::kYoung, allocation_site));
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  factory->NewJSArrayStorage(array, 0, 0, DONT_INITIALIZE_ARRAY_ELEMENTS);
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci  ElementsKind old_kind = array->GetElementsKind();
1301cb0ef41Sopenharmony_ci  RETURN_FAILURE_ON_EXCEPTION(isolate,
1311cb0ef41Sopenharmony_ci                              ArrayConstructInitializeElements(array, &argv));
1321cb0ef41Sopenharmony_ci  if (!site.is_null()) {
1331cb0ef41Sopenharmony_ci    if ((old_kind != array->GetElementsKind() || !can_use_type_feedback ||
1341cb0ef41Sopenharmony_ci         !can_inline_array_constructor)) {
1351cb0ef41Sopenharmony_ci      // The arguments passed in caused a transition. This kind of complexity
1361cb0ef41Sopenharmony_ci      // can't be dealt with in the inlined optimized array constructor case.
1371cb0ef41Sopenharmony_ci      // We must mark the allocationsite as un-inlinable.
1381cb0ef41Sopenharmony_ci      site->SetDoNotInlineCall();
1391cb0ef41Sopenharmony_ci    }
1401cb0ef41Sopenharmony_ci  } else {
1411cb0ef41Sopenharmony_ci    if (old_kind != array->GetElementsKind() || !can_inline_array_constructor) {
1421cb0ef41Sopenharmony_ci      // We don't have an AllocationSite for this Array constructor invocation,
1431cb0ef41Sopenharmony_ci      // i.e. it might a call from Array#map or from an Array subclass, so we
1441cb0ef41Sopenharmony_ci      // just flip the bit on the global protector cell instead.
1451cb0ef41Sopenharmony_ci      // TODO(bmeurer): Find a better way to mark this. Global protectors
1461cb0ef41Sopenharmony_ci      // tend to back-fire over time...
1471cb0ef41Sopenharmony_ci      if (Protectors::IsArrayConstructorIntact(isolate)) {
1481cb0ef41Sopenharmony_ci        Protectors::InvalidateArrayConstructor(isolate);
1491cb0ef41Sopenharmony_ci      }
1501cb0ef41Sopenharmony_ci    }
1511cb0ef41Sopenharmony_ci  }
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ci  return *array;
1541cb0ef41Sopenharmony_ci}
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_NormalizeElements) {
1571cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
1581cb0ef41Sopenharmony_ci  DCHECK_EQ(1, args.length());
1591cb0ef41Sopenharmony_ci  Handle<JSObject> array = args.at<JSObject>(0);
1601cb0ef41Sopenharmony_ci  CHECK(!array->HasTypedArrayOrRabGsabTypedArrayElements());
1611cb0ef41Sopenharmony_ci  CHECK(!array->IsJSGlobalProxy());
1621cb0ef41Sopenharmony_ci  JSObject::NormalizeElements(array);
1631cb0ef41Sopenharmony_ci  return *array;
1641cb0ef41Sopenharmony_ci}
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci// GrowArrayElements returns a sentinel Smi if the object was normalized or if
1671cb0ef41Sopenharmony_ci// the key is negative.
1681cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_GrowArrayElements) {
1691cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
1701cb0ef41Sopenharmony_ci  DCHECK_EQ(2, args.length());
1711cb0ef41Sopenharmony_ci  Handle<JSObject> object = args.at<JSObject>(0);
1721cb0ef41Sopenharmony_ci  Handle<Object> key = args.at(1);
1731cb0ef41Sopenharmony_ci  uint32_t index;
1741cb0ef41Sopenharmony_ci  if (key->IsSmi()) {
1751cb0ef41Sopenharmony_ci    int value = Smi::ToInt(*key);
1761cb0ef41Sopenharmony_ci    if (value < 0) return Smi::zero();
1771cb0ef41Sopenharmony_ci    index = static_cast<uint32_t>(value);
1781cb0ef41Sopenharmony_ci  } else {
1791cb0ef41Sopenharmony_ci    CHECK(key->IsHeapNumber());
1801cb0ef41Sopenharmony_ci    double value = HeapNumber::cast(*key).value();
1811cb0ef41Sopenharmony_ci    if (value < 0 || value > std::numeric_limits<uint32_t>::max()) {
1821cb0ef41Sopenharmony_ci      return Smi::zero();
1831cb0ef41Sopenharmony_ci    }
1841cb0ef41Sopenharmony_ci    index = static_cast<uint32_t>(value);
1851cb0ef41Sopenharmony_ci  }
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci  uint32_t capacity = static_cast<uint32_t>(object->elements().length());
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_ci  if (index >= capacity) {
1901cb0ef41Sopenharmony_ci    bool has_grown;
1911cb0ef41Sopenharmony_ci    MAYBE_ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1921cb0ef41Sopenharmony_ci        isolate, has_grown,
1931cb0ef41Sopenharmony_ci        object->GetElementsAccessor()->GrowCapacity(object, index));
1941cb0ef41Sopenharmony_ci    if (!has_grown) {
1951cb0ef41Sopenharmony_ci      return Smi::zero();
1961cb0ef41Sopenharmony_ci    }
1971cb0ef41Sopenharmony_ci  }
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ci  return object->elements();
2001cb0ef41Sopenharmony_ci}
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci// ES6 22.1.2.2 Array.isArray
2031cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_ArrayIsArray) {
2041cb0ef41Sopenharmony_ci  HandleScope shs(isolate);
2051cb0ef41Sopenharmony_ci  DCHECK_EQ(1, args.length());
2061cb0ef41Sopenharmony_ci  Handle<Object> object = args.at(0);
2071cb0ef41Sopenharmony_ci  Maybe<bool> result = Object::IsArray(object);
2081cb0ef41Sopenharmony_ci  MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
2091cb0ef41Sopenharmony_ci  return isolate->heap()->ToBoolean(result.FromJust());
2101cb0ef41Sopenharmony_ci}
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_IsArray) {
2131cb0ef41Sopenharmony_ci  SealHandleScope shs(isolate);
2141cb0ef41Sopenharmony_ci  DCHECK_EQ(1, args.length());
2151cb0ef41Sopenharmony_ci  Object obj = args[0];
2161cb0ef41Sopenharmony_ci  return isolate->heap()->ToBoolean(obj.IsJSArray());
2171cb0ef41Sopenharmony_ci}
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_ArraySpeciesConstructor) {
2201cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
2211cb0ef41Sopenharmony_ci  DCHECK_EQ(1, args.length());
2221cb0ef41Sopenharmony_ci  Handle<Object> original_array = args.at(0);
2231cb0ef41Sopenharmony_ci  RETURN_RESULT_OR_FAILURE(
2241cb0ef41Sopenharmony_ci      isolate, Object::ArraySpeciesConstructor(isolate, original_array));
2251cb0ef41Sopenharmony_ci}
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_ci// ES7 22.1.3.11 Array.prototype.includes
2281cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_ArrayIncludes_Slow) {
2291cb0ef41Sopenharmony_ci  HandleScope shs(isolate);
2301cb0ef41Sopenharmony_ci  DCHECK_EQ(3, args.length());
2311cb0ef41Sopenharmony_ci  Handle<Object> search_element = args.at(1);
2321cb0ef41Sopenharmony_ci  Handle<Object> from_index = args.at(2);
2331cb0ef41Sopenharmony_ci
2341cb0ef41Sopenharmony_ci  // Let O be ? ToObject(this value).
2351cb0ef41Sopenharmony_ci  Handle<JSReceiver> object;
2361cb0ef41Sopenharmony_ci  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2371cb0ef41Sopenharmony_ci      isolate, object,
2381cb0ef41Sopenharmony_ci      Object::ToObject(isolate, Handle<Object>(args[0], isolate)));
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_ci  // Let len be ? ToLength(? Get(O, "length")).
2411cb0ef41Sopenharmony_ci  int64_t len;
2421cb0ef41Sopenharmony_ci  {
2431cb0ef41Sopenharmony_ci    if (object->map().instance_type() == JS_ARRAY_TYPE) {
2441cb0ef41Sopenharmony_ci      uint32_t len32 = 0;
2451cb0ef41Sopenharmony_ci      bool success = JSArray::cast(*object).length().ToArrayLength(&len32);
2461cb0ef41Sopenharmony_ci      DCHECK(success);
2471cb0ef41Sopenharmony_ci      USE(success);
2481cb0ef41Sopenharmony_ci      len = len32;
2491cb0ef41Sopenharmony_ci    } else {
2501cb0ef41Sopenharmony_ci      Handle<Object> len_;
2511cb0ef41Sopenharmony_ci      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2521cb0ef41Sopenharmony_ci          isolate, len_,
2531cb0ef41Sopenharmony_ci          Object::GetProperty(isolate, object,
2541cb0ef41Sopenharmony_ci                              isolate->factory()->length_string()));
2551cb0ef41Sopenharmony_ci
2561cb0ef41Sopenharmony_ci      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, len_,
2571cb0ef41Sopenharmony_ci                                         Object::ToLength(isolate, len_));
2581cb0ef41Sopenharmony_ci      len = static_cast<int64_t>(len_->Number());
2591cb0ef41Sopenharmony_ci      DCHECK_EQ(len, len_->Number());
2601cb0ef41Sopenharmony_ci    }
2611cb0ef41Sopenharmony_ci  }
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_ci  if (len == 0) return ReadOnlyRoots(isolate).false_value();
2641cb0ef41Sopenharmony_ci
2651cb0ef41Sopenharmony_ci  // Let n be ? ToInteger(fromIndex). (If fromIndex is undefined, this step
2661cb0ef41Sopenharmony_ci  // produces the value 0.)
2671cb0ef41Sopenharmony_ci  int64_t index = 0;
2681cb0ef41Sopenharmony_ci  if (!from_index->IsUndefined(isolate)) {
2691cb0ef41Sopenharmony_ci    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, from_index,
2701cb0ef41Sopenharmony_ci                                       Object::ToInteger(isolate, from_index));
2711cb0ef41Sopenharmony_ci
2721cb0ef41Sopenharmony_ci    if (V8_LIKELY(from_index->IsSmi())) {
2731cb0ef41Sopenharmony_ci      int start_from = Smi::ToInt(*from_index);
2741cb0ef41Sopenharmony_ci      if (start_from < 0) {
2751cb0ef41Sopenharmony_ci        index = std::max<int64_t>(len + start_from, 0);
2761cb0ef41Sopenharmony_ci      } else {
2771cb0ef41Sopenharmony_ci        index = start_from;
2781cb0ef41Sopenharmony_ci      }
2791cb0ef41Sopenharmony_ci    } else {
2801cb0ef41Sopenharmony_ci      DCHECK(from_index->IsHeapNumber());
2811cb0ef41Sopenharmony_ci      double start_from = from_index->Number();
2821cb0ef41Sopenharmony_ci      if (start_from >= len) return ReadOnlyRoots(isolate).false_value();
2831cb0ef41Sopenharmony_ci      if (V8_LIKELY(std::isfinite(start_from))) {
2841cb0ef41Sopenharmony_ci        if (start_from < 0) {
2851cb0ef41Sopenharmony_ci          index = static_cast<int64_t>(std::max<double>(start_from + len, 0));
2861cb0ef41Sopenharmony_ci        } else {
2871cb0ef41Sopenharmony_ci          index = start_from;
2881cb0ef41Sopenharmony_ci        }
2891cb0ef41Sopenharmony_ci      }
2901cb0ef41Sopenharmony_ci    }
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_ci    DCHECK_GE(index, 0);
2931cb0ef41Sopenharmony_ci  }
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_ci  // If the receiver is not a special receiver type, and the length is a valid
2961cb0ef41Sopenharmony_ci  // element index, perform fast operation tailored to specific ElementsKinds.
2971cb0ef41Sopenharmony_ci  if (!object->map().IsSpecialReceiverMap() &&
2981cb0ef41Sopenharmony_ci      len <= JSObject::kMaxElementCount &&
2991cb0ef41Sopenharmony_ci      JSObject::PrototypeHasNoElements(isolate, JSObject::cast(*object))) {
3001cb0ef41Sopenharmony_ci    Handle<JSObject> obj = Handle<JSObject>::cast(object);
3011cb0ef41Sopenharmony_ci    ElementsAccessor* elements = obj->GetElementsAccessor();
3021cb0ef41Sopenharmony_ci    Maybe<bool> result =
3031cb0ef41Sopenharmony_ci        elements->IncludesValue(isolate, obj, search_element, index, len);
3041cb0ef41Sopenharmony_ci    MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
3051cb0ef41Sopenharmony_ci    return *isolate->factory()->ToBoolean(result.FromJust());
3061cb0ef41Sopenharmony_ci  }
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ci  // Otherwise, perform slow lookups for special receiver types.
3091cb0ef41Sopenharmony_ci  for (; index < len; ++index) {
3101cb0ef41Sopenharmony_ci    HandleScope iteration_hs(isolate);
3111cb0ef41Sopenharmony_ci
3121cb0ef41Sopenharmony_ci    // Let elementK be the result of ? Get(O, ! ToString(k)).
3131cb0ef41Sopenharmony_ci    Handle<Object> element_k;
3141cb0ef41Sopenharmony_ci    {
3151cb0ef41Sopenharmony_ci      PropertyKey key(isolate, static_cast<double>(index));
3161cb0ef41Sopenharmony_ci      LookupIterator it(isolate, object, key);
3171cb0ef41Sopenharmony_ci      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, element_k,
3181cb0ef41Sopenharmony_ci                                         Object::GetProperty(&it));
3191cb0ef41Sopenharmony_ci    }
3201cb0ef41Sopenharmony_ci
3211cb0ef41Sopenharmony_ci    // If SameValueZero(searchElement, elementK) is true, return true.
3221cb0ef41Sopenharmony_ci    if (search_element->SameValueZero(*element_k)) {
3231cb0ef41Sopenharmony_ci      return ReadOnlyRoots(isolate).true_value();
3241cb0ef41Sopenharmony_ci    }
3251cb0ef41Sopenharmony_ci  }
3261cb0ef41Sopenharmony_ci  return ReadOnlyRoots(isolate).false_value();
3271cb0ef41Sopenharmony_ci}
3281cb0ef41Sopenharmony_ci
3291cb0ef41Sopenharmony_ciRUNTIME_FUNCTION(Runtime_ArrayIndexOf) {
3301cb0ef41Sopenharmony_ci  HandleScope hs(isolate);
3311cb0ef41Sopenharmony_ci  DCHECK_EQ(3, args.length());
3321cb0ef41Sopenharmony_ci  Handle<Object> search_element = args.at(1);
3331cb0ef41Sopenharmony_ci  Handle<Object> from_index = args.at(2);
3341cb0ef41Sopenharmony_ci
3351cb0ef41Sopenharmony_ci  // Let O be ? ToObject(this value).
3361cb0ef41Sopenharmony_ci  Handle<JSReceiver> object;
3371cb0ef41Sopenharmony_ci  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3381cb0ef41Sopenharmony_ci      isolate, object,
3391cb0ef41Sopenharmony_ci      Object::ToObject(isolate, args.at(0), "Array.prototype.indexOf"));
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_ci  // Let len be ? ToLength(? Get(O, "length")).
3421cb0ef41Sopenharmony_ci  int64_t len;
3431cb0ef41Sopenharmony_ci  {
3441cb0ef41Sopenharmony_ci    if (object->IsJSArray()) {
3451cb0ef41Sopenharmony_ci      uint32_t len32 = 0;
3461cb0ef41Sopenharmony_ci      bool success = JSArray::cast(*object).length().ToArrayLength(&len32);
3471cb0ef41Sopenharmony_ci      DCHECK(success);
3481cb0ef41Sopenharmony_ci      USE(success);
3491cb0ef41Sopenharmony_ci      len = len32;
3501cb0ef41Sopenharmony_ci    } else {
3511cb0ef41Sopenharmony_ci      Handle<Object> len_;
3521cb0ef41Sopenharmony_ci      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3531cb0ef41Sopenharmony_ci          isolate, len_,
3541cb0ef41Sopenharmony_ci          Object::GetProperty(isolate, object,
3551cb0ef41Sopenharmony_ci                              isolate->factory()->length_string()));
3561cb0ef41Sopenharmony_ci
3571cb0ef41Sopenharmony_ci      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, len_,
3581cb0ef41Sopenharmony_ci                                         Object::ToLength(isolate, len_));
3591cb0ef41Sopenharmony_ci      len = static_cast<int64_t>(len_->Number());
3601cb0ef41Sopenharmony_ci      DCHECK_EQ(len, len_->Number());
3611cb0ef41Sopenharmony_ci    }
3621cb0ef41Sopenharmony_ci  }
3631cb0ef41Sopenharmony_ci
3641cb0ef41Sopenharmony_ci  if (len == 0) return Smi::FromInt(-1);
3651cb0ef41Sopenharmony_ci
3661cb0ef41Sopenharmony_ci  // Let n be ? ToInteger(fromIndex). (If fromIndex is undefined, this step
3671cb0ef41Sopenharmony_ci  // produces the value 0.)
3681cb0ef41Sopenharmony_ci  int64_t start_from;
3691cb0ef41Sopenharmony_ci  {
3701cb0ef41Sopenharmony_ci    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, from_index,
3711cb0ef41Sopenharmony_ci                                       Object::ToInteger(isolate, from_index));
3721cb0ef41Sopenharmony_ci    double fp = from_index->Number();
3731cb0ef41Sopenharmony_ci    if (fp > len) return Smi::FromInt(-1);
3741cb0ef41Sopenharmony_ci    if (V8_LIKELY(fp >=
3751cb0ef41Sopenharmony_ci                  static_cast<double>(std::numeric_limits<int64_t>::min()))) {
3761cb0ef41Sopenharmony_ci      DCHECK(fp < static_cast<double>(std::numeric_limits<int64_t>::max()));
3771cb0ef41Sopenharmony_ci      start_from = static_cast<int64_t>(fp);
3781cb0ef41Sopenharmony_ci    } else {
3791cb0ef41Sopenharmony_ci      start_from = std::numeric_limits<int64_t>::min();
3801cb0ef41Sopenharmony_ci    }
3811cb0ef41Sopenharmony_ci  }
3821cb0ef41Sopenharmony_ci
3831cb0ef41Sopenharmony_ci  int64_t index;
3841cb0ef41Sopenharmony_ci  if (start_from >= 0) {
3851cb0ef41Sopenharmony_ci    index = start_from;
3861cb0ef41Sopenharmony_ci  } else {
3871cb0ef41Sopenharmony_ci    index = len + start_from;
3881cb0ef41Sopenharmony_ci    if (index < 0) {
3891cb0ef41Sopenharmony_ci      index = 0;
3901cb0ef41Sopenharmony_ci    }
3911cb0ef41Sopenharmony_ci  }
3921cb0ef41Sopenharmony_ci
3931cb0ef41Sopenharmony_ci  // If the receiver is not a special receiver type, and the length fits
3941cb0ef41Sopenharmony_ci  // uint32_t, perform fast operation tailored to specific ElementsKinds.
3951cb0ef41Sopenharmony_ci  if (!object->map().IsSpecialReceiverMap() && len <= kMaxUInt32 &&
3961cb0ef41Sopenharmony_ci      JSObject::PrototypeHasNoElements(isolate, JSObject::cast(*object))) {
3971cb0ef41Sopenharmony_ci    Handle<JSObject> obj = Handle<JSObject>::cast(object);
3981cb0ef41Sopenharmony_ci    ElementsAccessor* elements = obj->GetElementsAccessor();
3991cb0ef41Sopenharmony_ci    Maybe<int64_t> result = elements->IndexOfValue(isolate, obj, search_element,
4001cb0ef41Sopenharmony_ci                                                   static_cast<uint32_t>(index),
4011cb0ef41Sopenharmony_ci                                                   static_cast<uint32_t>(len));
4021cb0ef41Sopenharmony_ci    MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
4031cb0ef41Sopenharmony_ci    return *isolate->factory()->NewNumberFromInt64(result.FromJust());
4041cb0ef41Sopenharmony_ci  }
4051cb0ef41Sopenharmony_ci
4061cb0ef41Sopenharmony_ci  // Otherwise, perform slow lookups for special receiver types.
4071cb0ef41Sopenharmony_ci  for (; index < len; ++index) {
4081cb0ef41Sopenharmony_ci    HandleScope iteration_hs(isolate);
4091cb0ef41Sopenharmony_ci    // Let elementK be the result of ? Get(O, ! ToString(k)).
4101cb0ef41Sopenharmony_ci    Handle<Object> element_k;
4111cb0ef41Sopenharmony_ci    {
4121cb0ef41Sopenharmony_ci      PropertyKey key(isolate, static_cast<double>(index));
4131cb0ef41Sopenharmony_ci      LookupIterator it(isolate, object, key);
4141cb0ef41Sopenharmony_ci      Maybe<bool> present = JSReceiver::HasProperty(&it);
4151cb0ef41Sopenharmony_ci      MAYBE_RETURN(present, ReadOnlyRoots(isolate).exception());
4161cb0ef41Sopenharmony_ci      if (!present.FromJust()) continue;
4171cb0ef41Sopenharmony_ci      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, element_k,
4181cb0ef41Sopenharmony_ci                                         Object::GetProperty(&it));
4191cb0ef41Sopenharmony_ci      if (search_element->StrictEquals(*element_k)) {
4201cb0ef41Sopenharmony_ci        return *isolate->factory()->NewNumberFromInt64(index);
4211cb0ef41Sopenharmony_ci      }
4221cb0ef41Sopenharmony_ci    }
4231cb0ef41Sopenharmony_ci  }
4241cb0ef41Sopenharmony_ci  return Smi::FromInt(-1);
4251cb0ef41Sopenharmony_ci}
4261cb0ef41Sopenharmony_ci
4271cb0ef41Sopenharmony_ci}  // namespace internal
4281cb0ef41Sopenharmony_ci}  // namespace v8
429