summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2021-01-27 19:43:15 +0100
committerUlf Hermann <ulf.hermann@qt.io>2021-01-29 16:52:20 +0100
commit4bec8958bb8f709efe74216fb68f36976c5a7a5b (patch)
tree848d91bd7d5749698e5cfe852bcd367fd7ab6fa7
parentbb3f78b22a4f74f27ec99ef6dcca46543881e92a (diff)
QmlCompiler: Generate AOT functions in same order as interpreted ones
Otherwise various internal indices may be off, in particular the internal classes. Change-Id: I3c2a6b8150590fc41ec55bf2dfbc989078ddce42 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r--src/qmlcompiler/qqmljscompiler.cpp105
1 files changed, 71 insertions, 34 deletions
diff --git a/src/qmlcompiler/qqmljscompiler.cpp b/src/qmlcompiler/qqmljscompiler.cpp
index 549ee9116b..1b6583ccf6 100644
--- a/src/qmlcompiler/qqmljscompiler.cpp
+++ b/src/qmlcompiler/qqmljscompiler.cpp
@@ -36,6 +36,8 @@
#include <QtCore/qfile.h>
#include <QtCore/qloggingcategory.h>
+#include <limits>
+
Q_LOGGING_CATEGORY(lcAotCompiler, "qml.compiler.aot", QtWarningMsg);
QT_BEGIN_NAMESPACE
@@ -162,6 +164,34 @@ static bool checkArgumentsObjectUseInSignalHandlers(const QmlIR::Document &doc,
return true;
}
+class BindingOrFunction
+{
+public:
+ BindingOrFunction(const QmlIR::Binding &b) : m_binding(&b) {}
+ BindingOrFunction(const QmlIR::Function &f) : m_function(&f) {}
+
+ friend bool operator<(const BindingOrFunction &lhs, const BindingOrFunction &rhs)
+ {
+ return lhs.index() < rhs.index();
+ }
+
+ const QmlIR::Binding *binding() const { return m_binding; }
+ const QmlIR::Function *function() const { return m_function; }
+
+ quint32 index() const
+ {
+ return m_binding
+ ? m_binding->value.compiledScriptIndex
+ : (m_function
+ ? m_function->index
+ : std::numeric_limits<quint32>::max());
+ }
+
+private:
+ const QmlIR::Binding *m_binding = nullptr;
+ const QmlIR::Function *m_function = nullptr;
+};
+
bool qCompileQmlFile(const QString &inputFileName, QQmlJSSaveFunction saveFunction,
QQmlJSAotCompiler *aotCompiler, QQmlJSCompileError *error)
{
@@ -224,48 +254,55 @@ bool qCompileQmlFile(const QString &inputFileName, QQmlJSSaveFunction saveFuncti
}
aotCompiler->setScope(object, scope);
-
aotFunctionsByIndex[FileScopeCodeIndex] = aotCompiler->globalCode();
- std::for_each(object->bindingsBegin(), object->bindingsEnd(), [&](const QmlIR::Binding &binding) {
- switch (binding.type) {
- case QmlIR::Binding::Type_AttachedProperty:
- case QmlIR::Binding::Type_GroupProperty:
- effectiveScopes.insert(irDocument.objects.at(binding.value.objectIndex), scope);
- return;
- case QmlIR::Binding::Type_Boolean:
- case QmlIR::Binding::Type_Number:
- case QmlIR::Binding::Type_String:
- case QmlIR::Binding::Type_Null:
- return;
- default:
- break;
+ std::vector<BindingOrFunction> bindingsAndFunctions;
+ bindingsAndFunctions.reserve(object->bindingCount() + object->functionCount());
+
+ std::copy(object->bindingsBegin(), object->bindingsEnd(),
+ std::back_inserter(bindingsAndFunctions));
+ std::copy(object->functionsBegin(), object->functionsEnd(),
+ std::back_inserter(bindingsAndFunctions));
+
+ // AOT-compile bindings and functions in the same order as above so that the runtime
+ // class indices match
+ std::sort(bindingsAndFunctions.begin(), bindingsAndFunctions.end());
+ std::for_each(bindingsAndFunctions.begin(), bindingsAndFunctions.end(),
+ [&](const BindingOrFunction &bindingOrFunction) {
+ std::variant<QQmlJSAotFunction, QQmlJS::DiagnosticMessage> result;
+ if (const auto *binding = bindingOrFunction.binding()) {
+ switch (binding->type) {
+ case QmlIR::Binding::Type_AttachedProperty:
+ case QmlIR::Binding::Type_GroupProperty:
+ effectiveScopes.insert(
+ irDocument.objects.at(binding->value.objectIndex), scope);
+ return;
+ case QmlIR::Binding::Type_Boolean:
+ case QmlIR::Binding::Type_Number:
+ case QmlIR::Binding::Type_String:
+ case QmlIR::Binding::Type_Null:
+ return;
+ default:
+ break;
+ }
+
+ qCDebug(lcAotCompiler) << "Compiling binding for property"
+ << irDocument.stringAt(binding->propertyNameIndex);
+ result = aotCompiler->compileBinding(*binding);
+ } else if (const auto *function = bindingOrFunction.function()) {
+ qCDebug(lcAotCompiler) << "Compiling function"
+ << irDocument.stringAt(function->nameIndex);
+ result = aotCompiler->compileFunction(*function);
+ } else {
+ Q_UNREACHABLE();
}
- qCDebug(lcAotCompiler) << "Compiling binding for property"
- << irDocument.stringAt(binding.propertyNameIndex);
- auto result = aotCompiler->compileBinding(binding);
- if (auto *error = std::get_if<QQmlJS::DiagnosticMessage>(&result)) {
- qCDebug(lcAotCompiler) << "Could not compile binding:"
- << diagnosticErrorMessage(inputFileName, *error);
- } else if (auto *func = std::get_if<QQmlJSAotFunction>(&result)) {
- qCInfo(lcAotCompiler) << "Generated code:" << func->code;
- aotFunctionsByIndex[runtimeFunctionIndices[binding.value.compiledScriptIndex]] = *func;
- }
- });
-
- std::for_each(object->functionsBegin(), object->functionsEnd(),
- [&](const QmlIR::Function &function) {
-
- qCDebug(lcAotCompiler) << "Compiling function"
- << irDocument.stringAt(function.nameIndex);
- auto result = aotCompiler->compileFunction(function);
if (auto *error = std::get_if<QQmlJS::DiagnosticMessage>(&result)) {
- qCDebug(lcAotCompiler) << "Could not compile function:"
+ qCDebug(lcAotCompiler) << "Compilation failed:"
<< diagnosticErrorMessage(inputFileName, *error);
} else if (auto *func = std::get_if<QQmlJSAotFunction>(&result)) {
qCInfo(lcAotCompiler) << "Generated code:" << func->code;
- aotFunctionsByIndex[runtimeFunctionIndices[function.index]] = *func;
+ aotFunctionsByIndex[runtimeFunctionIndices[bindingOrFunction.index()]] = *func;
}
});
}