blob: f651ed40e122d6810f1607214bb2ceabaa940d7b [file] [log] [blame]
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005#include "src/runtime/runtime-utils.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006
7#include "src/arguments.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include "src/conversions-inl.h"
9#include "src/elements.h"
10#include "src/factory.h"
11#include "src/isolate-inl.h"
12#include "src/key-accumulator.h"
13#include "src/messages.h"
14#include "src/prototype.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015
16namespace v8 {
17namespace internal {
18
19RUNTIME_FUNCTION(Runtime_FinishArrayPrototypeSetup) {
20 HandleScope scope(isolate);
21 DCHECK(args.length() == 1);
22 CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0);
23 Object* length = prototype->length();
24 RUNTIME_ASSERT(length->IsSmi() && Smi::cast(length)->value() == 0);
25 RUNTIME_ASSERT(prototype->HasFastSmiOrObjectElements());
26 // This is necessary to enable fast checks for absence of elements
27 // on Array.prototype and below.
28 prototype->set_elements(isolate->heap()->empty_fixed_array());
29 return Smi::FromInt(0);
30}
31
32
33static void InstallBuiltin(Isolate* isolate, Handle<JSObject> holder,
34 const char* name, Builtins::Name builtin_name) {
35 Handle<String> key = isolate->factory()->InternalizeUtf8String(name);
36 Handle<Code> code(isolate->builtins()->builtin(builtin_name));
37 Handle<JSFunction> optimized =
38 isolate->factory()->NewFunctionWithoutPrototype(key, code);
39 optimized->shared()->DontAdaptArguments();
40 JSObject::AddProperty(holder, key, optimized, NONE);
41}
42
43
44RUNTIME_FUNCTION(Runtime_SpecialArrayFunctions) {
45 HandleScope scope(isolate);
46 DCHECK(args.length() == 0);
47 Handle<JSObject> holder =
48 isolate->factory()->NewJSObject(isolate->object_function());
49
50 InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop);
51 InstallBuiltin(isolate, holder, "push", Builtins::kArrayPush);
52 InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift);
53 InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift);
54 InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
55 InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040056
57 return *holder;
58}
59
60
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000061RUNTIME_FUNCTION(Runtime_FixedArrayGet) {
62 SealHandleScope shs(isolate);
63 DCHECK(args.length() == 2);
64 CONVERT_ARG_CHECKED(FixedArray, object, 0);
65 CONVERT_SMI_ARG_CHECKED(index, 1);
66 return object->get(index);
67}
68
69
70RUNTIME_FUNCTION(Runtime_FixedArraySet) {
71 SealHandleScope shs(isolate);
72 DCHECK(args.length() == 3);
73 CONVERT_ARG_CHECKED(FixedArray, object, 0);
74 CONVERT_SMI_ARG_CHECKED(index, 1);
75 CONVERT_ARG_CHECKED(Object, value, 2);
76 object->set(index, value);
77 return isolate->heap()->undefined_value();
78}
79
80
Emily Bernierd0a1eb72015-03-24 16:35:39 -040081RUNTIME_FUNCTION(Runtime_TransitionElementsKind) {
82 HandleScope scope(isolate);
83 RUNTIME_ASSERT(args.length() == 2);
84 CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
85 CONVERT_ARG_HANDLE_CHECKED(Map, map, 1);
86 JSObject::TransitionElementsKind(array, map->elements_kind());
87 return *array;
88}
89
90
91// Push an object unto an array of objects if it is not already in the
92// array. Returns true if the element was pushed on the stack and
93// false otherwise.
94RUNTIME_FUNCTION(Runtime_PushIfAbsent) {
95 HandleScope scope(isolate);
96 DCHECK(args.length() == 2);
97 CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
98 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, element, 1);
99 RUNTIME_ASSERT(array->HasFastSmiOrObjectElements());
100 int length = Smi::cast(array->length())->value();
101 FixedArray* elements = FixedArray::cast(array->elements());
102 for (int i = 0; i < length; i++) {
103 if (elements->get(i) == *element) return isolate->heap()->false_value();
104 }
105
106 // Strict not needed. Used for cycle detection in Array join implementation.
107 RETURN_FAILURE_ON_EXCEPTION(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000108 isolate, JSObject::AddDataElement(array, length, element, NONE));
109 JSObject::ValidateElements(array);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400110 return isolate->heap()->true_value();
111}
112
113
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400114// Moves all own elements of an object, that are below a limit, to positions
115// starting at zero. All undefined values are placed after non-undefined values,
116// and are followed by non-existing element. Does not change the length
117// property.
118// Returns the number of non-undefined elements collected.
119// Returns -1 if hole removal is not supported by this method.
120RUNTIME_FUNCTION(Runtime_RemoveArrayHoles) {
121 HandleScope scope(isolate);
122 DCHECK(args.length() == 2);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100123 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400124 CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100125 if (object->IsJSProxy()) return Smi::FromInt(-1);
126 return *JSObject::PrepareElementsForSort(Handle<JSObject>::cast(object),
127 limit);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400128}
129
130
131// Move contents of argument 0 (an array) to argument 1 (an array)
132RUNTIME_FUNCTION(Runtime_MoveArrayContents) {
133 HandleScope scope(isolate);
134 DCHECK(args.length() == 2);
135 CONVERT_ARG_HANDLE_CHECKED(JSArray, from, 0);
136 CONVERT_ARG_HANDLE_CHECKED(JSArray, to, 1);
137 JSObject::ValidateElements(from);
138 JSObject::ValidateElements(to);
139
140 Handle<FixedArrayBase> new_elements(from->elements());
141 ElementsKind from_kind = from->GetElementsKind();
142 Handle<Map> new_map = JSObject::GetElementsTransitionMap(to, from_kind);
143 JSObject::SetMapAndElements(to, new_map, new_elements);
144 to->set_length(from->length());
145
146 JSObject::ResetElements(from);
147 from->set_length(Smi::FromInt(0));
148
149 JSObject::ValidateElements(to);
150 return *to;
151}
152
153
154// How many elements does this object/array have?
155RUNTIME_FUNCTION(Runtime_EstimateNumberOfElements) {
156 HandleScope scope(isolate);
157 DCHECK(args.length() == 1);
158 CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
159 Handle<FixedArrayBase> elements(array->elements(), isolate);
160 SealHandleScope shs(isolate);
161 if (elements->IsDictionary()) {
162 int result =
163 Handle<SeededNumberDictionary>::cast(elements)->NumberOfElements();
164 return Smi::FromInt(result);
165 } else {
166 DCHECK(array->length()->IsSmi());
167 // For packed elements, we know the exact number of elements
168 int length = elements->length();
169 ElementsKind kind = array->GetElementsKind();
170 if (IsFastPackedElementsKind(kind)) {
171 return Smi::FromInt(length);
172 }
173 // For holey elements, take samples from the buffer checking for holes
174 // to generate the estimate.
175 const int kNumberOfHoleCheckSamples = 97;
176 int increment = (length < kNumberOfHoleCheckSamples)
177 ? 1
178 : static_cast<int>(length / kNumberOfHoleCheckSamples);
179 ElementsAccessor* accessor = array->GetElementsAccessor();
180 int holes = 0;
181 for (int i = 0; i < length; i += increment) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000182 if (!accessor->HasElement(array, i, elements)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400183 ++holes;
184 }
185 }
186 int estimate = static_cast<int>((kNumberOfHoleCheckSamples - holes) /
187 kNumberOfHoleCheckSamples * length);
188 return Smi::FromInt(estimate);
189 }
190}
191
192
193// Returns an array that tells you where in the [0, length) interval an array
194// might have elements. Can either return an array of keys (positive integers
195// or undefined) or a number representing the positive length of an interval
196// starting at index 0.
197// Intervals can span over some keys that are not in the object.
198RUNTIME_FUNCTION(Runtime_GetArrayKeys) {
199 HandleScope scope(isolate);
200 DCHECK(args.length() == 2);
201 CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
202 CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203
Ben Murdoch097c5b22016-05-18 11:27:45 +0100204 if (array->HasFastStringWrapperElements()) {
205 int string_length =
206 String::cast(Handle<JSValue>::cast(array)->value())->length();
207 int backing_store_length = array->elements()->length();
208 return *isolate->factory()->NewNumberFromUint(
209 Min(length,
210 static_cast<uint32_t>(Max(string_length, backing_store_length))));
211 }
212
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000213 if (!array->elements()->IsDictionary()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400214 RUNTIME_ASSERT(array->HasFastSmiOrObjectElements() ||
215 array->HasFastDoubleElements());
216 uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
217 return *isolate->factory()->NewNumberFromUint(Min(actual_length, length));
218 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000219
Ben Murdoch097c5b22016-05-18 11:27:45 +0100220 KeyAccumulator accumulator(isolate, OWN_ONLY, ALL_PROPERTIES);
221 // No need to separate prototype levels since we only get element keys.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000222 for (PrototypeIterator iter(isolate, array,
223 PrototypeIterator::START_AT_RECEIVER);
224 !iter.IsAtEnd(); iter.Advance()) {
225 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy() ||
226 PrototypeIterator::GetCurrent<JSObject>(iter)
227 ->HasIndexedInterceptor()) {
228 // Bail out if we find a proxy or interceptor, likely not worth
229 // collecting keys in that case.
230 return *isolate->factory()->NewNumberFromUint(length);
231 }
232 accumulator.NextPrototype();
233 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter);
234 JSObject::CollectOwnElementKeys(current, &accumulator, ALL_PROPERTIES);
235 }
236 // Erase any keys >= length.
237 // TODO(adamk): Remove this step when the contract of %GetArrayKeys
238 // is changed to let this happen on the JS side.
239 Handle<FixedArray> keys = accumulator.GetKeys(KEEP_NUMBERS);
240 for (int i = 0; i < keys->length(); i++) {
241 if (NumberToUint32(keys->get(i)) >= length) keys->set_undefined(i);
242 }
243 return *isolate->factory()->NewJSArrayWithElements(keys);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400244}
245
246
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000247namespace {
248
249Object* ArrayConstructorCommon(Isolate* isolate, Handle<JSFunction> constructor,
250 Handle<JSReceiver> new_target,
251 Handle<AllocationSite> site,
252 Arguments* caller_args) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400253 Factory* factory = isolate->factory();
254
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000255 // If called through new, new.target can be:
256 // - a subclass of constructor,
257 // - a proxy wrapper around constructor, or
258 // - the constructor itself.
259 // If called through Reflect.construct, it's guaranteed to be a constructor by
260 // REFLECT_CONSTRUCT_PREPARE.
261 DCHECK(new_target->IsConstructor());
262
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400263 bool holey = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000264 bool can_use_type_feedback = !site.is_null();
265 bool can_inline_array_constructor = true;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400266 if (caller_args->length() == 1) {
267 Handle<Object> argument_one = caller_args->at<Object>(0);
268 if (argument_one->IsSmi()) {
269 int value = Handle<Smi>::cast(argument_one)->value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000270 if (value < 0 ||
271 JSArray::SetLengthWouldNormalize(isolate->heap(), value)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400272 // the array is a dictionary in this case.
273 can_use_type_feedback = false;
274 } else if (value != 0) {
275 holey = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000276 if (value >= JSArray::kInitialMaxFastElementArray) {
277 can_inline_array_constructor = false;
278 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400279 }
280 } else {
281 // Non-smi length argument produces a dictionary
282 can_use_type_feedback = false;
283 }
284 }
285
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000286 Handle<Map> initial_map;
287 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
288 isolate, initial_map,
289 JSFunction::GetDerivedMap(isolate, constructor, new_target));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400290
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000291 ElementsKind to_kind = can_use_type_feedback ? site->GetElementsKind()
292 : initial_map->elements_kind();
293 if (holey && !IsFastHoleyElementsKind(to_kind)) {
294 to_kind = GetHoleyElementsKind(to_kind);
295 // Update the allocation site info to reflect the advice alteration.
296 if (!site.is_null()) site->SetElementsKind(to_kind);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400297 }
298
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000299 // We should allocate with an initial map that reflects the allocation site
300 // advice. Therefore we use AllocateJSObjectFromMap instead of passing
301 // the constructor.
302 if (to_kind != initial_map->elements_kind()) {
303 initial_map = Map::AsElementsKind(initial_map, to_kind);
304 }
305
306 // If we don't care to track arrays of to_kind ElementsKind, then
307 // don't emit a memento for them.
308 Handle<AllocationSite> allocation_site;
309 if (AllocationSite::GetMode(to_kind) == TRACK_ALLOCATION_SITE) {
310 allocation_site = site;
311 }
312
313 Handle<JSArray> array = Handle<JSArray>::cast(
314 factory->NewJSObjectFromMap(initial_map, NOT_TENURED, allocation_site));
315
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400316 factory->NewJSArrayStorage(array, 0, 0, DONT_INITIALIZE_ARRAY_ELEMENTS);
317
318 ElementsKind old_kind = array->GetElementsKind();
319 RETURN_FAILURE_ON_EXCEPTION(
320 isolate, ArrayConstructInitializeElements(array, caller_args));
321 if (!site.is_null() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000322 (old_kind != array->GetElementsKind() || !can_use_type_feedback ||
323 !can_inline_array_constructor)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400324 // The arguments passed in caused a transition. This kind of complexity
325 // can't be dealt with in the inlined hydrogen array constructor case.
326 // We must mark the allocationsite as un-inlinable.
327 site->SetDoNotInlineCall();
328 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000329
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400330 return *array;
331}
332
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000333} // namespace
334
335
336RUNTIME_FUNCTION(Runtime_NewArray) {
337 HandleScope scope(isolate);
338 DCHECK_LE(3, args.length());
339 int const argc = args.length() - 3;
340 // TODO(bmeurer): Remove this Arguments nonsense.
341 Arguments argv(argc, args.arguments() - 1);
342 CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
343 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, new_target, argc + 1);
344 CONVERT_ARG_HANDLE_CHECKED(HeapObject, type_info, argc + 2);
345 // TODO(bmeurer): Use MaybeHandle to pass around the AllocationSite.
346 Handle<AllocationSite> site = type_info->IsAllocationSite()
347 ? Handle<AllocationSite>::cast(type_info)
348 : Handle<AllocationSite>::null();
349 return ArrayConstructorCommon(isolate, constructor, new_target, site, &argv);
350}
351
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400352
353RUNTIME_FUNCTION(Runtime_ArrayConstructor) {
354 HandleScope scope(isolate);
355 // If we get 2 arguments then they are the stub parameters (constructor, type
356 // info). If we get 4, then the first one is a pointer to the arguments
357 // passed by the caller, and the last one is the length of the arguments
358 // passed to the caller (redundant, but useful to check on the deoptimizer
359 // with an assert).
360 Arguments empty_args(0, NULL);
361 bool no_caller_args = args.length() == 2;
362 DCHECK(no_caller_args || args.length() == 4);
363 int parameters_start = no_caller_args ? 0 : 1;
364 Arguments* caller_args =
365 no_caller_args ? &empty_args : reinterpret_cast<Arguments*>(args[0]);
366 CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
367 CONVERT_ARG_HANDLE_CHECKED(Object, type_info, parameters_start + 1);
368#ifdef DEBUG
369 if (!no_caller_args) {
370 CONVERT_SMI_ARG_CHECKED(arg_count, parameters_start + 2);
371 DCHECK(arg_count == caller_args->length());
372 }
373#endif
374
375 Handle<AllocationSite> site;
376 if (!type_info.is_null() &&
377 *type_info != isolate->heap()->undefined_value()) {
378 site = Handle<AllocationSite>::cast(type_info);
379 DCHECK(!site->SitePointsToLiteral());
380 }
381
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000382 return ArrayConstructorCommon(isolate, constructor, constructor, site,
383 caller_args);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400384}
385
386
387RUNTIME_FUNCTION(Runtime_InternalArrayConstructor) {
388 HandleScope scope(isolate);
389 Arguments empty_args(0, NULL);
390 bool no_caller_args = args.length() == 1;
391 DCHECK(no_caller_args || args.length() == 3);
392 int parameters_start = no_caller_args ? 0 : 1;
393 Arguments* caller_args =
394 no_caller_args ? &empty_args : reinterpret_cast<Arguments*>(args[0]);
395 CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
396#ifdef DEBUG
397 if (!no_caller_args) {
398 CONVERT_SMI_ARG_CHECKED(arg_count, parameters_start + 1);
399 DCHECK(arg_count == caller_args->length());
400 }
401#endif
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000402 return ArrayConstructorCommon(isolate, constructor, constructor,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400403 Handle<AllocationSite>::null(), caller_args);
404}
405
406
407RUNTIME_FUNCTION(Runtime_NormalizeElements) {
408 HandleScope scope(isolate);
409 DCHECK(args.length() == 1);
410 CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000411 RUNTIME_ASSERT(!array->HasFixedTypedArrayElements() &&
412 !array->IsJSGlobalProxy());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400413 JSObject::NormalizeElements(array);
414 return *array;
415}
416
417
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000418// GrowArrayElements returns a sentinel Smi if the object was normalized.
419RUNTIME_FUNCTION(Runtime_GrowArrayElements) {
420 HandleScope scope(isolate);
421 DCHECK(args.length() == 2);
422 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
423 CONVERT_NUMBER_CHECKED(int, key, Int32, args[1]);
424
425 if (key < 0) {
426 return object->elements();
427 }
428
429 uint32_t capacity = static_cast<uint32_t>(object->elements()->length());
430 uint32_t index = static_cast<uint32_t>(key);
431
432 if (index >= capacity) {
433 if (object->WouldConvertToSlowElements(index)) {
434 // We don't want to allow operations that cause lazy deopt. Return a Smi
435 // as a signal that optimized code should eagerly deoptimize.
436 return Smi::FromInt(0);
437 }
438
439 uint32_t new_capacity = JSObject::NewElementsCapacity(index + 1);
440 object->GetElementsAccessor()->GrowCapacityAndConvert(object, new_capacity);
441 }
442
443 // On success, return the fixed array elements.
444 return object->elements();
445}
446
447
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400448RUNTIME_FUNCTION(Runtime_HasComplexElements) {
449 HandleScope scope(isolate);
450 DCHECK(args.length() == 1);
451 CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
452 for (PrototypeIterator iter(isolate, array,
453 PrototypeIterator::START_AT_RECEIVER);
454 !iter.IsAtEnd(); iter.Advance()) {
455 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
456 return isolate->heap()->true_value();
457 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000458 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400459 if (current->HasIndexedInterceptor()) {
460 return isolate->heap()->true_value();
461 }
462 if (!current->HasDictionaryElements()) continue;
463 if (current->element_dictionary()->HasComplexElements()) {
464 return isolate->heap()->true_value();
465 }
466 }
467 return isolate->heap()->false_value();
468}
469
470
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000471RUNTIME_FUNCTION(Runtime_IsArray) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400472 SealHandleScope shs(isolate);
473 DCHECK(args.length() == 1);
474 CONVERT_ARG_CHECKED(Object, obj, 0);
475 return isolate->heap()->ToBoolean(obj->IsJSArray());
476}
477
478
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000479RUNTIME_FUNCTION(Runtime_HasCachedArrayIndex) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400480 SealHandleScope shs(isolate);
481 DCHECK(args.length() == 1);
482 return isolate->heap()->false_value();
483}
484
485
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000486RUNTIME_FUNCTION(Runtime_GetCachedArrayIndex) {
487 // This can never be reached, because Runtime_HasCachedArrayIndex always
488 // returns false.
489 UNIMPLEMENTED();
490 return nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400491}
492
493
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000494RUNTIME_FUNCTION(Runtime_ArraySpeciesConstructor) {
495 HandleScope scope(isolate);
496 DCHECK(args.length() == 1);
497 CONVERT_ARG_HANDLE_CHECKED(Object, original_array, 0);
498 Handle<Object> constructor;
499 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
500 isolate, constructor,
501 Object::ArraySpeciesConstructor(isolate, original_array));
502 return *constructor;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400503}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000504
505} // namespace internal
506} // namespace v8