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