Index: src/x64/builtins-x64.cc |
diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc |
index cb7ba304e8dc3eefed4d5799a99aafbefae24ac3..54d36f5bdb4b113fc77d4009e35025a382f80243 100644 |
--- a/src/x64/builtins-x64.cc |
+++ b/src/x64/builtins-x64.cc |
@@ -39,10 +39,126 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm, |
masm->int3(); // UNIMPLEMENTED. |
} |
+static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { |
+ __ push(rbp); |
+ __ movq(rbp, rsp); |
+ |
+ // Store the arguments adaptor context sentinel. |
+ __ push(Immediate(ArgumentsAdaptorFrame::SENTINEL)); |
+ |
+ // Push the function on the stack. |
+ __ push(rdi); |
+ |
+ // Preserve the number of arguments on the stack. Must preserve both |
+ // eax and ebx because these registers are used when copying the |
+ // arguments and the receiver. |
+ ASSERT(kSmiTagSize == 1); |
+ __ lea(rcx, Operand(rax, rax, kTimes1, kSmiTag)); |
+ __ push(rcx); |
+} |
+ |
+ |
+static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { |
+ // Retrieve the number of arguments from the stack. Number is a Smi. |
+ __ movq(rbx, Operand(rbp, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
+ |
+ // Leave the frame. |
+ __ movq(rsp, rbp); |
+ __ pop(rbp); |
+ |
+ // Remove caller arguments from the stack. |
+ // rbx holds a Smi. |
William Hesse
2009/06/11 09:32:29
holds a Smi. Therefore, we convert to a dword off
|
+ ASSERT_EQ(kSmiTagSize, 1 && kSmiTag == 0); |
+ ASSERT_EQ(kPointerSize, (1 << kSmiTagSize) * 4); |
+ __ pop(rcx); |
+ __ lea(rsp, Operand(rsp, rbx, kTimes4, 1 * kPointerSize)); // 1 ~ receiver |
+ __ push(rcx); |
+} |
+ |
+ |
void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { |
- masm->int3(); // UNIMPLEMENTED. |
+ // ----------- S t a t e ------------- |
+ // -- rax : actual number of arguments |
+ // -- rbx : expected number of arguments |
+ // -- rdx : code entry to call |
+ // ----------------------------------- |
+ |
+ Label invoke, dont_adapt_arguments; |
+ __ IncrementCounter(&Counters::arguments_adaptors, 1); |
+ |
+ Label enough, too_few; |
+ __ cmp(rax, rbx); |
+ __ j(less, &too_few); |
+ __ cmp(rbx, Immediate(SharedFunctionInfo::kDontAdaptArgumentsSentinel)); |
+ __ j(equal, &dont_adapt_arguments); |
+ |
+ { // Enough parameters: Actual >= expected. |
+ __ bind(&enough); |
+ EnterArgumentsAdaptorFrame(masm); |
+ |
+ // Copy receiver and all expected arguments. |
+ const int offset = StandardFrameConstants::kCallerSPOffset; |
+ __ lea(rax, Operand(rbp, rax, kTimesPointerSize, offset)); |
+ __ movq(rcx, Immediate(-1)); // account for receiver |
+ |
+ Label copy; |
+ __ bind(©); |
+ __ inc(rcx); |
+ __ push(Operand(rax, 0)); |
+ __ sub(rax, Immediate(kPointerSize)); |
+ __ cmp(rcx, rbx); |
+ __ j(less, ©); |
+ __ jmp(&invoke); |
+ } |
+ |
+ { // Too few parameters: Actual < expected. |
+ __ bind(&too_few); |
+ EnterArgumentsAdaptorFrame(masm); |
+ |
+ // Copy receiver and all actual arguments. |
+ const int offset = StandardFrameConstants::kCallerSPOffset; |
+ __ lea(rdi, Operand(rbp, rax, kTimesPointerSize, offset)); |
+ __ movq(rcx, Immediate(-1)); // account for receiver |
+ |
+ Label copy; |
+ __ bind(©); |
+ __ inc(rcx); |
+ __ push(Operand(rdi, 0)); |
+ __ sub(rdi, Immediate(kPointerSize)); |
+ __ cmp(rcx, rax); |
+ __ j(less, ©); |
+ |
+ // Fill remaining expected arguments with undefined values. |
+ Label fill; |
+ __ movq(kScratchRegister, |
+ Factory::undefined_value(), |
+ RelocInfo::EMBEDDED_OBJECT); |
+ __ bind(&fill); |
+ __ inc(rcx); |
+ __ push(kScratchRegister); |
+ __ cmp(rcx, rbx); |
+ __ j(less, &fill); |
+ |
+ // Restore function pointer. |
+ __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
+ } |
+ |
+ // Call the entry point. |
+ __ bind(&invoke); |
+ __ call(rdx); |
+ |
+ // Leave frame and return. |
+ LeaveArgumentsAdaptorFrame(masm); |
+ __ ret(0); |
+ |
+ // ------------------------------------------- |
+ // Dont adapt arguments. |
+ // ------------------------------------------- |
+ __ bind(&dont_adapt_arguments); |
+ __ jmp(rdx); |
} |
+ |
void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
masm->int3(); // UNIMPLEMENTED. |
} |
@@ -82,7 +198,6 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, |
// Enter an internal frame. |
__ EnterInternalFrame(); |
- |
// Load the function context into rsi. |
__ movq(rsi, FieldOperand(rdx, JSFunction::kContextOffset)); |
@@ -155,6 +270,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, |
__ call(kScratchRegister); |
} else { |
ParameterCount actual(rax); |
+ // Function must be in rdi. |
__ InvokeFunction(rdi, actual, CALL_FUNCTION); |
} |