From 8be7fd052e434ea467e7476ecc792b51d9892805 Mon Sep 17 00:00:00 2001 From: "lrn@chromium.org" Date: Fri, 12 Jun 2009 13:14:35 +0000 Subject: [PATCH] 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 --- src/x64/codegen-x64.cc | 39 +++++++++++++++++++++------------- src/x64/frames-x64.h | 14 ++++++------ src/x64/macro-assembler-x64.cc | 30 ++++++++++++++++---------- 3 files changed, 50 insertions(+), 33 deletions(-) diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc index 0fe3e1192..71b7d5413 100644 --- a/src/x64/codegen-x64.cc +++ b/src/x64/codegen-x64.cc @@ -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, diff --git a/src/x64/frames-x64.h b/src/x64/frames-x64.h index 32793db84..31d8a2d9e 100644 --- a/src/x64/frames-x64.h +++ b/src/x64/frames-x64.h @@ -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; }; diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc index 67ea4ac5c..e60286a3e 100644 --- a/src/x64/macro-assembler-x64.cc +++ b/src/x64/macro-assembler-x64.cc @@ -65,10 +65,16 @@ void MacroAssembler::ConstructAndTestJSFunction() { MacroAssembler masm(buffer, initial_buffer_size); const uint64_t secret = V8_INT64_C(0xdeadbeefcafebabe); + Handle constant = + Factory::NewStringFromAscii(Vector("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(*result)); + CHECK(secret + (451 << kSmiTagSize) == reinterpret_cast(*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); -- 2.34.1