diff options
author | Erik Verbruggen <erik.verbruggen@me.com> | 2013-08-21 13:45:24 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-08-28 11:00:51 +0200 |
commit | 9a7489cc925540611383f8db044a5c79fe472317 (patch) | |
tree | a9abff3767aa07aba9c8effea0404b90eaa0b83a /src | |
parent | 8ecb5288c96ede33970536d0f819c16a78f18238 (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.h | 10 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_masm.cpp | 65 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_masm_p.h | 20 | ||||
-rw-r--r-- | src/qml/compiler/qv4regalloc.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 5 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime_p.h | 1 |
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); |