aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-08-06 22:08:49 +0200
committerErik Verbruggen <erik.verbruggen@qt.io>2017-08-18 09:56:08 +0000
commitebc6979801d86ae79dbbbb64c8793d90e0508d18 (patch)
tree47b1cb3ea38bafc6e874066b53c4754a52b001b2 /src
parent1109b9df83b78fa8703c063f117b365a21fdccb1 (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.cpp66
-rw-r--r--src/qml/jsruntime/qv4value_p.h94
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp33
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)