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