| Index: src/mips/builtins-mips.cc
|
| diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc
|
| index f8c112605c96f4e0bc1f0685e9e59ecabc57a5cc..2089e1a993076da76efbb1ee7b418a3df757a579 100644
|
| --- a/src/mips/builtins-mips.cc
|
| +++ b/src/mips/builtins-mips.cc
|
| @@ -1351,49 +1351,99 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
|
| }
|
|
|
|
|
| -void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
|
| - const int kIndexOffset =
|
| - StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize);
|
| - const int kLimitOffset =
|
| - StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize);
|
| - const int kArgsOffset = 2 * kPointerSize;
|
| - const int kRecvOffset = 3 * kPointerSize;
|
| - const int kFunctionOffset = 4 * kPointerSize;
|
| +static void Generate_CheckStackOverflow(MacroAssembler* masm,
|
| + const int calleeOffset) {
|
| + // Check the stack for overflow. We are not trying to catch
|
| + // interruptions (e.g. debug break and preemption) here, so the "real stack
|
| + // limit" is checked.
|
| + Label okay;
|
| + __ LoadRoot(a2, Heap::kRealStackLimitRootIndex);
|
| + // Make a2 the space we have left. The stack might already be overflowed
|
| + // here which will cause a2 to become negative.
|
| + __ Subu(a2, sp, a2);
|
| + // Check if the arguments will overflow the stack.
|
| + __ sll(t3, v0, kPointerSizeLog2 - kSmiTagSize);
|
| + // Signed comparison.
|
| + __ Branch(&okay, gt, a2, Operand(t3));
|
| +
|
| + // Out of stack space.
|
| + __ lw(a1, MemOperand(fp, calleeOffset));
|
| + __ Push(a1, v0);
|
| + __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
|
| +
|
| + __ bind(&okay);
|
| +}
|
| +
|
| +
|
| +static void Generate_PushAppliedArguments(MacroAssembler* masm,
|
| + const int argumentsOffset,
|
| + const int indexOffset,
|
| + const int limitOffset) {
|
| + Label entry, loop;
|
| + __ lw(a0, MemOperand(fp, indexOffset));
|
| + __ Branch(&entry);
|
| +
|
| + // Load the current argument from the arguments array and push it to the
|
| + // stack.
|
| + // a0: current argument index
|
| + __ bind(&loop);
|
| + __ lw(a1, MemOperand(fp, argumentsOffset));
|
| + __ Push(a1, a0);
|
| +
|
| + // Call the runtime to access the property in the arguments array.
|
| + __ CallRuntime(Runtime::kGetProperty, 2);
|
| + __ push(v0);
|
| +
|
| + // Use inline caching to access the arguments.
|
| + __ lw(a0, MemOperand(fp, indexOffset));
|
| + __ Addu(a0, a0, Operand(1 << kSmiTagSize));
|
| + __ sw(a0, MemOperand(fp, indexOffset));
|
| +
|
| + // Test if the copy loop has finished copying all the elements from the
|
| + // arguments object.
|
| + __ bind(&entry);
|
| + __ lw(a1, MemOperand(fp, limitOffset));
|
| + __ Branch(&loop, ne, a0, Operand(a1));
|
| +
|
| + // On exit, the pushed arguments count is in a0, untagged
|
| + __ SmiUntag(a0);
|
| +}
|
| +
|
| +
|
| +// Used by FunctionApply and ReflectApply
|
| +static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
|
| + const int kFormalParameters = targetIsArgument ? 3 : 2;
|
| + const int kStackSize = kFormalParameters + 1;
|
|
|
| {
|
| FrameScope frame_scope(masm, StackFrame::INTERNAL);
|
| + const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
|
| + const int kReceiverOffset = kArgumentsOffset + kPointerSize;
|
| + const int kFunctionOffset = kReceiverOffset + kPointerSize;
|
| +
|
| __ lw(a0, MemOperand(fp, kFunctionOffset)); // Get the function.
|
| __ push(a0);
|
| - __ lw(a0, MemOperand(fp, kArgsOffset)); // Get the args array.
|
| + __ lw(a0, MemOperand(fp, kArgumentsOffset)); // Get the args array.
|
| __ push(a0);
|
| // Returns (in v0) number of arguments to copy to stack as Smi.
|
| - __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
|
| -
|
| - // Check the stack for overflow. We are not trying to catch
|
| - // interruptions (e.g. debug break and preemption) here, so the "real stack
|
| - // limit" is checked.
|
| - Label okay;
|
| - __ LoadRoot(a2, Heap::kRealStackLimitRootIndex);
|
| - // Make a2 the space we have left. The stack might already be overflowed
|
| - // here which will cause a2 to become negative.
|
| - __ subu(a2, sp, a2);
|
| - // Check if the arguments will overflow the stack.
|
| - __ sll(t3, v0, kPointerSizeLog2 - kSmiTagSize);
|
| - __ Branch(&okay, gt, a2, Operand(t3)); // Signed comparison.
|
| -
|
| - // Out of stack space.
|
| - __ lw(a1, MemOperand(fp, kFunctionOffset));
|
| - __ Push(a1, v0);
|
| - __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
|
| - // End of stack check.
|
| + if (targetIsArgument) {
|
| + __ InvokeBuiltin(Builtins::REFLECT_APPLY_PREPARE, CALL_FUNCTION);
|
| + } else {
|
| + __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
|
| + }
|
| +
|
| + Generate_CheckStackOverflow(masm, kFunctionOffset);
|
|
|
| // Push current limit and index.
|
| - __ bind(&okay);
|
| + const int kIndexOffset =
|
| + StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize);
|
| + const int kLimitOffset =
|
| + StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize);
|
| __ mov(a1, zero_reg);
|
| __ Push(v0, a1); // Limit and initial index.
|
|
|
| // Get the receiver.
|
| - __ lw(a0, MemOperand(fp, kRecvOffset));
|
| + __ lw(a0, MemOperand(fp, kReceiverOffset));
|
|
|
| // Check that the function is a JS function (otherwise it must be a proxy).
|
| Label push_receiver;
|
| @@ -1449,36 +1499,12 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
|
| __ push(a0);
|
|
|
| // Copy all arguments from the array to the stack.
|
| - Label entry, loop;
|
| - __ lw(a0, MemOperand(fp, kIndexOffset));
|
| - __ Branch(&entry);
|
| -
|
| - // Load the current argument from the arguments array and push it to the
|
| - // stack.
|
| - // a0: current argument index
|
| - __ bind(&loop);
|
| - __ lw(a1, MemOperand(fp, kArgsOffset));
|
| - __ Push(a1, a0);
|
| -
|
| - // Call the runtime to access the property in the arguments array.
|
| - __ CallRuntime(Runtime::kGetProperty, 2);
|
| - __ push(v0);
|
| -
|
| - // Use inline caching to access the arguments.
|
| - __ lw(a0, MemOperand(fp, kIndexOffset));
|
| - __ Addu(a0, a0, Operand(1 << kSmiTagSize));
|
| - __ sw(a0, MemOperand(fp, kIndexOffset));
|
| -
|
| - // Test if the copy loop has finished copying all the elements from the
|
| - // arguments object.
|
| - __ bind(&entry);
|
| - __ lw(a1, MemOperand(fp, kLimitOffset));
|
| - __ Branch(&loop, ne, a0, Operand(a1));
|
| + Generate_PushAppliedArguments(
|
| + masm, kArgumentsOffset, kIndexOffset, kLimitOffset);
|
|
|
| // Call the function.
|
| Label call_proxy;
|
| ParameterCount actual(a0);
|
| - __ sra(a0, a0, kSmiTagSize);
|
| __ lw(a1, MemOperand(fp, kFunctionOffset));
|
| __ GetObjectType(a1, a2, a2);
|
| __ Branch(&call_proxy, ne, a2, Operand(JS_FUNCTION_TYPE));
|
| @@ -1487,7 +1513,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
|
|
|
| frame_scope.GenerateLeaveFrame();
|
| __ Ret(USE_DELAY_SLOT);
|
| - __ Addu(sp, sp, Operand(3 * kPointerSize)); // In delay slot.
|
| + __ Addu(sp, sp, Operand(kStackSize * kPointerSize)); // In delay slot.
|
|
|
| // Call the function proxy.
|
| __ bind(&call_proxy);
|
| @@ -1505,6 +1531,86 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
|
| }
|
|
|
|
|
| +static void Generate_ConstructHelper(MacroAssembler* masm) {
|
| + const int kFormalParameters = 3;
|
| + const int kStackSize = kFormalParameters + 1;
|
| +
|
| + {
|
| + FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL);
|
| + const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize;
|
| + const int kArgumentsOffset = kNewTargetOffset + kPointerSize;
|
| + const int kFunctionOffset = kArgumentsOffset + kPointerSize;
|
| +
|
| + // If newTarget is not supplied, set it to constructor
|
| + Label validate_arguments;
|
| + __ lw(a0, MemOperand(fp, kNewTargetOffset));
|
| + __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
|
| + __ Branch(&validate_arguments, ne, a0, Operand(at));
|
| + __ lw(a0, MemOperand(fp, kFunctionOffset));
|
| + __ sw(a0, MemOperand(fp, kNewTargetOffset));
|
| +
|
| + // Validate arguments
|
| + __ bind(&validate_arguments);
|
| + __ lw(a0, MemOperand(fp, kFunctionOffset)); // get the function
|
| + __ push(a0);
|
| + __ lw(a0, MemOperand(fp, kArgumentsOffset)); // get the args array
|
| + __ push(a0);
|
| + __ lw(a0, MemOperand(fp, kNewTargetOffset)); // get the new.target
|
| + __ push(a0);
|
| + __ InvokeBuiltin(Builtins::REFLECT_CONSTRUCT_PREPARE, CALL_FUNCTION);
|
| +
|
| + Generate_CheckStackOverflow(masm, kFunctionOffset);
|
| +
|
| + // Push current limit and index.
|
| + const int kIndexOffset =
|
| + StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize);
|
| + const int kLimitOffset =
|
| + StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize);
|
| + __ push(a0); // limit
|
| + __ mov(a1, zero_reg); // initial index
|
| + __ push(a1);
|
| + // Push newTarget and callee functions
|
| + __ lw(a0, MemOperand(fp, kNewTargetOffset));
|
| + __ push(a0);
|
| + __ lw(a0, MemOperand(fp, kFunctionOffset));
|
| + __ push(a0);
|
| +
|
| + // Copy all arguments from the array to the stack.
|
| + Generate_PushAppliedArguments(
|
| + masm, kArgumentsOffset, kIndexOffset, kLimitOffset);
|
| +
|
| + // Use undefined feedback vector
|
| + __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
|
| + __ lw(a1, MemOperand(fp, kFunctionOffset));
|
| +
|
| + // Call the function.
|
| + CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL);
|
| + __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
|
| +
|
| + __ Drop(1);
|
| +
|
| + // Leave internal frame.
|
| + }
|
| + __ Addu(sp, sp, Operand(kStackSize * kPointerSize));
|
| + __ Jump(ra);
|
| +}
|
| +
|
| +
|
| +void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
|
| + Generate_ApplyHelper(masm, false);
|
| +}
|
| +
|
| +
|
| +void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
|
| + Generate_ApplyHelper(masm, true);
|
| +}
|
| +
|
| +
|
| +void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
|
| + Generate_ConstructHelper(masm);
|
| +}
|
| +
|
| +
|
| static void ArgumentAdaptorStackCheck(MacroAssembler* masm,
|
| Label* stack_overflow) {
|
| // ----------- S t a t e -------------
|
|
|