[masm] Prepare local stack frame for new upcoming exception handling
authorSimon Hausmann <simon.hausmann@digia.com>
Tue, 26 Feb 2013 11:58:16 +0000 (12:58 +0100)
committerLars Knoll <lars.knoll@digia.com>
Tue, 26 Feb 2013 22:46:17 +0000 (23:46 +0100)
Access local temps through a newly allocated LocalsRegister instead of the
regular frame pointer register. In the new exception handling we're going to
re-enter our function in the middle and want to access the same local temps,
but we can't do that through the stack frame pointer then, because that one
will _have_ to continue to point to the local stack frame in order for
unwinding to work properly.

Also the callee saved registers are now stored right below the stack
frame pointer instead of at the bottom of the stack. This way they
can be described easily in the unwind info as always relative to the
canonical frame address.

Change-Id: I53ef6291d99396577a72ceb9246f7ca3d99e5137
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
src/v4/qv4isel_masm.cpp
src/v4/qv4isel_masm_p.h

index 2160b40..6b687a6 100644 (file)
@@ -65,8 +65,9 @@ using namespace QQmlJS::VM;
 static const Assembler::RegisterID calleeSavedRegisters[] = {
     // Not used: JSC::X86Registers::rbx,
     // Not used: JSC::X86Registers::r10,
+    JSC::X86Registers::r12, // LocalsRegister
     // Not used: JSC::X86Registers::r13,
-    JSC::X86Registers::r14
+    JSC::X86Registers::r14 // ContextRegister
     // Not used: JSC::X86Registers::r15,
 };
 #endif
@@ -74,8 +75,8 @@ static const Assembler::RegisterID calleeSavedRegisters[] = {
 #if CPU(X86)
 static const Assembler::RegisterID calleeSavedRegisters[] = {
     // Not used: JSC::X86Registers::ebx,
-    JSC::X86Registers::esi
-    // Not used: JSC::X86Registers::edi,
+    JSC::X86Registers::esi, // ContextRegister
+    JSC::X86Registers::edi  // LocalsRegister
 };
 #endif
 
@@ -93,7 +94,7 @@ static const Assembler::RegisterID calleeSavedRegisters[] = {
 };
 #endif
 
-static const int calleeSavedRegisterCount = sizeof(calleeSavedRegisters) / sizeof(calleeSavedRegisters[0]);
+const int Assembler::calleeSavedRegisterCount = sizeof(calleeSavedRegisters) / sizeof(calleeSavedRegisters[0]);
 
 /* End of platform/calling convention/architecture specific section */
 
@@ -149,10 +150,9 @@ Assembler::Pointer Assembler::loadTempAddress(RegisterID reg, IR::Temp *t)
     } else {
         assert(t->scope == 0);
         const int arg = _function->maxNumberOfArguments + t->index - _function->locals.size() + 1;
-        // StackFrameRegister points to its old value on the stack, so even for the first temp we need to
-        // subtract at least sizeof(Value).
         offset = - sizeof(Value) * (arg + 1);
-        reg = StackFrameRegister;
+        offset -= sizeof(void*) * calleeSavedRegisterCount;
+        reg = LocalsRegister;
     }
     return Pointer(reg, offset);
 }
@@ -195,14 +195,16 @@ void Assembler::enterStandardStackFrame(int locals)
     subPtr(TrustedImm32(frameSize), StackPointerRegister);
 
     for (int i = 0; i < calleeSavedRegisterCount; ++i)
-        storePtr(calleeSavedRegisters[i], Address(StackPointerRegister, i * sizeof(void*)));
+        storePtr(calleeSavedRegisters[i], Address(StackFrameRegister, -(i + 1) * sizeof(void*)));
+
+    move(StackFrameRegister, LocalsRegister);
 }
 
 void Assembler::leaveStandardStackFrame(int locals)
 {
     // restore the callee saved registers
     for (int i = calleeSavedRegisterCount - 1; i >= 0; --i)
-        loadPtr(Address(StackPointerRegister, i * sizeof(void*)), calleeSavedRegisters[i]);
+        loadPtr(Address(StackFrameRegister, -(i + 1) * sizeof(void*)), calleeSavedRegisters[i]);
 
     // space for the locals and the callee saved registers
     int32_t frameSize = locals * sizeof(QQmlJS::VM::Value) + sizeof(void*) * calleeSavedRegisterCount;
index 28d5dca..efe0a32 100644 (file)
@@ -68,6 +68,7 @@ public:
 
     static const RegisterID StackFrameRegister = JSC::X86Registers::ebp;
     static const RegisterID StackPointerRegister = JSC::X86Registers::esp;
+    static const RegisterID LocalsRegister = JSC::X86Registers::edi;
     static const RegisterID ContextRegister = JSC::X86Registers::esi;
     static const RegisterID ReturnValueRegister = JSC::X86Registers::eax;
     static const RegisterID ScratchRegister = JSC::X86Registers::ecx;
@@ -94,6 +95,7 @@ public:
 
     static const RegisterID StackFrameRegister = JSC::X86Registers::ebp;
     static const RegisterID StackPointerRegister = JSC::X86Registers::esp;
+    static const RegisterID LocalsRegister = JSC::X86Registers::r12;
     static const RegisterID ContextRegister = JSC::X86Registers::r14;
     static const RegisterID ReturnValueRegister = JSC::X86Registers::eax;
     static const RegisterID ScratchRegister = JSC::X86Registers::r10;
@@ -167,6 +169,7 @@ public:
 #else
 #error Argh.
 #endif
+    static const int calleeSavedRegisterCount;
 
     // Explicit type to allow distinguishing between
     // pushing an address itself or the value it points
@@ -797,8 +800,9 @@ protected:
     Pointer argumentAddressForCall(int argument)
     {
         const int index = _function->maxNumberOfArguments - argument;
-        return Pointer(Assembler::StackFrameRegister, sizeof(VM::Value) * (-index)
+        return Pointer(Assembler::LocalsRegister, sizeof(VM::Value) * (-index)
                                                       - sizeof(void*) // size of ebp
+                                                  - sizeof(void*) * Assembler::calleeSavedRegisterCount
                        );
     }
     Pointer baseAddressForCallArguments()