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

[array] Prepare Array.p.shift for removal of the JavaScript fall-back

This CL changes the ArrayPrototypeShift builtin to a CSA macro which
is used in a newly created Torque builtin.

This is in preparation for removing the JavaScript fall-back, which
will be replaced by a baseline Torque implementation.

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

Bug: v8:7624
Change-Id: I9b7898beea2802cc02d394e040a1e500387cf108
Reviewed-on: https://chromium-review.googlesource.com/1169172Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Commit-Queue: Simon Zünd <szuend@google.com>
Cr-Commit-Position: refs/heads/master@{#55036}
parent 1536ef90
......@@ -872,6 +872,7 @@ torque_files = [
"src/builtins/array.tq",
"src/builtins/array-copywithin.tq",
"src/builtins/array-foreach.tq",
"src/builtins/array-shift.tq",
"src/builtins/typed-array.tq",
"src/builtins/data-view.tq",
"test/torque/test-torque.tq",
......
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module array {
extern macro GenerateFastArrayShift(Context, Object): Object labels Slow;
extern builtin ArrayShift(Context, JSFunction, Object, int32): void;
// https://tc39.github.io/ecma262/#sec-array.prototype.shift
javascript builtin ArrayPrototypeShift(
context: Context, receiver: Object, ...arguments): Object {
try {
return GenerateFastArrayShift(context, receiver) otherwise Slow;
}
label Slow {
// TODO(szuend): Move checks if FastElementsAccessor::shift can be used
// from the C++ builtin here.
tail ArrayShift(
context, LoadTargetFromFrame(), Undefined,
convert<int32>(arguments.length));
}
// TODO(szuend): Implement baseline Array.p.shift that replaces JS fallback.
}
}
......@@ -738,6 +738,7 @@ extern macro IsFixedArray(HeapObject): bool;
extern macro IsExtensibleMap(Map): bool;
extern macro IsCustomElementsReceiverInstanceType(int32): bool;
extern macro Typeof(Object): Object;
extern macro LoadTargetFromFrame(): JSFunction;
// Return true iff number is NaN.
macro NumberIsNaN(number: Number): bool {
......
......@@ -18,6 +18,8 @@ namespace v8 {
namespace internal {
using Node = compiler::Node;
template <class T>
using TNode = compiler::TNode<T>;
ArrayBuiltinsAssembler::ArrayBuiltinsAssembler(
compiler::CodeAssemblerState* state)
......@@ -1503,17 +1505,9 @@ TF_BUILTIN(ArrayPrototypeSlice, ArrayPrototypeSliceCodeStubAssembler) {
args.PopAndReturn(a);
}
TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) {
TNode<Int32T> argc =
UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount));
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
CSA_ASSERT(this, IsUndefined(Parameter(Descriptor::kJSNewTarget)));
CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
TNode<Object> receiver = args.GetReceiver();
Label runtime(this, Label::kDeferred);
Label fast(this);
TNode<Object> ArrayBuiltinsAssembler::GenerateFastArrayShift(
TNode<Context> context, TNode<Object> receiver, Label* slow) {
Label fast(this), done(this);
// Only shift in this stub if
// 1) the array has fast elements
......@@ -1523,10 +1517,11 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) {
// 5) we aren't supposed to left-trim the backing store.
// 1) Check that the array has fast elements.
BranchIfFastJSArray(receiver, context, &fast, &runtime);
BranchIfFastJSArray(receiver, context, &fast, slow);
BIND(&fast);
{
TVARIABLE(Object, result, UndefinedConstant());
TNode<JSArray> array_receiver = CAST(receiver);
CSA_ASSERT(this, TaggedIsPositiveSmi(LoadJSArrayLength(array_receiver)));
Node* length =
......@@ -1536,13 +1531,13 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) {
GotoIf(IntPtrEqual(length, IntPtrConstant(0)), &return_undefined);
// 2) Ensure that the length is writable.
EnsureArrayLengthWritable(LoadMap(array_receiver), &runtime);
EnsureArrayLengthWritable(LoadMap(array_receiver), slow);
// 3) Check that the elements backing store isn't copy-on-write.
Node* elements = LoadElements(array_receiver);
GotoIf(WordEqual(LoadMap(elements),
LoadRoot(Heap::kFixedCOWArrayMapRootIndex)),
&runtime);
slow);
Node* new_length = IntPtrSub(length, IntPtrConstant(1));
......@@ -1553,13 +1548,13 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) {
IntPtrAdd(IntPtrAdd(new_length, new_length),
IntPtrConstant(JSObject::kMinAddedElementsCapacity)),
capacity),
&runtime);
slow);
// 5) Check that we're not supposed to left-trim the backing store, as
// implemented in elements.cc:FastElementsAccessor::MoveElements.
GotoIf(IntPtrGreaterThan(new_length,
IntPtrConstant(JSArray::kMaxCopyElements)),
&runtime);
slow);
StoreObjectFieldNoWriteBarrier(array_receiver, JSArray::kLengthOffset,
SmiTag(new_length));
......@@ -1577,12 +1572,10 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) {
Int32LessThanOrEqual(elements_kind,
Int32Constant(HOLEY_DOUBLE_ELEMENTS)));
VARIABLE(result, MachineRepresentation::kTagged, UndefinedConstant());
Label move_elements(this);
result.Bind(AllocateHeapNumberWithValue(LoadFixedDoubleArrayElement(
result = AllocateHeapNumberWithValue(LoadFixedDoubleArrayElement(
elements, IntPtrConstant(0), MachineType::Float64(), 0,
INTPTR_PARAMETERS, &move_elements)));
INTPTR_PARAMETERS, &move_elements));
Goto(&move_elements);
BIND(&move_elements);
......@@ -1612,13 +1605,14 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) {
IntPtrAdd(offset, IntPtrConstant(kPointerSize)),
double_hole);
}
args.PopAndReturn(result.value());
Goto(&done);
}
BIND(&fast_elements_tagged);
{
TNode<FixedArray> elements_fixed_array = CAST(elements);
Node* value = LoadFixedArrayElement(elements_fixed_array, 0);
TNode<Object> value = LoadFixedArrayElement(elements_fixed_array, 0);
BuildFastLoop(
IntPtrConstant(0), new_length,
[&](Node* index) {
......@@ -1631,13 +1625,15 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) {
StoreFixedArrayElement(elements_fixed_array, new_length,
TheHoleConstant());
GotoIf(WordEqual(value, TheHoleConstant()), &return_undefined);
args.PopAndReturn(value);
result = value;
Goto(&done);
}
BIND(&fast_elements_smi);
{
TNode<FixedArray> elements_fixed_array = CAST(elements);
Node* value = LoadFixedArrayElement(elements_fixed_array, 0);
TNode<Object> value = LoadFixedArrayElement(elements_fixed_array, 0);
BuildFastLoop(
IntPtrConstant(0), new_length,
[&](Node* index) {
......@@ -1651,21 +1647,19 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) {
StoreFixedArrayElement(elements_fixed_array, new_length,
TheHoleConstant());
GotoIf(WordEqual(value, TheHoleConstant()), &return_undefined);
args.PopAndReturn(value);
result = value;
Goto(&done);
}
BIND(&return_undefined);
{ args.PopAndReturn(UndefinedConstant()); }
}
{
result = UndefinedConstant();
Goto(&done);
}
BIND(&runtime);
{
// We are not using Parameter(Descriptor::kJSTarget) and loading the value
// from the current frame here in order to reduce register pressure on the
// fast path.
TNode<JSFunction> target = LoadTargetFromFrame();
TailCallBuiltin(Builtins::kArrayShift, context, target, UndefinedConstant(),
argc);
BIND(&done);
return result.value();
}
}
......
......@@ -145,6 +145,9 @@ class ArrayBuiltinsAssembler : public BaseBuiltinsFromDSLAssembler {
void GenerateInternalArrayNoArgumentConstructor(ElementsKind kind);
void GenerateInternalArraySingleArgumentConstructor(ElementsKind kind);
TNode<Object> GenerateFastArrayShift(TNode<Context> context,
TNode<Object> receiver, Label* slow);
private:
static ElementsKind ElementsKindForInstanceType(InstanceType type);
......
......@@ -312,7 +312,6 @@ namespace internal {
TFJ(ArrayPrototypePush, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.shift */ \
CPP(ArrayShift) \
TFJ(ArrayPrototypeShift, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.slice */ \
TFJ(ArrayPrototypeSlice, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.splice */ \
......
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