V4 JIT: optimize mem2mem copies.
authorErik Verbruggen <erik.verbruggen@me.com>
Tue, 24 Sep 2013 09:42:03 +0000 (11:42 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Sat, 28 Sep 2013 21:56:53 +0000 (23:56 +0200)
Instead of loading and decoding a value and then encoding and storing
it, we can just as well fold that into a load+store.

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

index 33c2279..3f3c47d 100644 (file)
@@ -358,7 +358,6 @@ void Assembler::copyValue(Result result, V4IR::Expr* source)
     }
 }
 
-
 void Assembler::storeValue(QV4::Value value, V4IR::Temp* destination)
 {
     Address addr = loadTempAddress(ScratchRegister, destination);
@@ -1128,7 +1127,9 @@ void InstructionSelection::copyValue(V4IR::Temp *sourceTemp, V4IR::Temp *targetT
         }
     }
 
-    _as->copyValue(targetTemp, sourceTemp);
+    // The target is not a physical register, nor is the source. So we can do a memory-to-memory copy:
+    _as->memcopyValue(_as->loadTempAddress(Assembler::ReturnValueRegister, targetTemp), sourceTemp,
+                      Assembler::ScratchRegister);
 }
 
 void InstructionSelection::swapValues(V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp)
@@ -1910,7 +1911,11 @@ int InstructionSelection::prepareVariableArguments(V4IR::ExprList* args)
     for (V4IR::ExprList *it = args; it; it = it->next, ++i) {
         V4IR::Expr *arg = it->expr;
         Q_ASSERT(arg != 0);
-        _as->copyValue(_as->stackLayout().argumentAddressForCall(i), arg);
+        Pointer dst(_as->stackLayout().argumentAddressForCall(i));
+        if (arg->asTemp() && arg->asTemp()->kind != V4IR::Temp::PhysicalRegister)
+            _as->memcopyValue(dst, arg->asTemp(), Assembler::ScratchRegister);
+        else
+            _as->copyValue(dst, arg);
     }
 
     return argc;
@@ -1937,7 +1942,11 @@ int InstructionSelection::prepareCallData(V4IR::ExprList* args, V4IR::Expr *this
     for (V4IR::ExprList *it = args; it; it = it->next, ++i) {
         V4IR::Expr *arg = it->expr;
         Q_ASSERT(arg != 0);
-        _as->copyValue(_as->stackLayout().argumentAddressForCall(i), arg);
+        Pointer dst(_as->stackLayout().argumentAddressForCall(i));
+        if (arg->asTemp() && arg->asTemp()->kind != V4IR::Temp::PhysicalRegister)
+            _as->memcopyValue(dst, arg->asTemp(), Assembler::ScratchRegister);
+        else
+            _as->copyValue(dst, arg);
     }
     return argc;
 }
index a4550c6..86a4dd6 100644 (file)
@@ -808,6 +808,15 @@ public:
     template <typename Result>
     void copyValue(Result result, V4IR::Expr* source);
 
+    // The scratch register is used to calculate the temp address for the source.
+    void memcopyValue(Pointer target, V4IR::Temp *sourceTemp, RegisterID scratchRegister)
+    {
+        Q_ASSERT(sourceTemp->kind != V4IR::Temp::PhysicalRegister);
+        Q_ASSERT(target.base != scratchRegister);
+        JSC::MacroAssembler::loadDouble(loadTempAddress(scratchRegister, sourceTemp), FPGpr0);
+        JSC::MacroAssembler::storeDouble(FPGpr0, target);
+    }
+
     void storeValue(QV4::Value value, RegisterID destination)
     {
         Q_UNUSED(value);