QmlCompiler: Use lookupResultMetaType() also for calls

This is generally better than doing a string lookup of the type. In
turn, drop the lookup preparation for SetLookup. It's not doing anything
useful anymore and would fail on the new lookupResultMetaType().

Change-Id: If52a44161f106c72c34d0d4ada2052fc2e287b4d
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Ulf Hermann 2024-08-23 14:52:35 +02:00
parent ec124524ec
commit 1d59171d19
3 changed files with 63 additions and 53 deletions

View File

@ -974,6 +974,8 @@ void qmlRegisterTypeAndRevisions<QQmlTypeNotAvailable, void>(
qmlregister(TypeAndRevisionsRegistration, &type); qmlregister(TypeAndRevisionsRegistration, &type);
} }
struct LookupNotInitialized {};
QObject *AOTCompiledContext::thisObject() const QObject *AOTCompiledContext::thisObject() const
{ {
return static_cast<QV4::MetaTypesStackFrame *>(engine->handle()->currentStackFrame) return static_cast<QV4::MetaTypesStackFrame *>(engine->handle()->currentStackFrame)
@ -1283,8 +1285,8 @@ static ObjectPropertyResult resetFallbackProperty(
static bool isTypeCompatible(QMetaType lookupType, QMetaType propertyType) static bool isTypeCompatible(QMetaType lookupType, QMetaType propertyType)
{ {
if (!lookupType.isValid()) { if (lookupType == QMetaType::fromType<LookupNotInitialized>()) {
// If type is invalid, then the calling code depends on the lookup // 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. // to be set up in order to query the type, via lookupResultMetaType.
// We cannot verify the type in this case. // We cannot verify the type in this case.
} else if ((lookupType.flags() & QMetaType::IsQmlList) } else if ((lookupType.flags() & QMetaType::IsQmlList)
@ -1597,8 +1599,10 @@ QMetaType AOTCompiledContext::lookupResultMetaType(uint index) const
= reinterpret_cast<const QMetaObject *>(l->qobjectFallbackLookup.metaObject - 1); = reinterpret_cast<const QMetaObject *>(l->qobjectFallbackLookup.metaObject - 1);
const int coreIndex = l->qobjectFallbackLookup.coreIndex; const int coreIndex = l->qobjectFallbackLookup.coreIndex;
return metaObject->property(coreIndex).metaType(); return metaObject->property(coreIndex).metaType();
} else if (l->getter == QV4::Lookup::getterQObjectMethod) {
return l->qobjectMethodLookup.propertyData->propType();
} }
return QMetaType(); return QMetaType::fromType<LookupNotInitialized>();
} }
static bool isUndefined(const void *value, QMetaType type) static bool isUndefined(const void *value, QMetaType type)
@ -1625,7 +1629,7 @@ void AOTCompiledContext::storeNameSloppy(uint nameIndex, void *value, QMetaType
l.nameIndex = nameIndex; l.nameIndex = nameIndex;
l.forCall = false; l.forCall = false;
ObjectPropertyResult storeResult = ObjectPropertyResult::NeedsInit; ObjectPropertyResult storeResult = ObjectPropertyResult::NeedsInit;
switch (initObjectLookup(this, &l, qmlScopeObject, QMetaType())) { switch (initObjectLookup(this, &l, qmlScopeObject, QMetaType::fromType<LookupNotInitialized>())) {
case ObjectLookupResult::ObjectAsVariant: case ObjectLookupResult::ObjectAsVariant:
case ObjectLookupResult::Object: { case ObjectLookupResult::Object: {
const QMetaType propType = l.qobjectLookup.propertyData->propType(); const QMetaType propType = l.qobjectLookup.propertyData->propType();
@ -1780,6 +1784,9 @@ bool AOTCompiledContext::callQmlContextPropertyLookup(
return false; return false;
} }
if (types[0] == QMetaType::fromType<LookupNotInitialized>())
return false;
function->call(qmlScopeObject, args, types, argc); function->call(qmlScopeObject, args, types, argc);
return !scope.hasException(); return !scope.hasException();
} }
@ -1787,8 +1794,8 @@ bool AOTCompiledContext::callQmlContextPropertyLookup(
void AOTCompiledContext::initCallQmlContextPropertyLookup(uint index) const void AOTCompiledContext::initCallQmlContextPropertyLookup(uint index) const
{ {
Q_UNUSED(index); Q_UNUSED(index);
Q_ASSERT(engine->hasError()); if (engine->hasError())
amendException(engine->handle()); amendException(engine->handle());
} }
bool AOTCompiledContext::loadContextIdLookup(uint index, void *target) const bool AOTCompiledContext::loadContextIdLookup(uint index, void *target) const
@ -1862,6 +1869,9 @@ bool AOTCompiledContext::callObjectPropertyLookup(
return false; return false;
} }
if (types[0] == QMetaType::fromType<LookupNotInitialized>())
return false;
function->call(object, args, types, argc); function->call(object, args, types, argc);
return !scope.hasException(); return !scope.hasException();
} }
@ -1869,8 +1879,8 @@ bool AOTCompiledContext::callObjectPropertyLookup(
void AOTCompiledContext::initCallObjectPropertyLookup(uint index) const void AOTCompiledContext::initCallObjectPropertyLookup(uint index) const
{ {
Q_UNUSED(index); Q_UNUSED(index);
Q_ASSERT(engine->hasError()); if (engine->hasError())
amendException(engine->handle()); amendException(engine->handle());
} }
bool AOTCompiledContext::callGlobalLookup( bool AOTCompiledContext::callGlobalLookup(

View File

@ -1551,22 +1551,6 @@ void QQmlJSCodeGenerator::generate_StoreProperty(int nameIndex, int baseReg)
reject(u"StoreProperty"_s); 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) void QQmlJSCodeGenerator::generate_SetLookup(int index, int baseReg)
{ {
INJECT_TRACE_INFO(generate_SetLookup); INJECT_TRACE_INFO(generate_SetLookup);
@ -1605,7 +1589,6 @@ void QQmlJSCodeGenerator::generate_SetLookup(int index, int baseReg)
m_body += u"{\n"_s; m_body += u"{\n"_s;
QString variableIn; QString variableIn;
QString variableInType; QString variableInType;
QString preparation;
QString argType; QString argType;
if (!m_typeResolver->registerContains( if (!m_typeResolver->registerContains(
m_state.accumulatorIn(), property.containedType())) { m_state.accumulatorIn(), property.containedType())) {
@ -1614,11 +1597,7 @@ void QQmlJSCodeGenerator::generate_SetLookup(int index, int baseReg)
+ u";\n"_s; + u";\n"_s;
variableIn = contentPointer(property, u"converted"_s); variableIn = contentPointer(property, u"converted"_s);
variableInType = contentType(property, u"converted"_s); variableInType = contentType(property, u"converted"_s);
preparation = setLookupPreparation(property, u"converted"_s, index); argType = contentType(property, u"converted"_s);
if (preparation.isEmpty())
argType = contentType(property, u"converted"_s);
else
argType = u"argType"_s;
} else { } else {
variableIn = contentPointer(property, m_state.accumulatorVariableIn); variableIn = contentPointer(property, m_state.accumulatorVariableIn);
variableInType = contentType(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')'; + u", "_s + basePointer + u", "_s + variableIn + u')';
const QString initialization = u"aotContext->initSetObjectLookup("_s const QString initialization = u"aotContext->initSetObjectLookup("_s
+ indexString + u", "_s + basePointer + u", "_s + argType + u')'; + indexString + u", "_s + basePointer + u", "_s + argType + u')';
generateLookup(lookup, initialization, preparation); generateLookup(lookup, initialization);
break; break;
} }
case QQmlJSScope::AccessSemantics::Sequence: { case QQmlJSScope::AccessSemantics::Sequence: {
@ -1675,7 +1654,7 @@ void QQmlJSCodeGenerator::generate_SetLookup(int index, int baseReg)
+ indexString + u", "_s + metaObject(originalScope) + indexString + u", "_s + metaObject(originalScope)
+ u", "_s + argType + u')'; + u", "_s + argType + u')';
generateLookup(lookup, initialization, preparation); generateLookup(lookup, initialization);
generateWriteBack(baseReg); generateWriteBack(baseReg);
break; break;
@ -1715,7 +1694,8 @@ void QQmlJSCodeGenerator::generate_Resume(int)
BYTECODE_UNIMPLEMENTED(); BYTECODE_UNIMPLEMENTED();
} }
QString QQmlJSCodeGenerator::argumentsList(int argc, int argv, QString *outVar) QQmlJSCodeGenerator::ArgumentsAndTypes QQmlJSCodeGenerator::argumentsList(
int argc, int argv, QString *outVar)
{ {
QString types; QString types;
QString args; QString args;
@ -1729,12 +1709,6 @@ QString QQmlJSCodeGenerator::argumentsList(int argc, int argv, QString *outVar)
*outVar = u"callResult"_s; *outVar = u"callResult"_s;
const QQmlJSScope::ConstPtr outType = m_state.accumulatorOut().storedType(); const QQmlJSScope::ConstPtr outType = m_state.accumulatorOut().storedType();
m_body += outType->augmentedInternalName() + u' ' + *outVar; 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"; m_body += u";\n";
args = contentPointer(m_state.accumulatorOut(), *outVar); 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); types += u", "_s + contentType(content, var);
} }
return u"void *args[] = { "_s + args + u" };\n"_s return {args, types};
+ u"const QMetaType types[] = { "_s + types + u" };\n"_s;
} }
void QQmlJSCodeGenerator::generateMoveOutVar(const QString &outVar) 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; m_body += u"{\n"_s;
QString outVar; QString outVar;
m_body += argumentsList(argc, argv, &outVar); const ArgumentsAndTypes argsAndTypes = argumentsList(argc, argv, &outVar);
const QString lookup = u"aotContext->callObjectPropertyLookup("_s + indexString
+ u", "_s + inputPointer m_body += u"const auto doCall = [&]() {\n"_s
+ u", args, types, "_s + QString::number(argc) + u')'; + 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 const QString initialization = u"aotContext->initCallObjectPropertyLookup("_s
+ indexString + u')'; + indexString + u')';
generateLookup(lookup, initialization); const QString preparation = getLookupPreparation(m_state.accumulatorOut(), outVar, index);
generateLookup(lookup, initialization, preparation);
generateMoveOutVar(outVar); generateMoveOutVar(outVar);
m_body += u"}\n"_s; m_body += u"}\n"_s;
@ -2320,12 +2302,19 @@ void QQmlJSCodeGenerator::generate_CallQmlContextPropertyLookup(int index, int a
m_body += u"{\n"_s; m_body += u"{\n"_s;
QString outVar; QString outVar;
m_body += argumentsList(argc, argv, &outVar); const ArgumentsAndTypes argsAndTypes = argumentsList(argc, argv, &outVar);
const QString lookup = u"aotContext->callQmlContextPropertyLookup("_s + indexString m_body += u"const auto doCall = [&]() {\n"_s
+ u", args, types, "_s + QString::number(argc) + u')'; + 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 const QString initialization = u"aotContext->initCallQmlContextPropertyLookup("_s
+ indexString + u')'; + indexString + u')';
generateLookup(lookup, initialization); const QString preparation = getLookupPreparation(m_state.accumulatorOut(), outVar, index);
generateLookup(lookup, initialization, preparation);
generateMoveOutVar(outVar); generateMoveOutVar(outVar);
m_body += u"}\n"_s; m_body += u"}\n"_s;
@ -2920,6 +2909,12 @@ QString QQmlJSCodeGenerator::getLookupPreparation(
return var + u" = QVariant(aotContext->lookupResultMetaType("_s return var + u" = QVariant(aotContext->lookupResultMetaType("_s
+ QString::number(lookup) + u"))"_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. // TODO: We could make sure they're compatible, for example QObject pointers.
return QString(); return QString();
} }

View File

@ -260,8 +260,6 @@ protected:
const QString &resultPreparation = QString()); const QString &resultPreparation = QString());
QString getLookupPreparation( QString getLookupPreparation(
const QQmlJSRegisterContent &content, const QString &var, int lookup); const QQmlJSRegisterContent &content, const QString &var, int lookup);
QString setLookupPreparation(
const QQmlJSRegisterContent &content, const QString &arg, int lookup);
void generateEnumLookup(int index); void generateEnumLookup(int index);
QString registerVariable(int index) const; QString registerVariable(int index) const;
@ -316,7 +314,14 @@ private:
QString eqIntExpression(int lhsConst); 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; QString castTargetName(const QQmlJSScope::ConstPtr &type) const;
bool inlineStringMethod(const QString &name, int base, int argc, int argv); bool inlineStringMethod(const QString &name, int base, int argc, int argv);