1958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Copyright 2014 the V8 project authors. All rights reserved. 2958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Use of this source code is governed by a BSD-style license that can be 3958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// found in the LICENSE file. 4958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/runtime/runtime-utils.h" 6958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 7958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/arguments.h" 83b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#include "src/code-stubs.h" 9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/conversions-inl.h" 10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/elements.h" 11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/factory.h" 12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/isolate-inl.h" 133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#include "src/keys.h" 14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/messages.h" 15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/prototype.h" 16958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 17958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace v8 { 18958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace internal { 19958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 20958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION(Runtime_FinishArrayPrototypeSetup) { 21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier HandleScope scope(isolate); 2262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(1, args.length()); 23958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0); 24958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Object* length = prototype->length(); 2513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch CHECK(length->IsSmi()); 2613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch CHECK(Smi::cast(length)->value() == 0); 2713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch CHECK(prototype->HasFastSmiOrObjectElements()); 28958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // This is necessary to enable fast checks for absence of elements 29958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // on Array.prototype and below. 30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier prototype->set_elements(isolate->heap()->empty_fixed_array()); 31c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return Smi::kZero; 32958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 33958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 34c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochstatic void InstallCode( 35c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Isolate* isolate, Handle<JSObject> holder, const char* name, 36c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Handle<Code> code, int argc = -1, 37c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch BuiltinFunctionId id = static_cast<BuiltinFunctionId>(-1)) { 38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<String> key = isolate->factory()->InternalizeUtf8String(name); 39958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<JSFunction> optimized = 4062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch isolate->factory()->NewFunctionWithoutPrototype(key, code, true); 41f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (argc < 0) { 42f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch optimized->shared()->DontAdaptArguments(); 43f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 44f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch optimized->shared()->set_internal_formal_parameter_count(argc); 45f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 46c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (id >= 0) { 47c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch optimized->shared()->set_builtin_function_id(id); 48c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 4962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch optimized->shared()->set_language_mode(STRICT); 5062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch optimized->shared()->set_native(true); 51958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier JSObject::AddProperty(holder, key, optimized, NONE); 52958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 53958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 54c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochstatic void InstallBuiltin( 55c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Isolate* isolate, Handle<JSObject> holder, const char* name, 56c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Builtins::Name builtin_name, int argc = -1, 57c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch BuiltinFunctionId id = static_cast<BuiltinFunctionId>(-1)) { 583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch InstallCode(isolate, holder, name, 59c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch handle(isolate->builtins()->builtin(builtin_name), isolate), argc, 60c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch id); 613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch} 62958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 63958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION(Runtime_SpecialArrayFunctions) { 64958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier HandleScope scope(isolate); 6562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(0, args.length()); 66958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<JSObject> holder = 67958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier isolate->factory()->NewJSObject(isolate->object_function()); 68958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 69958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop); 7062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch InstallBuiltin(isolate, holder, "push", Builtins::kFastArrayPush); 71958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift); 72958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift); 73958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice); 74958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice); 75f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch InstallBuiltin(isolate, holder, "includes", Builtins::kArrayIncludes, 2); 76f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch InstallBuiltin(isolate, holder, "indexOf", Builtins::kArrayIndexOf, 2); 77c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch InstallBuiltin(isolate, holder, "keys", Builtins::kArrayPrototypeKeys, 0, 78c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch kArrayKeys); 79c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch InstallBuiltin(isolate, holder, "values", Builtins::kArrayPrototypeValues, 0, 80c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch kArrayValues); 81c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch InstallBuiltin(isolate, holder, "entries", Builtins::kArrayPrototypeEntries, 82c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 0, kArrayEntries); 83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return *holder; 84958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 85958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochRUNTIME_FUNCTION(Runtime_FixedArrayGet) { 87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SealHandleScope shs(isolate); 8862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(2, args.length()); 89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CONVERT_ARG_CHECKED(FixedArray, object, 0); 90014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CONVERT_SMI_ARG_CHECKED(index, 1); 91014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return object->get(index); 92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochRUNTIME_FUNCTION(Runtime_FixedArraySet) { 96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SealHandleScope shs(isolate); 9762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(3, args.length()); 98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CONVERT_ARG_CHECKED(FixedArray, object, 0); 99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CONVERT_SMI_ARG_CHECKED(index, 1); 100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CONVERT_ARG_CHECKED(Object, value, 2); 101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch object->set(index, value); 102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return isolate->heap()->undefined_value(); 103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION(Runtime_TransitionElementsKind) { 107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier HandleScope scope(isolate); 108f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK_EQ(2, args.length()); 109f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); 110f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CONVERT_ARG_HANDLE_CHECKED(Map, to_map, 1); 111f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ElementsKind to_kind = to_map->elements_kind(); 112f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ElementsAccessor::ForKind(to_kind)->TransitionElementsKind(object, to_map); 113f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return *object; 114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Moves all own elements of an object, that are below a limit, to positions 118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// starting at zero. All undefined values are placed after non-undefined values, 119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// and are followed by non-existing element. Does not change the length 120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// property. 121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Returns the number of non-undefined elements collected. 122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Returns -1 if hole removal is not supported by this method. 123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION(Runtime_RemoveArrayHoles) { 124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier HandleScope scope(isolate); 12562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(2, args.length()); 126109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); 127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]); 128109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (object->IsJSProxy()) return Smi::FromInt(-1); 129109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch return *JSObject::PrepareElementsForSort(Handle<JSObject>::cast(object), 130109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch limit); 131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Move contents of argument 0 (an array) to argument 1 (an array) 135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION(Runtime_MoveArrayContents) { 136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier HandleScope scope(isolate); 13762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(2, args.length()); 138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CONVERT_ARG_HANDLE_CHECKED(JSArray, from, 0); 139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CONVERT_ARG_HANDLE_CHECKED(JSArray, to, 1); 140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier JSObject::ValidateElements(from); 141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier JSObject::ValidateElements(to); 142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<FixedArrayBase> new_elements(from->elements()); 144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ElementsKind from_kind = from->GetElementsKind(); 145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Map> new_map = JSObject::GetElementsTransitionMap(to, from_kind); 146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier JSObject::SetMapAndElements(to, new_map, new_elements); 147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier to->set_length(from->length()); 148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier JSObject::ResetElements(from); 150c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch from->set_length(Smi::kZero); 151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier JSObject::ValidateElements(to); 153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return *to; 154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// How many elements does this object/array have? 158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION(Runtime_EstimateNumberOfElements) { 159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier HandleScope scope(isolate); 16062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(1, args.length()); 161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0); 162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<FixedArrayBase> elements(array->elements(), isolate); 163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SealHandleScope shs(isolate); 164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (elements->IsDictionary()) { 165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int result = 166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<SeededNumberDictionary>::cast(elements)->NumberOfElements(); 167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return Smi::FromInt(result); 168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(array->length()->IsSmi()); 170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // For packed elements, we know the exact number of elements 171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int length = elements->length(); 172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ElementsKind kind = array->GetElementsKind(); 173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (IsFastPackedElementsKind(kind)) { 174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return Smi::FromInt(length); 175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // For holey elements, take samples from the buffer checking for holes 177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // to generate the estimate. 178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const int kNumberOfHoleCheckSamples = 97; 179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int increment = (length < kNumberOfHoleCheckSamples) 180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ? 1 181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier : static_cast<int>(length / kNumberOfHoleCheckSamples); 182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ElementsAccessor* accessor = array->GetElementsAccessor(); 183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int holes = 0; 184958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for (int i = 0; i < length; i += increment) { 185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!accessor->HasElement(array, i, elements)) { 186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ++holes; 187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int estimate = static_cast<int>((kNumberOfHoleCheckSamples - holes) / 190958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier kNumberOfHoleCheckSamples * length); 191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return Smi::FromInt(estimate); 192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Returns an array that tells you where in the [0, length) interval an array 197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// might have elements. Can either return an array of keys (positive integers 198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// or undefined) or a number representing the positive length of an interval 199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// starting at index 0. 200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Intervals can span over some keys that are not in the object. 201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION(Runtime_GetArrayKeys) { 202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier HandleScope scope(isolate); 20362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(2, args.length()); 204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0); 205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]); 20613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch ElementsKind kind = array->GetElementsKind(); 20713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 20813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (IsFastElementsKind(kind) || IsFixedTypedArrayElementsKind(kind)) { 20913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch uint32_t actual_length = static_cast<uint32_t>(array->elements()->length()); 21013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return *isolate->factory()->NewNumberFromUint(Min(actual_length, length)); 21113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 21313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (kind == FAST_STRING_WRAPPER_ELEMENTS) { 214109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int string_length = 215109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch String::cast(Handle<JSValue>::cast(array)->value())->length(); 216109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int backing_store_length = array->elements()->length(); 217109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch return *isolate->factory()->NewNumberFromUint( 218109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Min(length, 219109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch static_cast<uint32_t>(Max(string_length, backing_store_length)))); 220109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 221109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 22213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch KeyAccumulator accumulator(isolate, KeyCollectionMode::kOwnOnly, 22313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch ALL_PROPERTIES); 22413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch for (PrototypeIterator iter(isolate, array, kStartAtReceiver); 225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch !iter.IsAtEnd(); iter.Advance()) { 226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (PrototypeIterator::GetCurrent(iter)->IsJSProxy() || 227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PrototypeIterator::GetCurrent<JSObject>(iter) 228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ->HasIndexedInterceptor()) { 229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Bail out if we find a proxy or interceptor, likely not worth 230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // collecting keys in that case. 231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return *isolate->factory()->NewNumberFromUint(length); 232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter); 23413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch accumulator.CollectOwnElementIndices(array, current); 235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Erase any keys >= length. 23713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Handle<FixedArray> keys = 23813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch accumulator.GetKeys(GetKeysConversion::kKeepNumbers); 2393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch int j = 0; 240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < keys->length(); i++) { 2413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (NumberToUint32(keys->get(i)) >= length) continue; 2423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (i != j) keys->set(j, keys->get(i)); 2433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch j++; 244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 2463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (j != keys->length()) { 24762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch isolate->heap()->RightTrimFixedArray(*keys, keys->length() - j); 2483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 2493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return *isolate->factory()->NewJSArrayWithElements(keys); 251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace { 255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochObject* ArrayConstructorCommon(Isolate* isolate, Handle<JSFunction> constructor, 257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<JSReceiver> new_target, 258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<AllocationSite> site, 259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Arguments* caller_args) { 260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Factory* factory = isolate->factory(); 261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If called through new, new.target can be: 263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // - a subclass of constructor, 264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // - a proxy wrapper around constructor, or 265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // - the constructor itself. 266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If called through Reflect.construct, it's guaranteed to be a constructor by 267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // REFLECT_CONSTRUCT_PREPARE. 268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(new_target->IsConstructor()); 269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool holey = false; 271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool can_use_type_feedback = !site.is_null(); 272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool can_inline_array_constructor = true; 273958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (caller_args->length() == 1) { 274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Object> argument_one = caller_args->at<Object>(0); 275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (argument_one->IsSmi()) { 276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int value = Handle<Smi>::cast(argument_one)->value(); 277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (value < 0 || 278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSArray::SetLengthWouldNormalize(isolate->heap(), value)) { 279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the array is a dictionary in this case. 280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier can_use_type_feedback = false; 281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (value != 0) { 282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier holey = true; 283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (value >= JSArray::kInitialMaxFastElementArray) { 284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch can_inline_array_constructor = false; 285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Non-smi length argument produces a dictionary 289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier can_use_type_feedback = false; 290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Map> initial_map; 294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch isolate, initial_map, 296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSFunction::GetDerivedMap(isolate, constructor, new_target)); 297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ElementsKind to_kind = can_use_type_feedback ? site->GetElementsKind() 299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch : initial_map->elements_kind(); 300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (holey && !IsFastHoleyElementsKind(to_kind)) { 301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch to_kind = GetHoleyElementsKind(to_kind); 302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Update the allocation site info to reflect the advice alteration. 303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!site.is_null()) site->SetElementsKind(to_kind); 304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We should allocate with an initial map that reflects the allocation site 307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // advice. Therefore we use AllocateJSObjectFromMap instead of passing 308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // the constructor. 309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (to_kind != initial_map->elements_kind()) { 310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch initial_map = Map::AsElementsKind(initial_map, to_kind); 311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If we don't care to track arrays of to_kind ElementsKind, then 314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // don't emit a memento for them. 315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<AllocationSite> allocation_site; 316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (AllocationSite::GetMode(to_kind) == TRACK_ALLOCATION_SITE) { 317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch allocation_site = site; 318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<JSArray> array = Handle<JSArray>::cast( 321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch factory->NewJSObjectFromMap(initial_map, NOT_TENURED, allocation_site)); 322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier factory->NewJSArrayStorage(array, 0, 0, DONT_INITIALIZE_ARRAY_ELEMENTS); 324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ElementsKind old_kind = array->GetElementsKind(); 326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier RETURN_FAILURE_ON_EXCEPTION( 327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier isolate, ArrayConstructInitializeElements(array, caller_args)); 328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!site.is_null() && 329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch (old_kind != array->GetElementsKind() || !can_use_type_feedback || 330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch !can_inline_array_constructor)) { 331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The arguments passed in caused a transition. This kind of complexity 332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // can't be dealt with in the inlined hydrogen array constructor case. 333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // We must mark the allocationsite as un-inlinable. 334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier site->SetDoNotInlineCall(); 335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 336014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return *array; 338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace 341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochRUNTIME_FUNCTION(Runtime_NewArray) { 343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HandleScope scope(isolate); 344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_LE(3, args.length()); 345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int const argc = args.length() - 3; 346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // TODO(bmeurer): Remove this Arguments nonsense. 347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Arguments argv(argc, args.arguments() - 1); 348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0); 349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CONVERT_ARG_HANDLE_CHECKED(JSReceiver, new_target, argc + 1); 350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CONVERT_ARG_HANDLE_CHECKED(HeapObject, type_info, argc + 2); 351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // TODO(bmeurer): Use MaybeHandle to pass around the AllocationSite. 352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<AllocationSite> site = type_info->IsAllocationSite() 353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ? Handle<AllocationSite>::cast(type_info) 354014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch : Handle<AllocationSite>::null(); 355014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return ArrayConstructorCommon(isolate, constructor, new_target, site, &argv); 356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION(Runtime_NormalizeElements) { 359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier HandleScope scope(isolate); 36062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(1, args.length()); 361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0); 36213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch CHECK(!array->HasFixedTypedArrayElements()); 36313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch CHECK(!array->IsJSGlobalProxy()); 364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier JSObject::NormalizeElements(array); 365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return *array; 366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 367958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 368958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// GrowArrayElements returns a sentinel Smi if the object was normalized. 370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochRUNTIME_FUNCTION(Runtime_GrowArrayElements) { 371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HandleScope scope(isolate); 37262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(2, args.length()); 373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); 374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CONVERT_NUMBER_CHECKED(int, key, Int32, args[1]); 375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (key < 0) { 377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return object->elements(); 378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uint32_t capacity = static_cast<uint32_t>(object->elements()->length()); 381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uint32_t index = static_cast<uint32_t>(key); 382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (index >= capacity) { 384f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (!object->GetElementsAccessor()->GrowCapacity(object, index)) { 385c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return Smi::kZero; 386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // On success, return the fixed array elements. 390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return object->elements(); 391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION(Runtime_HasComplexElements) { 395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier HandleScope scope(isolate); 39662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(1, args.length()); 397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0); 39813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch for (PrototypeIterator iter(isolate, array, kStartAtReceiver); 399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier !iter.IsAtEnd(); iter.Advance()) { 400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { 401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return isolate->heap()->true_value(); 402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter); 404958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (current->HasIndexedInterceptor()) { 405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return isolate->heap()->true_value(); 406958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 407958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!current->HasDictionaryElements()) continue; 408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (current->element_dictionary()->HasComplexElements()) { 409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return isolate->heap()->true_value(); 410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return isolate->heap()->false_value(); 413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 415bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// ES6 22.1.2.2 Array.isArray 416bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochRUNTIME_FUNCTION(Runtime_ArrayIsArray) { 417bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch HandleScope shs(isolate); 41862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(1, args.length()); 419bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); 420bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Maybe<bool> result = Object::IsArray(object); 421bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch MAYBE_RETURN(result, isolate->heap()->exception()); 422bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return isolate->heap()->ToBoolean(result.FromJust()); 423bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 424958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochRUNTIME_FUNCTION(Runtime_IsArray) { 426958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SealHandleScope shs(isolate); 42762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(1, args.length()); 428958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CONVERT_ARG_CHECKED(Object, obj, 0); 429958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return isolate->heap()->ToBoolean(obj->IsJSArray()); 430958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 432014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochRUNTIME_FUNCTION(Runtime_ArraySpeciesConstructor) { 433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HandleScope scope(isolate); 43462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(1, args.length()); 435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CONVERT_ARG_HANDLE_CHECKED(Object, original_array, 0); 43613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch RETURN_RESULT_OR_FAILURE( 43713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch isolate, Object::ArraySpeciesConstructor(isolate, original_array)); 438958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 440f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ES7 22.1.3.11 Array.prototype.includes 441f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochRUNTIME_FUNCTION(Runtime_ArrayIncludes_Slow) { 442f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch HandleScope shs(isolate); 44362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(3, args.length()); 444f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CONVERT_ARG_HANDLE_CHECKED(Object, search_element, 1); 445f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CONVERT_ARG_HANDLE_CHECKED(Object, from_index, 2); 446f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 447f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Let O be ? ToObject(this value). 448f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<JSReceiver> object; 449f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 450f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate, object, Object::ToObject(isolate, handle(args[0], isolate))); 451f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 452f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Let len be ? ToLength(? Get(O, "length")). 453f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int64_t len; 454f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 455f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (object->map()->instance_type() == JS_ARRAY_TYPE) { 456f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch uint32_t len32 = 0; 457f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch bool success = JSArray::cast(*object)->length()->ToArrayLength(&len32); 458f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(success); 459f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch USE(success); 460f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch len = len32; 461f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 462f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<Object> len_; 463f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 464f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate, len_, 465f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Object::GetProperty(object, isolate->factory()->length_string())); 466f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 467f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, len_, 468f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Object::ToLength(isolate, len_)); 469f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch len = static_cast<int64_t>(len_->Number()); 470f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK_EQ(len, len_->Number()); 471f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 472f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 473f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 474f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (len == 0) return isolate->heap()->false_value(); 475f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 476f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Let n be ? ToInteger(fromIndex). (If fromIndex is undefined, this step 477f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // produces the value 0.) 47862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int64_t index = 0; 47962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!from_index->IsUndefined(isolate)) { 480f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, from_index, 481f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Object::ToInteger(isolate, from_index)); 482f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 48362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (V8_LIKELY(from_index->IsSmi())) { 48462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int start_from = Smi::cast(*from_index)->value(); 48562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (start_from < 0) { 48662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch index = std::max<int64_t>(len + start_from, 0); 48762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 48862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch index = start_from; 48962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 49062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 49162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(from_index->IsHeapNumber()); 49262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch double start_from = from_index->Number(); 49362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (start_from >= len) return isolate->heap()->false_value(); 49462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (V8_LIKELY(std::isfinite(start_from))) { 49562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (start_from < 0) { 49662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch index = static_cast<int64_t>(std::max<double>(start_from + len, 0)); 49762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 49862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch index = start_from; 49962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 50062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 501f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 50262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 50362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_GE(index, 0); 504f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 505f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 506f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // If the receiver is not a special receiver type, and the length is a valid 507f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // element index, perform fast operation tailored to specific ElementsKinds. 50862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!object->map()->IsSpecialReceiverMap() && len < kMaxUInt32 && 509f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch JSObject::PrototypeHasNoElements(isolate, JSObject::cast(*object))) { 510f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<JSObject> obj = Handle<JSObject>::cast(object); 511f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ElementsAccessor* elements = obj->GetElementsAccessor(); 512f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Maybe<bool> result = elements->IncludesValue(isolate, obj, search_element, 513f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch static_cast<uint32_t>(index), 514f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch static_cast<uint32_t>(len)); 515f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch MAYBE_RETURN(result, isolate->heap()->exception()); 516f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return *isolate->factory()->ToBoolean(result.FromJust()); 517f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 518f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 519f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Otherwise, perform slow lookups for special receiver types 520f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (; index < len; ++index) { 521f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Let elementK be the result of ? Get(O, ! ToString(k)). 522f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<Object> element_k; 523f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 524f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<Object> index_obj = isolate->factory()->NewNumberFromInt64(index); 525f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch bool success; 526f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch LookupIterator it = LookupIterator::PropertyOrElement( 527f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate, object, index_obj, &success); 528f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(success); 529f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, element_k, 530f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Object::GetProperty(&it)); 531f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 532f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 533f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // If SameValueZero(searchElement, elementK) is true, return true. 534f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (search_element->SameValueZero(*element_k)) { 535f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return isolate->heap()->true_value(); 536f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 537f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 538f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return isolate->heap()->false_value(); 539f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 540f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 541f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochRUNTIME_FUNCTION(Runtime_ArrayIndexOf) { 542f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch HandleScope shs(isolate); 54362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(3, args.length()); 544f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CONVERT_ARG_HANDLE_CHECKED(Object, search_element, 1); 545f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CONVERT_ARG_HANDLE_CHECKED(Object, from_index, 2); 546f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 547f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Let O be ? ToObject(this value). 54862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Handle<Object> receiver_obj = args.at(0); 54962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (receiver_obj->IsNullOrUndefined(isolate)) { 550f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch THROW_NEW_ERROR_RETURN_FAILURE( 551f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined, 552f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate->factory()->NewStringFromAsciiChecked( 553f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Array.prototype.indexOf"))); 554f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 555f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<JSReceiver> object; 55662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, object, 55762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Object::ToObject(isolate, args.at(0))); 558f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 559f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Let len be ? ToLength(? Get(O, "length")). 560f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int64_t len; 561f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 562f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (object->IsJSArray()) { 563f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch uint32_t len32 = 0; 564f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch bool success = JSArray::cast(*object)->length()->ToArrayLength(&len32); 565f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(success); 566f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch USE(success); 567f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch len = len32; 568f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 569f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<Object> len_; 570f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 571f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate, len_, 572f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Object::GetProperty(object, isolate->factory()->length_string())); 573f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 574f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, len_, 575f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Object::ToLength(isolate, len_)); 576f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch len = static_cast<int64_t>(len_->Number()); 577f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK_EQ(len, len_->Number()); 578f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 579f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 580f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 581f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (len == 0) return Smi::FromInt(-1); 582f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 583f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Let n be ? ToInteger(fromIndex). (If fromIndex is undefined, this step 584f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // produces the value 0.) 585f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int64_t start_from; 586f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 587f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, from_index, 588f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Object::ToInteger(isolate, from_index)); 589f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch double fp = from_index->Number(); 590f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (fp > len) return Smi::FromInt(-1); 591f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch start_from = static_cast<int64_t>(fp); 592f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 593f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 594f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int64_t index; 595f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (start_from >= 0) { 596f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch index = start_from; 597f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 598f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch index = len + start_from; 599f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (index < 0) { 600f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch index = 0; 601f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 602f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 603f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 604f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // If the receiver is not a special receiver type, and the length is a valid 605f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // element index, perform fast operation tailored to specific ElementsKinds. 60662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!object->map()->IsSpecialReceiverMap() && len < kMaxUInt32 && 607f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch JSObject::PrototypeHasNoElements(isolate, JSObject::cast(*object))) { 608f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<JSObject> obj = Handle<JSObject>::cast(object); 609f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ElementsAccessor* elements = obj->GetElementsAccessor(); 610f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Maybe<int64_t> result = elements->IndexOfValue(isolate, obj, search_element, 611f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch static_cast<uint32_t>(index), 612f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch static_cast<uint32_t>(len)); 613f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch MAYBE_RETURN(result, isolate->heap()->exception()); 614f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return *isolate->factory()->NewNumberFromInt64(result.FromJust()); 615f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 616f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 617f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Otherwise, perform slow lookups for special receiver types 618f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (; index < len; ++index) { 619f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Let elementK be the result of ? Get(O, ! ToString(k)). 620f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<Object> element_k; 621f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 622f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<Object> index_obj = isolate->factory()->NewNumberFromInt64(index); 623f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch bool success; 624f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch LookupIterator it = LookupIterator::PropertyOrElement( 625f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch isolate, object, index_obj, &success); 626f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(success); 627f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!JSReceiver::HasProperty(&it).FromJust()) { 628f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch continue; 629f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 630f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, element_k, 631f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Object::GetProperty(&it)); 632f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (search_element->StrictEquals(*element_k)) { 633f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return *index_obj; 634f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 635f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 636f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 637f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return Smi::FromInt(-1); 638f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 639f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 64062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 641c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochRUNTIME_FUNCTION(Runtime_SpreadIterablePrepare) { 642c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch HandleScope scope(isolate); 643c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK_EQ(1, args.length()); 644c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CONVERT_ARG_HANDLE_CHECKED(Object, spread, 0); 645c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 64662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Iterate over the spread if we need to. 64762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (spread->IterationHasObservableEffects()) { 64862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Handle<JSFunction> spread_iterable_function = isolate->spread_iterable(); 64962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 65062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch isolate, spread, 65162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Execution::Call(isolate, spread_iterable_function, 65262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch isolate->factory()->undefined_value(), 1, &spread)); 653c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 654c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 65562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return *spread; 65662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 657c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 65862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochRUNTIME_FUNCTION(Runtime_SpreadIterableFixed) { 65962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch HandleScope scope(isolate); 66062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(1, args.length()); 66162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CONVERT_ARG_HANDLE_CHECKED(Object, spread, 0); 66262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 66362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // The caller should check if proper iteration is necessary. 66462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Handle<JSFunction> spread_iterable_function = isolate->spread_iterable(); 665c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 66662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch isolate, spread, 667c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Execution::Call(isolate, spread_iterable_function, 668c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch isolate->factory()->undefined_value(), 1, &spread)); 669c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 67062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Create a new FixedArray and put the result of the spread into it. 67162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Handle<JSArray> spread_array = Handle<JSArray>::cast(spread); 67262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch uint32_t spread_length; 67362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CHECK(spread_array->length()->ToArrayIndex(&spread_length)); 67462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 67562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Handle<FixedArray> result = isolate->factory()->NewFixedArray(spread_length); 67662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ElementsAccessor* accessor = spread_array->GetElementsAccessor(); 67762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch for (uint32_t i = 0; i < spread_length; i++) { 67862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(accessor->HasElement(spread_array, i)); 67962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Handle<Object> element = accessor->Get(spread_array, i); 68062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch result->set(i, *element); 68162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 68262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 68362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return *result; 684c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 685c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 688