Skip to content

Commit

Permalink
QML: Collapse all NaNs into one single (encoded) NaN
Browse files Browse the repository at this point in the history
The idea of NaN boxing is to use one single NaN as a "true" NaN, and all
others as a boxed value. So when encoding some NaN, be sure to use that
one "true" NaN. Otherwise, it will be interpreted as an encoded value.

Task-number: QTBUG-65998
Change-Id: Ia6e4641be180f3d626c40a57b473f181358e04db
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
  • Loading branch information
Erik Verbruggen committed Feb 5, 2018
1 parent c2bd33a commit 8501993
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/qml/jsruntime/qv4value_p.h
Expand Up @@ -56,6 +56,8 @@
#include "qv4global_p.h"
#include <private/qv4heap_p.h>

#include <private/qnumeric_p.h>

#if QT_POINTER_SIZE == 8
#define QV4_USE_64_BIT_VALUE_ENCODING
#endif
Expand Down Expand Up @@ -362,6 +364,8 @@ struct Q_QML_PRIVATE_EXPORT Value
return d;
}
QML_NEARLY_ALWAYS_INLINE void setDouble(double d) {
if (qt_is_nan(d))
d = qt_qnan();
memcpy(&_val, &d, 8);
#ifdef QV4_USE_64_BIT_VALUE_ENCODING
_val ^= NaNEncodeMask;
Expand Down
5 changes: 5 additions & 0 deletions tests/auto/qml/qqmlecmascript/data/nans.qml
@@ -0,0 +1,5 @@
import QtQuick 2.0

QtObject {
property var prop: undefined
}
15 changes: 15 additions & 0 deletions tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
Expand Up @@ -338,6 +338,7 @@ private slots:
void freeze_empty_object();
void singleBlockLoops();
void qtbug_60547();
void anotherNaN();

private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
Expand Down Expand Up @@ -8266,6 +8267,20 @@ void tst_qqmlecmascript::qtbug_60547()
QCOMPARE(object->property("counter"), QVariant(int(1)));
}

void tst_qqmlecmascript::anotherNaN()
{
QQmlComponent component(&engine, testFileUrl("nans.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY2(!object.isNull(), qPrintable(component.errorString()));
object->setProperty("prop", std::numeric_limits<double>::quiet_NaN()); // don't crash

std::uint64_t anotherNaN = 0xFFFFFF01000000F7ul;
double d;
std::memcpy(&d, &anotherNaN, sizeof(d));
QVERIFY(std::isnan(d));
object->setProperty("prop", d); // don't crash
}

QTEST_MAIN(tst_qqmlecmascript)

#include "tst_qqmlecmascript.moc"

0 comments on commit 8501993

Please sign in to comment.