Commit 575e582e authored by Simon Zünd's avatar Simon Zünd Committed by Commit Bot

[array] Move Array.p.pop fall-back from JS to C++

This CL extends the existing ArrayPop C++ builtin with a generic
slow-path that replaces the JavaScript fallback.

R=cbruni@chromium.org, jgruber@chromium.org

Bug: v8:7624
Change-Id: Ie3ce5379e5c65df67cbc4d956390a8701345ea3c
Reviewed-on: https://chromium-review.googlesource.com/1127162
Commit-Queue: Simon Zünd <szuend@google.com>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54284}
parent b8e10488
......@@ -232,20 +232,76 @@ BUILTIN(ArrayPush) {
return *isolate->factory()->NewNumberFromUint((new_length));
}
namespace {
V8_WARN_UNUSED_RESULT Object* GenericArrayPop(Isolate* isolate,
BuiltinArguments* args) {
// 1. Let O be ? ToObject(this value).
Handle<JSReceiver> receiver;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, receiver, Object::ToObject(isolate, args->receiver()));
// 2. Let len be ? ToLength(? Get(O, "length")).
Handle<Object> raw_length_number;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, raw_length_number,
Object::GetLengthFromArrayLike(isolate, receiver));
double length = raw_length_number->Number();
// 3. If len is zero, then.
if (length == 0) {
// a. Perform ? Set(O, "length", 0, true).
RETURN_FAILURE_ON_EXCEPTION(
isolate, Object::SetProperty(
receiver, isolate->factory()->length_string(),
Handle<Smi>(Smi::kZero, isolate), LanguageMode::kStrict));
// b. Return undefined.
return ReadOnlyRoots(isolate).undefined_value();
}
// 4. Else len > 0.
// a. Let new_len be len-1.
Handle<Object> new_length = isolate->factory()->NewNumber(length - 1);
// b. Let index be ! ToString(newLen).
Handle<String> index = isolate->factory()->NumberToString(new_length);
// c. Let element be ? Get(O, index).
Handle<Object> element;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, element, JSReceiver::GetPropertyOrElement(receiver, index));
// d. Perform ? DeletePropertyOrThrow(O, index).
MAYBE_RETURN(JSReceiver::DeletePropertyOrElement(receiver, index,
LanguageMode::kStrict),
ReadOnlyRoots(isolate).exception());
// e. Perform ? Set(O, "length", newLen, true).
RETURN_FAILURE_ON_EXCEPTION(
isolate,
Object::SetProperty(receiver, isolate->factory()->length_string(),
new_length, LanguageMode::kStrict));
// f. Return element.
return *element;
}
} // namespace
BUILTIN(ArrayPop) {
HandleScope scope(isolate);
Handle<Object> receiver = args.receiver();
if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, nullptr, 0)) {
return CallJsIntrinsic(isolate, isolate->array_pop(), args);
return GenericArrayPop(isolate, &args);
}
Handle<JSArray> array = Handle<JSArray>::cast(receiver);
uint32_t len = static_cast<uint32_t>(Smi::ToInt(array->length()));
uint32_t len = static_cast<uint32_t>(array->length()->Number());
if (len == 0) return ReadOnlyRoots(isolate).undefined_value();
if (JSArray::HasReadOnlyLength(array)) {
return CallJsIntrinsic(isolate, isolate->array_pop(), args);
return GenericArrayPop(isolate, &args);
}
Handle<Object> result;
......@@ -259,6 +315,7 @@ BUILTIN(ArrayPop) {
isolate, result, JSReceiver::GetElement(isolate, array, new_length));
JSArray::SetLength(array, new_length);
}
return *result;
}
......
......@@ -71,7 +71,6 @@ enum ContextLookupFlags {
V(ASYNC_GENERATOR_AWAIT_UNCAUGHT, JSFunction, async_generator_await_uncaught)
#define NATIVE_CONTEXT_IMPORTED_FIELDS(V) \
V(ARRAY_POP_INDEX, JSFunction, array_pop) \
V(ARRAY_SHIFT_INDEX, JSFunction, array_shift) \
V(ARRAY_SPLICE_INDEX, JSFunction, array_splice) \
V(ARRAY_UNSHIFT_INDEX, JSFunction, array_unshift) \
......
......@@ -391,24 +391,6 @@ DEFINE_METHOD(
);
// Removes the last element from the array and returns it. See
// ECMA-262, section 15.4.4.6.
function ArrayPopFallback() {
var array = TO_OBJECT(this);
var n = TO_LENGTH(array.length);
if (n == 0) {
array.length = n;
return;
}
n--;
var value = array[n];
delete array[n];
array.length = n;
return value;
}
// For implementing reverse() on large, sparse arrays.
function SparseReverse(array, len) {
var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len));
......@@ -1037,7 +1019,6 @@ utils.Export(function(to) {
"array_keys_iterator", ArrayKeys,
"array_values_iterator", ArrayValues,
// Fallback implementations of Array builtins.
"array_pop", ArrayPopFallback,
"array_shift", ArrayShiftFallback,
"array_splice", ArraySpliceFallback,
"array_unshift", ArrayUnshiftFallback,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment