Commit 9385fd40 authored by bjaideep's avatar bjaideep Committed by Commit Bot

PPC/s390: [builtins] Start refactoring the Apply builtin.

Port af76779a

Original Commit Message:

    This splits the monolithic Apply builtin into several smaller builtins,
    namely CallVargargs and ConstructVarargs, which accept a length and a
    FixedArray of elements and deal with the actual stack manipulation, and
    CallWithArrayLike / ConstructWithArrayLike that deal with getting the
    elements from the receiver (for Function.prototype.apply, Reflect.apply
    and Reflect.construct), which can now be written using the CSA.

    The idea is that these builtins can be reused by TurboFan directly in
    the future when we optimize apply better, and that we can also reuse the
    core logic in the handling of spread calls/constructs.

R=bmeurer@chromium.org, joransiu@ca.ibm.com, jyan@ca.ibm.com, michael_dawson@ca.ibm.com
BUG=v8:4587,v8:5269
LOG=N

Review-Url: https://codereview.chromium.org/2932833002
Cr-Commit-Position: refs/heads/master@{#45826}
parent 3b16f676
......@@ -1898,31 +1898,31 @@ void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
// -- sp[8] : receiver
// -----------------------------------
// 1. Load receiver into r4, argArray into r3 (if present), remove all
// 1. Load receiver into r4, argArray into r5 (if present), remove all
// arguments from the stack (including the receiver), and push thisArg (if
// present) instead.
{
Label skip;
Register arg_size = r5;
Register arg_size = r8;
Register new_sp = r6;
Register scratch = r7;
__ ShiftLeftImm(arg_size, r3, Operand(kPointerSizeLog2));
__ add(new_sp, sp, arg_size);
__ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
__ mr(scratch, r3);
__ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
__ mr(r5, scratch);
__ LoadP(r4, MemOperand(new_sp, 0)); // receiver
__ cmpi(arg_size, Operand(kPointerSize));
__ blt(&skip);
__ LoadP(scratch, MemOperand(new_sp, 1 * -kPointerSize)); // thisArg
__ beq(&skip);
__ LoadP(r3, MemOperand(new_sp, 2 * -kPointerSize)); // argArray
__ LoadP(r5, MemOperand(new_sp, 2 * -kPointerSize)); // argArray
__ bind(&skip);
__ mr(sp, new_sp);
__ StoreP(scratch, MemOperand(sp, 0));
}
// ----------- S t a t e -------------
// -- r3 : argArray
// -- r5 : argArray
// -- r4 : receiver
// -- sp[0] : thisArg
// -----------------------------------
......@@ -1937,13 +1937,12 @@ void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
// 3. Tail call with no arguments if argArray is null or undefined.
Label no_arguments;
__ JumpIfRoot(r3, Heap::kNullValueRootIndex, &no_arguments);
__ JumpIfRoot(r3, Heap::kUndefinedValueRootIndex, &no_arguments);
__ JumpIfRoot(r5, Heap::kNullValueRootIndex, &no_arguments);
__ JumpIfRoot(r5, Heap::kUndefinedValueRootIndex, &no_arguments);
// 4a. Apply the receiver to the given argArray (passing undefined for
// new.target).
__ LoadRoot(r6, Heap::kUndefinedValueRootIndex);
__ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
// 4a. Apply the receiver to the given argArray.
__ Jump(masm->isolate()->builtins()->CallWithArrayLike(),
RelocInfo::CODE_TARGET);
// 4b. The argArray is either null or undefined, so we tail call without any
// arguments to the receiver.
......@@ -2014,19 +2013,19 @@ void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
// -- sp[12] : receiver
// -----------------------------------
// 1. Load target into r4 (if present), argumentsList into r3 (if present),
// 1. Load target into r4 (if present), argumentsList into r5 (if present),
// remove all arguments from the stack (including the receiver), and push
// thisArgument (if present) instead.
{
Label skip;
Register arg_size = r5;
Register arg_size = r8;
Register new_sp = r6;
Register scratch = r7;
__ ShiftLeftImm(arg_size, r3, Operand(kPointerSizeLog2));
__ add(new_sp, sp, arg_size);
__ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
__ mr(scratch, r4);
__ mr(r3, r4);
__ mr(r5, r4);
__ cmpi(arg_size, Operand(kPointerSize));
__ blt(&skip);
__ LoadP(r4, MemOperand(new_sp, 1 * -kPointerSize)); // target
......@@ -2034,14 +2033,14 @@ void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
__ LoadP(scratch, MemOperand(new_sp, 2 * -kPointerSize)); // thisArgument
__ cmpi(arg_size, Operand(2 * kPointerSize));
__ beq(&skip);
__ LoadP(r3, MemOperand(new_sp, 3 * -kPointerSize)); // argumentsList
__ LoadP(r5, MemOperand(new_sp, 3 * -kPointerSize)); // argumentsList
__ bind(&skip);
__ mr(sp, new_sp);
__ StoreP(scratch, MemOperand(sp, 0));
}
// ----------- S t a t e -------------
// -- r3 : argumentsList
// -- r5 : argumentsList
// -- r4 : target
// -- sp[0] : thisArgument
// -----------------------------------
......@@ -2054,10 +2053,9 @@ void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
__ TestBit(r7, Map::kIsCallable, r0);
__ beq(&target_not_callable, cr0);
// 3a. Apply the target to the given argumentsList (passing undefined for
// new.target).
__ LoadRoot(r6, Heap::kUndefinedValueRootIndex);
__ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
// 3a. Apply the target to the given argumentsList.
__ Jump(masm->isolate()->builtins()->CallWithArrayLike(),
RelocInfo::CODE_TARGET);
// 3b. The target is not callable, throw an appropriate TypeError.
__ bind(&target_not_callable);
......@@ -2076,18 +2074,18 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
// -- sp[12] : receiver
// -----------------------------------
// 1. Load target into r4 (if present), argumentsList into r3 (if present),
// 1. Load target into r4 (if present), argumentsList into r5 (if present),
// new.target into r6 (if present, otherwise use target), remove all
// arguments from the stack (including the receiver), and push thisArgument
// (if present) instead.
{
Label skip;
Register arg_size = r5;
Register arg_size = r8;
Register new_sp = r7;
__ ShiftLeftImm(arg_size, r3, Operand(kPointerSizeLog2));
__ add(new_sp, sp, arg_size);
__ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
__ mr(r3, r4);
__ mr(r5, r4);
__ mr(r6, r4);
__ StoreP(r4, MemOperand(new_sp, 0)); // receiver (undefined)
__ cmpi(arg_size, Operand(kPointerSize));
......@@ -2095,7 +2093,7 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
__ LoadP(r4, MemOperand(new_sp, 1 * -kPointerSize)); // target
__ mr(r6, r4); // new.target defaults to target
__ beq(&skip);
__ LoadP(r3, MemOperand(new_sp, 2 * -kPointerSize)); // argumentsList
__ LoadP(r5, MemOperand(new_sp, 2 * -kPointerSize)); // argumentsList
__ cmpi(arg_size, Operand(2 * kPointerSize));
__ beq(&skip);
__ LoadP(r6, MemOperand(new_sp, 3 * -kPointerSize)); // new.target
......@@ -2104,7 +2102,7 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
}
// ----------- S t a t e -------------
// -- r3 : argumentsList
// -- r5 : argumentsList
// -- r6 : new.target
// -- r4 : target
// -- sp[0] : receiver (undefined)
......@@ -2127,7 +2125,8 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
__ beq(&new_target_not_constructor, cr0);
// 4a. Construct the target with the given new.target and argumentsList.
__ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
__ Jump(masm->isolate()->builtins()->ConstructWithArrayLike(),
RelocInfo::CODE_TARGET);
// 4b. The target is not a constructor, throw an appropriate TypeError.
__ bind(&target_not_constructor);
......@@ -2173,99 +2172,17 @@ static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
}
// static
void Builtins::Generate_Apply(MacroAssembler* masm) {
void Builtins::Generate_CallOrConstructVarargs(MacroAssembler* masm,
Handle<Code> code) {
// ----------- S t a t e -------------
// -- r3 : argumentsList
// -- r4 : target
// -- r6 : new.target (checked to be constructor or undefined)
// -- sp[0] : thisArgument
// -- r3 : number of parameters on the stack (not including the receiver)
// -- r5 : arguments list (a FixedArray)
// -- r7 : len (number of elements to push from args)
// -- r6 : new.target (for [[Construct]])
// -----------------------------------
// Create the list of arguments from the array-like argumentsList.
{
Label create_arguments, create_array, create_holey_array, create_runtime,
done_create;
__ JumpIfSmi(r3, &create_runtime);
// Load the map of argumentsList into r5.
__ LoadP(r5, FieldMemOperand(r3, HeapObject::kMapOffset));
// Load native context into r7.
__ LoadP(r7, NativeContextMemOperand());
// Check if argumentsList is an (unmodified) arguments object.
__ LoadP(ip, ContextMemOperand(r7, Context::SLOPPY_ARGUMENTS_MAP_INDEX));
__ cmp(ip, r5);
__ beq(&create_arguments);
__ LoadP(ip, ContextMemOperand(r7, Context::STRICT_ARGUMENTS_MAP_INDEX));
__ cmp(ip, r5);
__ beq(&create_arguments);
// Check if argumentsList is a fast JSArray.
__ CompareInstanceType(r5, ip, JS_ARRAY_TYPE);
__ beq(&create_array);
// Ask the runtime to create the list (actually a FixedArray).
__ bind(&create_runtime);
{
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
__ Push(r4, r6, r3);
__ CallRuntime(Runtime::kCreateListFromArrayLike);
__ Pop(r4, r6);
__ LoadP(r5, FieldMemOperand(r3, FixedArray::kLengthOffset));
__ SmiUntag(r5);
}
__ b(&done_create);
// Try to create the list from an arguments object.
__ bind(&create_arguments);
__ LoadP(r5, FieldMemOperand(r3, JSArgumentsObject::kLengthOffset));
__ LoadP(r7, FieldMemOperand(r3, JSObject::kElementsOffset));
__ LoadP(ip, FieldMemOperand(r7, FixedArray::kLengthOffset));
__ cmp(r5, ip);
__ bne(&create_runtime);
__ SmiUntag(r5);
__ mr(r3, r7);
__ 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);
__ LoadP(r5, FieldMemOperand(r5, Map::kPrototypeOffset));
__ LoadP(r7, ContextMemOperand(r7, Context::INITIAL_ARRAY_PROTOTYPE_INDEX));
__ cmp(r5, r7);
__ bne(&create_runtime);
__ LoadRoot(r7, Heap::kArrayProtectorRootIndex);
__ LoadP(r5, FieldMemOperand(r7, PropertyCell::kValueOffset));
__ CmpSmiLiteral(r5, Smi::FromInt(Isolate::kProtectorValid), r0);
__ bne(&create_runtime);
__ LoadP(r5, FieldMemOperand(r3, JSArray::kLengthOffset));
__ LoadP(r3, FieldMemOperand(r3, JSArray::kElementsOffset));
__ SmiUntag(r5);
__ b(&done_create);
// Try to create the list from a JSArray object.
// -- r5 and r7 must be preserved till bne create_holey_array.
__ bind(&create_array);
__ lbz(r8, FieldMemOperand(r5, Map::kBitField2Offset));
__ DecodeField<Map::ElementsKindBits>(r8);
STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
STATIC_ASSERT(FAST_ELEMENTS == 2);
STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
__ cmpi(r8, Operand(FAST_HOLEY_ELEMENTS));
__ bgt(&create_runtime);
// Only FAST_XXX after this point, FAST_HOLEY_XXX are odd values.
__ TestBit(r8, Map::kHasNonInstancePrototype, r0);
__ bne(&create_holey_array, cr0);
// FAST_SMI_ELEMENTS or FAST_ELEMENTS after this point.
__ LoadP(r5, FieldMemOperand(r3, JSArray::kLengthOffset));
__ LoadP(r3, FieldMemOperand(r3, JSArray::kElementsOffset));
__ SmiUntag(r5);
__ bind(&done_create);
}
__ AssertFixedArray(r5);
// Check for stack overflow.
{
// Check the stack for overflow. We are not trying to catch interruptions
......@@ -2276,52 +2193,39 @@ void Builtins::Generate_Apply(MacroAssembler* masm) {
// here which will cause ip to become negative.
__ sub(ip, sp, ip);
// Check if the arguments will overflow the stack.
__ ShiftLeftImm(r0, r5, Operand(kPointerSizeLog2));
__ ShiftLeftImm(r0, r7, Operand(kPointerSizeLog2));
__ cmp(ip, r0); // Signed comparison.
__ bgt(&done);
__ TailCallRuntime(Runtime::kThrowStackOverflow);
__ bind(&done);
}
// ----------- S t a t e -------------
// -- r4 : target
// -- r3 : args (a FixedArray built from argumentsList)
// -- r5 : len (number of elements to push from args)
// -- r6 : new.target (checked to be constructor or undefined)
// -- sp[0] : thisArgument
// -----------------------------------
// Push arguments onto the stack (thisArgument is already on the stack).
{
__ LoadRoot(r9, Heap::kUndefinedValueRootIndex);
Label loop, no_args, skip;
__ cmpi(r5, Operand::Zero());
__ cmpi(r7, Operand::Zero());
__ beq(&no_args);
__ addi(r3, r3,
__ addi(r5, r5,
Operand(FixedArray::kHeaderSize - kHeapObjectTag - kPointerSize));
__ mtctr(r5);
__ mtctr(r7);
__ bind(&loop);
__ LoadPU(ip, MemOperand(r3, kPointerSize));
__ LoadPU(ip, MemOperand(r5, kPointerSize));
__ CompareRoot(ip, Heap::kTheHoleValueRootIndex);
__ bne(&skip);
__ mr(ip, r9);
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
__ bind(&skip);
__ push(ip);
__ bdnz(&loop);
__ bind(&no_args);
__ mr(r3, r5);
__ add(r3, r3, r7);
}
// Dispatch to Call or Construct depending on whether new.target is undefined.
{
__ CompareRoot(r6, Heap::kUndefinedValueRootIndex);
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET, eq);
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
}
// Tail-call to the actual Call or Construct builtin.
__ Jump(code, RelocInfo::CODE_TARGET);
}
// static
void Builtins::Generate_ForwardVarargs(MacroAssembler* masm,
void Builtins::Generate_CallOrConstructForwardVarargs(MacroAssembler* masm,
Handle<Code> code) {
// ----------- S t a t e -------------
// -- r3 : the number of arguments (not including the receiver)
......
......@@ -1886,31 +1886,31 @@ void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
// -- sp[8] : receiver
// -----------------------------------
// 1. Load receiver into r3, argArray into r2 (if present), remove all
// 1. Load receiver into r3, argArray into r4 (if present), remove all
// arguments from the stack (including the receiver), and push thisArg (if
// present) instead.
{
Label skip;
Register arg_size = r4;
Register arg_size = r7;
Register new_sp = r5;
Register scratch = r6;
__ ShiftLeftP(arg_size, r2, Operand(kPointerSizeLog2));
__ AddP(new_sp, sp, arg_size);
__ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
__ LoadRR(scratch, r2);
__ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
__ LoadRR(r4, scratch);
__ LoadP(r3, MemOperand(new_sp, 0)); // receiver
__ CmpP(arg_size, Operand(kPointerSize));
__ blt(&skip);
__ LoadP(scratch, MemOperand(new_sp, 1 * -kPointerSize)); // thisArg
__ beq(&skip);
__ LoadP(r2, MemOperand(new_sp, 2 * -kPointerSize)); // argArray
__ LoadP(r4, MemOperand(new_sp, 2 * -kPointerSize)); // argArray
__ bind(&skip);
__ LoadRR(sp, new_sp);
__ StoreP(scratch, MemOperand(sp, 0));
}
// ----------- S t a t e -------------
// -- r2 : argArray
// -- r4 : argArray
// -- r3 : receiver
// -- sp[0] : thisArg
// -----------------------------------
......@@ -1925,13 +1925,12 @@ void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
// 3. Tail call with no arguments if argArray is null or undefined.
Label no_arguments;
__ JumpIfRoot(r2, Heap::kNullValueRootIndex, &no_arguments);
__ JumpIfRoot(r2, Heap::kUndefinedValueRootIndex, &no_arguments);
__ JumpIfRoot(r4, Heap::kNullValueRootIndex, &no_arguments);
__ JumpIfRoot(r4, Heap::kUndefinedValueRootIndex, &no_arguments);
// 4a. Apply the receiver to the given argArray (passing undefined for
// new.target).
__ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
__ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
// 4a. Apply the receiver to the given argArray.
__ Jump(masm->isolate()->builtins()->CallWithArrayLike(),
RelocInfo::CODE_TARGET);
// 4b. The argArray is either null or undefined, so we tail call without any
// arguments to the receiver.
......@@ -2002,19 +2001,19 @@ void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
// -- sp[12] : receiver
// -----------------------------------
// 1. Load target into r3 (if present), argumentsList into r2 (if present),
// 1. Load target into r3 (if present), argumentsList into r4 (if present),
// remove all arguments from the stack (including the receiver), and push
// thisArgument (if present) instead.
{
Label skip;
Register arg_size = r4;
Register arg_size = r7;
Register new_sp = r5;
Register scratch = r6;
__ ShiftLeftP(arg_size, r2, Operand(kPointerSizeLog2));
__ AddP(new_sp, sp, arg_size);
__ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
__ LoadRR(scratch, r3);
__ LoadRR(r2, r3);
__ LoadRR(r4, r3);
__ CmpP(arg_size, Operand(kPointerSize));
__ blt(&skip);
__ LoadP(r3, MemOperand(new_sp, 1 * -kPointerSize)); // target
......@@ -2022,14 +2021,14 @@ void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
__ LoadP(scratch, MemOperand(new_sp, 2 * -kPointerSize)); // thisArgument
__ CmpP(arg_size, Operand(2 * kPointerSize));
__ beq(&skip);
__ LoadP(r2, MemOperand(new_sp, 3 * -kPointerSize)); // argumentsList
__ LoadP(r4, MemOperand(new_sp, 3 * -kPointerSize)); // argumentsList
__ bind(&skip);
__ LoadRR(sp, new_sp);
__ StoreP(scratch, MemOperand(sp, 0));
}
// ----------- S t a t e -------------
// -- r2 : argumentsList
// -- r4 : argumentsList
// -- r3 : target
// -- sp[0] : thisArgument
// -----------------------------------
......@@ -2042,10 +2041,9 @@ void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
__ TestBit(r6, Map::kIsCallable);
__ beq(&target_not_callable);
// 3a. Apply the target to the given argumentsList (passing undefined for
// new.target).
__ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
__ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
// 3a. Apply the target to the given argumentsList.
__ Jump(masm->isolate()->builtins()->CallWithArrayLike(),
RelocInfo::CODE_TARGET);
// 3b. The target is not callable, throw an appropriate TypeError.
__ bind(&target_not_callable);
......@@ -2064,18 +2062,18 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
// -- sp[12] : receiver
// -----------------------------------
// 1. Load target into r3 (if present), argumentsList into r2 (if present),
// 1. Load target into r3 (if present), argumentsList into r4 (if present),
// new.target into r5 (if present, otherwise use target), remove all
// arguments from the stack (including the receiver), and push thisArgument
// (if present) instead.
{
Label skip;
Register arg_size = r4;
Register arg_size = r7;
Register new_sp = r6;
__ ShiftLeftP(arg_size, r2, Operand(kPointerSizeLog2));
__ AddP(new_sp, sp, arg_size);
__ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
__ LoadRR(r2, r3);
__ LoadRR(r4, r3);
__ LoadRR(r5, r3);
__ StoreP(r3, MemOperand(new_sp, 0)); // receiver (undefined)
__ CmpP(arg_size, Operand(kPointerSize));
......@@ -2083,7 +2081,7 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
__ LoadP(r3, MemOperand(new_sp, 1 * -kPointerSize)); // target
__ LoadRR(r5, r3); // new.target defaults to target
__ beq(&skip);
__ LoadP(r2, MemOperand(new_sp, 2 * -kPointerSize)); // argumentsList
__ LoadP(r4, MemOperand(new_sp, 2 * -kPointerSize)); // argumentsList
__ CmpP(arg_size, Operand(2 * kPointerSize));
__ beq(&skip);
__ LoadP(r5, MemOperand(new_sp, 3 * -kPointerSize)); // new.target
......@@ -2092,7 +2090,7 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
}
// ----------- S t a t e -------------
// -- r2 : argumentsList
// -- r4 : argumentsList
// -- r5 : new.target
// -- r3 : target
// -- sp[0] : receiver (undefined)
......@@ -2115,7 +2113,8 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
__ beq(&new_target_not_constructor);
// 4a. Construct the target with the given new.target and argumentsList.
__ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
__ Jump(masm->isolate()->builtins()->ConstructWithArrayLike(),
RelocInfo::CODE_TARGET);
// 4b. The target is not a constructor, throw an appropriate TypeError.
__ bind(&target_not_constructor);
......@@ -2170,99 +2169,17 @@ static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
}
// static
void Builtins::Generate_Apply(MacroAssembler* masm) {
void Builtins::Generate_CallOrConstructVarargs(MacroAssembler* masm,
Handle<Code> code) {
// ----------- S t a t e -------------
// -- r2 : argumentsList
// -- r3 : target
// -- r5 : new.target (checked to be constructor or undefined)
// -- sp[0] : thisArgument
// -- r2 : number of parameters on the stack (not including the receiver)
// -- r4 : arguments list (a FixedArray)
// -- r6 : len (number of elements to push from args)
// -- r5 : new.target (for [[Construct]])
// -----------------------------------
// Create the list of arguments from the array-like argumentsList.
{
Label create_arguments, create_array, create_holey_array, create_runtime,
done_create;
__ JumpIfSmi(r2, &create_runtime);
// Load the map of argumentsList into r4.
__ LoadP(r4, FieldMemOperand(r2, HeapObject::kMapOffset));
// Load native context into r6.
__ LoadP(r6, NativeContextMemOperand());
// Check if argumentsList is an (unmodified) arguments object.
__ LoadP(ip, ContextMemOperand(r6, Context::SLOPPY_ARGUMENTS_MAP_INDEX));
__ CmpP(ip, r4);
__ beq(&create_arguments);
__ LoadP(ip, ContextMemOperand(r6, Context::STRICT_ARGUMENTS_MAP_INDEX));
__ CmpP(ip, r4);
__ beq(&create_arguments);
// Check if argumentsList is a fast JSArray.
__ CompareInstanceType(r4, ip, JS_ARRAY_TYPE);
__ beq(&create_array);
// Ask the runtime to create the list (actually a FixedArray).
__ bind(&create_runtime);
{
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
__ Push(r3, r5, r2);
__ CallRuntime(Runtime::kCreateListFromArrayLike);
__ Pop(r3, r5);
__ LoadP(r4, FieldMemOperand(r2, FixedArray::kLengthOffset));
__ SmiUntag(r4);
}
__ b(&done_create);
// Try to create the list from an arguments object.
__ bind(&create_arguments);
__ LoadP(r4, FieldMemOperand(r2, JSArgumentsObject::kLengthOffset));
__ LoadP(r6, FieldMemOperand(r2, JSObject::kElementsOffset));
__ LoadP(ip, FieldMemOperand(r6, FixedArray::kLengthOffset));
__ CmpP(r4, ip);
__ bne(&create_runtime);
__ SmiUntag(r4);
__ LoadRR(r2, r6);
__ 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);
__ LoadP(r4, FieldMemOperand(r4, Map::kPrototypeOffset));
__ LoadP(r6, ContextMemOperand(r6, Context::INITIAL_ARRAY_PROTOTYPE_INDEX));
__ CmpP(r4, r6);
__ bne(&create_runtime);
__ LoadRoot(r6, Heap::kArrayProtectorRootIndex);
__ LoadP(r4, FieldMemOperand(r6, PropertyCell::kValueOffset));
__ CmpSmiLiteral(r4, Smi::FromInt(Isolate::kProtectorValid), r0);
__ bne(&create_runtime);
__ LoadP(r4, FieldMemOperand(r2, JSArray::kLengthOffset));
__ LoadP(r2, FieldMemOperand(r2, JSArray::kElementsOffset));
__ SmiUntag(r4);
__ b(&done_create);
// Try to create the list from a JSArray object.
// -- r4 and r6 must be preserved till bne create_holey_array.
__ bind(&create_array);
__ LoadlB(r7, FieldMemOperand(r4, Map::kBitField2Offset));
__ DecodeField<Map::ElementsKindBits>(r7);
STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
STATIC_ASSERT(FAST_ELEMENTS == 2);
STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
__ CmpP(r7, Operand(FAST_HOLEY_ELEMENTS));
__ bgt(&create_runtime);
// Only FAST_XXX after this point, FAST_HOLEY_XXX are odd values.
__ TestBit(r7, Map::kHasNonInstancePrototype, r0);
__ bne(&create_holey_array);
// FAST_SMI_ELEMENTS or FAST_ELEMENTS after this point.
__ LoadP(r4, FieldMemOperand(r2, JSArray::kLengthOffset));
__ LoadP(r2, FieldMemOperand(r2, JSArray::kElementsOffset));
__ SmiUntag(r4);
__ bind(&done_create);
}
__ AssertFixedArray(r4);
// Check for stack overflow.
{
// Check the stack for overflow. We are not trying to catch interruptions
......@@ -2273,53 +2190,40 @@ void Builtins::Generate_Apply(MacroAssembler* masm) {
// here which will cause ip to become negative.
__ SubP(ip, sp, ip);
// Check if the arguments will overflow the stack.
__ ShiftLeftP(r0, r4, Operand(kPointerSizeLog2));
__ ShiftLeftP(r0, r6, Operand(kPointerSizeLog2));
__ CmpP(ip, r0); // Signed comparison.
__ bgt(&done);
__ TailCallRuntime(Runtime::kThrowStackOverflow);
__ bind(&done);
}
// ----------- S t a t e -------------
// -- r3 : target
// -- r2 : args (a FixedArray built from argumentsList)
// -- r4 : len (number of elements to push from args)
// -- r5 : new.target (checked to be constructor or undefined)
// -- sp[0] : thisArgument
// -----------------------------------
// Push arguments onto the stack (thisArgument is already on the stack).
{
__ LoadRoot(r8, Heap::kUndefinedValueRootIndex);
Label loop, no_args, skip;
__ CmpP(r4, Operand::Zero());
__ CmpP(r6, Operand::Zero());
__ beq(&no_args);
__ AddP(r2, r2,
__ AddP(r4, r4,
Operand(FixedArray::kHeaderSize - kHeapObjectTag - kPointerSize));
__ LoadRR(r1, r4);
__ LoadRR(r1, r6);
__ bind(&loop);
__ LoadP(ip, MemOperand(r2, kPointerSize));
__ la(r2, MemOperand(r2, kPointerSize));
__ LoadP(ip, MemOperand(r4, kPointerSize));
__ la(r4, MemOperand(r4, kPointerSize));
__ CompareRoot(ip, Heap::kTheHoleValueRootIndex);
__ bne(&skip, Label::kNear);
__ LoadRR(ip, r8);
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
__ bind(&skip);
__ push(ip);
__ BranchOnCount(r1, &loop);
__ bind(&no_args);
__ LoadRR(r2, r4);
__ AddP(r2, r2, r6);
}
// Dispatch to Call or Construct depending on whether new.target is undefined.
{
__ CompareRoot(r5, Heap::kUndefinedValueRootIndex);
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET, eq);
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
}
// Tail-call to the actual Call or Construct builtin.
__ Jump(code, RelocInfo::CODE_TARGET);
}
// static
void Builtins::Generate_ForwardVarargs(MacroAssembler* masm,
void Builtins::Generate_CallOrConstructForwardVarargs(MacroAssembler* masm,
Handle<Code> code) {
// ----------- S t a t e -------------
// -- r2 : the number of arguments (not including the receiver)
......
......@@ -155,6 +155,16 @@ void CallTrampolineDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r3 : number of arguments (on the stack, not including receiver)
// r4 : the target to call
// r5 : arguments list (FixedArray)
// r7 : arguments list length (untagged)
Register registers[] = {r4, r3, r5, r7};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r3 : number of arguments
......@@ -164,6 +174,25 @@ void CallForwardVarargsDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallWithArrayLikeDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r4 : the target to call
// r5 : the arguments list
Register registers[] = {r4, r5};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r3 : number of arguments (on the stack, not including receiver)
// r4 : the target to call
// r6 : the new target
// r5 : arguments list (FixedArray)
// r7 : arguments list length (untagged)
Register registers[] = {r4, r6, r3, r5, r7};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r3 : number of arguments
......@@ -174,6 +203,15 @@ void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructWithArrayLikeDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r4 : the target to call
// r6 : the new target
// r5 : the arguments list
Register registers[] = {r4, r6, r5};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructStubDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r3 : number of arguments
......
......@@ -2598,6 +2598,17 @@ void MacroAssembler::AssertSmi(Register object) {
}
}
void MacroAssembler::AssertFixedArray(Register object) {
if (emit_debug_code()) {
STATIC_ASSERT(kSmiTag == 0);
TestIfSmi(object, r0);
Check(ne, kOperandIsASmiAndNotAFixedArray, cr0);
push(object);
CompareObjectType(object, object, object, FIXED_ARRAY_TYPE);
pop(object);
Check(eq, kOperandIsNotAFixedArray);
}
}
void MacroAssembler::AssertFunction(Register object) {
if (emit_debug_code()) {
......
......@@ -1303,6 +1303,9 @@ class MacroAssembler : public Assembler {
#define SmiWordOffset(offset) offset
#endif
// Abort execution if argument is not a FixedArray, enabled via --debug-code.
void AssertFixedArray(Register object);
void AssertFunction(Register object);
// Abort execution if argument is not a JSBoundFunction,
......
......@@ -145,6 +145,16 @@ void CallTrampolineDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r2 : number of arguments (on the stack, not including receiver)
// r3 : the target to call
// r4 : arguments list (FixedArray)
// r6 : arguments list length (untagged)
Register registers[] = {r3, r2, r4, r6};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r2 : number of arguments
......@@ -154,6 +164,25 @@ void CallForwardVarargsDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallWithArrayLikeDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r3 : the target to call
// r4 : the arguments list
Register registers[] = {r3, r4};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r2 : number of arguments (on the stack, not including receiver)
// r3 : the target to call
// r5 : the new target
// r4 : arguments list (FixedArray)
// r6 : arguments list length (untagged)
Register registers[] = {r3, r5, r2, r4, r6};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r2 : number of arguments
......@@ -164,6 +193,15 @@ void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructWithArrayLikeDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r3 : the target to call
// r5 : the new target
// r4 : the arguments list
Register registers[] = {r3, r5, r4};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void ConstructStubDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// r2 : number of arguments
......
......@@ -2374,6 +2374,18 @@ void MacroAssembler::AssertSmi(Register object) {
}
}
void MacroAssembler::AssertFixedArray(Register object) {
if (emit_debug_code()) {
STATIC_ASSERT(kSmiTag == 0);
TestIfSmi(object);
Check(ne, kOperandIsASmiAndNotAFixedArray, cr0);
push(object);
CompareObjectType(object, object, object, FIXED_ARRAY_TYPE);
pop(object);
Check(eq, kOperandIsNotAFixedArray);
}
}
void MacroAssembler::AssertFunction(Register object) {
if (emit_debug_code()) {
STATIC_ASSERT(kSmiTag == 0);
......
......@@ -1621,6 +1621,9 @@ class MacroAssembler : public Assembler {
#define SmiWordOffset(offset) offset
#endif
// Abort execution if argument is not a FixedArray, enabled via --debug-code.
void AssertFixedArray(Register object);
void AssertFunction(Register object);
// Abort execution if argument is not a JSBoundFunction,
......
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