| Index: src/arm/macro-assembler-arm.cc
|
| ===================================================================
|
| --- src/arm/macro-assembler-arm.cc (revision 6446)
|
| +++ src/arm/macro-assembler-arm.cc (working copy)
|
| @@ -1,4 +1,4 @@
|
| -// Copyright 2010 the V8 project authors. All rights reserved.
|
| +// Copyright 2011 the V8 project authors. All rights reserved.
|
| // Redistribution and use in source and binary forms, with or without
|
| // modification, are permitted provided that the following conditions are
|
| // met:
|
| @@ -615,37 +615,24 @@
|
|
|
|
|
| void MacroAssembler::EnterExitFrame(bool save_doubles) {
|
| - // r0 is argc.
|
| - // Compute callee's stack pointer before making changes and save it as
|
| - // ip register so that it is restored as sp register on exit, thereby
|
| - // popping the args.
|
| + // Compute the argv pointer in a callee-saved register.
|
| + add(r6, sp, Operand(r0, LSL, kPointerSizeLog2));
|
| + sub(r6, r6, Operand(kPointerSize));
|
|
|
| - // ip = sp + kPointerSize * #args;
|
| - add(ip, sp, Operand(r0, LSL, kPointerSizeLog2));
|
| -
|
| - // Compute the argv pointer and keep it in a callee-saved register.
|
| - sub(r6, ip, Operand(kPointerSize));
|
| -
|
| - // Prepare the stack to be aligned when calling into C. After this point there
|
| - // are 5 pushes before the call into C, so the stack needs to be aligned after
|
| - // 5 pushes.
|
| - int frame_alignment = ActivationFrameAlignment();
|
| - int frame_alignment_mask = frame_alignment - 1;
|
| - if (frame_alignment != kPointerSize) {
|
| - // The following code needs to be more general if this assert does not hold.
|
| - ASSERT(frame_alignment == 2 * kPointerSize);
|
| - // With 5 pushes left the frame must be unaligned at this point.
|
| - mov(r7, Operand(Smi::FromInt(0)));
|
| - tst(sp, Operand((frame_alignment - kPointerSize) & frame_alignment_mask));
|
| - push(r7, eq); // Push if aligned to make it unaligned.
|
| - }
|
| -
|
| - // Push in reverse order: caller_fp, sp_on_exit, and caller_pc.
|
| - stm(db_w, sp, fp.bit() | ip.bit() | lr.bit());
|
| + // Setup the frame structure on the stack.
|
| + ASSERT_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement);
|
| + ASSERT_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset);
|
| + ASSERT_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset);
|
| + Push(lr, fp);
|
| mov(fp, Operand(sp)); // Setup new frame pointer.
|
| -
|
| + // Reserve room for saved entry sp and code object.
|
| + sub(sp, sp, Operand(2 * kPointerSize));
|
| + if (FLAG_debug_code) {
|
| + mov(ip, Operand(0));
|
| + str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset));
|
| + }
|
| mov(ip, Operand(CodeObject()));
|
| - push(ip); // Accessed from ExitFrame::code_slot.
|
| + str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset));
|
|
|
| // Save the frame pointer and the context in top.
|
| mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address)));
|
| @@ -659,25 +646,30 @@
|
|
|
| // Optionally save all double registers.
|
| if (save_doubles) {
|
| - // TODO(regis): Use vstrm instruction.
|
| - // The stack alignment code above made sp unaligned, so add space for one
|
| - // more double register and use aligned addresses.
|
| - ASSERT(kDoubleSize == frame_alignment);
|
| - // Mark the frame as containing doubles by pushing a non-valid return
|
| - // address, i.e. 0.
|
| - ASSERT(ExitFrameConstants::kMarkerOffset == -2 * kPointerSize);
|
| - mov(ip, Operand(0)); // Marker and alignment word.
|
| - push(ip);
|
| - int space = DwVfpRegister::kNumRegisters * kDoubleSize + kPointerSize;
|
| - sub(sp, sp, Operand(space));
|
| + sub(sp, sp, Operand(DwVfpRegister::kNumRegisters * kDoubleSize));
|
| + const int offset = -2 * kPointerSize;
|
| for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) {
|
| DwVfpRegister reg = DwVfpRegister::from_code(i);
|
| - vstr(reg, sp, i * kDoubleSize + kPointerSize);
|
| + vstr(reg, fp, offset - ((i + 1) * kDoubleSize));
|
| }
|
| - // Note that d0 will be accessible at fp - 2*kPointerSize -
|
| - // DwVfpRegister::kNumRegisters * kDoubleSize, since the code slot and the
|
| - // alignment word were pushed after the fp.
|
| + // Note that d0 will be accessible at
|
| + // fp - 2 * kPointerSize - DwVfpRegister::kNumRegisters * kDoubleSize,
|
| + // since the sp slot and code slot were pushed after the fp.
|
| }
|
| +
|
| + // Reserve place for the return address and align the frame preparing for
|
| + // calling the runtime function.
|
| + const int frame_alignment = MacroAssembler::ActivationFrameAlignment();
|
| + sub(sp, sp, Operand(kPointerSize));
|
| + if (frame_alignment > 0) {
|
| + ASSERT(IsPowerOf2(frame_alignment));
|
| + and_(sp, sp, Operand(-frame_alignment));
|
| + }
|
| +
|
| + // Set the exit frame sp value to point just before the return address
|
| + // location.
|
| + add(ip, sp, Operand(kPointerSize));
|
| + str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset));
|
| }
|
|
|
|
|
| @@ -715,12 +707,10 @@
|
| void MacroAssembler::LeaveExitFrame(bool save_doubles) {
|
| // Optionally restore all double registers.
|
| if (save_doubles) {
|
| - // TODO(regis): Use vldrm instruction.
|
| for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) {
|
| DwVfpRegister reg = DwVfpRegister::from_code(i);
|
| - // Register d15 is just below the marker.
|
| - const int offset = ExitFrameConstants::kMarkerOffset;
|
| - vldr(reg, fp, (i - DwVfpRegister::kNumRegisters) * kDoubleSize + offset);
|
| + const int offset = -2 * kPointerSize;
|
| + vldr(reg, fp, offset - ((i + 1) * kDoubleSize));
|
| }
|
| }
|
|
|
| @@ -736,9 +726,12 @@
|
| str(r3, MemOperand(ip));
|
| #endif
|
|
|
| - // Pop the arguments, restore registers, and return.
|
| - mov(sp, Operand(fp)); // respect ABI stack constraint
|
| - ldm(ia, sp, fp.bit() | sp.bit() | pc.bit());
|
| + // Tear down the exit frame, pop the arguments, and return. Callee-saved
|
| + // register r4 still holds argc.
|
| + mov(sp, Operand(fp));
|
| + ldm(ia_w, sp, fp.bit() | lr.bit());
|
| + add(sp, sp, Operand(r4, LSL, kPointerSizeLog2));
|
| + mov(pc, lr);
|
| }
|
|
|
|
|
|
|