aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@digia.com>2013-10-04 15:38:42 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-10-11 16:01:24 +0200
commitf6de6160b915b5a35e75746a35c4ef94ceb9b2c2 (patch)
treeb75e37bc0579a2195c36074999cd4b116aeb7a1f /src
parent886c359ebb86afcad3a62ce6cf7697fd7d6a1ea8 (diff)
Optimise code generation for convertTypeToSInt32
Add 64 bit code patch and avoid some duplicated calculation in 32 bit mode Change-Id: I0e111de8ac4e733aa8802c49b4b15d785688d7ea Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/masm/assembler/MacroAssemblerX86Common.h4
-rw-r--r--src/3rdparty/masm/assembler/MacroAssemblerX86_64.h10
-rw-r--r--src/3rdparty/masm/assembler/X86Assembler.h23
-rw-r--r--src/qml/compiler/qv4isel_masm.cpp57
-rw-r--r--src/qml/jsruntime/qv4value_def_p.h3
-rw-r--r--src/qml/jsruntime/qv4value_p.h7
6 files changed, 96 insertions, 8 deletions
diff --git a/src/3rdparty/masm/assembler/MacroAssemblerX86Common.h b/src/3rdparty/masm/assembler/MacroAssemblerX86Common.h
index 53cb80c210..520cf915fa 100644
--- a/src/3rdparty/masm/assembler/MacroAssemblerX86Common.h
+++ b/src/3rdparty/masm/assembler/MacroAssemblerX86Common.h
@@ -318,7 +318,7 @@ public:
{
m_assembler.sarl_i8r(imm.m_value, dest);
}
-
+
void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
{
if (src != dest)
@@ -362,7 +362,7 @@ public:
move(src, dest);
urshift32(imm, dest);
}
-
+
void sub32(RegisterID src, RegisterID dest)
{
m_assembler.subl_rr(src, dest);
diff --git a/src/3rdparty/masm/assembler/MacroAssemblerX86_64.h b/src/3rdparty/masm/assembler/MacroAssemblerX86_64.h
index 3aaa0fd1bc..db0e880cb9 100644
--- a/src/3rdparty/masm/assembler/MacroAssemblerX86_64.h
+++ b/src/3rdparty/masm/assembler/MacroAssemblerX86_64.h
@@ -295,6 +295,16 @@ public:
m_assembler.xorq_ir(imm.m_value, srcDest);
}
+ void urshift64(TrustedImm32 imm, RegisterID dest)
+ {
+ m_assembler.shrq_i8r(imm.m_value, dest);
+ }
+
+ void lshift64(TrustedImm32 imm, RegisterID dest)
+ {
+ m_assembler.shlq_i8r(imm.m_value, dest);
+ }
+
void load64(ImplicitAddress address, RegisterID dest)
{
m_assembler.movq_mr(address.offset, address.base, dest);
diff --git a/src/3rdparty/masm/assembler/X86Assembler.h b/src/3rdparty/masm/assembler/X86Assembler.h
index a3a480541c..1875ebaff0 100644
--- a/src/3rdparty/masm/assembler/X86Assembler.h
+++ b/src/3rdparty/masm/assembler/X86Assembler.h
@@ -683,6 +683,29 @@ public:
}
}
+ void shrq_i8r(int imm, RegisterID dst)
+ {
+ // ### doesn't work when removing the "0 &&"
+ if (0 && imm == 1)
+ m_formatter.oneByteOp64(OP_GROUP2_Ev1, GROUP2_OP_SHR, dst);
+ else {
+ m_formatter.oneByteOp64(OP_GROUP2_EvIb, GROUP2_OP_SHR, dst);
+ m_formatter.immediate8(imm);
+ }
+ }
+
+ void shlq_i8r(int imm, RegisterID dst)
+ {
+ // ### doesn't work when removing the "0 &&"
+ if (0 && imm == 1)
+ m_formatter.oneByteOp64(OP_GROUP2_Ev1, GROUP2_OP_SHL, dst);
+ else {
+ m_formatter.oneByteOp64(OP_GROUP2_EvIb, GROUP2_OP_SHL, dst);
+ m_formatter.immediate8(imm);
+ }
+ }
+
+
#endif
void sarl_i8r(int imm, RegisterID dst)
diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp
index 574b4e278b..4ca4f82cef 100644
--- a/src/qml/compiler/qv4isel_masm.cpp
+++ b/src/qml/compiler/qv4isel_masm.cpp
@@ -1590,15 +1590,60 @@ void InstructionSelection::convertTypeToSInt32(V4IR::Temp *source, V4IR::Temp *t
{
switch (source->type) {
case V4IR::VarType: {
+
+#if QT_POINTER_SIZE == 8
+ Assembler::Pointer addr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+ _as->load64(addr, Assembler::ScratchRegister);
+ _as->move(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
+
+ // check if it's a number
+ _as->urshift64(Assembler::TrustedImm32(QV4::Value::IsNumber_Shift), Assembler::ScratchRegister);
+ Assembler::Jump fallback = _as->branch32(Assembler::Equal, Assembler::ScratchRegister, Assembler::TrustedImm32(0));
+ // we have a number
+ _as->urshift64(Assembler::TrustedImm32(1), Assembler::ScratchRegister);
+ Assembler::Jump isInt = _as->branch32(Assembler::Equal, Assembler::ScratchRegister, Assembler::TrustedImm32(0));
+
+ // it's a double
+ _as->move(Assembler::TrustedImm64(QV4::Value::NaNEncodeMask), Assembler::ScratchRegister);
+ _as->xor64(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
+ _as->move64ToDouble(Assembler::ReturnValueRegister, Assembler::FPGpr0);
+ Assembler::Jump success =
+ _as->branchTruncateDoubleToInt32(Assembler::FPGpr0, Assembler::ReturnValueRegister,
+ Assembler::BranchIfTruncateSuccessful);
+ generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_double_to_int32,
+ Assembler::PointerToValue(source));
+ Assembler::Jump converted = _as->jump();
+
+ // not an int:
+ fallback.link(_as);
+ generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_value_to_int32,
+ _as->loadTempAddress(Assembler::ScratchRegister, source));
+
+ isInt.link(_as);
+ success.link(_as);
+ converted.link(_as);
+ if (target->kind == V4IR::Temp::StackSlot) {
+// _as->move(Assembler::TrustedImm32(QV4::Value::_Integer_Type), Assembler::ScratchRegister);
+// _as->lshift64(Assembler::TrustedImm32(32), Assembler::ScratchRegister);
+// _as->or64(Assembler::ScratchRegister, Assembler::ReturnValueRegister, Assembler::ScratchRegister);
+// _as->store64(Assembler::ScratchRegister, target);
+ Assembler::Pointer targetAddr = _as->stackSlotPointer(target);
+ _as->store32(Assembler::ReturnValueRegister, targetAddr);
+ targetAddr.offset += 4;
+ _as->store32(Assembler::TrustedImm32(Value::_Integer_Type), targetAddr);
+ } else {
+ _as->storeInt32(Assembler::ReturnValueRegister, target);
+ }
+#else
// load the tag:
- Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+ Assembler::Pointer addr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+ Assembler::Pointer tagAddr = addr;
tagAddr.offset += 4;
- _as->load32(tagAddr, Assembler::ScratchRegister);
+ _as->load32(tagAddr, Assembler::ReturnValueRegister);
// check if it's an int32:
- Assembler::Jump isNoInt = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
+ Assembler::Jump fallback = _as->branch32(Assembler::NotEqual, Assembler::ReturnValueRegister,
Assembler::TrustedImm32(Value::_Integer_Type));
- Assembler::Pointer addr = _as->loadTempAddress(Assembler::ScratchRegister, source);
if (target->kind == V4IR::Temp::StackSlot) {
_as->load32(addr, Assembler::ScratchRegister);
Assembler::Pointer targetAddr = _as->stackSlotPointer(target);
@@ -1611,12 +1656,14 @@ void InstructionSelection::convertTypeToSInt32(V4IR::Temp *source, V4IR::Temp *t
Assembler::Jump intDone = _as->jump();
// not an int:
- isNoInt.link(_as);
+ fallback.link(_as);
generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_value_to_int32,
_as->loadTempAddress(Assembler::ScratchRegister, source));
_as->storeInt32(Assembler::ReturnValueRegister, target);
intDone.link(_as);
+#endif
+
} break;
case V4IR::DoubleType: {
Assembler::FPRegisterID reg = _as->toDoubleRegister(source);
diff --git a/src/qml/jsruntime/qv4value_def_p.h b/src/qml/jsruntime/qv4value_def_p.h
index 82f8d02dfe..163aed9abc 100644
--- a/src/qml/jsruntime/qv4value_def_p.h
+++ b/src/qml/jsruntime/qv4value_def_p.h
@@ -194,8 +194,8 @@ struct Q_QML_EXPORT Value
inline bool isUndefined() const { return tag == Undefined_Type; }
inline bool isNull() const { return tag == _Null_Type; }
inline bool isBoolean() const { return tag == _Boolean_Type; }
- inline bool isInteger() const { return tag == _Integer_Type; }
#if QT_POINTER_SIZE == 8
+ inline bool isInteger() const { return (val >> IsNumber_Shift) == 1; }
inline bool isDouble() const { return (val >> IsDouble_Shift); }
inline bool isNumber() const { return (val >> IsNumber_Shift); }
inline bool isManaged() const { return !(val >> IsManaged_Shift); }
@@ -227,6 +227,7 @@ struct Q_QML_EXPORT Value
}
bool isNaN() const { return (tag & 0x7fff8000) == 0x00078000; }
#else
+ inline bool isInteger() const { return tag == _Integer_Type; }
inline bool isDouble() const { return (tag & NotDouble_Mask) != NotDouble_Mask; }
inline bool isNumber() const { return tag == _Integer_Type || (tag & NotDouble_Mask) != NotDouble_Mask; }
inline bool isManaged() const { return tag == Managed_Type; }
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 362f41affe..a2137ee849 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -200,10 +200,17 @@ inline bool Value::toBoolean() const
inline uint Value::asArrayIndex() const
{
+#if QT_POINTER_SIZE == 8
+ if (!isNumber())
+ return UINT_MAX;
+ if (isInteger())
+ return int_32 >= 0 ? (uint)int_32 : UINT_MAX;
+#else
if (isInteger() && int_32 >= 0)
return (uint)int_32;
if (!isDouble())
return UINT_MAX;
+#endif
double d = doubleValue();
uint idx = (uint)d;
if (idx != d)