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 = [ ...@@ -872,6 +872,7 @@ torque_files = [
"src/builtins/array.tq", "src/builtins/array.tq",
"src/builtins/array-copywithin.tq", "src/builtins/array-copywithin.tq",
"src/builtins/array-foreach.tq", "src/builtins/array-foreach.tq",
"src/builtins/array-shift.tq",
"src/builtins/typed-array.tq", "src/builtins/typed-array.tq",
"src/builtins/data-view.tq", "src/builtins/data-view.tq",
"test/torque/test-torque.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; ...@@ -738,6 +738,7 @@ extern macro IsFixedArray(HeapObject): bool;
extern macro IsExtensibleMap(Map): bool; extern macro IsExtensibleMap(Map): bool;
extern macro IsCustomElementsReceiverInstanceType(int32): bool; extern macro IsCustomElementsReceiverInstanceType(int32): bool;
extern macro Typeof(Object): Object; extern macro Typeof(Object): Object;
extern macro LoadTargetFromFrame(): JSFunction;
// Return true iff number is NaN. // Return true iff number is NaN.
macro NumberIsNaN(number: Number): bool { macro NumberIsNaN(number: Number): bool {
......
...@@ -18,6 +18,8 @@ namespace v8 { ...@@ -18,6 +18,8 @@ namespace v8 {
namespace internal { namespace internal {
using Node = compiler::Node; using Node = compiler::Node;
template <class T>
using TNode = compiler::TNode<T>;
ArrayBuiltinsAssembler::ArrayBuiltinsAssembler( ArrayBuiltinsAssembler::ArrayBuiltinsAssembler(
compiler::CodeAssemblerState* state) compiler::CodeAssemblerState* state)
...@@ -1503,17 +1505,9 @@ TF_BUILTIN(ArrayPrototypeSlice, ArrayPrototypeSliceCodeStubAssembler) { ...@@ -1503,17 +1505,9 @@ TF_BUILTIN(ArrayPrototypeSlice, ArrayPrototypeSliceCodeStubAssembler) {
args.PopAndReturn(a); args.PopAndReturn(a);
} }
TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) { TNode<Object> ArrayBuiltinsAssembler::GenerateFastArrayShift(
TNode<Int32T> argc = TNode<Context> context, TNode<Object> receiver, Label* slow) {
UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount)); Label fast(this), done(this);
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);
// Only shift in this stub if // Only shift in this stub if
// 1) the array has fast elements // 1) the array has fast elements
...@@ -1523,10 +1517,11 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) { ...@@ -1523,10 +1517,11 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) {
// 5) we aren't supposed to left-trim the backing store. // 5) we aren't supposed to left-trim the backing store.
// 1) Check that the array has fast elements. // 1) Check that the array has fast elements.
BranchIfFastJSArray(receiver, context, &fast, &runtime); BranchIfFastJSArray(receiver, context, &fast, slow);
BIND(&fast); BIND(&fast);
{ {
TVARIABLE(Object, result, UndefinedConstant());
TNode<JSArray> array_receiver = CAST(receiver); TNode<JSArray> array_receiver = CAST(receiver);
CSA_ASSERT(this, TaggedIsPositiveSmi(LoadJSArrayLength(array_receiver))); CSA_ASSERT(this, TaggedIsPositiveSmi(LoadJSArrayLength(array_receiver)));
Node* length = Node* length =
...@@ -1536,13 +1531,13 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) { ...@@ -1536,13 +1531,13 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) {
GotoIf(IntPtrEqual(length, IntPtrConstant(0)), &return_undefined); GotoIf(IntPtrEqual(length, IntPtrConstant(0)), &return_undefined);
// 2) Ensure that the length is writable. // 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. // 3) Check that the elements backing store isn't copy-on-write.
Node* elements = LoadElements(array_receiver); Node* elements = LoadElements(array_receiver);
GotoIf(WordEqual(LoadMap(elements), GotoIf(WordEqual(LoadMap(elements),
LoadRoot(Heap::kFixedCOWArrayMapRootIndex)), LoadRoot(Heap::kFixedCOWArrayMapRootIndex)),
&runtime); slow);
Node* new_length = IntPtrSub(length, IntPtrConstant(1)); Node* new_length = IntPtrSub(length, IntPtrConstant(1));
...@@ -1553,13 +1548,13 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) { ...@@ -1553,13 +1548,13 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) {
IntPtrAdd(IntPtrAdd(new_length, new_length), IntPtrAdd(IntPtrAdd(new_length, new_length),
IntPtrConstant(JSObject::kMinAddedElementsCapacity)), IntPtrConstant(JSObject::kMinAddedElementsCapacity)),
capacity), capacity),
&runtime); slow);
// 5) Check that we're not supposed to left-trim the backing store, as // 5) Check that we're not supposed to left-trim the backing store, as
// implemented in elements.cc:FastElementsAccessor::MoveElements. // implemented in elements.cc:FastElementsAccessor::MoveElements.
GotoIf(IntPtrGreaterThan(new_length, GotoIf(IntPtrGreaterThan(new_length,
IntPtrConstant(JSArray::kMaxCopyElements)), IntPtrConstant(JSArray::kMaxCopyElements)),
&runtime); slow);
StoreObjectFieldNoWriteBarrier(array_receiver, JSArray::kLengthOffset, StoreObjectFieldNoWriteBarrier(array_receiver, JSArray::kLengthOffset,
SmiTag(new_length)); SmiTag(new_length));
...@@ -1577,12 +1572,10 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) { ...@@ -1577,12 +1572,10 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) {
Int32LessThanOrEqual(elements_kind, Int32LessThanOrEqual(elements_kind,
Int32Constant(HOLEY_DOUBLE_ELEMENTS))); Int32Constant(HOLEY_DOUBLE_ELEMENTS)));
VARIABLE(result, MachineRepresentation::kTagged, UndefinedConstant());
Label move_elements(this); Label move_elements(this);
result.Bind(AllocateHeapNumberWithValue(LoadFixedDoubleArrayElement( result = AllocateHeapNumberWithValue(LoadFixedDoubleArrayElement(
elements, IntPtrConstant(0), MachineType::Float64(), 0, elements, IntPtrConstant(0), MachineType::Float64(), 0,
INTPTR_PARAMETERS, &move_elements))); INTPTR_PARAMETERS, &move_elements));
Goto(&move_elements); Goto(&move_elements);
BIND(&move_elements); BIND(&move_elements);
...@@ -1612,13 +1605,14 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) { ...@@ -1612,13 +1605,14 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) {
IntPtrAdd(offset, IntPtrConstant(kPointerSize)), IntPtrAdd(offset, IntPtrConstant(kPointerSize)),
double_hole); double_hole);
} }
args.PopAndReturn(result.value());
Goto(&done);
} }
BIND(&fast_elements_tagged); BIND(&fast_elements_tagged);
{ {
TNode<FixedArray> elements_fixed_array = CAST(elements); TNode<FixedArray> elements_fixed_array = CAST(elements);
Node* value = LoadFixedArrayElement(elements_fixed_array, 0); TNode<Object> value = LoadFixedArrayElement(elements_fixed_array, 0);
BuildFastLoop( BuildFastLoop(
IntPtrConstant(0), new_length, IntPtrConstant(0), new_length,
[&](Node* index) { [&](Node* index) {
...@@ -1631,13 +1625,15 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) { ...@@ -1631,13 +1625,15 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) {
StoreFixedArrayElement(elements_fixed_array, new_length, StoreFixedArrayElement(elements_fixed_array, new_length,
TheHoleConstant()); TheHoleConstant());
GotoIf(WordEqual(value, TheHoleConstant()), &return_undefined); GotoIf(WordEqual(value, TheHoleConstant()), &return_undefined);
args.PopAndReturn(value);
result = value;
Goto(&done);
} }
BIND(&fast_elements_smi); BIND(&fast_elements_smi);
{ {
TNode<FixedArray> elements_fixed_array = CAST(elements); TNode<FixedArray> elements_fixed_array = CAST(elements);
Node* value = LoadFixedArrayElement(elements_fixed_array, 0); TNode<Object> value = LoadFixedArrayElement(elements_fixed_array, 0);
BuildFastLoop( BuildFastLoop(
IntPtrConstant(0), new_length, IntPtrConstant(0), new_length,
[&](Node* index) { [&](Node* index) {
...@@ -1651,21 +1647,19 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) { ...@@ -1651,21 +1647,19 @@ TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) {
StoreFixedArrayElement(elements_fixed_array, new_length, StoreFixedArrayElement(elements_fixed_array, new_length,
TheHoleConstant()); TheHoleConstant());
GotoIf(WordEqual(value, TheHoleConstant()), &return_undefined); GotoIf(WordEqual(value, TheHoleConstant()), &return_undefined);
args.PopAndReturn(value);
result = value;
Goto(&done);
} }
BIND(&return_undefined); BIND(&return_undefined);
{ args.PopAndReturn(UndefinedConstant()); } {
result = UndefinedConstant();
Goto(&done);
} }
BIND(&runtime); BIND(&done);
{ return result.value();
// 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);
} }
} }
......
...@@ -145,6 +145,9 @@ class ArrayBuiltinsAssembler : public BaseBuiltinsFromDSLAssembler { ...@@ -145,6 +145,9 @@ class ArrayBuiltinsAssembler : public BaseBuiltinsFromDSLAssembler {
void GenerateInternalArrayNoArgumentConstructor(ElementsKind kind); void GenerateInternalArrayNoArgumentConstructor(ElementsKind kind);
void GenerateInternalArraySingleArgumentConstructor(ElementsKind kind); void GenerateInternalArraySingleArgumentConstructor(ElementsKind kind);
TNode<Object> GenerateFastArrayShift(TNode<Context> context,
TNode<Object> receiver, Label* slow);
private: private:
static ElementsKind ElementsKindForInstanceType(InstanceType type); static ElementsKind ElementsKindForInstanceType(InstanceType type);
......
...@@ -312,7 +312,6 @@ namespace internal { ...@@ -312,7 +312,6 @@ namespace internal {
TFJ(ArrayPrototypePush, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ TFJ(ArrayPrototypePush, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.shift */ \ /* ES6 #sec-array.prototype.shift */ \
CPP(ArrayShift) \ CPP(ArrayShift) \
TFJ(ArrayPrototypeShift, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.slice */ \ /* ES6 #sec-array.prototype.slice */ \
TFJ(ArrayPrototypeSlice, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ TFJ(ArrayPrototypeSlice, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.splice */ \ /* 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