aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@me.com>2013-08-21 13:45:24 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-08-28 11:00:51 +0200
commit9a7489cc925540611383f8db044a5c79fe472317 (patch)
treea9abff3767aa07aba9c8effea0404b90eaa0b83a /src
parent8ecb5288c96ede33970536d0f819c16a78f18238 (diff)
Generate code conversion to double.
Performance improves by about 15% on fact.3.js when Qt is build in debug mode. Change-Id: I4a1c868fe211c1e0f9e7d9a5652f7726b37405d1 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/masm/assembler/MacroAssemblerX86.h10
-rw-r--r--src/qml/compiler/qv4isel_masm.cpp65
-rw-r--r--src/qml/compiler/qv4isel_masm_p.h20
-rw-r--r--src/qml/compiler/qv4regalloc.cpp4
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp5
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h1
6 files changed, 94 insertions, 11 deletions
diff --git a/src/3rdparty/masm/assembler/MacroAssemblerX86.h b/src/3rdparty/masm/assembler/MacroAssemblerX86.h
index eb0702d464..7a01e41e11 100644
--- a/src/3rdparty/masm/assembler/MacroAssemblerX86.h
+++ b/src/3rdparty/masm/assembler/MacroAssemblerX86.h
@@ -123,20 +123,18 @@ public:
m_assembler.cvtsi2sd_mr(src.m_ptr, dest);
}
-#if 0 // FIXME: UNTESTED!
void convertUInt32ToDouble(RegisterID src, FPRegisterID dest, RegisterID scratch)
{
Jump intRange = branch32(GreaterThanOrEqual, src, TrustedImm32(0));
and32(TrustedImm32(INT_MAX), src, scratch);
- convertInt32ToDouble(scratch, dst);
- static const double magic = INT_MAX + 1;
- addDouble(&magic, dst);
+ convertInt32ToDouble(scratch, dest);
+ static const double magic = double(INT_MAX) + 1;
+ addDouble(AbsoluteAddress(&magic), dest);
Jump done = jump();
intRange.link(this);
- convertInt32ToDouble(src, dst);
+ convertInt32ToDouble(src, dest);
done.link(this);
}
-#endif
void store32(TrustedImm32 imm, void* address)
{
diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp
index e6735b0ca5..31a8257c32 100644
--- a/src/qml/compiler/qv4isel_masm.cpp
+++ b/src/qml/compiler/qv4isel_masm.cpp
@@ -1359,7 +1359,14 @@ void InstructionSelection::callSubscript(V4IR::Expr *base, V4IR::Expr *index, V4
void InstructionSelection::convertType(V4IR::Temp *source, V4IR::Temp *target)
{
- // FIXME: do something more useful with this info
+ if (target->type == V4IR::DoubleType)
+ convertTypeToDouble(source, target);
+ else
+ convertTypeSlowPath(source, target);
+}
+
+void InstructionSelection::convertTypeSlowPath(V4IR::Temp *source, V4IR::Temp *target)
+{
if (target->type & V4IR::NumberType)
unop(V4IR::OpUPlus, source, target);
else if (target->type == V4IR::BoolType) {
@@ -1370,6 +1377,62 @@ void InstructionSelection::convertType(V4IR::Temp *source, V4IR::Temp *target)
copyValue(source, target);
}
+void InstructionSelection::convertTypeToDouble(V4IR::Temp *source, V4IR::Temp *target)
+{
+ switch (source->type) {
+ case V4IR::SInt32Type:
+ case V4IR::BoolType:
+ case V4IR::NullType:
+ convertIntToDouble(source, target);
+ break;
+ case V4IR::UInt32Type:
+ convertUIntToDouble(source, target);
+ break;
+ case V4IR::UndefinedType:
+ case V4IR::StringType:
+ case V4IR::ObjectType: {
+ // load the tag:
+ Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+ tagAddr.offset += 4;
+ _as->load32(tagAddr, Assembler::ScratchRegister);
+
+ // check if it's an int32:
+ Assembler::Jump isNoInt = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
+ Assembler::TrustedImm32(Value::_Integer_Type));
+ convertIntToDouble(source, target);
+ Assembler::Jump intDone = _as->jump();
+
+ // not an int, check if it's NOT a double:
+ isNoInt.link(_as);
+ _as->and32(Assembler::TrustedImm32(Value::NotDouble_Mask), Assembler::ScratchRegister);
+ Assembler::Jump isDbl = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
+ Assembler::TrustedImm32(Value::NotDouble_Mask));
+
+ generateFunctionCall(Assembler::Void, __qmljs_value_to_double,
+ Assembler::PointerToValue(target),
+ Assembler::PointerToValue(source));
+ storeTarget(0, target);
+ Assembler::Jump noDoubleDone = _as->jump();
+
+ // it is a double:
+ isDbl.link(_as);
+ Assembler::Pointer addr2 = _as->loadTempAddress(Assembler::ScratchRegister, source);
+ if (target->kind == V4IR::Temp::StackSlot) {
+ _as->loadDouble(addr2, Assembler::FPGpr0);
+ _as->storeDouble(Assembler::FPGpr0, _as->stackSlotPointer(target));
+ } else {
+ _as->loadDouble(addr2, (Assembler::FPRegisterID) target->index);
+ }
+
+ noDoubleDone.link(_as);
+ intDone.link(_as);
+ } break;
+ default:
+ convertTypeSlowPath(source, target);
+ break;
+ }
+}
+
void InstructionSelection::constructActivationProperty(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result)
{
assert(func != 0);
diff --git a/src/qml/compiler/qv4isel_masm_p.h b/src/qml/compiler/qv4isel_masm_p.h
index ef79e3524a..09bd614b30 100644
--- a/src/qml/compiler/qv4isel_masm_p.h
+++ b/src/qml/compiler/qv4isel_masm_p.h
@@ -546,6 +546,11 @@ public:
move(ReturnValueRegister, dest);
}
+ void storeReturnValue(FPRegisterID dest)
+ {
+ moveDouble(FPGpr0, dest);
+ }
+
#ifdef VALUE_FITS_IN_REGISTER
void storeReturnValue(const Pointer &dest)
{
@@ -1033,7 +1038,7 @@ public:
void storeUInt32(RegisterID reg, Pointer addr)
{
-#if CPU(X86_64)
+#if CPU(X86_64) | CPU(X86)
Q_ASSERT(reg != ScratchRegister);
Jump intRange = branch32(GreaterThanOrEqual, reg, TrustedImm32(0));
convertUInt32ToDouble(reg, FPGpr0, ScratchRegister);
@@ -1233,6 +1238,9 @@ protected:
virtual void visitTry(V4IR::Try *);
private:
+ void convertTypeSlowPath(V4IR::Temp *source, V4IR::Temp *target);
+ void convertTypeToDouble(V4IR::Temp *source, V4IR::Temp *target);
+
void convertIntToDouble(V4IR::Temp *source, V4IR::Temp *target)
{
if (target->kind == V4IR::Temp::PhysicalRegister) {
@@ -1250,13 +1258,21 @@ private:
void convertUIntToDouble(V4IR::Temp *source, V4IR::Temp *target)
{
if (target->kind == V4IR::Temp::PhysicalRegister) {
-#if CPU(X86_64)
+#if CPU(X86_64) || CPU(X86)
_as->convertUInt32ToDouble(_as->toInt32Register(source, Assembler::ScratchRegister),
(Assembler::FPRegisterID) target->index,
Assembler::ScratchRegister);
#else
Q_ASSERT(!"Not supported on this platform!");
#endif
+ } else if (target->kind == V4IR::Temp::StackSlot) {
+#if CPU(X86_64) || CPU(X86)
+ _as->convertUInt32ToDouble(_as->toUInt32Register(source, Assembler::ScratchRegister),
+ Assembler::FPGpr0, Assembler::ScratchRegister);
+ _as->storeDouble(Assembler::FPGpr0, _as->stackSlotPointer(target));
+#else
+ Q_ASSERT(!"Not supported on this platform!");
+#endif
} else {
Q_UNIMPLEMENTED();
}
diff --git a/src/qml/compiler/qv4regalloc.cpp b/src/qml/compiler/qv4regalloc.cpp
index 9b3a427c95..d2f2fe318b 100644
--- a/src/qml/compiler/qv4regalloc.cpp
+++ b/src/qml/compiler/qv4regalloc.cpp
@@ -240,7 +240,6 @@ protected: // IRDecoder
bool needsCall = true;
Use::RegisterFlag sourceReg = Use::CouldHaveRegister;
-#if 0 // TODO: change masm to generate code
// TODO: verify this method
switch (target->type) {
case DoubleType:
@@ -249,9 +248,11 @@ protected: // IRDecoder
needsCall = false;
break;
}
+#if 0 // TODO: change masm to generate code
case SInt32Type:
case UInt32Type:
case BoolType:
+#endif
switch (source->type) {
case BoolType:
case DoubleType:
@@ -268,7 +269,6 @@ protected: // IRDecoder
default:
break;
}
-#endif
addUses(source, sourceReg);
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 5f043347dd..f91f8690f8 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -1232,6 +1232,11 @@ void __qmljs_decrement(Value *result, const Value &value)
}
}
+void __qmljs_value_to_double(double *result, const Value &value)
+{
+ *result = __qmljs_to_number(value);
+}
+
int __qmljs_value_to_int32(const Value &value)
{
return value.toInt32();
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index 4ae28ab094..af293a2df1 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -178,6 +178,7 @@ void __qmljs_not(QV4::Value *result, const QV4::Value &value);
void __qmljs_increment(QV4::Value *result, const QV4::Value &value);
void __qmljs_decrement(QV4::Value *result, const QV4::Value &value);
+Q_QML_EXPORT void __qmljs_value_to_double(double *result, const Value &value);
Q_QML_EXPORT int __qmljs_value_to_int32(const Value &value);
Q_QML_EXPORT int __qmljs_double_to_int32(double d);
Q_QML_EXPORT unsigned __qmljs_value_to_uint32(const Value &value);