Modified:
branches/bleeding_edge/src/x64/codegen-x64.cc
branches/bleeding_edge/src/x64/frames-x64.h
branches/bleeding_edge/src/x64/macro-assembler-x64.cc
Log:
X64: Call runtime function from JS stack frame.
Review URL: http://codereview.chromium.org/125049
Modified: branches/bleeding_edge/src/x64/codegen-x64.cc
==============================================================================
--- branches/bleeding_edge/src/x64/codegen-x64.cc (original)
+++ branches/bleeding_edge/src/x64/codegen-x64.cc Fri Jun 12 06:14:35 2009
@@ -429,12 +429,14 @@
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 @@
#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 @@
// 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 @@
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,
Modified: branches/bleeding_edge/src/x64/frames-x64.h
==============================================================================
--- branches/bleeding_edge/src/x64/frames-x64.h (original)
+++ branches/bleeding_edge/src/x64/frames-x64.h Fri Jun 12 06:14:35 2009
@@ -84,22 +84,22 @@
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;
};
Modified: branches/bleeding_edge/src/x64/macro-assembler-x64.cc
==============================================================================
--- branches/bleeding_edge/src/x64/macro-assembler-x64.cc (original)
+++ branches/bleeding_edge/src/x64/macro-assembler-x64.cc Fri Jun 12
06:14:35 2009
@@ -65,10 +65,16 @@
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 @@
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 @@
// 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 @@
}
#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::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 @@
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);