Commit 8be7fd05 authored by lrn@chromium.org's avatar lrn@chromium.org

X64: Call runtime function from JS stack frame.

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


git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2156 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d4cc50e1
...@@ -429,12 +429,14 @@ void CEntryStub::GenerateCore(MacroAssembler* masm, ...@@ -429,12 +429,14 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
StackFrame::Type frame_type, StackFrame::Type frame_type,
bool do_gc, bool do_gc,
bool always_allocate_scope) { bool always_allocate_scope) {
// rax: result parameter for PerformGC, if any // rax: result parameter for PerformGC, if any.
// rbx: pointer to C function (C callee-saved) // rbx: pointer to C function (C callee-saved).
// rbp: frame pointer (restored after C call) // rbp: frame pointer (restored after C call).
// rsp: stack pointer (restored after C call) // rsp: stack pointer (restored after C call).
// rdi: number of arguments including receiver (C callee-saved) // rdi: number of arguments including receiver.
// rsi: pointer to the first argument (C callee-saved) // r15: pointer to the first argument (C callee-saved).
// This pointer is reused in LeaveExitFrame(), so it is stored in a
// callee-saved register.
if (do_gc) { if (do_gc) {
__ movq(Operand(rsp, 0), rax); // Result. __ movq(Operand(rsp, 0), rax); // Result.
...@@ -455,10 +457,11 @@ void CEntryStub::GenerateCore(MacroAssembler* masm, ...@@ -455,10 +457,11 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
#ifdef __MSVC__ #ifdef __MSVC__
// MSVC passes arguments in rcx, rdx, r8, r9 // MSVC passes arguments in rcx, rdx, r8, r9
__ movq(rcx, rdi); // argc. __ movq(rcx, rdi); // argc.
__ movq(rdx, rsi); // argv. __ movq(rdx, r15); // argv.
#else // ! defined(__MSVC__) #else // ! defined(__MSVC__)
// GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9. // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9.
// First two arguments are already in rdi, rsi. // First argument is already in rdi.
__ movq(rsi, r15); // argv.
#endif #endif
__ call(rbx); __ call(rbx);
// Result is in rax - do not destroy this register! // Result is in rax - do not destroy this register!
...@@ -588,12 +591,17 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) { ...@@ -588,12 +591,17 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
// Enter the exit frame that transitions from JavaScript to C++. // Enter the exit frame that transitions from JavaScript to C++.
__ EnterExitFrame(frame_type); __ EnterExitFrame(frame_type);
// rax: result parameter for PerformGC, if any (setup below) // rax: result parameter for PerformGC, if any (setup below).
// rbx: pointer to builtin function (C callee-saved) // Holds the result of a previous call to GenerateCore that
// rbp: frame pointer (restored after C call) // returned a failure. On next call, it's used as parameter
// rsp: stack pointer (restored after C call) // to Runtime::PerformGC.
// rdi: number of arguments including receiver (C callee-saved) // rbx: pointer to builtin function (C callee-saved).
// rsi: argv pointer (C callee-saved) // rbp: frame pointer (restored after C call).
// rsp: stack pointer (restored after C call).
// rdi: number of arguments including receiver (destroyed by C call).
// The rdi register is not callee-save in Unix 64-bit ABI, so
// we must treat it as volatile.
// r15: argv pointer (C callee-saved).
Label throw_out_of_memory_exception; Label throw_out_of_memory_exception;
Label throw_normal_exception; Label throw_normal_exception;
...@@ -604,7 +612,8 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) { ...@@ -604,7 +612,8 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
Failure* failure = Failure::RetryAfterGC(0); Failure* failure = Failure::RetryAfterGC(0);
__ movq(rax, failure, RelocInfo::NONE); __ movq(rax, failure, RelocInfo::NONE);
} }
GenerateCore(masm, &throw_normal_exception, GenerateCore(masm,
&throw_normal_exception,
&throw_out_of_memory_exception, &throw_out_of_memory_exception,
frame_type, frame_type,
FLAG_gc_greedy, FLAG_gc_greedy,
......
...@@ -84,22 +84,22 @@ class ExitFrameConstants : public AllStatic { ...@@ -84,22 +84,22 @@ class ExitFrameConstants : public AllStatic {
class StandardFrameConstants : public AllStatic { class StandardFrameConstants : public AllStatic {
public: public:
static const int kExpressionsOffset = -1 * kPointerSize; static const int kExpressionsOffset = -3 * kPointerSize;
static const int kMarkerOffset = -1 * kPointerSize; static const int kMarkerOffset = -2 * kPointerSize;
static const int kContextOffset = -1 * kPointerSize; static const int kContextOffset = -1 * kPointerSize;
static const int kCallerFPOffset = -1 * kPointerSize; static const int kCallerFPOffset = 0 * kPointerSize;
static const int kCallerPCOffset = -1 * kPointerSize; static const int kCallerPCOffset = +1 * kPointerSize;
static const int kCallerSPOffset = -1 * kPointerSize; static const int kCallerSPOffset = +2 * kPointerSize;
}; };
class JavaScriptFrameConstants : public AllStatic { class JavaScriptFrameConstants : public AllStatic {
public: public:
static const int kLocal0Offset = StandardFrameConstants::kExpressionsOffset; static const int kLocal0Offset = StandardFrameConstants::kExpressionsOffset;
static const int kSavedRegistersOffset = -1 * kPointerSize; static const int kSavedRegistersOffset = +2 * kPointerSize;
static const int kFunctionOffset = StandardFrameConstants::kMarkerOffset; static const int kFunctionOffset = StandardFrameConstants::kMarkerOffset;
static const int kParam0Offset = -1 * kPointerSize; static const int kParam0Offset = -2 * kPointerSize;
static const int kReceiverOffset = -1 * kPointerSize; static const int kReceiverOffset = -1 * kPointerSize;
}; };
......
...@@ -65,10 +65,16 @@ void MacroAssembler::ConstructAndTestJSFunction() { ...@@ -65,10 +65,16 @@ void MacroAssembler::ConstructAndTestJSFunction() {
MacroAssembler masm(buffer, initial_buffer_size); MacroAssembler masm(buffer, initial_buffer_size);
const uint64_t secret = V8_INT64_C(0xdeadbeefcafebabe); const uint64_t secret = V8_INT64_C(0xdeadbeefcafebabe);
Handle<String> constant =
Factory::NewStringFromAscii(Vector<const char>("451", 3), TENURED);
#define __ ACCESS_MASM((&masm)) #define __ ACCESS_MASM((&masm))
// Construct a simple JSfunction here, using Assembler and MacroAssembler // Construct a simple JSfunction here, using Assembler and MacroAssembler
// commands. // commands.
__ movq(rax, secret, RelocInfo::NONE); __ movq(rax, constant, RelocInfo::EMBEDDED_OBJECT);
__ push(rax);
__ CallRuntime(Runtime::kStringParseFloat, 1);
__ movq(kScratchRegister, secret, RelocInfo::NONE);
__ addq(rax, kScratchRegister);
__ ret(0); __ ret(0);
#undef __ #undef __
CodeDesc desc; CodeDesc desc;
...@@ -93,7 +99,7 @@ void MacroAssembler::ConstructAndTestJSFunction() { ...@@ -93,7 +99,7 @@ void MacroAssembler::ConstructAndTestJSFunction() {
NULL, NULL,
&pending_exceptions); &pending_exceptions);
CHECK(result->IsSmi()); CHECK(result->IsSmi());
CHECK(secret == reinterpret_cast<uint64_t>(*result)); CHECK(secret + (451 << kSmiTagSize) == reinterpret_cast<uint64_t>(*result));
} }
} }
...@@ -581,17 +587,17 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type) { ...@@ -581,17 +587,17 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
// Save the frame pointer and the context in top. // Save the frame pointer and the context in top.
ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
ExternalReference context_address(Top::k_context_address); ExternalReference context_address(Top::k_context_address);
movq(kScratchRegister, rax); movq(rdi, rax); // Backup rax before we use it.
movq(rax, rbp); movq(rax, rbp);
store_rax(c_entry_fp_address); store_rax(c_entry_fp_address);
movq(rax, rsi); movq(rax, rsi);
store_rax(context_address); store_rax(context_address);
movq(rax, kScratchRegister);
// Setup argc and argv in callee-saved registers. // Setup argv in callee-saved register r15. It is reused in LeaveExitFrame,
// so it must be retained across the C-call.
int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
movq(rdi, rax); lea(r15, Operand(rbp, rdi, kTimesPointerSize, offset));
lea(rsi, Operand(rbp, rax, kTimesPointerSize, offset));
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
// Save the state of all registers to the stack from the memory // Save the state of all registers to the stack from the memory
...@@ -607,15 +613,15 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type) { ...@@ -607,15 +613,15 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
} }
#endif #endif
// Reserve space for two arguments: argc and argv. // Reserve space for two arguments: argc and argv
subq(rsp, Immediate(2 * kPointerSize)); subq(rsp, Immediate(2 * 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();
if (kFrameAlignment > 0) { if (kFrameAlignment > 0) {
ASSERT(IsPowerOf2(kFrameAlignment)); ASSERT(IsPowerOf2(kFrameAlignment));
movq(r10, Immediate(-kFrameAlignment)); movq(kScratchRegister, Immediate(-kFrameAlignment));
and_(rsp, r10); and_(rsp, kScratchRegister);
} }
// Patch the saved entry sp. // Patch the saved entry sp.
...@@ -624,6 +630,8 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type) { ...@@ -624,6 +630,8 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
void MacroAssembler::LeaveExitFrame(StackFrame::Type type) { void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
// Registers:
// r15 : argv
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
// Restore the memory copy of the registers by digging them out from // Restore the memory copy of the registers by digging them out from
// the stack. This is needed to allow nested break points. // the stack. This is needed to allow nested break points.
...@@ -642,7 +650,7 @@ void MacroAssembler::LeaveExitFrame(StackFrame::Type type) { ...@@ -642,7 +650,7 @@ void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
movq(rbp, Operand(rbp, 0 * kPointerSize)); movq(rbp, Operand(rbp, 0 * kPointerSize));
// Pop the arguments and the receiver from the caller stack. // Pop the arguments and the receiver from the caller stack.
lea(rsp, Operand(rsi, 1 * kPointerSize)); lea(rsp, Operand(r15, 1 * kPointerSize));
// Restore current context from top and clear it in debug mode. // Restore current context from top and clear it in debug mode.
ExternalReference context_address(Top::k_context_address); ExternalReference context_address(Top::k_context_address);
......
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