V4 JIT: Change function call generation with registers.
authorErik Verbruggen <erik.verbruggen@me.com>
Tue, 27 Aug 2013 11:02:32 +0000 (13:02 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Sun, 8 Sep 2013 11:29:23 +0000 (13:29 +0200)
When generating a function call where arguments are passed by reference,
first save all arguments that are in registers to the stack, and only
then put the references into the outgoing positions (stack or register).

Change-Id: Iaec4db6836e33627723eb4709fd6dad2b4ea8a1d
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
src/qml/compiler/qv4isel_masm_p.h

index f89d469..8de7192 100644 (file)
@@ -431,6 +431,38 @@ public:
         return Pointer(_stackLayout.stackSlotPointer(t->index));
     }
 
+    template <int argumentNumber>
+    void saveOutRegister(PointerToValue arg)
+    {
+        if (!arg.value)
+            return;
+        if (V4IR::Temp *t = arg.value->asTemp()) {
+            if (t->kind == V4IR::Temp::PhysicalRegister) {
+                Pointer addr(_stackLayout.savedRegPointer(argumentNumber));
+                switch (t->type) {
+                case V4IR::BoolType:
+                    storeBool((RegisterID) t->index, addr);
+                    break;
+                case V4IR::SInt32Type:
+                    storeInt32((RegisterID) t->index, addr);
+                    break;
+                case V4IR::UInt32Type:
+                    storeUInt32((RegisterID) t->index, addr);
+                    break;
+                case V4IR::DoubleType:
+                    storeDouble((FPRegisterID) t->index, addr);
+                    break;
+                default:
+                    Q_UNIMPLEMENTED();
+                }
+            }
+        }
+    }
+
+    template <int, typename ArgType>
+    void saveOutRegister(ArgType)
+    {}
+
     void loadArgumentInRegister(RegisterID source, RegisterID dest, int argumentNumber)
     {
         Q_UNUSED(argumentNumber);
@@ -747,6 +779,15 @@ public:
             sub32(TrustedImm32(stackSpaceNeeded), StackPointerRegister);
         }
 
+        // First save any arguments that reside in registers, because they could be overwritten
+        // if that register is also used to pass arguments.
+        saveOutRegister<5>(arg6);
+        saveOutRegister<4>(arg5);
+        saveOutRegister<3>(arg4);
+        saveOutRegister<2>(arg3);
+        saveOutRegister<1>(arg2);
+        saveOutRegister<0>(arg1);
+
         loadArgumentOnStackOrRegister<5>(arg6);
         loadArgumentOnStackOrRegister<4>(arg5);
         loadArgumentOnStackOrRegister<3>(arg4);
@@ -967,25 +1008,8 @@ public:
         if (t->kind != V4IR::Temp::PhysicalRegister)
             return loadTempAddress(tmpReg, t);
 
-        Pointer addr(_stackLayout.savedRegPointer(offset));
-        switch (t->type) {
-        case V4IR::BoolType:
-            storeBool((RegisterID) t->index, addr);
-            break;
-        case V4IR::SInt32Type:
-            storeInt32((RegisterID) t->index, addr);
-            break;
-        case V4IR::UInt32Type:
-            storeUInt32((RegisterID) t->index, addr);
-            break;
-        case V4IR::DoubleType:
-            storeDouble((FPRegisterID) t->index, addr);
-            break;
-        default:
-            Q_UNIMPLEMENTED();
-        }
 
-        return addr;
+        return Pointer(_stackLayout.savedRegPointer(offset));
     }
 
     void storeBool(RegisterID reg, Pointer addr)