Commit 42130fd6 authored by Daniel Clifford's avatar Daniel Clifford Committed by Commit Bot

[builtins] Remove obsolete implementation of Array.prototype.slice

In the process, use the correct ArrayPrototype* naming convention for
the slice and splice builtins.

Change-Id: I1f85e5512dbde8f92e7c764aef9f137d0a6693e0
Reviewed-on: https://chromium-review.googlesource.com/c/1350869Reviewed-by: 's avatarMichael Stanton <mvstanton@chromium.org>
Commit-Queue: Daniel Clifford <danno@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57840}
parent d1b2edbf
......@@ -1708,12 +1708,12 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
Builtins::kArrayPrototypeShift, 0, false);
SimpleInstallFunction(isolate_, proto, "unshift",
Builtins::kArrayPrototypeUnshift, 1, false);
SimpleInstallFunction(isolate_, proto, "slice", Builtins::kArraySlice, 2,
false);
SimpleInstallFunction(isolate_, proto, "slice",
Builtins::kArrayPrototypeSlice, 2, false);
SimpleInstallFunction(isolate_, proto, "sort",
Builtins::kArrayPrototypeSort, 1, false);
SimpleInstallFunction(isolate_, proto, "splice", Builtins::kArraySplice, 2,
false);
SimpleInstallFunction(isolate_, proto, "splice",
Builtins::kArrayPrototypeSplice, 2, false);
SimpleInstallFunction(isolate_, proto, "includes", Builtins::kArrayIncludes,
1, false);
SimpleInstallFunction(isolate_, proto, "indexOf", Builtins::kArrayIndexOf,
......
......@@ -119,7 +119,8 @@ namespace array {
// https://tc39.github.io/ecma262/#sec-array.prototype.slice
transitioning javascript builtin
ArraySlice(context: Context, receiver: Object, ...arguments): Object {
ArrayPrototypeSlice(context: Context, receiver: Object, ...arguments):
Object {
// Handle array cloning case if the receiver is a fast array.
if (arguments.length == 0) {
typeswitch (receiver) {
......
......@@ -349,7 +349,8 @@ namespace array {
// https://tc39.github.io/ecma262/#sec-array.prototype.splice
transitioning javascript builtin
ArraySplice(context: Context, receiver: Object, ...arguments): Object {
ArrayPrototypeSplice(context: Context, receiver: Object, ...arguments):
Object {
// 1. Let O be ? ToObject(this value).
const o: JSReceiver = ToObject(context, receiver);
......
......@@ -1140,341 +1140,6 @@ TF_BUILTIN(ArrayPrototypePush, CodeStubAssembler) {
}
}
class ArrayPrototypeSliceCodeStubAssembler : public CodeStubAssembler {
public:
explicit ArrayPrototypeSliceCodeStubAssembler(
compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {}
Node* HandleFastSlice(TNode<Context> context, Node* array, Node* from,
Node* count, Label* slow) {
VARIABLE(result, MachineRepresentation::kTagged);
Label done(this);
GotoIf(TaggedIsNotSmi(from), slow);
GotoIf(TaggedIsNotSmi(count), slow);
Label try_fast_arguments(this), try_simple_slice(this);
Node* map = LoadMap(array);
GotoIfNot(IsJSArrayMap(map), &try_fast_arguments);
// Check prototype chain if receiver does not have packed elements
GotoIfNot(IsPrototypeInitialArrayPrototype(context, map), slow);
GotoIf(IsNoElementsProtectorCellInvalid(), slow);
GotoIf(IsArraySpeciesProtectorCellInvalid(), slow);
// Bailout if receiver has slow elements.
Node* elements_kind = LoadMapElementsKind(map);
GotoIfNot(IsFastElementsKind(elements_kind), &try_simple_slice);
// Make sure that the length hasn't been changed by side-effect.
Node* array_length = LoadJSArrayLength(array);
GotoIf(TaggedIsNotSmi(array_length), slow);
GotoIf(SmiAbove(SmiAdd(CAST(from), CAST(count)), CAST(array_length)), slow);
CSA_ASSERT(this, SmiGreaterThanOrEqual(CAST(from), SmiConstant(0)));
result.Bind(CallBuiltin(Builtins::kExtractFastJSArray, context, array, from,
count));
Goto(&done);
BIND(&try_fast_arguments);
Node* const native_context = LoadNativeContext(context);
Node* const fast_aliasted_arguments_map = LoadContextElement(
native_context, Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX);
GotoIf(WordNotEqual(map, fast_aliasted_arguments_map), &try_simple_slice);
TNode<SloppyArgumentsElements> sloppy_elements = CAST(LoadElements(array));
TNode<Smi> sloppy_elements_length =
LoadFixedArrayBaseLength(sloppy_elements);
TNode<Smi> parameter_map_length =
SmiSub(sloppy_elements_length,
SmiConstant(SloppyArgumentsElements::kParameterMapStart));
VARIABLE(index_out, MachineType::PointerRepresentation());
int max_fast_elements =
(kMaxRegularHeapObjectSize - FixedArray::kHeaderSize - JSArray::kSize -
AllocationMemento::kSize) /
kPointerSize;
GotoIf(SmiAboveOrEqual(CAST(count), SmiConstant(max_fast_elements)),
&try_simple_slice);
GotoIf(SmiLessThan(CAST(from), SmiConstant(0)), slow);
TNode<Smi> end = SmiAdd(CAST(from), CAST(count));
TNode<FixedArray> unmapped_elements = CAST(LoadFixedArrayElement(
sloppy_elements, SloppyArgumentsElements::kArgumentsIndex));
TNode<Smi> unmapped_elements_length =
LoadFixedArrayBaseLength(unmapped_elements);
GotoIf(SmiAbove(end, unmapped_elements_length), slow);
TNode<Map> array_map =
LoadJSArrayElementsMap(HOLEY_ELEMENTS, native_context);
result.Bind(AllocateJSArray(HOLEY_ELEMENTS, array_map, count, CAST(count),
nullptr, SMI_PARAMETERS));
index_out.Bind(IntPtrConstant(0));
TNode<FixedArray> result_elements = CAST(LoadElements(result.value()));
TNode<Smi> from_mapped = SmiMin(parameter_map_length, CAST(from));
TNode<Smi> to = SmiMin(parameter_map_length, end);
Node* arguments_context = LoadFixedArrayElement(
sloppy_elements, SloppyArgumentsElements::kContextIndex);
VariableList var_list({&index_out}, zone());
BuildFastLoop(
var_list, from_mapped, to,
[this, result_elements, arguments_context, sloppy_elements,
unmapped_elements, &index_out](Node* current) {
Node* context_index = LoadFixedArrayElement(
sloppy_elements, current,
kPointerSize * SloppyArgumentsElements::kParameterMapStart,
SMI_PARAMETERS);
Label is_the_hole(this), done(this);
GotoIf(IsTheHole(context_index), &is_the_hole);
Node* mapped_argument =
LoadContextElement(arguments_context, SmiUntag(context_index));
StoreFixedArrayElement(result_elements, index_out.value(),
mapped_argument, SKIP_WRITE_BARRIER);
Goto(&done);
BIND(&is_the_hole);
Node* argument = LoadFixedArrayElement(unmapped_elements, current, 0,
SMI_PARAMETERS);
StoreFixedArrayElement(result_elements, index_out.value(), argument,
SKIP_WRITE_BARRIER);
Goto(&done);
BIND(&done);
index_out.Bind(IntPtrAdd(index_out.value(), IntPtrConstant(1)));
},
1, SMI_PARAMETERS, IndexAdvanceMode::kPost);
TNode<Smi> unmapped_from =
SmiMin(SmiMax(parameter_map_length, CAST(from)), end);
BuildFastLoop(
var_list, unmapped_from, end,
[this, unmapped_elements, result_elements, &index_out](Node* current) {
Node* argument = LoadFixedArrayElement(unmapped_elements, current, 0,
SMI_PARAMETERS);
StoreFixedArrayElement(result_elements, index_out.value(), argument,
SKIP_WRITE_BARRIER);
index_out.Bind(IntPtrAdd(index_out.value(), IntPtrConstant(1)));
},
1, SMI_PARAMETERS, IndexAdvanceMode::kPost);
Goto(&done);
BIND(&try_simple_slice);
Node* simple_result = CallRuntime(Runtime::kTrySliceSimpleNonFastElements,
context, array, from, count);
GotoIfNumber(simple_result, slow);
result.Bind(simple_result);
Goto(&done);
BIND(&done);
return result.value();
}
void CopyOneElement(TNode<Context> context, Node* o, Node* a, Node* p_k,
Variable& n) {
// b. Let kPresent be HasProperty(O, Pk).
// c. ReturnIfAbrupt(kPresent).
TNode<Oddball> k_present = HasProperty(context, o, p_k, kHasProperty);
// d. If kPresent is true, then
Label done_element(this);
GotoIf(IsFalse(k_present), &done_element);
// i. Let kValue be Get(O, Pk).
// ii. ReturnIfAbrupt(kValue).
Node* k_value = GetProperty(context, o, p_k);
// iii. Let status be CreateDataPropertyOrThrow(A, ToString(n), kValue).
// iv. ReturnIfAbrupt(status).
CallRuntime(Runtime::kCreateDataProperty, context, a, n.value(), k_value);
Goto(&done_element);
BIND(&done_element);
}
};
TF_BUILTIN(ArrayPrototypeSlice, ArrayPrototypeSliceCodeStubAssembler) {
Node* const argc =
ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
Label slow(this, Label::kDeferred), fast_elements_kind(this);
CodeStubArguments args(this, argc);
TNode<Object> receiver = args.GetReceiver();
TVARIABLE(JSReceiver, o);
VARIABLE(len, MachineRepresentation::kTagged);
Label length_done(this), generic_length(this), check_arguments_length(this),
load_arguments_length(this);
GotoIf(TaggedIsSmi(receiver), &generic_length);
GotoIfNot(IsJSArray(CAST(receiver)), &check_arguments_length);
TNode<JSArray> array_receiver = CAST(receiver);
o = array_receiver;
len.Bind(LoadJSArrayLength(array_receiver));
// Check for the array clone case. There can be no arguments to slice, the
// array prototype chain must be intact and have no elements, the array has to
// have fast elements.
GotoIf(WordNotEqual(argc, IntPtrConstant(0)), &length_done);
Label clone(this);
BranchIfFastJSArrayForCopy(receiver, context, &clone, &length_done);
BIND(&clone);
args.PopAndReturn(
CallBuiltin(Builtins::kCloneFastJSArray, context, receiver));
BIND(&check_arguments_length);
Node* map = LoadMap(array_receiver);
Node* native_context = LoadNativeContext(context);
GotoIfContextElementEqual(map, native_context,
Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX,
&load_arguments_length);
GotoIfContextElementEqual(map, native_context,
Context::SLOW_ALIASED_ARGUMENTS_MAP_INDEX,
&load_arguments_length);
GotoIfContextElementEqual(map, native_context,
Context::STRICT_ARGUMENTS_MAP_INDEX,
&load_arguments_length);
GotoIfContextElementEqual(map, native_context,
Context::SLOPPY_ARGUMENTS_MAP_INDEX,
&load_arguments_length);
Goto(&generic_length);
BIND(&load_arguments_length);
Node* arguments_length = LoadObjectField(
array_receiver, JSArgumentsObjectWithLength::kLengthOffset);
GotoIf(TaggedIsNotSmi(arguments_length), &generic_length);
o = CAST(receiver);
len.Bind(arguments_length);
Goto(&length_done);
BIND(&generic_length);
// 1. Let O be ToObject(this value).
// 2. ReturnIfAbrupt(O).
o = ToObject_Inline(context, receiver);
// 3. Let len be ToLength(Get(O, "length")).
// 4. ReturnIfAbrupt(len).
len.Bind(ToLength_Inline(
context,
GetProperty(context, o.value(), isolate()->factory()->length_string())));
Goto(&length_done);
BIND(&length_done);
// 5. Let relativeStart be ToInteger(start).
// 6. ReturnIfAbrupt(relativeStart).
TNode<Object> arg0 = args.GetOptionalArgumentValue(0, SmiConstant(0));
Node* relative_start = ToInteger_Inline(context, arg0);
// 7. If relativeStart < 0, let k be max((len + relativeStart),0);
// else let k be min(relativeStart, len.value()).
VARIABLE(k, MachineRepresentation::kTagged);
Label relative_start_positive(this), relative_start_done(this);
GotoIfNumberGreaterThanOrEqual(relative_start, SmiConstant(0),
&relative_start_positive);
k.Bind(NumberMax(NumberAdd(len.value(), relative_start), NumberConstant(0)));
Goto(&relative_start_done);
BIND(&relative_start_positive);
k.Bind(NumberMin(relative_start, len.value()));
Goto(&relative_start_done);
BIND(&relative_start_done);
// 8. If end is undefined, let relativeEnd be len;
// else let relativeEnd be ToInteger(end).
// 9. ReturnIfAbrupt(relativeEnd).
TNode<Object> end = args.GetOptionalArgumentValue(1, UndefinedConstant());
Label end_undefined(this), end_done(this);
VARIABLE(relative_end, MachineRepresentation::kTagged);
GotoIf(WordEqual(end, UndefinedConstant()), &end_undefined);
relative_end.Bind(ToInteger_Inline(context, end));
Goto(&end_done);
BIND(&end_undefined);
relative_end.Bind(len.value());
Goto(&end_done);
BIND(&end_done);
// 10. If relativeEnd < 0, let final be max((len + relativeEnd),0);
// else let final be min(relativeEnd, len).
VARIABLE(final, MachineRepresentation::kTagged);
Label relative_end_positive(this), relative_end_done(this);
GotoIfNumberGreaterThanOrEqual(relative_end.value(), NumberConstant(0),
&relative_end_positive);
final.Bind(NumberMax(NumberAdd(len.value(), relative_end.value()),
NumberConstant(0)));
Goto(&relative_end_done);
BIND(&relative_end_positive);
final.Bind(NumberMin(relative_end.value(), len.value()));
Goto(&relative_end_done);
BIND(&relative_end_done);
// 11. Let count be max(final – k, 0).
TNode<Number> count =
NumberMax(NumberSub(final.value(), k.value()), NumberConstant(0));
// Handle FAST_ELEMENTS
Label non_fast(this);
Node* fast_result =
HandleFastSlice(context, o.value(), k.value(), count, &non_fast);
args.PopAndReturn(fast_result);
// 12. Let A be ArraySpeciesCreate(O, count).
// 13. ReturnIfAbrupt(A).
BIND(&non_fast);
TNode<JSReceiver> constructor =
CAST(CallRuntime(Runtime::kArraySpeciesConstructor, context, o.value()));
TNode<JSReceiver> a = Construct(context, constructor, count);
// 14. Let n be 0.
VARIABLE(n, MachineRepresentation::kTagged);
n.Bind(SmiConstant(0));
Label loop(this, {&k, &n});
Label after_loop(this);
Goto(&loop);
BIND(&loop);
{
// 15. Repeat, while k < final
GotoIfNumberGreaterThanOrEqual(k.value(), final.value(), &after_loop);
Node* p_k = k.value(); // ToString(context, k.value()) is no-op
CopyOneElement(context, o.value(), a, p_k, n);
// e. Increase k by 1.
k.Bind(NumberInc(k.value()));
// f. Increase n by 1.
n.Bind(NumberInc(n.value()));
Goto(&loop);
}
BIND(&after_loop);
// 16. Let setStatus be Set(A, "length", n, true).
// 17. ReturnIfAbrupt(setStatus).
SetPropertyStrict(context, a, CodeStubAssembler::LengthStringConstant(),
CAST(n.value()));
args.PopAndReturn(a);
}
TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) {
TNode<Int32T> argc =
UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount));
......
......@@ -334,8 +334,6 @@ namespace internal {
/* ES6 #sec-array.prototype.shift */ \
CPP(ArrayShift) \
TFJ(ArrayPrototypeShift, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.slice */ \
TFJ(ArrayPrototypeSlice, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.unshift */ \
CPP(ArrayUnshift) \
/* Support for Array.from and other array-copying idioms */ \
......
......@@ -3447,7 +3447,6 @@ Reduction JSCallReducer::ReduceJSCall(Node* node,
case Builtins::kArrayPrototypeShift:
return ReduceArrayPrototypeShift(node);
case Builtins::kArrayPrototypeSlice:
case Builtins::kArraySlice:
return ReduceArrayPrototypeSlice(node);
case Builtins::kArrayPrototypeEntries:
return ReduceArrayIterator(node, IterationKind::kEntries);
......
......@@ -384,8 +384,6 @@ bool BuiltinToIntrinsicHasNoSideEffect(Builtins::Name builtin_id,
/* Arrays */ \
V(Builtins::kArrayFilter, W(CreateDataProperty)) \
V(Builtins::kArrayMap, W(CreateDataProperty)) \
V(Builtins::kArraySlice, \
W(CreateDataProperty) W(SetKeyedProperty) W(SetNamedProperty)) \
V(Builtins::kArrayPrototypeSlice, \
W(CreateDataProperty) W(SetKeyedProperty) W(SetNamedProperty)) \
/* TypedArrays */ \
......@@ -558,7 +556,6 @@ DebugInfo::SideEffectState BuiltinGetSideEffectState(Builtins::Name id) {
case Builtins::kArrayPrototypeKeys:
case Builtins::kArrayPrototypeLastIndexOf:
case Builtins::kArrayPrototypeSlice:
case Builtins::kArraySlice:
case Builtins::kArrayPrototypeSort:
case Builtins::kArrayPrototypeToLocaleString:
case Builtins::kArrayPrototypeToString:
......@@ -822,7 +819,7 @@ DebugInfo::SideEffectState BuiltinGetSideEffectState(Builtins::Name id) {
case Builtins::kArrayPrototypeReverse:
case Builtins::kArrayPrototypeShift:
case Builtins::kArrayPrototypeUnshift:
case Builtins::kArraySplice:
case Builtins::kArrayPrototypeSplice:
case Builtins::kArrayUnshift:
// Map builtins.
case Builtins::kMapIteratorPrototypeNext:
......
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