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) { ...@@ -1898,31 +1898,31 @@ void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
// -- sp[8] : receiver // -- 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 // arguments from the stack (including the receiver), and push thisArg (if
// present) instead. // present) instead.
{ {
Label skip; Label skip;
Register arg_size = r5; Register arg_size = r8;
Register new_sp = r6; Register new_sp = r6;
Register scratch = r7; Register scratch = r7;
__ ShiftLeftImm(arg_size, r3, Operand(kPointerSizeLog2)); __ ShiftLeftImm(arg_size, r3, Operand(kPointerSizeLog2));
__ add(new_sp, sp, arg_size); __ add(new_sp, sp, arg_size);
__ LoadRoot(r3, Heap::kUndefinedValueRootIndex); __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
__ mr(scratch, r3); __ mr(r5, scratch);
__ LoadP(r4, MemOperand(new_sp, 0)); // receiver __ LoadP(r4, MemOperand(new_sp, 0)); // receiver
__ cmpi(arg_size, Operand(kPointerSize)); __ cmpi(arg_size, Operand(kPointerSize));
__ blt(&skip); __ blt(&skip);
__ LoadP(scratch, MemOperand(new_sp, 1 * -kPointerSize)); // thisArg __ LoadP(scratch, MemOperand(new_sp, 1 * -kPointerSize)); // thisArg
__ beq(&skip); __ beq(&skip);
__ LoadP(r3, MemOperand(new_sp, 2 * -kPointerSize)); // argArray __ LoadP(r5, MemOperand(new_sp, 2 * -kPointerSize)); // argArray
__ bind(&skip); __ bind(&skip);
__ mr(sp, new_sp); __ mr(sp, new_sp);
__ StoreP(scratch, MemOperand(sp, 0)); __ StoreP(scratch, MemOperand(sp, 0));
} }
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r3 : argArray // -- r5 : argArray
// -- r4 : receiver // -- r4 : receiver
// -- sp[0] : thisArg // -- sp[0] : thisArg
// ----------------------------------- // -----------------------------------
...@@ -1937,13 +1937,12 @@ void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) { ...@@ -1937,13 +1937,12 @@ void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
// 3. Tail call with no arguments if argArray is null or undefined. // 3. Tail call with no arguments if argArray is null or undefined.
Label no_arguments; Label no_arguments;
__ JumpIfRoot(r3, Heap::kNullValueRootIndex, &no_arguments); __ JumpIfRoot(r5, Heap::kNullValueRootIndex, &no_arguments);
__ JumpIfRoot(r3, Heap::kUndefinedValueRootIndex, &no_arguments); __ JumpIfRoot(r5, Heap::kUndefinedValueRootIndex, &no_arguments);
// 4a. Apply the receiver to the given argArray (passing undefined for // 4a. Apply the receiver to the given argArray.
// new.target). __ Jump(masm->isolate()->builtins()->CallWithArrayLike(),
__ LoadRoot(r6, Heap::kUndefinedValueRootIndex); RelocInfo::CODE_TARGET);
__ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
// 4b. The argArray is either null or undefined, so we tail call without any // 4b. The argArray is either null or undefined, so we tail call without any
// arguments to the receiver. // arguments to the receiver.
...@@ -2014,19 +2013,19 @@ void Builtins::Generate_ReflectApply(MacroAssembler* masm) { ...@@ -2014,19 +2013,19 @@ void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
// -- sp[12] : receiver // -- 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 // remove all arguments from the stack (including the receiver), and push
// thisArgument (if present) instead. // thisArgument (if present) instead.
{ {
Label skip; Label skip;
Register arg_size = r5; Register arg_size = r8;
Register new_sp = r6; Register new_sp = r6;
Register scratch = r7; Register scratch = r7;
__ ShiftLeftImm(arg_size, r3, Operand(kPointerSizeLog2)); __ ShiftLeftImm(arg_size, r3, Operand(kPointerSizeLog2));
__ add(new_sp, sp, arg_size); __ add(new_sp, sp, arg_size);
__ LoadRoot(r4, Heap::kUndefinedValueRootIndex); __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
__ mr(scratch, r4); __ mr(scratch, r4);
__ mr(r3, r4); __ mr(r5, r4);
__ cmpi(arg_size, Operand(kPointerSize)); __ cmpi(arg_size, Operand(kPointerSize));
__ blt(&skip); __ blt(&skip);
__ LoadP(r4, MemOperand(new_sp, 1 * -kPointerSize)); // target __ LoadP(r4, MemOperand(new_sp, 1 * -kPointerSize)); // target
...@@ -2034,14 +2033,14 @@ void Builtins::Generate_ReflectApply(MacroAssembler* masm) { ...@@ -2034,14 +2033,14 @@ void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
__ LoadP(scratch, MemOperand(new_sp, 2 * -kPointerSize)); // thisArgument __ LoadP(scratch, MemOperand(new_sp, 2 * -kPointerSize)); // thisArgument
__ cmpi(arg_size, Operand(2 * kPointerSize)); __ cmpi(arg_size, Operand(2 * kPointerSize));
__ beq(&skip); __ beq(&skip);
__ LoadP(r3, MemOperand(new_sp, 3 * -kPointerSize)); // argumentsList __ LoadP(r5, MemOperand(new_sp, 3 * -kPointerSize)); // argumentsList
__ bind(&skip); __ bind(&skip);
__ mr(sp, new_sp); __ mr(sp, new_sp);
__ StoreP(scratch, MemOperand(sp, 0)); __ StoreP(scratch, MemOperand(sp, 0));
} }
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r3 : argumentsList // -- r5 : argumentsList
// -- r4 : target // -- r4 : target
// -- sp[0] : thisArgument // -- sp[0] : thisArgument
// ----------------------------------- // -----------------------------------
...@@ -2054,10 +2053,9 @@ void Builtins::Generate_ReflectApply(MacroAssembler* masm) { ...@@ -2054,10 +2053,9 @@ void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
__ TestBit(r7, Map::kIsCallable, r0); __ TestBit(r7, Map::kIsCallable, r0);
__ beq(&target_not_callable, cr0); __ beq(&target_not_callable, cr0);
// 3a. Apply the target to the given argumentsList (passing undefined for // 3a. Apply the target to the given argumentsList.
// new.target). __ Jump(masm->isolate()->builtins()->CallWithArrayLike(),
__ LoadRoot(r6, Heap::kUndefinedValueRootIndex); RelocInfo::CODE_TARGET);
__ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
// 3b. The target is not callable, throw an appropriate TypeError. // 3b. The target is not callable, throw an appropriate TypeError.
__ bind(&target_not_callable); __ bind(&target_not_callable);
...@@ -2076,18 +2074,18 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { ...@@ -2076,18 +2074,18 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
// -- sp[12] : receiver // -- 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 // new.target into r6 (if present, otherwise use target), remove all
// arguments from the stack (including the receiver), and push thisArgument // arguments from the stack (including the receiver), and push thisArgument
// (if present) instead. // (if present) instead.
{ {
Label skip; Label skip;
Register arg_size = r5; Register arg_size = r8;
Register new_sp = r7; Register new_sp = r7;
__ ShiftLeftImm(arg_size, r3, Operand(kPointerSizeLog2)); __ ShiftLeftImm(arg_size, r3, Operand(kPointerSizeLog2));
__ add(new_sp, sp, arg_size); __ add(new_sp, sp, arg_size);
__ LoadRoot(r4, Heap::kUndefinedValueRootIndex); __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
__ mr(r3, r4); __ mr(r5, r4);
__ mr(r6, r4); __ mr(r6, r4);
__ StoreP(r4, MemOperand(new_sp, 0)); // receiver (undefined) __ StoreP(r4, MemOperand(new_sp, 0)); // receiver (undefined)
__ cmpi(arg_size, Operand(kPointerSize)); __ cmpi(arg_size, Operand(kPointerSize));
...@@ -2095,7 +2093,7 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { ...@@ -2095,7 +2093,7 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
__ LoadP(r4, MemOperand(new_sp, 1 * -kPointerSize)); // target __ LoadP(r4, MemOperand(new_sp, 1 * -kPointerSize)); // target
__ mr(r6, r4); // new.target defaults to target __ mr(r6, r4); // new.target defaults to target
__ beq(&skip); __ beq(&skip);
__ LoadP(r3, MemOperand(new_sp, 2 * -kPointerSize)); // argumentsList __ LoadP(r5, MemOperand(new_sp, 2 * -kPointerSize)); // argumentsList
__ cmpi(arg_size, Operand(2 * kPointerSize)); __ cmpi(arg_size, Operand(2 * kPointerSize));
__ beq(&skip); __ beq(&skip);
__ LoadP(r6, MemOperand(new_sp, 3 * -kPointerSize)); // new.target __ LoadP(r6, MemOperand(new_sp, 3 * -kPointerSize)); // new.target
...@@ -2104,7 +2102,7 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { ...@@ -2104,7 +2102,7 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
} }
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r3 : argumentsList // -- r5 : argumentsList
// -- r6 : new.target // -- r6 : new.target
// -- r4 : target // -- r4 : target
// -- sp[0] : receiver (undefined) // -- sp[0] : receiver (undefined)
...@@ -2127,7 +2125,8 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { ...@@ -2127,7 +2125,8 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
__ beq(&new_target_not_constructor, cr0); __ beq(&new_target_not_constructor, cr0);
// 4a. Construct the target with the given new.target and argumentsList. // 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. // 4b. The target is not a constructor, throw an appropriate TypeError.
__ bind(&target_not_constructor); __ bind(&target_not_constructor);
...@@ -2173,99 +2172,17 @@ static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { ...@@ -2173,99 +2172,17 @@ static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
} }
// static // static
void Builtins::Generate_Apply(MacroAssembler* masm) { void Builtins::Generate_CallOrConstructVarargs(MacroAssembler* masm,
Handle<Code> code) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r3 : argumentsList
// -- r4 : target // -- r4 : target
// -- r6 : new.target (checked to be constructor or undefined) // -- r3 : number of parameters on the stack (not including the receiver)
// -- sp[0] : thisArgument // -- 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. __ AssertFixedArray(r5);
{
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);
}
// Check for stack overflow. // Check for stack overflow.
{ {
// Check the stack for overflow. We are not trying to catch interruptions // Check the stack for overflow. We are not trying to catch interruptions
...@@ -2276,52 +2193,39 @@ void Builtins::Generate_Apply(MacroAssembler* masm) { ...@@ -2276,52 +2193,39 @@ void Builtins::Generate_Apply(MacroAssembler* masm) {
// here which will cause ip to become negative. // here which will cause ip to become negative.
__ sub(ip, sp, ip); __ sub(ip, sp, ip);
// Check if the arguments will overflow the stack. // Check if the arguments will overflow the stack.
__ ShiftLeftImm(r0, r5, Operand(kPointerSizeLog2)); __ ShiftLeftImm(r0, r7, Operand(kPointerSizeLog2));
__ cmp(ip, r0); // Signed comparison. __ cmp(ip, r0); // Signed comparison.
__ bgt(&done); __ bgt(&done);
__ TailCallRuntime(Runtime::kThrowStackOverflow); __ TailCallRuntime(Runtime::kThrowStackOverflow);
__ bind(&done); __ 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). // Push arguments onto the stack (thisArgument is already on the stack).
{ {
__ LoadRoot(r9, Heap::kUndefinedValueRootIndex);
Label loop, no_args, skip; Label loop, no_args, skip;
__ cmpi(r5, Operand::Zero()); __ cmpi(r7, Operand::Zero());
__ beq(&no_args); __ beq(&no_args);
__ addi(r3, r3, __ addi(r5, r5,
Operand(FixedArray::kHeaderSize - kHeapObjectTag - kPointerSize)); Operand(FixedArray::kHeaderSize - kHeapObjectTag - kPointerSize));
__ mtctr(r5); __ mtctr(r7);
__ bind(&loop); __ bind(&loop);
__ LoadPU(ip, MemOperand(r3, kPointerSize)); __ LoadPU(ip, MemOperand(r5, kPointerSize));
__ CompareRoot(ip, Heap::kTheHoleValueRootIndex); __ CompareRoot(ip, Heap::kTheHoleValueRootIndex);
__ bne(&skip); __ bne(&skip);
__ mr(ip, r9); __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
__ bind(&skip); __ bind(&skip);
__ push(ip); __ push(ip);
__ bdnz(&loop); __ bdnz(&loop);
__ bind(&no_args); __ bind(&no_args);
__ mr(r3, r5); __ add(r3, r3, r7);
} }
// Dispatch to Call or Construct depending on whether new.target is undefined. // Tail-call to the actual Call or Construct builtin.
{ __ Jump(code, RelocInfo::CODE_TARGET);
__ CompareRoot(r6, Heap::kUndefinedValueRootIndex);
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET, eq);
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
}
} }
// static // static
void Builtins::Generate_ForwardVarargs(MacroAssembler* masm, void Builtins::Generate_CallOrConstructForwardVarargs(MacroAssembler* masm,
Handle<Code> code) { Handle<Code> code) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r3 : the number of arguments (not including the receiver) // -- r3 : the number of arguments (not including the receiver)
......
...@@ -1886,31 +1886,31 @@ void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) { ...@@ -1886,31 +1886,31 @@ void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
// -- sp[8] : receiver // -- 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 // arguments from the stack (including the receiver), and push thisArg (if
// present) instead. // present) instead.
{ {
Label skip; Label skip;
Register arg_size = r4; Register arg_size = r7;
Register new_sp = r5; Register new_sp = r5;
Register scratch = r6; Register scratch = r6;
__ ShiftLeftP(arg_size, r2, Operand(kPointerSizeLog2)); __ ShiftLeftP(arg_size, r2, Operand(kPointerSizeLog2));
__ AddP(new_sp, sp, arg_size); __ AddP(new_sp, sp, arg_size);
__ LoadRoot(r2, Heap::kUndefinedValueRootIndex); __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
__ LoadRR(scratch, r2); __ LoadRR(r4, scratch);
__ LoadP(r3, MemOperand(new_sp, 0)); // receiver __ LoadP(r3, MemOperand(new_sp, 0)); // receiver
__ CmpP(arg_size, Operand(kPointerSize)); __ CmpP(arg_size, Operand(kPointerSize));
__ blt(&skip); __ blt(&skip);
__ LoadP(scratch, MemOperand(new_sp, 1 * -kPointerSize)); // thisArg __ LoadP(scratch, MemOperand(new_sp, 1 * -kPointerSize)); // thisArg
__ beq(&skip); __ beq(&skip);
__ LoadP(r2, MemOperand(new_sp, 2 * -kPointerSize)); // argArray __ LoadP(r4, MemOperand(new_sp, 2 * -kPointerSize)); // argArray
__ bind(&skip); __ bind(&skip);
__ LoadRR(sp, new_sp); __ LoadRR(sp, new_sp);
__ StoreP(scratch, MemOperand(sp, 0)); __ StoreP(scratch, MemOperand(sp, 0));
} }
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r2 : argArray // -- r4 : argArray
// -- r3 : receiver // -- r3 : receiver
// -- sp[0] : thisArg // -- sp[0] : thisArg
// ----------------------------------- // -----------------------------------
...@@ -1925,13 +1925,12 @@ void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) { ...@@ -1925,13 +1925,12 @@ void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
// 3. Tail call with no arguments if argArray is null or undefined. // 3. Tail call with no arguments if argArray is null or undefined.
Label no_arguments; Label no_arguments;
__ JumpIfRoot(r2, Heap::kNullValueRootIndex, &no_arguments); __ JumpIfRoot(r4, Heap::kNullValueRootIndex, &no_arguments);
__ JumpIfRoot(r2, Heap::kUndefinedValueRootIndex, &no_arguments); __ JumpIfRoot(r4, Heap::kUndefinedValueRootIndex, &no_arguments);
// 4a. Apply the receiver to the given argArray (passing undefined for // 4a. Apply the receiver to the given argArray.
// new.target). __ Jump(masm->isolate()->builtins()->CallWithArrayLike(),
__ LoadRoot(r5, Heap::kUndefinedValueRootIndex); RelocInfo::CODE_TARGET);
__ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
// 4b. The argArray is either null or undefined, so we tail call without any // 4b. The argArray is either null or undefined, so we tail call without any
// arguments to the receiver. // arguments to the receiver.
...@@ -2002,19 +2001,19 @@ void Builtins::Generate_ReflectApply(MacroAssembler* masm) { ...@@ -2002,19 +2001,19 @@ void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
// -- sp[12] : receiver // -- 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 // remove all arguments from the stack (including the receiver), and push
// thisArgument (if present) instead. // thisArgument (if present) instead.
{ {
Label skip; Label skip;
Register arg_size = r4; Register arg_size = r7;
Register new_sp = r5; Register new_sp = r5;
Register scratch = r6; Register scratch = r6;
__ ShiftLeftP(arg_size, r2, Operand(kPointerSizeLog2)); __ ShiftLeftP(arg_size, r2, Operand(kPointerSizeLog2));
__ AddP(new_sp, sp, arg_size); __ AddP(new_sp, sp, arg_size);
__ LoadRoot(r3, Heap::kUndefinedValueRootIndex); __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
__ LoadRR(scratch, r3); __ LoadRR(scratch, r3);
__ LoadRR(r2, r3); __ LoadRR(r4, r3);
__ CmpP(arg_size, Operand(kPointerSize)); __ CmpP(arg_size, Operand(kPointerSize));
__ blt(&skip); __ blt(&skip);
__ LoadP(r3, MemOperand(new_sp, 1 * -kPointerSize)); // target __ LoadP(r3, MemOperand(new_sp, 1 * -kPointerSize)); // target
...@@ -2022,14 +2021,14 @@ void Builtins::Generate_ReflectApply(MacroAssembler* masm) { ...@@ -2022,14 +2021,14 @@ void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
__ LoadP(scratch, MemOperand(new_sp, 2 * -kPointerSize)); // thisArgument __ LoadP(scratch, MemOperand(new_sp, 2 * -kPointerSize)); // thisArgument
__ CmpP(arg_size, Operand(2 * kPointerSize)); __ CmpP(arg_size, Operand(2 * kPointerSize));
__ beq(&skip); __ beq(&skip);
__ LoadP(r2, MemOperand(new_sp, 3 * -kPointerSize)); // argumentsList __ LoadP(r4, MemOperand(new_sp, 3 * -kPointerSize)); // argumentsList
__ bind(&skip); __ bind(&skip);
__ LoadRR(sp, new_sp); __ LoadRR(sp, new_sp);
__ StoreP(scratch, MemOperand(sp, 0)); __ StoreP(scratch, MemOperand(sp, 0));
} }
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r2 : argumentsList // -- r4 : argumentsList
// -- r3 : target // -- r3 : target
// -- sp[0] : thisArgument // -- sp[0] : thisArgument
// ----------------------------------- // -----------------------------------
...@@ -2042,10 +2041,9 @@ void Builtins::Generate_ReflectApply(MacroAssembler* masm) { ...@@ -2042,10 +2041,9 @@ void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
__ TestBit(r6, Map::kIsCallable); __ TestBit(r6, Map::kIsCallable);
__ beq(&target_not_callable); __ beq(&target_not_callable);
// 3a. Apply the target to the given argumentsList (passing undefined for // 3a. Apply the target to the given argumentsList.
// new.target). __ Jump(masm->isolate()->builtins()->CallWithArrayLike(),
__ LoadRoot(r5, Heap::kUndefinedValueRootIndex); RelocInfo::CODE_TARGET);
__ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
// 3b. The target is not callable, throw an appropriate TypeError. // 3b. The target is not callable, throw an appropriate TypeError.
__ bind(&target_not_callable); __ bind(&target_not_callable);
...@@ -2064,18 +2062,18 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { ...@@ -2064,18 +2062,18 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
// -- sp[12] : receiver // -- 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 // new.target into r5 (if present, otherwise use target), remove all
// arguments from the stack (including the receiver), and push thisArgument // arguments from the stack (including the receiver), and push thisArgument
// (if present) instead. // (if present) instead.
{ {
Label skip; Label skip;
Register arg_size = r4; Register arg_size = r7;
Register new_sp = r6; Register new_sp = r6;
__ ShiftLeftP(arg_size, r2, Operand(kPointerSizeLog2)); __ ShiftLeftP(arg_size, r2, Operand(kPointerSizeLog2));
__ AddP(new_sp, sp, arg_size); __ AddP(new_sp, sp, arg_size);
__ LoadRoot(r3, Heap::kUndefinedValueRootIndex); __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
__ LoadRR(r2, r3); __ LoadRR(r4, r3);
__ LoadRR(r5, r3); __ LoadRR(r5, r3);
__ StoreP(r3, MemOperand(new_sp, 0)); // receiver (undefined) __ StoreP(r3, MemOperand(new_sp, 0)); // receiver (undefined)
__ CmpP(arg_size, Operand(kPointerSize)); __ CmpP(arg_size, Operand(kPointerSize));
...@@ -2083,7 +2081,7 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { ...@@ -2083,7 +2081,7 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
__ LoadP(r3, MemOperand(new_sp, 1 * -kPointerSize)); // target __ LoadP(r3, MemOperand(new_sp, 1 * -kPointerSize)); // target
__ LoadRR(r5, r3); // new.target defaults to target __ LoadRR(r5, r3); // new.target defaults to target
__ beq(&skip); __ beq(&skip);
__ LoadP(r2, MemOperand(new_sp, 2 * -kPointerSize)); // argumentsList __ LoadP(r4, MemOperand(new_sp, 2 * -kPointerSize)); // argumentsList
__ CmpP(arg_size, Operand(2 * kPointerSize)); __ CmpP(arg_size, Operand(2 * kPointerSize));
__ beq(&skip); __ beq(&skip);
__ LoadP(r5, MemOperand(new_sp, 3 * -kPointerSize)); // new.target __ LoadP(r5, MemOperand(new_sp, 3 * -kPointerSize)); // new.target
...@@ -2092,7 +2090,7 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { ...@@ -2092,7 +2090,7 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
} }
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r2 : argumentsList // -- r4 : argumentsList
// -- r5 : new.target // -- r5 : new.target
// -- r3 : target // -- r3 : target
// -- sp[0] : receiver (undefined) // -- sp[0] : receiver (undefined)
...@@ -2115,7 +2113,8 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { ...@@ -2115,7 +2113,8 @@ void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
__ beq(&new_target_not_constructor); __ beq(&new_target_not_constructor);
// 4a. Construct the target with the given new.target and argumentsList. // 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. // 4b. The target is not a constructor, throw an appropriate TypeError.
__ bind(&target_not_constructor); __ bind(&target_not_constructor);
...@@ -2170,99 +2169,17 @@ static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { ...@@ -2170,99 +2169,17 @@ static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
} }
// static // static
void Builtins::Generate_Apply(MacroAssembler* masm) { void Builtins::Generate_CallOrConstructVarargs(MacroAssembler* masm,
Handle<Code> code) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r2 : argumentsList
// -- r3 : target // -- r3 : target
// -- r5 : new.target (checked to be constructor or undefined) // -- r2 : number of parameters on the stack (not including the receiver)
// -- sp[0] : thisArgument // -- 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. __ AssertFixedArray(r4);
{
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);
}
// Check for stack overflow. // Check for stack overflow.
{ {
// Check the stack for overflow. We are not trying to catch interruptions // Check the stack for overflow. We are not trying to catch interruptions
...@@ -2273,53 +2190,40 @@ void Builtins::Generate_Apply(MacroAssembler* masm) { ...@@ -2273,53 +2190,40 @@ void Builtins::Generate_Apply(MacroAssembler* masm) {
// here which will cause ip to become negative. // here which will cause ip to become negative.
__ SubP(ip, sp, ip); __ SubP(ip, sp, ip);
// Check if the arguments will overflow the stack. // Check if the arguments will overflow the stack.
__ ShiftLeftP(r0, r4, Operand(kPointerSizeLog2)); __ ShiftLeftP(r0, r6, Operand(kPointerSizeLog2));
__ CmpP(ip, r0); // Signed comparison. __ CmpP(ip, r0); // Signed comparison.
__ bgt(&done); __ bgt(&done);
__ TailCallRuntime(Runtime::kThrowStackOverflow); __ TailCallRuntime(Runtime::kThrowStackOverflow);
__ bind(&done); __ 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). // Push arguments onto the stack (thisArgument is already on the stack).
{ {
__ LoadRoot(r8, Heap::kUndefinedValueRootIndex);
Label loop, no_args, skip; Label loop, no_args, skip;
__ CmpP(r4, Operand::Zero()); __ CmpP(r6, Operand::Zero());
__ beq(&no_args); __ beq(&no_args);
__ AddP(r2, r2, __ AddP(r4, r4,
Operand(FixedArray::kHeaderSize - kHeapObjectTag - kPointerSize)); Operand(FixedArray::kHeaderSize - kHeapObjectTag - kPointerSize));
__ LoadRR(r1, r4); __ LoadRR(r1, r6);
__ bind(&loop); __ bind(&loop);
__ LoadP(ip, MemOperand(r2, kPointerSize)); __ LoadP(ip, MemOperand(r4, kPointerSize));
__ la(r2, MemOperand(r2, kPointerSize)); __ la(r4, MemOperand(r4, kPointerSize));
__ CompareRoot(ip, Heap::kTheHoleValueRootIndex); __ CompareRoot(ip, Heap::kTheHoleValueRootIndex);
__ bne(&skip, Label::kNear); __ bne(&skip, Label::kNear);
__ LoadRR(ip, r8); __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
__ bind(&skip); __ bind(&skip);
__ push(ip); __ push(ip);
__ BranchOnCount(r1, &loop); __ BranchOnCount(r1, &loop);
__ bind(&no_args); __ bind(&no_args);
__ LoadRR(r2, r4); __ AddP(r2, r2, r6);
} }
// Dispatch to Call or Construct depending on whether new.target is undefined. // Tail-call to the actual Call or Construct builtin.
{ __ Jump(code, RelocInfo::CODE_TARGET);
__ CompareRoot(r5, Heap::kUndefinedValueRootIndex);
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET, eq);
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
}
} }
// static // static
void Builtins::Generate_ForwardVarargs(MacroAssembler* masm, void Builtins::Generate_CallOrConstructForwardVarargs(MacroAssembler* masm,
Handle<Code> code) { Handle<Code> code) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r2 : the number of arguments (not including the receiver) // -- r2 : the number of arguments (not including the receiver)
......
...@@ -155,6 +155,16 @@ void CallTrampolineDescriptor::InitializePlatformSpecific( ...@@ -155,6 +155,16 @@ void CallTrampolineDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); 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( void CallForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
// r3 : number of arguments // r3 : number of arguments
...@@ -164,6 +174,25 @@ void CallForwardVarargsDescriptor::InitializePlatformSpecific( ...@@ -164,6 +174,25 @@ void CallForwardVarargsDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); 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( void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
// r3 : number of arguments // r3 : number of arguments
...@@ -174,6 +203,15 @@ void ConstructForwardVarargsDescriptor::InitializePlatformSpecific( ...@@ -174,6 +203,15 @@ void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); 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( void ConstructStubDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
// r3 : number of arguments // r3 : number of arguments
......
...@@ -2598,6 +2598,17 @@ void MacroAssembler::AssertSmi(Register object) { ...@@ -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) { void MacroAssembler::AssertFunction(Register object) {
if (emit_debug_code()) { if (emit_debug_code()) {
......
...@@ -1303,6 +1303,9 @@ class MacroAssembler : public Assembler { ...@@ -1303,6 +1303,9 @@ class MacroAssembler : public Assembler {
#define SmiWordOffset(offset) offset #define SmiWordOffset(offset) offset
#endif #endif
// Abort execution if argument is not a FixedArray, enabled via --debug-code.
void AssertFixedArray(Register object);
void AssertFunction(Register object); void AssertFunction(Register object);
// Abort execution if argument is not a JSBoundFunction, // Abort execution if argument is not a JSBoundFunction,
......
...@@ -145,6 +145,16 @@ void CallTrampolineDescriptor::InitializePlatformSpecific( ...@@ -145,6 +145,16 @@ void CallTrampolineDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); 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( void CallForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
// r2 : number of arguments // r2 : number of arguments
...@@ -154,6 +164,25 @@ void CallForwardVarargsDescriptor::InitializePlatformSpecific( ...@@ -154,6 +164,25 @@ void CallForwardVarargsDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); 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( void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
// r2 : number of arguments // r2 : number of arguments
...@@ -164,6 +193,15 @@ void ConstructForwardVarargsDescriptor::InitializePlatformSpecific( ...@@ -164,6 +193,15 @@ void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); 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( void ConstructStubDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
// r2 : number of arguments // r2 : number of arguments
......
...@@ -2374,6 +2374,18 @@ void MacroAssembler::AssertSmi(Register object) { ...@@ -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) { void MacroAssembler::AssertFunction(Register object) {
if (emit_debug_code()) { if (emit_debug_code()) {
STATIC_ASSERT(kSmiTag == 0); STATIC_ASSERT(kSmiTag == 0);
......
...@@ -1621,6 +1621,9 @@ class MacroAssembler : public Assembler { ...@@ -1621,6 +1621,9 @@ class MacroAssembler : public Assembler {
#define SmiWordOffset(offset) offset #define SmiWordOffset(offset) offset
#endif #endif
// Abort execution if argument is not a FixedArray, enabled via --debug-code.
void AssertFixedArray(Register object);
void AssertFunction(Register object); void AssertFunction(Register object);
// Abort execution if argument is not a JSBoundFunction, // 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