diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp index 0642cb28e3..bf04081336 100644 --- a/src/qml/qml/qqml.cpp +++ b/src/qml/qml/qqml.cpp @@ -974,6 +974,8 @@ void qmlRegisterTypeAndRevisions( qmlregister(TypeAndRevisionsRegistration, &type); } +struct LookupNotInitialized {}; + QObject *AOTCompiledContext::thisObject() const { return static_cast(engine->handle()->currentStackFrame) @@ -1283,8 +1285,8 @@ static ObjectPropertyResult resetFallbackProperty( static bool isTypeCompatible(QMetaType lookupType, QMetaType propertyType) { - if (!lookupType.isValid()) { - // If type is invalid, then the calling code depends on the lookup + if (lookupType == QMetaType::fromType()) { + // If lookup is not initialized, then the calling code depends on the lookup // to be set up in order to query the type, via lookupResultMetaType. // We cannot verify the type in this case. } else if ((lookupType.flags() & QMetaType::IsQmlList) @@ -1597,8 +1599,10 @@ QMetaType AOTCompiledContext::lookupResultMetaType(uint index) const = reinterpret_cast(l->qobjectFallbackLookup.metaObject - 1); const int coreIndex = l->qobjectFallbackLookup.coreIndex; return metaObject->property(coreIndex).metaType(); + } else if (l->getter == QV4::Lookup::getterQObjectMethod) { + return l->qobjectMethodLookup.propertyData->propType(); } - return QMetaType(); + return QMetaType::fromType(); } static bool isUndefined(const void *value, QMetaType type) @@ -1625,7 +1629,7 @@ void AOTCompiledContext::storeNameSloppy(uint nameIndex, void *value, QMetaType l.nameIndex = nameIndex; l.forCall = false; ObjectPropertyResult storeResult = ObjectPropertyResult::NeedsInit; - switch (initObjectLookup(this, &l, qmlScopeObject, QMetaType())) { + switch (initObjectLookup(this, &l, qmlScopeObject, QMetaType::fromType())) { case ObjectLookupResult::ObjectAsVariant: case ObjectLookupResult::Object: { const QMetaType propType = l.qobjectLookup.propertyData->propType(); @@ -1780,6 +1784,9 @@ bool AOTCompiledContext::callQmlContextPropertyLookup( return false; } + if (types[0] == QMetaType::fromType()) + return false; + function->call(qmlScopeObject, args, types, argc); return !scope.hasException(); } @@ -1787,8 +1794,8 @@ bool AOTCompiledContext::callQmlContextPropertyLookup( void AOTCompiledContext::initCallQmlContextPropertyLookup(uint index) const { Q_UNUSED(index); - Q_ASSERT(engine->hasError()); - amendException(engine->handle()); + if (engine->hasError()) + amendException(engine->handle()); } bool AOTCompiledContext::loadContextIdLookup(uint index, void *target) const @@ -1862,6 +1869,9 @@ bool AOTCompiledContext::callObjectPropertyLookup( return false; } + if (types[0] == QMetaType::fromType()) + return false; + function->call(object, args, types, argc); return !scope.hasException(); } @@ -1869,8 +1879,8 @@ bool AOTCompiledContext::callObjectPropertyLookup( void AOTCompiledContext::initCallObjectPropertyLookup(uint index) const { Q_UNUSED(index); - Q_ASSERT(engine->hasError()); - amendException(engine->handle()); + if (engine->hasError()) + amendException(engine->handle()); } bool AOTCompiledContext::callGlobalLookup( diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp index dba9cfbd2f..18c596e93d 100644 --- a/src/qmlcompiler/qqmljscodegenerator.cpp +++ b/src/qmlcompiler/qqmljscodegenerator.cpp @@ -1551,22 +1551,6 @@ void QQmlJSCodeGenerator::generate_StoreProperty(int nameIndex, int baseReg) reject(u"StoreProperty"_s); } -QString QQmlJSCodeGenerator::setLookupPreparation( - const QQmlJSRegisterContent &content, const QString &arg, int lookup) -{ - if (m_typeResolver->registerContains(content, content.storedType())) - return QString(); - - if (registerIsStoredIn(content, m_typeResolver->varType())) { - return u"const QMetaType argType = aotContext->lookupResultMetaType("_s - + QString::number(lookup) + u");\n"_s - + u"if (argType.isValid())\n "_s + arg + u".convert(argType)"; - } - // TODO: We could make sure they're compatible, for example QObject pointers. - return QString(); -} - - void QQmlJSCodeGenerator::generate_SetLookup(int index, int baseReg) { INJECT_TRACE_INFO(generate_SetLookup); @@ -1605,7 +1589,6 @@ void QQmlJSCodeGenerator::generate_SetLookup(int index, int baseReg) m_body += u"{\n"_s; QString variableIn; QString variableInType; - QString preparation; QString argType; if (!m_typeResolver->registerContains( m_state.accumulatorIn(), property.containedType())) { @@ -1614,11 +1597,7 @@ void QQmlJSCodeGenerator::generate_SetLookup(int index, int baseReg) + u";\n"_s; variableIn = contentPointer(property, u"converted"_s); variableInType = contentType(property, u"converted"_s); - preparation = setLookupPreparation(property, u"converted"_s, index); - if (preparation.isEmpty()) - argType = contentType(property, u"converted"_s); - else - argType = u"argType"_s; + argType = contentType(property, u"converted"_s); } else { variableIn = contentPointer(property, m_state.accumulatorVariableIn); variableInType = contentType(property, m_state.accumulatorVariableIn); @@ -1635,7 +1614,7 @@ void QQmlJSCodeGenerator::generate_SetLookup(int index, int baseReg) + u", "_s + basePointer + u", "_s + variableIn + u')'; const QString initialization = u"aotContext->initSetObjectLookup("_s + indexString + u", "_s + basePointer + u", "_s + argType + u')'; - generateLookup(lookup, initialization, preparation); + generateLookup(lookup, initialization); break; } case QQmlJSScope::AccessSemantics::Sequence: { @@ -1675,7 +1654,7 @@ void QQmlJSCodeGenerator::generate_SetLookup(int index, int baseReg) + indexString + u", "_s + metaObject(originalScope) + u", "_s + argType + u')'; - generateLookup(lookup, initialization, preparation); + generateLookup(lookup, initialization); generateWriteBack(baseReg); break; @@ -1715,7 +1694,8 @@ void QQmlJSCodeGenerator::generate_Resume(int) BYTECODE_UNIMPLEMENTED(); } -QString QQmlJSCodeGenerator::argumentsList(int argc, int argv, QString *outVar) +QQmlJSCodeGenerator::ArgumentsAndTypes QQmlJSCodeGenerator::argumentsList( + int argc, int argv, QString *outVar) { QString types; QString args; @@ -1729,12 +1709,6 @@ QString QQmlJSCodeGenerator::argumentsList(int argc, int argv, QString *outVar) *outVar = u"callResult"_s; const QQmlJSScope::ConstPtr outType = m_state.accumulatorOut().storedType(); 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_state.accumulatorOut().containedType()) + u')'; - } - } m_body += u";\n"; args = contentPointer(m_state.accumulatorOut(), *outVar); @@ -1748,8 +1722,7 @@ QString QQmlJSCodeGenerator::argumentsList(int argc, int argv, QString *outVar) types += u", "_s + contentType(content, var); } - return u"void *args[] = { "_s + args + u" };\n"_s - + u"const QMetaType types[] = { "_s + types + u" };\n"_s; + return {args, types}; } void QQmlJSCodeGenerator::generateMoveOutVar(const QString &outVar) @@ -2264,13 +2237,22 @@ void QQmlJSCodeGenerator::generate_CallPropertyLookup(int index, int base, int a m_body += u"{\n"_s; QString outVar; - m_body += argumentsList(argc, argv, &outVar); - const QString lookup = u"aotContext->callObjectPropertyLookup("_s + indexString - + u", "_s + inputPointer - + u", args, types, "_s + QString::number(argc) + u')'; + const ArgumentsAndTypes argsAndTypes = argumentsList(argc, argv, &outVar); + + m_body += u"const auto doCall = [&]() {\n"_s + + u" void *args[] = {" + argsAndTypes.arguments + u"};\n"_s + + u" QMetaType types[] = {" + argsAndTypes.types + u"};\n"_s + + u" return aotContext->callObjectPropertyLookup("_s + + indexString + u", "_s + inputPointer + u", args, types, " + + QString::number(argc) + u");\n" + + u"};\n"_s; + + const QString lookup = u"doCall()"_s; const QString initialization = u"aotContext->initCallObjectPropertyLookup("_s + indexString + u')'; - generateLookup(lookup, initialization); + const QString preparation = getLookupPreparation(m_state.accumulatorOut(), outVar, index); + + generateLookup(lookup, initialization, preparation); generateMoveOutVar(outVar); m_body += u"}\n"_s; @@ -2320,12 +2302,19 @@ void QQmlJSCodeGenerator::generate_CallQmlContextPropertyLookup(int index, int a m_body += u"{\n"_s; QString outVar; - m_body += argumentsList(argc, argv, &outVar); - const QString lookup = u"aotContext->callQmlContextPropertyLookup("_s + indexString - + u", args, types, "_s + QString::number(argc) + u')'; + const ArgumentsAndTypes argsAndTypes = argumentsList(argc, argv, &outVar); + m_body += u"const auto doCall = [&]() {\n"_s + + u" void *args[] = {" + argsAndTypes.arguments + u"};\n"_s + + u" QMetaType types[] = {" + argsAndTypes.types + u"};\n"_s + + u" return aotContext->callQmlContextPropertyLookup("_s + + indexString + u", args, types, " + QString::number(argc) + u");\n" + + u"};\n"_s; + + const QString lookup = u"doCall()"_s; const QString initialization = u"aotContext->initCallQmlContextPropertyLookup("_s + indexString + u')'; - generateLookup(lookup, initialization); + const QString preparation = getLookupPreparation(m_state.accumulatorOut(), outVar, index); + generateLookup(lookup, initialization, preparation); generateMoveOutVar(outVar); m_body += u"}\n"_s; @@ -2920,6 +2909,12 @@ QString QQmlJSCodeGenerator::getLookupPreparation( return var + u" = QVariant(aotContext->lookupResultMetaType("_s + QString::number(lookup) + u"))"_s; } + + if (registerIsStoredIn(content, m_typeResolver->jsPrimitiveType())) { + return var + u" = QJSPrimitiveValue(aotContext->lookupResultMetaType("_s + + QString::number(lookup) + u"))"_s; + } + // TODO: We could make sure they're compatible, for example QObject pointers. return QString(); } diff --git a/src/qmlcompiler/qqmljscodegenerator_p.h b/src/qmlcompiler/qqmljscodegenerator_p.h index 27bf2b1116..72b91f0c90 100644 --- a/src/qmlcompiler/qqmljscodegenerator_p.h +++ b/src/qmlcompiler/qqmljscodegenerator_p.h @@ -260,8 +260,6 @@ protected: const QString &resultPreparation = QString()); QString getLookupPreparation( const QQmlJSRegisterContent &content, const QString &var, int lookup); - QString setLookupPreparation( - const QQmlJSRegisterContent &content, const QString &arg, int lookup); void generateEnumLookup(int index); QString registerVariable(int index) const; @@ -316,7 +314,14 @@ private: QString eqIntExpression(int lhsConst); - QString argumentsList(int argc, int argv, QString *outVar); + + struct ArgumentsAndTypes + { + QString arguments; + QString types; + }; + + ArgumentsAndTypes argumentsList(int argc, int argv, QString *outVar); QString castTargetName(const QQmlJSScope::ConstPtr &type) const; bool inlineStringMethod(const QString &name, int base, int argc, int argv);