Index: src/arm/macro-assembler-arm.cc |
=================================================================== |
--- src/arm/macro-assembler-arm.cc (revision 4424) |
+++ src/arm/macro-assembler-arm.cc (working copy) |
@@ -355,10 +355,19 @@ |
// 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 in AlignStack. |
- AlignStack(1); |
+ // 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()); |
@@ -389,27 +398,20 @@ |
} |
-void MacroAssembler::AlignStack(int offset) { |
+int MacroAssembler::ActivationFrameAlignment() { |
#if defined(V8_HOST_ARCH_ARM) |
// Running on the real platform. Use the alignment as mandated by the local |
// environment. |
// Note: This will break if we ever start generating snapshots on one ARM |
// platform for another ARM platform with a different alignment. |
- int activation_frame_alignment = OS::ActivationFrameAlignment(); |
+ return OS::ActivationFrameAlignment(); |
#else // defined(V8_HOST_ARCH_ARM) |
// If we are using the simulator then we should always align to the expected |
// alignment. As the simulator is used to generate snapshots we do not know |
- // if the target platform will need alignment, so we will always align at |
- // this point here. |
- int activation_frame_alignment = 2 * kPointerSize; |
+ // if the target platform will need alignment, so this is controlled from a |
+ // flag. |
+ return FLAG_sim_stack_alignment; |
#endif // defined(V8_HOST_ARCH_ARM) |
- if (activation_frame_alignment != kPointerSize) { |
- // This code needs to be made more general if this assert doesn't hold. |
- ASSERT(activation_frame_alignment == 2 * kPointerSize); |
- mov(r7, Operand(Smi::FromInt(0))); |
- tst(sp, Operand(activation_frame_alignment - offset)); |
- push(r7, eq); // Conditional push instruction. |
- } |
} |
@@ -1572,16 +1574,16 @@ |
void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) { |
- int frameAlignment = OS::ActivationFrameAlignment(); |
+ int frame_alignment = ActivationFrameAlignment(); |
// Up to four simple arguments are passed in registers r0..r3. |
int stack_passed_arguments = (num_arguments <= 4) ? 0 : num_arguments - 4; |
- if (frameAlignment > kPointerSize) { |
+ if (frame_alignment > kPointerSize) { |
// Make stack end at alignment and make room for num_arguments - 4 words |
// and the original value of sp. |
mov(scratch, sp); |
sub(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize)); |
- ASSERT(IsPowerOf2(frameAlignment)); |
- and_(sp, sp, Operand(-frameAlignment)); |
+ ASSERT(IsPowerOf2(frame_alignment)); |
+ and_(sp, sp, Operand(-frame_alignment)); |
str(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize)); |
} else { |
sub(sp, sp, Operand(stack_passed_arguments * kPointerSize)); |
@@ -1597,6 +1599,26 @@ |
void MacroAssembler::CallCFunction(Register function, int num_arguments) { |
+ // Make sure that the stack is aligned before calling a C function unless |
+ // running in the simulator. The simulator has its own alignment check which |
+ // provides more information. |
+#if defined(V8_HOST_ARCH_ARM) |
+ if (FLAG_debug_code) { |
+ int frame_alignment = OS::ActivationFrameAlignment(); |
+ int frame_alignment_mask = frame_alignment - 1; |
+ if (frame_alignment > kPointerSize) { |
+ ASSERT(IsPowerOf2(frame_alignment)); |
+ Label alignment_as_expected; |
+ tst(sp, Operand(frame_alignment_mask)); |
+ b(eq, &alignment_as_expected); |
+ // Don't use Check here, as it will call Runtime_Abort possibly |
+ // re-entering here. |
+ stop("Unexpected alignment"); |
+ bind(&alignment_as_expected); |
+ } |
+ } |
+#endif |
+ |
// Just call directly. The function called cannot cause a GC, or |
// allow preemption, so the return address in the link register |
// stays correct. |