Reviewers: Søren Gjesse, Description: Fix fp problems in runtime code on ARM EABI by 8-byte aligning the stack on exit to C.
Please review this at http://codereview.chromium.org/115256 SVN Base: http://v8.googlecode.com/svn/branches/bleeding_edge/ Affected files: M src/arm/assembler-arm.h M src/arm/macro-assembler-arm.cc M src/platform-linux.cc Index: src/platform-linux.cc =================================================================== --- src/platform-linux.cc (revision 1918) +++ src/platform-linux.cc (working copy) @@ -88,6 +88,8 @@ int OS::ActivationFrameAlignment() { // Floating point code runs faster if the stack is 8-byte aligned. + // On EABI ARM targets this is required for fp correctness in the + // runtime system. return 8; } Index: src/arm/assembler-arm.h =================================================================== --- src/arm/assembler-arm.h (revision 1918) +++ src/arm/assembler-arm.h (working copy) @@ -622,8 +622,8 @@ // Pseudo instructions void nop() { mov(r0, Operand(r0)); } - void push(Register src) { - str(src, MemOperand(sp, 4, NegPreIndex), al); + void push(Register src, Condition cond = al) { + str(src, MemOperand(sp, 4, NegPreIndex), cond); } void pop(Register dst) { Index: src/arm/macro-assembler-arm.cc =================================================================== --- src/arm/macro-assembler-arm.cc (revision 1918) +++ src/arm/macro-assembler-arm.cc (working copy) @@ -291,6 +291,12 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type) { ASSERT(type == StackFrame::EXIT || type == StackFrame::EXIT_DEBUG); + + // Compute the argv pointer and keep it in a callee-saved register. + // r0 is argc. + add(r6, sp, Operand(r0, LSL, kPointerSizeLog2)); + sub(r6, r6, Operand(kPointerSize)); + // Compute parameter pointer before making changes and save it as ip // register so that it is restored as sp register on exit, thereby // popping the args. @@ -298,6 +304,17 @@ // ip = sp + kPointerSize * #args; add(ip, sp, Operand(r0, LSL, kPointerSizeLog2)); + // Align the stack at this point. After this point we have 5 pushes, + // so in fact we have to unalign here! See also the assert on the + // alignment immediately below. + if (OS::ActivationFrameAlignment() != kPointerSize) { + // This code needs to be made more general if this assert doesn't hold. + ASSERT(OS::ActivationFrameAlignment() == 2 * kPointerSize); + mov(r7, Operand(Smi::FromInt(0))); + tst(sp, Operand(OS::ActivationFrameAlignment() - 1)); + push(r7, eq); // Conditional push instruction. + } + // Push in reverse order: caller_fp, sp_on_exit, and caller_pc. stm(db_w, sp, fp.bit() | ip.bit() | lr.bit()); mov(fp, Operand(sp)); // setup new frame pointer @@ -316,9 +333,6 @@ mov(r4, Operand(r0)); mov(r5, Operand(r1)); - // Compute the argv pointer and keep it in a callee-saved register. - add(r6, fp, Operand(r4, LSL, kPointerSizeLog2)); - add(r6, r6, Operand(ExitFrameConstants::kPPDisplacement - kPointerSize)); #ifdef ENABLE_DEBUGGER_SUPPORT // Save the state of all registers to the stack from the memory --~--~---------~--~----~------------~-------~--~----~ v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev -~----------~----~----~----~------~----~------~--~---
