aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@qt.io>2018-07-06 14:36:11 +0200
committerErik Verbruggen <erik.verbruggen@qt.io>2018-07-13 10:20:07 +0000
commit8fdfd9ff5ded388a3d29c917aebb795485abfbfd (patch)
treee9b614f90adbd7943a4c6190e8e1ba39cec37d40
parenteab3371b91a2a752a123c4995d977a36ff952168 (diff)
JS: Encode result of Math.min and Math.max as int when possible
So now Math.max(array1.length, array2.length) won't return a double anymore. This improves the score in the crypto benchmark by ~10% Change-Id: I8453a671d28d7f2a39ba74b18b3155f031d9b12f Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/qml/jsapi/qjsvalue_p.h2
-rw-r--r--src/qml/jsruntime/qv4mathobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4value_p.h11
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp17
4 files changed, 27 insertions, 7 deletions
diff --git a/src/qml/jsapi/qjsvalue_p.h b/src/qml/jsapi/qjsvalue_p.h
index 62e09f72be..bcf0a9d12d 100644
--- a/src/qml/jsapi/qjsvalue_p.h
+++ b/src/qml/jsapi/qjsvalue_p.h
@@ -62,7 +62,7 @@
QT_BEGIN_NAMESPACE
-class QJSValuePrivate
+class Q_AUTOTEST_EXPORT QJSValuePrivate
{
public:
static inline QV4::Value *getValue(const QJSValue *jsval)
diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp
index 652f6c603e..e176235786 100644
--- a/src/qml/jsruntime/qv4mathobject.cpp
+++ b/src/qml/jsruntime/qv4mathobject.cpp
@@ -399,7 +399,7 @@ ReturnedValue MathObject::method_max(const FunctionObject *, const Value *, cons
if (x > mx || std::isnan(x))
mx = x;
}
- RETURN_RESULT(Encode(mx));
+ RETURN_RESULT(Encode::smallestNumber(mx));
}
ReturnedValue MathObject::method_min(const FunctionObject *, const Value *, const Value *argv, int argc)
@@ -412,7 +412,7 @@ ReturnedValue MathObject::method_min(const FunctionObject *, const Value *, cons
mx = x;
}
}
- RETURN_RESULT(Encode(mx));
+ RETURN_RESULT(Encode::smallestNumber(mx));
}
ReturnedValue MathObject::method_pow(const FunctionObject *, const Value *, const Value *argv, int argc)
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 7c9ca9c0bf..6a6df3eb6d 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -334,14 +334,17 @@ public:
return true;
if (isDouble()) {
double d = doubleValue();
- int i = (int)d;
- if (i == d && !(d == 0 && std::signbit(d))) {
- setInt_32(i);
+ if (isInt32(d)) {
+ setInt_32(int(d));
return true;
}
}
return false;
}
+ QML_NEARLY_ALWAYS_INLINE static bool isInt32(double d) {
+ int i = int(d);
+ return (i == d && !(d == 0 && std::signbit(d)));
+ }
double asDouble() const {
if (tag() == quint32(ValueTypeInternal::Integer))
return int_32();
@@ -733,7 +736,7 @@ struct Encode {
}
static ReturnedValue smallestNumber(double d) {
- if (static_cast<int>(d) == d && !(d == 0. && std::signbit(d)))
+ if (Value::isInt32(d))
return Encode(static_cast<int>(d));
else
return Encode(d);
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index c20937f9a1..935fd53a42 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -39,6 +39,7 @@
#include <qqmlcomponent.h>
#include <stdlib.h>
#include <private/qv4alloca_p.h>
+#include <private/qjsvalue_p.h>
#ifdef Q_CC_MSVC
#define NO_INLINE __declspec(noinline)
@@ -220,6 +221,7 @@ private slots:
void multilineStrings();
void throwError();
+ void mathMinMax();
public:
Q_INVOKABLE QJSValue throwingCppMethod();
@@ -4326,6 +4328,21 @@ QJSValue tst_QJSEngine::throwingCppMethod()
return QJSValue(47);
}
+void tst_QJSEngine::mathMinMax()
+{
+ QJSEngine engine;
+
+ QJSValue result = engine.evaluate("var a = .5; Math.min(1, 2, 3.5 + a, '5')");
+ QCOMPARE(result.toNumber(), 1.0);
+ QVERIFY(QJSValuePrivate::getValue(&result) != nullptr);
+ QVERIFY(QJSValuePrivate::getValue(&result)->isInteger());
+
+ result = engine.evaluate("var a = .5; Math.max('0', 1, 2, 3.5 + a)");
+ QCOMPARE(result.toNumber(), 4.0);
+ QVERIFY(QJSValuePrivate::getValue(&result) != nullptr);
+ QVERIFY(QJSValuePrivate::getValue(&result)->isInteger());
+}
+
QTEST_MAIN(tst_QJSEngine)
#include "tst_qjsengine.moc"