diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2023-05-09 12:00:03 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2023-05-11 08:04:02 +0200 |
commit | 2316da3a800428d41432a052280ea0cd26465c2c (patch) | |
tree | 058448cf0b0360f83c7a672052ddc590c3c74ad0 | |
parent | 60a34c33934e264e42d7aef00500f5ebf7f03bff (diff) | |
download | qtdeclarative-2316da3a800428d41432a052280ea0cd26465c2c.tar.gz |
QmlCompiler: Improve argument construction in generated code
We don't have to pass types that don't fit if we actually have the
correct types in suitable wrappers.
This still invokes the internal conversions of the call frame setup if
we call with really generic types, for example if the same value is read
multiple times with different target types. However, that is acceptable.
Fixes: QTBUG-113465
Change-Id: I8ec4afeb39bbe6585e5268c0e9b0cfd2788d761a
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r-- | src/qml/jsapi/qjsprimitivevalue.cpp | 11 | ||||
-rw-r--r-- | src/qml/jsapi/qjsprimitivevalue.h | 27 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljscodegenerator.cpp | 45 |
3 files changed, 55 insertions, 28 deletions
diff --git a/src/qml/jsapi/qjsprimitivevalue.cpp b/src/qml/jsapi/qjsprimitivevalue.cpp index 3ab2ade0dc..0bef52b5d8 100644 --- a/src/qml/jsapi/qjsprimitivevalue.cpp +++ b/src/qml/jsapi/qjsprimitivevalue.cpp @@ -146,6 +146,17 @@ QT_BEGIN_NAMESPACE */ /*! + \fn QJSPrimitiveValue::QJSPrimitiveValue(QMetaType type) + \since 6.6 + \internal + + Creates a QJSPrimitiveValue of type \a type, and initializes with a + default-constructed value if \a type can be stored in QJSPrimtiveValue. + If \a type cannot be stored this results in a QJSPrimitiveValue of type + Undefined. +*/ + +/*! \fn QJSPrimitiveValue::QJSPrimitiveValue(const QVariant &value) Creates a QJSPrimitiveValue from the contents of \a value if those contents diff --git a/src/qml/jsapi/qjsprimitivevalue.h b/src/qml/jsapi/qjsprimitivevalue.h index bb710eb31b..1f41743f65 100644 --- a/src/qml/jsapi/qjsprimitivevalue.h +++ b/src/qml/jsapi/qjsprimitivevalue.h @@ -163,6 +163,33 @@ public: } } + explicit QJSPrimitiveValue(const QMetaType type) noexcept + { + switch (type.id()) { + case QMetaType::UnknownType: + d = QJSPrimitiveUndefined(); + break; + case QMetaType::Nullptr: + d = QJSPrimitiveNull(); + break; + case QMetaType::Bool: + d = false; + break; + case QMetaType::Int: + d = 0; + break; + case QMetaType::Double: + d = 0.0; + break; + case QMetaType::QString: + d = QString(); + break; + default: + // Unsupported. Remains undefined. + break; + } + } + explicit QJSPrimitiveValue(const QVariant &variant) noexcept : QJSPrimitiveValue(variant.metaType(), variant.data()) { diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp index c1df2d9cca..810ed90cc9 100644 --- a/src/qmlcompiler/qqmljscodegenerator.cpp +++ b/src/qmlcompiler/qqmljscodegenerator.cpp @@ -1316,7 +1316,6 @@ QString QQmlJSCodeGenerator::argumentsList(int argc, int argv, QString *outVar) { QString types; QString args; - QString conversions; if (m_state.changedRegisterIndex() == InvalidRegister || m_typeResolver->registerContains( @@ -1326,39 +1325,29 @@ QString QQmlJSCodeGenerator::argumentsList(int argc, int argv, QString *outVar) } else { *outVar = u"callResult"_s; const QQmlJSScope::ConstPtr outType = m_state.accumulatorOut().storedType(); - m_body += outType->internalName(); - if (outType->accessSemantics() == QQmlJSScope::AccessSemantics::Reference) - m_body += u" *"_s; - else - m_body += u' '; - m_body += *outVar + u";\n"; + m_body += outType->augmentedInternalName() + u' ' + *outVar; + if (!m_typeResolver->registerContains(m_state.accumulatorOut(), outType)) { + if (m_typeResolver->equals(outType, m_typeResolver->varType()) + || m_typeResolver->equals(outType, m_typeResolver->jsPrimitiveType())) { + m_body += u'(' + + metaType(m_typeResolver->containedType(m_state.accumulatorOut())) + + u')'; + } + } + m_body += u";\n"; - types = metaTypeFromType(m_state.accumulatorOut().storedType()); - args = u'&' + *outVar; + args = contentPointer(m_state.accumulatorOut(), *outVar); + types = contentType(m_state.accumulatorOut(), *outVar); } for (int i = 0; i < argc; ++i) { const QQmlJSRegisterContent content = registerType(argv + i); - if (m_typeResolver->registerIsStoredIn(content, m_typeResolver->jsPrimitiveType())) { - QString argName = u"arg"_s + QString::number(i); - conversions += u"QVariant "_s + argName + u" = "_s - + convertStored(content.storedType(), m_typeResolver->varType(), - consumedRegisterVariable(argv + i)) + u";\n"_s; - args += u", "_s + argName + u".data()"_s; - types += u", "_s + argName + u".metaType()"_s; - } else if (m_typeResolver->registerIsStoredIn(content, m_typeResolver->varType()) - && !m_typeResolver->registerContains(content, m_typeResolver->varType())) { - const QString var = registerVariable(argv + i); - args += u", "_s + var + u".data()"_s; - types += u", "_s + var + u".metaType()"_s; - } else { - const QString var = registerVariable(argv + i); - args += u", &"_s + var; - types += u", "_s + metaTypeFromType(content.storedType()); - } + const QString var = registerVariable(argv + i); + args += u", "_s + contentPointer(content, var); + types += u", "_s + contentType(content, var); } - return conversions - + u"void *args[] = { "_s + args + u" };\n"_s + + return u"void *args[] = { "_s + args + u" };\n"_s + u"const QMetaType types[] = { "_s + types + u" };\n"_s; } |