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,
StackFrame::Type frame_type,
bool do_gc,
bool always_allocate_scope) {
// rax: result parameter for PerformGC, if any
// rbx: pointer to C function (C callee-saved)
// rbp: frame pointer (restored after C call)
// rsp: stack pointer (restored after C call)
// rdi: number of arguments including receiver (C callee-saved)
// rsi: pointer to the first argument (C callee-saved)
// rax: result parameter for PerformGC, if any.
// rbx: pointer to C function (C callee-saved).
// rbp: frame pointer (restored after C call).
// rsp: stack pointer (restored after C call).
// rdi: number of arguments including receiver.
// 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) {
__ movq(Operand(rsp, 0), rax); // Result.
......@@ -455,10 +457,11 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
#ifdef __MSVC__
// MSVC passes arguments in rcx, rdx, r8, r9
__ movq(rcx, rdi); // argc.
__ movq(rdx, rsi); // argv.
__ movq(rdx, r15); // argv.
#else // ! defined(__MSVC__)
// 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
__ call(rbx);
// Result is in rax - do not destroy this register!
......@@ -588,12 +591,17 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
// Enter the exit frame that transitions from JavaScript to C++.
__ EnterExitFrame(frame_type);
// rax: result parameter for PerformGC, if any (setup below)
// rbx: pointer to builtin function (C callee-saved)
// rbp: frame pointer (restored after C call)
// rsp: stack pointer (restored after C call)
// rdi: number of arguments including receiver (C callee-saved)
// rsi: argv pointer (C callee-saved)
// rax: result parameter for PerformGC, if any (setup below).
// Holds the result of a previous call to GenerateCore that
// returned a failure. On next call, it's used as parameter
// to Runtime::PerformGC.
// rbx: pointer to builtin function (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_normal_exception;
......@@ -604,7 +612,8 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
Failure* failure = Failure::RetryAfterGC(0);
__ movq(rax, failure, RelocInfo::NONE);
}
GenerateCore(masm, &throw_normal_exception,
GenerateCore(masm,
&throw_normal_exception,
&throw_out_of_memory_exception,
frame_type,
FLAG_gc_greedy,
......
......@@ -84,22 +84,22 @@ class ExitFrameConstants : public AllStatic {
class StandardFrameConstants : public AllStatic {
public:
static const int kExpressionsOffset = -1 * kPointerSize;
static const int kMarkerOffset = -1 * kPointerSize;
static const int kExpressionsOffset = -3 * kPointerSize;
static const int kMarkerOffset = -2 * kPointerSize;
static const int kContextOffset = -1 * kPointerSize;
static const int kCallerFPOffset = -1 * kPointerSize;
static const int kCallerPCOffset = -1 * kPointerSize;
static const int kCallerSPOffset = -1 * kPointerSize;
static const int kCallerFPOffset = 0 * kPointerSize;
static const int kCallerPCOffset = +1 * kPointerSize;
static const int kCallerSPOffset = +2 * kPointerSize;
};
class JavaScriptFrameConstants : public AllStatic {
public:
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 kParam0Offset = -1 * kPointerSize;
static const int kParam0Offset = -2 * kPointerSize;
static const int kReceiverOffset = -1 * kPointerSize;
};
......
......@@ -65,10 +65,16 @@ void MacroAssembler::ConstructAndTestJSFunction() {
MacroAssembler masm(buffer, initial_buffer_size);
const uint64_t secret = V8_INT64_C(0xdeadbeefcafebabe);
Handle<String> constant =
Factory::NewStringFromAscii(Vector<const char>("451", 3), TENURED);
#define __ ACCESS_MASM((&masm))
// Construct a simple JSfunction here, using Assembler and MacroAssembler
// 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);
#undef __
CodeDesc desc;
......@@ -93,7 +99,7 @@ void MacroAssembler::ConstructAndTestJSFunction() {
NULL,
&pending_exceptions);
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) {
// Save the frame pointer and the context in top.
ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
ExternalReference context_address(Top::k_context_address);
movq(kScratchRegister, rax);
movq(rdi, rax); // Backup rax before we use it.
movq(rax, rbp);
store_rax(c_entry_fp_address);
movq(rax, rsi);
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;
movq(rdi, rax);
lea(rsi, Operand(rbp, rax, kTimesPointerSize, offset));
lea(r15, Operand(rbp, rdi, kTimesPointerSize, offset));
#ifdef ENABLE_DEBUGGER_SUPPORT
// Save the state of all registers to the stack from the memory
......@@ -607,15 +613,15 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
}
#endif
// Reserve space for two arguments: argc and argv.
// Reserve space for two arguments: argc and argv
subq(rsp, Immediate(2 * kPointerSize));
// Get the required frame alignment for the OS.
static const int kFrameAlignment = OS::ActivationFrameAlignment();
if (kFrameAlignment > 0) {
ASSERT(IsPowerOf2(kFrameAlignment));
movq(r10, Immediate(-kFrameAlignment));
and_(rsp, r10);
movq(kScratchRegister, Immediate(-kFrameAlignment));
and_(rsp, kScratchRegister);
}
// Patch the saved entry sp.
......@@ -624,6 +630,8 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
// Registers:
// r15 : argv
#ifdef ENABLE_DEBUGGER_SUPPORT
// Restore the memory copy of the registers by digging them out from
// the stack. This is needed to allow nested break points.
......@@ -642,7 +650,7 @@ void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
movq(rbp, Operand(rbp, 0 * kPointerSize));
// 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.
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