Commit 1c112297 authored by rodolph.perfetta's avatar rodolph.perfetta Committed by Commit bot

[arm][arm64] deal with holey array in the Apply builtin.

BUG=

Review-Url: https://codereview.chromium.org/2537453003
Cr-Commit-Position: refs/heads/master@{#41325}
parent 12d821dd
......@@ -2116,7 +2116,8 @@ void Builtins::Generate_Apply(MacroAssembler* masm) {
// Create the list of arguments from the array-like argumentsList.
{
Label create_arguments, create_array, create_runtime, done_create;
Label create_arguments, create_array, create_holey_array, create_runtime,
done_create;
__ JumpIfSmi(r0, &create_runtime);
// Load the map of argumentsList into r2.
......@@ -2160,17 +2161,37 @@ void Builtins::Generate_Apply(MacroAssembler* masm) {
__ mov(r0, r4);
__ b(&done_create);
// For holey JSArrays we need to check that the array prototype chain
// protector is intact and our prototype is the Array.prototype actually.
__ bind(&create_holey_array);
__ ldr(r2, FieldMemOperand(r2, Map::kPrototypeOffset));
__ ldr(r4, ContextMemOperand(r4, Context::INITIAL_ARRAY_PROTOTYPE_INDEX));
__ cmp(r2, r4);
__ b(ne, &create_runtime);
__ LoadRoot(r4, Heap::kArrayProtectorRootIndex);
__ ldr(r2, FieldMemOperand(r4, PropertyCell::kValueOffset));
__ cmp(r2, Operand(Smi::FromInt(Isolate::kProtectorValid)));
__ b(ne, &create_runtime);
__ ldr(r2, FieldMemOperand(r0, JSArray::kLengthOffset));
__ ldr(r0, FieldMemOperand(r0, JSArray::kElementsOffset));
__ SmiUntag(r2);
__ b(&done_create);
// Try to create the list from a JSArray object.
// -- r2 and r4 must be preserved till bne create_holey_array.
__ bind(&create_array);
__ ldr(r2, FieldMemOperand(r2, Map::kBitField2Offset));
__ DecodeField<Map::ElementsKindBits>(r2);
__ ldr(r5, FieldMemOperand(r2, Map::kBitField2Offset));
__ DecodeField<Map::ElementsKindBits>(r5);
STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
STATIC_ASSERT(FAST_ELEMENTS == 2);
__ cmp(r2, Operand(FAST_ELEMENTS));
STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
__ cmp(r5, Operand(FAST_HOLEY_ELEMENTS));
__ b(hi, &create_runtime);
__ cmp(r2, Operand(FAST_HOLEY_SMI_ELEMENTS));
__ b(eq, &create_runtime);
// Only FAST_XXX after this point, FAST_HOLEY_XXX are odd values.
__ tst(r5, Operand(1));
__ b(ne, &create_holey_array);
// FAST_SMI_ELEMENTS or FAST_ELEMENTS after this point.
__ ldr(r2, FieldMemOperand(r0, JSArray::kLengthOffset));
__ ldr(r0, FieldMemOperand(r0, JSArray::kElementsOffset));
__ SmiUntag(r2);
......@@ -2205,12 +2226,16 @@ void Builtins::Generate_Apply(MacroAssembler* masm) {
// Push arguments onto the stack (thisArgument is already on the stack).
{
__ mov(r4, Operand(0));
__ LoadRoot(r5, Heap::kTheHoleValueRootIndex);
__ LoadRoot(r6, Heap::kUndefinedValueRootIndex);
Label done, loop;
__ bind(&loop);
__ cmp(r4, r2);
__ b(eq, &done);
__ add(ip, r0, Operand(r4, LSL, kPointerSizeLog2));
__ ldr(ip, FieldMemOperand(ip, FixedArray::kHeaderSize));
__ cmp(r5, ip);
__ mov(ip, r6, LeaveCC, eq);
__ Push(ip);
__ add(r4, r4, Operand(1));
__ b(&loop);
......
......@@ -2176,7 +2176,8 @@ void Builtins::Generate_Apply(MacroAssembler* masm) {
// Create the list of arguments from the array-like argumentsList.
{
Label create_arguments, create_array, create_runtime, done_create;
Label create_arguments, create_array, create_holey_array, create_runtime,
done_create;
__ JumpIfSmi(arguments_list, &create_runtime);
// Load native context.
......@@ -2198,7 +2199,7 @@ void Builtins::Generate_Apply(MacroAssembler* masm) {
__ B(eq, &create_arguments);
// Check if argumentsList is a fast JSArray.
__ CompareInstanceType(arguments_list_map, native_context, JS_ARRAY_TYPE);
__ CompareInstanceType(arguments_list_map, x10, JS_ARRAY_TYPE);
__ B(eq, &create_array);
// Ask the runtime to create the list (actually a FixedArray).
......@@ -2223,14 +2224,42 @@ void Builtins::Generate_Apply(MacroAssembler* masm) {
__ Mov(args, x10);
__ B(&done_create);
// For holey JSArrays we need to check that the array prototype chain
// protector is intact and our prototype is the Array.prototype actually.
__ Bind(&create_holey_array);
// -- x2 : arguments_list_map
// -- x4 : native_context
Register arguments_list_prototype = x2;
__ Ldr(arguments_list_prototype,
FieldMemOperand(arguments_list_map, Map::kPrototypeOffset));
__ Ldr(x10, ContextMemOperand(native_context,
Context::INITIAL_ARRAY_PROTOTYPE_INDEX));
__ Cmp(arguments_list_prototype, x10);
__ B(ne, &create_runtime);
__ LoadRoot(x10, Heap::kArrayProtectorRootIndex);
__ Ldrsw(x11, UntagSmiFieldMemOperand(x10, PropertyCell::kValueOffset));
__ Cmp(x11, Isolate::kProtectorValid);
__ B(ne, &create_runtime);
__ Ldrsw(len,
UntagSmiFieldMemOperand(arguments_list, JSArray::kLengthOffset));
__ Ldr(args, FieldMemOperand(arguments_list, JSArray::kElementsOffset));
__ B(&done_create);
// Try to create the list from a JSArray object.
__ Bind(&create_array);
__ Ldr(x10, FieldMemOperand(arguments_list_map, Map::kBitField2Offset));
__ DecodeField<Map::ElementsKindBits>(x10);
STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
STATIC_ASSERT(FAST_ELEMENTS == 2);
// Branch for anything that's not FAST_{SMI_}ELEMENTS.
__ TestAndBranchIfAnySet(x10, ~FAST_ELEMENTS, &create_runtime);
STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
// Check if it is a holey array, the order of the cmp is important as
// anything higher than FAST_HOLEY_ELEMENTS will fall back to runtime.
__ Cmp(x10, FAST_HOLEY_ELEMENTS);
__ B(hi, &create_runtime);
// Only FAST_XXX after this point, FAST_HOLEY_XXX are odd values.
__ Tbnz(x10, 0, &create_holey_array);
// FAST_SMI_ELEMENTS or FAST_ELEMENTS after this point.
__ Ldrsw(len,
UntagSmiFieldMemOperand(arguments_list, JSArray::kLengthOffset));
__ Ldr(args, FieldMemOperand(arguments_list, JSArray::kElementsOffset));
......@@ -2264,16 +2293,24 @@ void Builtins::Generate_Apply(MacroAssembler* masm) {
// Push arguments onto the stack (thisArgument is already on the stack).
{
Label done, loop;
Label done, push, loop;
Register src = x4;
__ Add(src, args, FixedArray::kHeaderSize - kHeapObjectTag);
__ Mov(x0, len); // The 'len' argument for Call() or Construct().
__ Cbz(len, &done);
Register the_hole_value = x11;
Register undefined_value = x12;
// We do not use the CompareRoot macro as it would do a LoadRoot behind the
// scenes and we want to avoid that in a loop.
__ LoadRoot(the_hole_value, Heap::kTheHoleValueRootIndex);
__ LoadRoot(undefined_value, Heap::kUndefinedValueRootIndex);
__ Claim(len);
__ Bind(&loop);
__ Sub(len, len, 1);
__ Ldr(x10, MemOperand(src, kPointerSize, PostIndex));
__ Cmp(x10, the_hole_value);
__ Csel(x10, x10, undefined_value, ne);
__ Poke(x10, Operand(len, LSL, kPointerSizeLog2));
__ Cbnz(len, &loop);
__ Bind(&done);
......
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