aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@digia.com>2013-10-13 21:03:44 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-10-14 21:59:59 +0200
commit1be51cc3e7c9ca5256a52136d6fcc9c22c997625 (patch)
treee0c4f1feae828c4f04f0b8b63201627aa20cf43c /src/qml/compiler
parent668eca2b9343cf5d79dc1faa6c251595e2e84918 (diff)
inline get_element calls
Inline calls to get_element if the base is an object with a simple array structure, and the index is an integer number. Implemented for 64bit only for now, saves ~25% on crypto.js Change-Id: I3e34a6409169d90d3937f62264707d52a6c2f9f7 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/qv4isel_masm.cpp100
-rw-r--r--src/qml/compiler/qv4isel_masm_p.h1
2 files changed, 92 insertions, 9 deletions
diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp
index 842b2611bb..1155322df2 100644
--- a/src/qml/compiler/qv4isel_masm.cpp
+++ b/src/qml/compiler/qv4isel_masm.cpp
@@ -671,7 +671,6 @@ void InstructionSelection::run(int functionIndex)
<< JSC::X86Registers::r15;
#endif
static const QVector<int> fpRegisters = QVector<int>()
- << JSC::X86Registers::xmm1
<< JSC::X86Registers::xmm2
<< JSC::X86Registers::xmm3
<< JSC::X86Registers::xmm4
@@ -1102,6 +1101,89 @@ void InstructionSelection::setProperty(V4IR::Expr *source, V4IR::Expr *targetBas
void InstructionSelection::getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR::Temp *target)
{
+#if QT_POINTER_SIZE == 8
+ V4IR::Temp *tbase = base->asTemp();
+ V4IR::Temp *tindex = index->asTemp();
+ if (tbase && tindex &&
+ tbase->kind != V4IR::Temp::PhysicalRegister) {
+ Assembler::Pointer addr = _as->loadTempAddress(Assembler::ReturnValueRegister, tbase);
+ _as->load64(addr, Assembler::ScratchRegister);
+ _as->move(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
+ _as->urshift64(Assembler::TrustedImm32(QV4::Value::IsManaged_Shift), Assembler::ReturnValueRegister);
+ Assembler::Jump notManaged = _as->branch64(Assembler::NotEqual, Assembler::ReturnValueRegister, Assembler::TrustedImm64(0));
+ // check whether we have an object with a simple array
+ Assembler::Address managedType(Assembler::ScratchRegister, qOffsetOf(QV4::Managed, flags));
+ _as->load8(managedType, Assembler::ReturnValueRegister);
+ _as->and32(Assembler::TrustedImm32(QV4::Managed::SimpleArray), Assembler::ReturnValueRegister);
+ Assembler::Jump notSimple = _as->branch32(Assembler::Equal, Assembler::ReturnValueRegister, Assembler::TrustedImm32(0));
+
+ Assembler::Jump fallback;
+ if (tindex->kind == V4IR::Temp::PhysicalRegister) {
+ if (tindex->type == V4IR::SInt32Type) {
+ _as->move((Assembler::RegisterID) tindex->index, Assembler::ScratchRegister);
+ } else {
+ // double, convert and check if it's a int
+ _as->truncateDoubleToUint32((Assembler::FPRegisterID) tindex->index, Assembler::ScratchRegister);
+ _as->convertInt32ToDouble(Assembler::ScratchRegister, Assembler::FPGpr0);
+ fallback = _as->branchDouble(Assembler::DoubleNotEqual, Assembler::FPGpr0, (Assembler::FPRegisterID) tindex->index);
+ }
+ } else {
+ Assembler::Pointer indexAddr = _as->loadTempAddress(Assembler::ReturnValueRegister, tindex);
+ _as->load64(indexAddr, Assembler::ScratchRegister);
+ _as->move(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
+ _as->urshift64(Assembler::TrustedImm32(QV4::Value::IsNumber_Shift), Assembler::ReturnValueRegister);
+ Assembler::Jump isInteger = _as->branch64(Assembler::Equal, Assembler::ReturnValueRegister, Assembler::TrustedImm64(1));
+
+ // other type, convert to double and check if it's a int
+ // this check is ok to do even if the type is something else than a double, as
+ // that would result in a NaN
+ _as->move(Assembler::TrustedImm64(QV4::Value::NaNEncodeMask), Assembler::ReturnValueRegister);
+ _as->xor64(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
+ _as->move64ToDouble(Assembler::ReturnValueRegister, Assembler::FPGpr0);
+ _as->truncateDoubleToUint32(Assembler::FPGpr0, Assembler::ScratchRegister);
+ _as->convertInt32ToDouble(Assembler::ScratchRegister, Assembler::FPGpr1);
+ fallback = _as->branchDouble(Assembler::DoubleNotEqualOrUnordered, Assembler::FPGpr0, Assembler::FPGpr1);
+
+ isInteger.link(_as);
+ _as->or32(Assembler::TrustedImm32(0), Assembler::ScratchRegister);
+ }
+
+ // get data, ScratchRegister holds index
+ addr = _as->loadTempAddress(Assembler::ReturnValueRegister, tbase);
+ _as->load64(addr, Assembler::ReturnValueRegister);
+ Address arrayDataLen(Assembler::ReturnValueRegister, qOffsetOf(Object, arrayDataLen));
+ Assembler::Jump outOfRange = _as->branch32(Assembler::GreaterThanOrEqual, Assembler::ScratchRegister, arrayDataLen);
+ Address arrayData(Assembler::ReturnValueRegister, qOffsetOf(Object, arrayData));
+ _as->load64(arrayData, Assembler::ReturnValueRegister);
+ Q_ASSERT(sizeof(Property) == (1<<4));
+ _as->lshift64(Assembler::TrustedImm32(4), Assembler::ScratchRegister);
+ _as->add64(Assembler::ReturnValueRegister, Assembler::ScratchRegister);
+ Address value(Assembler::ScratchRegister, qOffsetOf(Property, value));
+ _as->load64(value, Assembler::ReturnValueRegister);
+
+ // check that the value is not empty
+ _as->move(Assembler::ReturnValueRegister, Assembler::ScratchRegister);
+ _as->urshift64(Assembler::TrustedImm32(32), Assembler::ScratchRegister);
+ Assembler::Jump emptyValue = _as->branch32(Assembler::Equal, Assembler::TrustedImm32(QV4::Value::Empty_Type), Assembler::ScratchRegister);
+ _as->storeReturnValue(target);
+
+ Assembler::Jump done = _as->jump();
+
+ emptyValue.link(_as);
+ outOfRange.link(_as);
+ if (fallback.isSet())
+ fallback.link(_as);
+ notSimple.link(_as);
+ notManaged.link(_as);
+
+ generateFunctionCall(target, __qmljs_get_element, Assembler::ContextRegister,
+ Assembler::PointerToValue(base), Assembler::PointerToValue(index));
+
+ done.link(_as);
+ return;
+ }
+#endif
+
generateFunctionCall(target, __qmljs_get_element, Assembler::ContextRegister,
Assembler::PointerToValue(base), Assembler::PointerToValue(index));
}
@@ -1313,8 +1395,8 @@ Assembler::Jump InstructionSelection::genInlineBinop(V4IR::AluOp oper, V4IR::Exp
// register.
switch (oper) {
case V4IR::OpAdd: {
- Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 1);
- Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 3);
+ Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 2);
+ Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 4);
Assembler::Jump leftIsNoDbl = genTryDoubleConversion(leftSource, lReg);
Assembler::Jump rightIsNoDbl = genTryDoubleConversion(rightSource, rReg);
@@ -1328,8 +1410,8 @@ Assembler::Jump InstructionSelection::genInlineBinop(V4IR::AluOp oper, V4IR::Exp
rightIsNoDbl.link(_as);
} break;
case V4IR::OpMul: {
- Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 1);
- Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 3);
+ Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 2);
+ Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 4);
Assembler::Jump leftIsNoDbl = genTryDoubleConversion(leftSource, lReg);
Assembler::Jump rightIsNoDbl = genTryDoubleConversion(rightSource, rReg);
@@ -1343,8 +1425,8 @@ Assembler::Jump InstructionSelection::genInlineBinop(V4IR::AluOp oper, V4IR::Exp
rightIsNoDbl.link(_as);
} break;
case V4IR::OpSub: {
- Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 1);
- Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 3);
+ Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 2);
+ Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 4);
Assembler::Jump leftIsNoDbl = genTryDoubleConversion(leftSource, lReg);
Assembler::Jump rightIsNoDbl = genTryDoubleConversion(rightSource, rReg);
@@ -1358,8 +1440,8 @@ Assembler::Jump InstructionSelection::genInlineBinop(V4IR::AluOp oper, V4IR::Exp
rightIsNoDbl.link(_as);
} break;
case V4IR::OpDiv: {
- Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 1);
- Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 3);
+ Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 2);
+ Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 4);
Assembler::Jump leftIsNoDbl = genTryDoubleConversion(leftSource, lReg);
Assembler::Jump rightIsNoDbl = genTryDoubleConversion(rightSource, rReg);
diff --git a/src/qml/compiler/qv4isel_masm_p.h b/src/qml/compiler/qv4isel_masm_p.h
index fb990d0d53..4d1114e756 100644
--- a/src/qml/compiler/qv4isel_masm_p.h
+++ b/src/qml/compiler/qv4isel_masm_p.h
@@ -136,6 +136,7 @@ public:
static const RegisterID ScratchRegister = JSC::X86Registers::r10;
static const RegisterID IntegerOpRegister = JSC::X86Registers::eax;
static const FPRegisterID FPGpr0 = JSC::X86Registers::xmm0;
+ static const FPRegisterID FPGpr1 = JSC::X86Registers::xmm1;
static const int RegisterSize = 8;