diff options
author | Lars Knoll <lars.knoll@qt.io> | 2017-08-06 22:08:49 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2017-08-18 09:56:08 +0000 |
commit | ebc6979801d86ae79dbbbb64c8793d90e0508d18 (patch) | |
tree | 47b1cb3ea38bafc6e874066b53c4754a52b001b2 /src | |
parent | 1109b9df83b78fa8703c063f117b365a21fdccb1 (diff) |
Optimize toInt32()/toUInt32()
And with this there is no need to special case integers
in the BitXxx binops anymore.
Change-Id: I9f94651d776f4e31ff8152fe7ce00dc5b1fa706e
Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/jsruntime/qv4value.cpp | 66 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4value_p.h | 94 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 33 |
3 files changed, 87 insertions, 106 deletions
diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp index 8292a48e45..79035bf154 100644 --- a/src/qml/jsruntime/qv4value.cpp +++ b/src/qml/jsruntime/qv4value.cpp @@ -98,14 +98,6 @@ bool Value::toBoolean() const return d && !std::isnan(d); } -double Value::toInteger() const -{ - if (integerCompatible()) - return int_32(); - - return Primitive::toInteger(toNumber()); -} - double Value::toNumberImpl() const { switch (type()) { @@ -245,64 +237,6 @@ bool Value::sameValue(Value other) const { return false; } - -int Primitive::toInt32(double number) -{ - const double D32 = 4294967296.0; - const double D31 = D32 / 2.0; - - if ((number >= -D31 && number < D31)) - return static_cast<int>(number); - - - if (!std::isfinite(number)) - return 0; - - double d = ::floor(::fabs(number)); - if (std::signbit(number)) - d = -d; - - number = ::fmod(d , D32); - - if (number < -D31) - number += D32; - else if (number >= D31) - number -= D32; - - return int(number); -} - -unsigned int Primitive::toUInt32(double number) -{ - const double D32 = 4294967296.0; - if ((number >= 0 && number < D32)) - return static_cast<uint>(number); - - if (!std::isfinite(number)) - return +0; - - double d = ::floor(::fabs(number)); - if (std::signbit(number)) - d = -d; - - number = ::fmod(d , D32); - - if (number < 0) - number += D32; - - return unsigned(number); -} - -double Primitive::toInteger(double number) -{ - if (std::isnan(number)) - return +0; - else if (! number || std::isinf(number)) - return number; - const double v = floor(fabs(number)); - return std::signbit(number) ? -v : v; -} - #ifndef V4_BOOTSTRAP Heap::String *Value::toString(ExecutionEngine *e) const { diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index b6f2e837ba..41e5c47269 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -594,9 +594,9 @@ struct Q_QML_PRIVATE_EXPORT Primitive : public Value using Value::toInt32; using Value::toUInt32; - static double toInteger(double fromNumber); - static int toInt32(double value); - static unsigned int toUInt32(double value); + static double toInteger(double d); + static int toInt32(double d); + static unsigned int toUInt32(double d); }; inline Primitive Primitive::undefinedValue() @@ -659,6 +659,72 @@ inline Primitive Primitive::fromUInt32(uint i) return v; } +struct Double { + quint64 d; + + Double(double dbl) { + memcpy(&d, &dbl, sizeof(double)); + } + + int sign() const { + return (d >> 63) ? -1 : 1; + } + + bool isDenormal() const { + return static_cast<int>((d << 1) >> 53) == 0; + } + + int exponent() const { + return static_cast<int>((d << 1) >> 53) - 1023; + } + + quint64 significant() const { + quint64 m = (d << 12) >> 12; + if (!isDenormal()) + m |= (static_cast<quint64>(1) << 52); + return m; + } + + static int toInt32(double d) { + int i = static_cast<int>(d); + if (i == d) + return i; + return Double(d).toInt32(); + } + + int toInt32() { + int e = exponent() - 52; + if (e < 0) { + if (e <= -53) + return 0; + return sign() * static_cast<int>(significant() >> -e); + } else { + if (e > 31) + return 0; + return sign() * (static_cast<int>(significant()) << e); + } + } +}; + +inline double Primitive::toInteger(double d) +{ + if (std::isnan(d)) + return +0; + else if (!d || std::isinf(d)) + return d; + return d >= 0 ? std::floor(d) : std::ceil(d); +} + +inline int Primitive::toInt32(double value) +{ + return Double::toInt32(value); +} + +inline unsigned int Primitive::toUInt32(double d) +{ + return static_cast<uint>(toInt32(d)); +} + struct Encode { static ReturnedValue undefined() { return Primitive::undefinedValue().rawValue(); @@ -716,24 +782,28 @@ ReturnedValue value_convert(ExecutionEngine *e, const Value &v); inline int Value::toInt32() const { - if (isInteger()) + if (integerCompatible()) return int_32(); - double d = isNumber() ? doubleValue() : toNumberImpl(); - - const double D32 = 4294967296.0; - const double D31 = D32 / 2.0; - if ((d >= -D31 && d < D31)) - return static_cast<int>(d); + double d = isDouble() ? doubleValue() : toNumberImpl(); - return Primitive::toInt32(d); + return Double::toInt32(d); } inline unsigned int Value::toUInt32() const { - return (unsigned int)toInt32(); + return static_cast<unsigned int>(toInt32()); } +inline double Value::toInteger() const +{ + if (integerCompatible()) + return int_32(); + + return Primitive::toInteger(isDouble() ? doubleValue() : toNumberImpl()); +} + + } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index cfcda9731c..efab04b32d 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -1014,46 +1014,23 @@ QV4::ReturnedValue VME::exec(const FunctionObject *jsFunction, CallData *callDat MOTH_END_INSTR(Shl) MOTH_BEGIN_INSTR(BitAndConst) - if (Q_LIKELY(accumulator.isInteger())) { - accumulator.setInt_32(accumulator.int_32() & instr.rhs); - } else { - STORE_ACCUMULATOR(QV4::Primitive::fromInt32(accumulator.toInt32() & instr.rhs)); - } + STORE_ACCUMULATOR(QV4::Primitive::fromInt32(accumulator.toInt32() & instr.rhs)); MOTH_END_INSTR(BitAndConst) MOTH_BEGIN_INSTR(BitOrConst) - if (Q_LIKELY(accumulator.isInteger())) { - accumulator.setInt_32(accumulator.int_32() | instr.rhs); - } else if (accumulator.isDouble()) { - int i = (int)(qint64)accumulator.doubleValue(); - STORE_ACCUMULATOR(QV4::Primitive::fromInt32(i | instr.rhs)); - } else { - STORE_ACCUMULATOR(QV4::Primitive::fromInt32(accumulator.toInt32() | instr.rhs)); - } + STORE_ACCUMULATOR(QV4::Primitive::fromInt32(accumulator.toInt32() | instr.rhs)); MOTH_END_INSTR(BitOrConst) MOTH_BEGIN_INSTR(BitXorConst) - if (Q_LIKELY(accumulator.isInteger())) { - accumulator.setInt_32(accumulator.int_32() ^ instr.rhs); - } else { - STORE_ACCUMULATOR(QV4::Primitive::fromInt32(accumulator.toInt32() ^ instr.rhs)); - } + STORE_ACCUMULATOR(QV4::Primitive::fromInt32(accumulator.toInt32() ^ instr.rhs)); MOTH_END_INSTR(BitXorConst) MOTH_BEGIN_INSTR(ShrConst) - if (Q_LIKELY(accumulator.isInteger())) { - accumulator.setInt_32(accumulator.int_32() >> instr.rhs); - } else { - STORE_ACCUMULATOR(QV4::Primitive::fromInt32(accumulator.toInt32() >> instr.rhs)); - } + STORE_ACCUMULATOR(QV4::Primitive::fromInt32(accumulator.toInt32() >> instr.rhs)); MOTH_END_INSTR(ShrConst) MOTH_BEGIN_INSTR(ShlConst) - if (Q_LIKELY(accumulator.isInteger())) { - accumulator.setInt_32(accumulator.int_32() << instr.rhs); - } else { - STORE_ACCUMULATOR(QV4::Primitive::fromInt32(accumulator.toInt32() << instr.rhs)); - } + STORE_ACCUMULATOR(QV4::Primitive::fromInt32(accumulator.toInt32() << instr.rhs)); MOTH_END_INSTR(ShlConst) MOTH_BEGIN_INSTR(BinopContext) |