Commit ee78d118 authored by serya@chromium.org's avatar serya@chromium.org

Port direct API function call to x64 (ia32 CL is http://codereview.chromium.org/4456002/).

Review URL: http://codereview.chromium.org/5004004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5833 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 84541236
...@@ -506,7 +506,7 @@ static bool GenerateFastApiCall(MacroAssembler* masm, ...@@ -506,7 +506,7 @@ static bool GenerateFastApiCall(MacroAssembler* masm,
__ mov(ApiParameterOperand(2), eax); // v8::Arguments::values_. __ mov(ApiParameterOperand(2), eax); // v8::Arguments::values_.
__ Set(ApiParameterOperand(3), Immediate(argc)); // v8::Arguments::length_. __ Set(ApiParameterOperand(3), Immediate(argc)); // v8::Arguments::length_.
// v8::Arguments::is_construct_call_. // v8::Arguments::is_construct_call_.
__ mov(ApiParameterOperand(4), Immediate(0)); __ Set(ApiParameterOperand(4), Immediate(0));
// v8::InvocationCallback's argument. // v8::InvocationCallback's argument.
__ lea(eax, ApiParameterOperand(1)); __ lea(eax, ApiParameterOperand(1));
......
...@@ -2535,18 +2535,18 @@ void CEntryStub::GenerateCore(MacroAssembler* masm, ...@@ -2535,18 +2535,18 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
#ifdef _WIN64 #ifdef _WIN64
// Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9 // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9
// Store Arguments object on stack, below the 4 WIN64 ABI parameter slots. // Store Arguments object on stack, below the 4 WIN64 ABI parameter slots.
__ movq(Operand(rsp, 4 * kPointerSize), r14); // argc. __ movq(StackSpaceOperand(0), r14); // argc.
__ movq(Operand(rsp, 5 * kPointerSize), r12); // argv. __ movq(StackSpaceOperand(1), r12); // argv.
if (result_size_ < 2) { if (result_size_ < 2) {
// Pass a pointer to the Arguments object as the first argument. // Pass a pointer to the Arguments object as the first argument.
// Return result in single register (rax). // Return result in single register (rax).
__ lea(rcx, Operand(rsp, 4 * kPointerSize)); __ lea(rcx, StackSpaceOperand(0));
} else { } else {
ASSERT_EQ(2, result_size_); ASSERT_EQ(2, result_size_);
// Pass a pointer to the result location as the first argument. // Pass a pointer to the result location as the first argument.
__ lea(rcx, Operand(rsp, 6 * kPointerSize)); __ lea(rcx, StackSpaceOperand(2));
// Pass a pointer to the Arguments object as the second argument. // Pass a pointer to the Arguments object as the second argument.
__ lea(rdx, Operand(rsp, 4 * kPointerSize)); __ lea(rdx, StackSpaceOperand(0));
} }
#else // _WIN64 #else // _WIN64
...@@ -2686,7 +2686,12 @@ void CEntryStub::Generate(MacroAssembler* masm) { ...@@ -2686,7 +2686,12 @@ void CEntryStub::Generate(MacroAssembler* masm) {
// builtin once. // builtin once.
// Enter the exit frame that transitions from JavaScript to C++. // Enter the exit frame that transitions from JavaScript to C++.
__ EnterExitFrame(result_size_); #ifdef _WIN64
int arg_stack_space = (result_size_ < 2 ? 2 : 4);
#else
int arg_stack_space = 0;
#endif
__ EnterExitFrame(arg_stack_space);
// rax: Holds the context at this point, but should not be used. // rax: Holds the context at this point, but should not be used.
// On entry to code generated by GenerateCore, it must hold // On entry to code generated by GenerateCore, it must hold
......
...@@ -498,18 +498,17 @@ static int Offset(ExternalReference ref0, ExternalReference ref1) { ...@@ -498,18 +498,17 @@ static int Offset(ExternalReference ref0, ExternalReference ref1) {
} }
void MacroAssembler::PrepareCallApiFunction(int stack_space, int argc) { void MacroAssembler::PrepareCallApiFunction(int stack_space,
int arg_stack_space) {
#ifdef _WIN64 #ifdef _WIN64
// We need to prepare a slot for result handle on stack and put // We need to prepare a slot for result handle on stack and put
// a pointer to it into 1st arg register. // a pointer to it into 1st arg register.
int register_based_args = argc > 3 ? 3 : argc; EnterApiExitFrame(stack_space, arg_stack_space + 1);
EnterApiExitFrame(stack_space, argc - register_based_args + 1);
int return_value_slot = (argc > 3 ? argc - 3 + 1 : 4);
// rcx must be used to pass the pointer to the return value slot. // rcx must be used to pass the pointer to the return value slot.
lea(rcx, Operand(rsp, return_value_slot * kPointerSize)); lea(rcx, StackSpaceOperand(arg_stack_space));
#else #else
EnterApiExitFrame(stack_space, argc); EnterApiExitFrame(stack_space, arg_stack_space);
#endif #endif
} }
...@@ -1744,22 +1743,15 @@ void MacroAssembler::EnterExitFramePrologue(bool save_rax) { ...@@ -1744,22 +1743,15 @@ void MacroAssembler::EnterExitFramePrologue(bool save_rax) {
store_rax(context_address); store_rax(context_address);
} }
void MacroAssembler::EnterExitFrameEpilogue(int result_size,
int argc) { void MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space) {
#ifdef _WIN64 #ifdef _WIN64
// Reserve space on stack for result and argument structures, if necessary. const int kShaddowSpace = 4;
int result_stack_space = (result_size < 2) ? 0 : result_size * kPointerSize; arg_stack_space += kShaddowSpace;
// Reserve space for the Arguments object. The Windows 64-bit ABI
// requires us to pass this structure as a pointer to its location on
// the stack. The structure contains 2 values.
int argument_stack_space = argc * kPointerSize;
// We also need backing space for 4 parameters, even though
// we only pass one or two parameter, and it is in a register.
int argument_mirror_space = 4 * kPointerSize;
int total_stack_space =
argument_mirror_space + argument_stack_space + result_stack_space;
subq(rsp, Immediate(total_stack_space));
#endif #endif
if (arg_stack_space > 0) {
subq(rsp, Immediate(arg_stack_space * kPointerSize));
}
// Get the required frame alignment for the OS. // Get the required frame alignment for the OS.
static const int kFrameAlignment = OS::ActivationFrameAlignment(); static const int kFrameAlignment = OS::ActivationFrameAlignment();
...@@ -1774,7 +1766,7 @@ void MacroAssembler::EnterExitFrameEpilogue(int result_size, ...@@ -1774,7 +1766,7 @@ void MacroAssembler::EnterExitFrameEpilogue(int result_size,
} }
void MacroAssembler::EnterExitFrame(int result_size) { void MacroAssembler::EnterExitFrame(int arg_stack_space) {
EnterExitFramePrologue(true); EnterExitFramePrologue(true);
// Setup argv in callee-saved register r12. It is reused in LeaveExitFrame, // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame,
...@@ -1782,13 +1774,12 @@ void MacroAssembler::EnterExitFrame(int result_size) { ...@@ -1782,13 +1774,12 @@ void MacroAssembler::EnterExitFrame(int result_size) {
int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
lea(r12, Operand(rbp, r14, times_pointer_size, offset)); lea(r12, Operand(rbp, r14, times_pointer_size, offset));
EnterExitFrameEpilogue(result_size, 2); EnterExitFrameEpilogue(arg_stack_space);
} }
void MacroAssembler::EnterApiExitFrame(int stack_space, void MacroAssembler::EnterApiExitFrame(int stack_space,
int argc, int arg_stack_space) {
int result_size) {
EnterExitFramePrologue(false); EnterExitFramePrologue(false);
// Setup argv in callee-saved register r12. It is reused in LeaveExitFrame, // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame,
...@@ -1796,11 +1787,7 @@ void MacroAssembler::EnterApiExitFrame(int stack_space, ...@@ -1796,11 +1787,7 @@ void MacroAssembler::EnterApiExitFrame(int stack_space,
int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
lea(r12, Operand(rbp, (stack_space * kPointerSize) + offset)); lea(r12, Operand(rbp, (stack_space * kPointerSize) + offset));
#ifndef _WIN64 EnterExitFrameEpilogue(arg_stack_space);
ASSERT(argc <= 6); // EnterApiExitFrame supports only register based args.
#endif
EnterExitFrameEpilogue(result_size, argc);
} }
......
...@@ -155,11 +155,13 @@ class MacroAssembler: public Assembler { ...@@ -155,11 +155,13 @@ class MacroAssembler: public Assembler {
// debug mode. Expects the number of arguments in register rax and // debug mode. Expects the number of arguments in register rax and
// sets up the number of arguments in register rdi and the pointer // sets up the number of arguments in register rdi and the pointer
// to the first argument in register rsi. // to the first argument in register rsi.
void EnterExitFrame(int result_size = 1); //
// Allocates arg_stack_space * kPointerSize memory (not GCed) on the stack
// accessible via StackSpaceOperand.
void EnterExitFrame(int arg_stack_space = 0);
void EnterApiExitFrame(int stack_space, void EnterApiExitFrame(int stack_space,
int argc, int arg_stack_space);
int result_size = 1);
// Leave the current exit frame. Expects/provides the return value in // Leave the current exit frame. Expects/provides the return value in
// register rax:rdx (untouched) and the pointer to the first // register rax:rdx (untouched) and the pointer to the first
...@@ -838,7 +840,12 @@ class MacroAssembler: public Assembler { ...@@ -838,7 +840,12 @@ class MacroAssembler: public Assembler {
// (rcx must be preserverd until TryCallApiFunctionAndReturn). argc is number // (rcx must be preserverd until TryCallApiFunctionAndReturn). argc is number
// of arguments to be passed in C-function. stack_space * kPointerSize bytes // of arguments to be passed in C-function. stack_space * kPointerSize bytes
// will be removed from stack after the call. Saves context (rsi). // will be removed from stack after the call. Saves context (rsi).
void PrepareCallApiFunction(int stack_space, int argc); // Clobbers rax. Allocates arg_stack_space * kPointerSize inside the exit
// frame (not GCed).
//
// Assumes stack_space GCed references on top of the stack and return address.
// After call they will be removed.
void PrepareCallApiFunction(int stack_space, int arg_stack_space);
// Calls an API function. Allocates HandleScope, extracts // Calls an API function. Allocates HandleScope, extracts
// returned value from handle and propagates exceptions. // returned value from handle and propagates exceptions.
...@@ -935,7 +942,10 @@ class MacroAssembler: public Assembler { ...@@ -935,7 +942,10 @@ class MacroAssembler: public Assembler {
void LeaveFrame(StackFrame::Type type); void LeaveFrame(StackFrame::Type type);
void EnterExitFramePrologue(bool save_rax); void EnterExitFramePrologue(bool save_rax);
void EnterExitFrameEpilogue(int result_size, int argc);
// Allocates arg_stack_space * kPointerSize memory (not GCed) on the stack
// accessible via StackSpaceOperand.
void EnterExitFrameEpilogue(int arg_stack_space);
// Allocation support helpers. // Allocation support helpers.
// Loads the top of new-space into the result register. // Loads the top of new-space into the result register.
...@@ -1008,6 +1018,17 @@ static inline Operand GlobalObjectOperand() { ...@@ -1008,6 +1018,17 @@ static inline Operand GlobalObjectOperand() {
} }
// Provides access to exit frame stack space (not GCed).
static inline Operand StackSpaceOperand(int index) {
#ifdef _WIN64
const int kShaddowSpace = 4;
return Operand(rsp, (index + kShaddowSpace) * kPointerSize);
#else
return Operand(rsp, index * kPointerSize);
#endif
}
#ifdef GENERATED_CODE_COVERAGE #ifdef GENERATED_CODE_COVERAGE
extern void LogGeneratedCodeCoverage(const char* file_line); extern void LogGeneratedCodeCoverage(const char* file_line);
......
This diff is collapsed.
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