QtQml: Optimize reading properties into V4 values
We need to be more careful here since the builtins will become proper value types with metaobjects, but we don't want to encode them into QQmlValueTypeWrapper, but rather their specialized representations. Besides, avoiding the code path via QVariant and engine->fromVariant() is also a performance boost. Task-number: QTBUG-101143 Change-Id: I1c570ebcb6c4e129e9bdeef069b8a49e2a1e29d6 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io> Reviewed-by: Semih Yavuz <semih.yavuz@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
8b022182d2
commit
128d31cde0
|
@ -552,6 +552,7 @@ public:
|
|||
Heap::Object *newObject();
|
||||
Heap::Object *newObject(Heap::InternalClass *internalClass);
|
||||
|
||||
Heap::String *newString(char16_t c) { return newString(QChar(c)); }
|
||||
Heap::String *newString(const QString &s = QString());
|
||||
Heap::String *newIdentifier(const QString &text);
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <private/qqmlvaluetypewrapper_p.h>
|
||||
#include <private/qqmllistwrapper_p.h>
|
||||
#include <private/qqmlbuiltinfunctions_p.h>
|
||||
#include <private/qqmllocale_p.h>
|
||||
|
||||
#include <private/qv4arraybuffer_p.h>
|
||||
#include <private/qv4functionobject_p.h>
|
||||
|
@ -48,6 +49,7 @@
|
|||
#endif
|
||||
#include <QtCore/qloggingcategory.h>
|
||||
#include <QtCore/qqueue.h>
|
||||
#include <QtCore/qtypes.h>
|
||||
|
||||
#include <vector>
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
@ -131,37 +133,143 @@ static ReturnedValue loadProperty(
|
|||
if (property.isQList() && propMetaType.flags().testFlag(QMetaType::IsQmlList))
|
||||
return QmlListWrapper::create(v4, object, property.coreIndex(), propMetaType);
|
||||
|
||||
// TODO: Check all the builtin types here. See getGadgetProperty() in qqmlvaluetypewrapper.cpp
|
||||
switch (property.isEnum() ? propMetaType.underlyingType().id() : propMetaType.id()) {
|
||||
case QMetaType::Int: {
|
||||
int v = 0;
|
||||
const auto encodeSimple = [&](auto v) {
|
||||
property.readProperty(object, &v);
|
||||
return Encode(v);
|
||||
}
|
||||
case QMetaType::Bool: {
|
||||
bool v = false;
|
||||
};
|
||||
|
||||
const auto encodeInt = [&](auto v) {
|
||||
property.readProperty(object, &v);
|
||||
return Encode(v);
|
||||
}
|
||||
case QMetaType::QString: {
|
||||
QString v;
|
||||
return Encode(int(v));
|
||||
};
|
||||
|
||||
const auto encodeDouble = [&](auto v) {
|
||||
property.readProperty(object, &v);
|
||||
return Encode(double(v));
|
||||
};
|
||||
|
||||
const auto encodeDate = [&](auto v) {
|
||||
property.readProperty(object, &v);
|
||||
return Encode(v4->newDateObject(
|
||||
v, wrapper, property.coreIndex(), referenceFlags(scope.engine, property)));
|
||||
};
|
||||
|
||||
const auto encodeString = [&](auto v) {
|
||||
property.readProperty(object, &v);
|
||||
return v4->newString(v)->asReturnedValue();
|
||||
}
|
||||
case QMetaType::UInt: {
|
||||
uint v = 0;
|
||||
};
|
||||
|
||||
const auto encodeSequence = [&](QMetaSequence metaSequence) {
|
||||
// Pass nullptr as data. It's lazy-loaded.
|
||||
return QV4::SequencePrototype::newSequence(
|
||||
v4, propMetaType, metaSequence, nullptr,
|
||||
wrapper, property.coreIndex(), referenceFlags(scope.engine, property));
|
||||
};
|
||||
|
||||
|
||||
switch (property.isEnum() ? propMetaType.underlyingType().id() : propMetaType.id()) {
|
||||
case QMetaType::UnknownType:
|
||||
case QMetaType::Void:
|
||||
return Encode::undefined();
|
||||
case QMetaType::Nullptr:
|
||||
case QMetaType::VoidStar:
|
||||
return Encode::null();
|
||||
case QMetaType::Int:
|
||||
return encodeSimple(int());
|
||||
case QMetaType::Bool:
|
||||
return encodeSimple(bool());
|
||||
case QMetaType::QString:
|
||||
return encodeString(QString());
|
||||
case QMetaType::QByteArray: {
|
||||
QByteArray v;
|
||||
property.readProperty(object, &v);
|
||||
return Encode(v);
|
||||
return v4->newArrayBuffer(v)->asReturnedValue();
|
||||
}
|
||||
case QMetaType::Float: {
|
||||
float v = 0;
|
||||
case QMetaType::QChar:
|
||||
return encodeString(QChar());
|
||||
case QMetaType::Char16:
|
||||
return encodeString(char16_t());
|
||||
case QMetaType::UInt:
|
||||
return encodeSimple(uint());
|
||||
case QMetaType::Float:
|
||||
return encodeSimple(float());
|
||||
case QMetaType::Double:
|
||||
return encodeSimple(double());
|
||||
case QMetaType::Short:
|
||||
return encodeInt(short());
|
||||
case QMetaType::UShort:
|
||||
return encodeInt(ushort());
|
||||
case QMetaType::Char:
|
||||
return encodeInt(char());
|
||||
case QMetaType::UChar:
|
||||
return encodeInt(uchar());
|
||||
case QMetaType::SChar:
|
||||
return encodeInt(qint8());
|
||||
case QMetaType::Long:
|
||||
return encodeDouble(long());
|
||||
case QMetaType::ULong:
|
||||
return encodeDouble(ulong());
|
||||
case QMetaType::LongLong:
|
||||
return encodeDouble(qlonglong());
|
||||
case QMetaType::ULongLong:
|
||||
return encodeDouble(qulonglong());
|
||||
case QMetaType::QDateTime:
|
||||
return encodeDate(QDateTime());
|
||||
case QMetaType::QDate:
|
||||
return encodeDate(QDate());
|
||||
case QMetaType::QTime:
|
||||
return encodeDate(QTime());
|
||||
#if QT_CONFIG(regularexpression)
|
||||
case QMetaType::QRegularExpression: {
|
||||
QRegularExpression v;
|
||||
property.readProperty(object, &v);
|
||||
return Encode(v);
|
||||
return Encode(v4->newRegExpObject(v));
|
||||
}
|
||||
case QMetaType::Double: {
|
||||
double v = 0;
|
||||
#endif
|
||||
case QMetaType::QVariantMap: {
|
||||
QVariantMap v;
|
||||
property.readProperty(object, &v);
|
||||
return Encode(v);
|
||||
return scope.engine->fromData(
|
||||
propMetaType, &v, wrapper, property.coreIndex(), referenceFlags(v4, property));
|
||||
}
|
||||
case QMetaType::QJsonValue: {
|
||||
QJsonValue v;
|
||||
property.readProperty(object, &v);
|
||||
return QV4::JsonObject::fromJsonValue(v4, v);
|
||||
}
|
||||
case QMetaType::QJsonObject: {
|
||||
QJsonObject v;
|
||||
property.readProperty(object, &v);
|
||||
return QV4::JsonObject::fromJsonObject(v4, v);
|
||||
}
|
||||
case QMetaType::QJsonArray: {
|
||||
QJsonArray v;
|
||||
property.readProperty(object, &v);
|
||||
return QV4::JsonObject::fromJsonArray(v4, v);
|
||||
}
|
||||
#if QT_CONFIG(qml_locale)
|
||||
case QMetaType::QLocale: {
|
||||
QLocale v;
|
||||
property.readProperty(object, &v);
|
||||
return QQmlLocale::wrap(v4, v);
|
||||
}
|
||||
#endif
|
||||
case QMetaType::QStringList:
|
||||
return encodeSequence(QMetaSequence::fromContainer<QStringList>());
|
||||
case QMetaType::QVariantList:
|
||||
return encodeSequence(QMetaSequence::fromContainer<QVariantList>());
|
||||
case QMetaType::QUrl: {
|
||||
// ### Qt7: We really want this to be a JS URL object, but that would break things.
|
||||
QUrl v;
|
||||
property.readProperty(object, &v);
|
||||
return Encode(v4->newVariantObject(propMetaType, &v));
|
||||
}
|
||||
case QMetaType::QPixmap:
|
||||
case QMetaType::QImage: {
|
||||
// Scarce value types
|
||||
QVariant v(propMetaType);
|
||||
property.readProperty(object, v.data());
|
||||
return Encode(v4->newVariantObject(propMetaType, v.constData()));
|
||||
}
|
||||
default:
|
||||
break;
|
||||
|
@ -205,13 +313,9 @@ static ReturnedValue loadProperty(
|
|||
}
|
||||
|
||||
// See if it's a sequence type.
|
||||
// Pass nullptr as data. It's lazy-loaded.
|
||||
const QQmlType qmlType = QQmlMetaType::qmlListType(propMetaType);
|
||||
if (qmlType.isSequentialContainer()) {
|
||||
return QV4::SequencePrototype::newSequence(
|
||||
v4, propMetaType, qmlType.listMetaSequence(), nullptr,
|
||||
wrapper, property.coreIndex(), referenceFlags(scope.engine, property));
|
||||
}
|
||||
if (qmlType.isSequentialContainer())
|
||||
return encodeSequence(qmlType.listMetaSequence());
|
||||
|
||||
QVariant v(propMetaType);
|
||||
property.readProperty(object, v.data());
|
||||
|
|
Loading…
Reference in New Issue