diff options
author | Erik Verbruggen <erik.verbruggen@qt.io> | 2018-07-06 14:36:11 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2018-07-13 10:20:07 +0000 |
commit | 8fdfd9ff5ded388a3d29c917aebb795485abfbfd (patch) | |
tree | e9b614f90adbd7943a4c6190e8e1ba39cec37d40 | |
parent | eab3371b91a2a752a123c4995d977a36ff952168 (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.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4mathobject.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4value_p.h | 11 | ||||
-rw-r--r-- | tests/auto/qml/qjsengine/tst_qjsengine.cpp | 17 |
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" |