From e4c696dda3610a7c6e34bf705656d90babc9d461 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Tue, 24 Sep 2013 11:42:03 +0200 Subject: [PATCH] V4 JIT: optimize mem2mem copies. 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 --- src/qml/compiler/qv4isel_masm.cpp | 17 +++++++++++++---- src/qml/compiler/qv4isel_masm_p.h | 9 +++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp index 33c2279..3f3c47d 100644 --- a/src/qml/compiler/qv4isel_masm.cpp +++ b/src/qml/compiler/qv4isel_masm.cpp @@ -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; } diff --git a/src/qml/compiler/qv4isel_masm_p.h b/src/qml/compiler/qv4isel_masm_p.h index a4550c6..86a4dd6 100644 --- a/src/qml/compiler/qv4isel_masm_p.h +++ b/src/qml/compiler/qv4isel_masm_p.h @@ -808,6 +808,15 @@ public: template 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); -- 2.7.4