Revision: 4428
Author: [email protected]
Date: Thu Apr 15 05:41:30 2010
Log: Add stack alignment check to ia32 and x64

The stack is now checked for proper alignment before calling into C code when the flag --debug-code is turned on.
Review URL: http://codereview.chromium.org/1637015
http://code.google.com/p/v8/source/detail?r=4428

Modified:
 /branches/bleeding_edge/src/ia32/codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc
 /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h
 /branches/bleeding_edge/src/platform-linux.cc
 /branches/bleeding_edge/src/x64/codegen-x64.cc
 /branches/bleeding_edge/src/x64/macro-assembler-x64.cc
 /branches/bleeding_edge/src/x64/macro-assembler-x64.h

=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Thu Apr 15 02:34:47 2010 +++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Thu Apr 15 05:41:30 2010
@@ -11739,8 +11739,18 @@
   // esi: pointer to the first argument (C callee-saved)

   // Result returned in eax, or eax+edx if result_size_ is 2.
+
+  // Check stack alignment.
+  if (FLAG_debug_code) {
+    __ CheckStackAlignment();
+  }

   if (do_gc) {
+    // Pass failure code returned from last attempt as first argument to
+ // PerformGC. No need to use PrepareCallCFunction/CallCFunction here as the + // stack alignment is known to be correct. This function takes one argument
+    // which is passed on the stack, and we know that the stack has been
+    // prepared to pass at least one argument.
     __ mov(Operand(esp, 0 * kPointerSize), eax);  // Result.
     __ call(FUNCTION_ADDR(Runtime::PerformGC), RelocInfo::RUNTIME_ENTRY);
   }
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Wed Apr 14 13:16:19 2010 +++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Thu Apr 15 05:41:30 2010
@@ -1533,6 +1533,21 @@
   // will not return here
   bind(&L);
 }
+
+
+void MacroAssembler::CheckStackAlignment() {
+  int frame_alignment = OS::ActivationFrameAlignment();
+  int frame_alignment_mask = frame_alignment - 1;
+  if (frame_alignment > kPointerSize) {
+    ASSERT(IsPowerOf2(frame_alignment));
+    Label alignment_as_expected;
+    test(esp, Immediate(frame_alignment_mask));
+    j(zero, &alignment_as_expected);
+    // Abort if stack is not aligned.
+    int3();
+    bind(&alignment_as_expected);
+  }
+}


 void MacroAssembler::Abort(const char* msg) {
@@ -1634,6 +1649,11 @@

 void MacroAssembler::CallCFunction(Register function,
                                    int num_arguments) {
+  // Check stack alignment.
+  if (FLAG_debug_code) {
+    CheckStackAlignment();
+  }
+
   call(Operand(function));
   if (OS::ActivationFrameAlignment() != 0) {
     mov(esp, Operand(esp, num_arguments * kPointerSize));
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Fri Mar 19 05:01:17 2010 +++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Thu Apr 15 05:41:30 2010
@@ -463,6 +463,9 @@
   // Print a message to stdout and abort execution.
   void Abort(const char* msg);

+  // Check that the stack is aligned.
+  void CheckStackAlignment();
+
   // Verify restrictions about code generated in stubs.
   void set_generating_stub(bool value) { generating_stub_ = value; }
   bool generating_stub() { return generating_stub_; }
=======================================
--- /branches/bleeding_edge/src/platform-linux.cc       Wed Apr 14 11:48:05 2010
+++ /branches/bleeding_edge/src/platform-linux.cc       Thu Apr 15 05:41:30 2010
@@ -159,7 +159,7 @@
 #elif V8_TARGET_ARCH_MIPS
   return 8;
 #endif
-  // With gcc 4.4 the tree vectorization optimiser can generate code
+  // With gcc 4.4 the tree vectorization optimizer can generate code
   // that requires 16 byte alignment such as movdqa on x86.
   return 16;
 }
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc      Thu Apr 15 02:34:47 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc      Thu Apr 15 05:41:30 2010
@@ -8248,9 +8248,17 @@
// Simple results returned in rax (both AMD64 and Win64 calling conventions).
   // Complex results must be written to address passed as first argument.
   // AMD64 calling convention: a struct of two pointers in rax+rdx
+
+  // Check stack alignment.
+  if (FLAG_debug_code) {
+    __ CheckStackAlignment();
+  }

   if (do_gc) {
- // Pass failure code returned from last attempt as first argument to GC.
+    // Pass failure code returned from last attempt as first argument to
+ // PerformGC. No need to use PrepareCallCFunction/CallCFunction here as the + // stack is known to be aligned. This function takes one argument which is
+    // passed in register.
 #ifdef _WIN64
     __ movq(rcx, rax);
 #else  // ! defined(_WIN64)
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Wed Apr 14 13:16:19 2010 +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Thu Apr 15 05:41:30 2010
@@ -289,6 +289,21 @@
   // will not return here
   bind(&L);
 }
+
+
+void MacroAssembler::CheckStackAlignment() {
+  int frame_alignment = OS::ActivationFrameAlignment();
+  int frame_alignment_mask = frame_alignment - 1;
+  if (frame_alignment > kPointerSize) {
+    ASSERT(IsPowerOf2(frame_alignment));
+    Label alignment_as_expected;
+    testq(rsp, Immediate(frame_alignment_mask));
+    j(zero, &alignment_as_expected);
+    // Abort if stack is not aligned.
+    int3();
+    bind(&alignment_as_expected);
+  }
+}


 void MacroAssembler::NegativeZeroTest(Register result,
@@ -2628,6 +2643,11 @@


 void MacroAssembler::CallCFunction(Register function, int num_arguments) {
+  // Check stack alignment.
+  if (FLAG_debug_code) {
+    CheckStackAlignment();
+  }
+
   call(function);
   ASSERT(OS::ActivationFrameAlignment() != 0);
   ASSERT(num_arguments >= 0);
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.h Tue Apr 13 04:59:37 2010 +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.h Thu Apr 15 05:41:30 2010
@@ -737,6 +737,9 @@
   // Print a message to stdout and abort execution.
   void Abort(const char* msg);

+  // Check that the stack is aligned.
+  void CheckStackAlignment();
+
   // Verify restrictions about code generated in stubs.
   void set_generating_stub(bool value) { generating_stub_ = value; }
   bool generating_stub() { return generating_stub_; }

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

To unsubscribe, reply using "remove me" as the subject.

Reply via email to