Chromium Code Reviews| Index: src/mips64/builtins-mips64.cc |
| diff --git a/src/mips64/builtins-mips64.cc b/src/mips64/builtins-mips64.cc |
| index 53246335b7b73feb3f9863738ddce5235555105d..44767bf245ab59dcc7b7d3ed1590c205d9bd2acf 100644 |
| --- a/src/mips64/builtins-mips64.cc |
| +++ b/src/mips64/builtins-mips64.cc |
| @@ -1359,49 +1359,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. |
| + __ dsubu(a2, sp, a2); |
| + // Check if the arguments will overflow the stack. |
| + __ SmiScale(a7, v0, kPointerSizeLog2); |
| + __ Branch(&okay, gt, a2, Operand(a7)); // Signed comparison. |
| + |
| + // Out of stack space. |
| + __ ld(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; |
| + __ ld(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); |
| + __ ld(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. |
| + __ ld(a0, MemOperand(fp, indexOffset)); |
| + __ Daddu(a0, a0, Operand(Smi::FromInt(1))); |
| + __ sd(a0, MemOperand(fp, indexOffset)); |
| + |
| + // Test if the copy loop has finished copying all the elements from the |
| + // arguments object. |
| + __ bind(&entry); |
| + __ ld(a1, MemOperand(fp, limitOffset)); |
| + __ Branch(&loop, ne, a0, Operand(a1)); |
| + |
| + // On exit, the pushed arguments count is in r0, untagged |
|
paul.l...
2015/03/19 22:35:40
nit: regname a0
akos.palfi.imgtec
2015/03/20 00:07:24
Done.
|
| + __ 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; |
| + |
| __ ld(a0, MemOperand(fp, kFunctionOffset)); // Get the function. |
| __ push(a0); |
| - __ ld(a0, MemOperand(fp, kArgsOffset)); // Get the args array. |
| + __ ld(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. |
| - __ dsubu(a2, sp, a2); |
| - // Check if the arguments will overflow the stack. |
| - __ SmiScale(a7, v0, kPointerSizeLog2); |
| - __ Branch(&okay, gt, a2, Operand(a7)); // Signed comparison. |
| - |
| - // Out of stack space. |
| - __ ld(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. |
| - __ ld(a0, MemOperand(fp, kRecvOffset)); |
| + __ ld(a0, MemOperand(fp, kReceiverOffset)); |
| // Check that the function is a JS function (otherwise it must be a proxy). |
| Label push_receiver; |
| @@ -1457,36 +1507,12 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
| __ push(a0); |
| // Copy all arguments from the array to the stack. |
| - Label entry, loop; |
| - __ ld(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); |
| - __ ld(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. |
| - __ ld(a0, MemOperand(fp, kIndexOffset)); |
| - __ Daddu(a0, a0, Operand(Smi::FromInt(1))); |
| - __ sd(a0, MemOperand(fp, kIndexOffset)); |
| - |
| - // Test if the copy loop has finished copying all the elements from the |
| - // arguments object. |
| - __ bind(&entry); |
| - __ ld(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); |
| - __ SmiUntag(a0); |
| __ ld(a1, MemOperand(fp, kFunctionOffset)); |
| __ GetObjectType(a1, a2, a2); |
| __ Branch(&call_proxy, ne, a2, Operand(JS_FUNCTION_TYPE)); |
| @@ -1495,7 +1521,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
| frame_scope.GenerateLeaveFrame(); |
| __ Ret(USE_DELAY_SLOT); |
| - __ Daddu(sp, sp, Operand(3 * kPointerSize)); // In delay slot. |
| + __ Daddu(sp, sp, Operand(kStackSize * kPointerSize)); // In delay slot. |
| // Call the function proxy. |
| __ bind(&call_proxy); |
| @@ -1509,7 +1535,87 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
| } |
| __ Ret(USE_DELAY_SLOT); |
| - __ Daddu(sp, sp, Operand(3 * kPointerSize)); // In delay slot. |
| + __ Daddu(sp, sp, Operand(kStackSize * kPointerSize)); // In delay slot. |
| +} |
| + |
| + |
| +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; |
| + __ ld(a0, MemOperand(fp, kNewTargetOffset)); |
| + __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
| + __ Branch(&validate_arguments, ne, a0, Operand(at)); |
| + __ ld(a0, MemOperand(fp, kFunctionOffset)); |
| + __ sd(a0, MemOperand(fp, kNewTargetOffset)); |
| + |
| + // Validate arguments |
| + __ bind(&validate_arguments); |
| + __ ld(a0, MemOperand(fp, kFunctionOffset)); // get the function |
| + __ push(a0); |
| + __ ld(a0, MemOperand(fp, kArgumentsOffset)); // get the args array |
| + __ push(a0); |
| + __ ld(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 |
| + __ ld(a0, MemOperand(fp, kNewTargetOffset)); |
| + __ push(a0); |
| + __ ld(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); |
| + __ ld(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. |
| + } |
| + __ Daddu(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); |
| } |