Fix stack logic when removing bailout frames (bug 677871, r=sstangl).
authorDavid Anderson <danderson@mozilla.com>
Wed, 10 Aug 2011 15:27:11 -0700
changeset 75076 97ac85295f203175562783cb0e12abfe0a38802d
parent 75075 0fb0af47c876e4133a7547d11c968fd8acae477f
child 75077 28a71ebcf6c56255a62e18926af1eea4c5a13762
push id123
push userdanderson@mozilla.com
push dateWed, 10 Aug 2011 22:34:41 +0000
reviewerssstangl
bugs677871
milestone8.0a1
Fix stack logic when removing bailout frames (bug 677871, r=sstangl).
js/src/ion/x64/Trampoline-x64.cpp
js/src/ion/x86/Trampoline-x86.cpp
js/src/jit-test/tests/ion/bug677871.js
--- a/js/src/ion/x64/Trampoline-x64.cpp
+++ b/js/src/ion/x64/Trampoline-x64.cpp
@@ -207,25 +207,26 @@ GenerateBailoutThunk(MacroAssembler &mas
     // Get the stack pointer into a register, pre-alignment.
     masm.movq(rsp, r8);
 
     // Call the bailout function.
     masm.setupUnalignedABICall(1, rax);
     masm.setABIArg(0, r8);
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, Bailout));
 
-    // Remove the common bailout frame.
+    // Stack is:
+    //     [frame]
+    //     snapshotOffset
+    //     frameSize
+    //     [bailoutFrame]
     uint32 bailoutFrameSize = sizeof(void *) * Registers::Total +
-                              sizeof(double) * FloatRegisters::Total +
-                              sizeof(void *); // bailout id;
+                              sizeof(double) * FloatRegisters::Total;
     masm.addq(Imm32(bailoutFrameSize), rsp);
-
-    // Remove the Ion frame.
     masm.pop(rcx);
-    masm.addq(rcx, rsp);
+    masm.lea(Operand(rsp, rcx, TimesOne, sizeof(void *)), rsp);
 
     Label exception;
 
     // Either interpret or handle an exception.
     masm.testl(rax, rax);
     masm.j(Assembler::NonZero, &exception);
 
     // If we're about to interpret, we've removed the depth of the local ion
--- a/js/src/ion/x86/Trampoline-x86.cpp
+++ b/js/src/ion/x86/Trampoline-x86.cpp
@@ -215,30 +215,37 @@ GenerateBailoutThunk(MacroAssembler &mas
     // Get the stack pointer into a register, pre-alignment.
     masm.movl(esp, eax);
 
     // Call the bailout function.
     masm.setupUnalignedABICall(1, ecx);
     masm.setABIArg(0, eax);
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, Bailout));
 
-    // Remove the common bailout frame.
-    uint32 bailoutFrameSize = sizeof(void *) * Registers::Total +
+    // Common size of a bailout frame.
+    uint32 bailoutFrameSize = sizeof(void *) + // frameClass
                               sizeof(double) * FloatRegisters::Total +
-                              sizeof(void *) + // frameClass
-                              sizeof(void *);  // bailout id
-    masm.addl(Imm32(bailoutFrameSize), esp);
-
+                              sizeof(void *) * Registers::Total;
     // Remove the Ion frame.
     if (frameClass == NO_FRAME_SIZE_CLASS_ID) {
+        // Stack is:
+        //    ... frame ...
+        //    snapshotOffset
+        //    frameSize
+        //    ... bailoutFrame ...
+        masm.addl(Imm32(bailoutFrameSize), esp);
         masm.pop(ecx);
-        masm.addl(ecx, esp);
+        masm.lea(Operand(esp, ecx, TimesOne, sizeof(void *)), esp);
     } else {
+        // Stack is:
+        //    ... frame ...
+        //    bailoutId
+        //    ... bailoutFrame ...
         uint32 frameSize = FrameSizeClass::FromClass(frameClass).frameSize();
-        masm.addl(Imm32(frameSize), esp);
+        masm.addl(Imm32(bailoutFrameSize + sizeof(void *) + frameSize), esp);
     }
 
     Label exception;
 
     // Either interpret or handle an exception.
     masm.testl(eax, eax);
     masm.j(Assembler::NonZero, &exception);
 
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug677871.js
@@ -0,0 +1,18 @@
+function f0(p0,p1,p2,p3,p4,p5,p6) {
+    var v0;
+    var v1;
+    if (v1) {
+        do {
+            v0 = v0 + p3;
+            v1 = p3 + p3 + v1 + v0;
+            if (v1) {
+                v0 = v0 + p1 + p4 + p2 + p0 + v1;
+                continue;
+            }
+            break;
+        } while (v0);
+    }
+    v0 + v1;
+}
+assertEq(f0(1,2,3,4,5,6), undefined);
+