aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2021-01-07 16:07:00 +0100
committerUlf Hermann <ulf.hermann@qt.io>2021-01-11 22:59:34 +0100
commit9694e0631da9ae94dab4229091f382528700af90 (patch)
treebd2462d87e497829310df0bf6e2b18e5ea5161cb
parent05b5a0896da2c12d50898abb2bf3dc5c5f158a16 (diff)
Pass a more comprehensive context to AOT-compiled functions
We need the compilation unit, and a way to retrieve JavaScript metatypes from it. Also, prepare for cases where we only have a QJSEngine, not a QQmlEngine, and pass the scope object as part of the AOT context. Change-Id: Ica81e92c99f3c9b6baffd04db1e0e91603fd2ac7 Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp9
-rw-r--r--src/qml/qml/qqml.cpp7
-rw-r--r--src/qml/qml/qqmlprivate.h12
-rw-r--r--src/qml/qml/qqmlpropertybinding.cpp11
-rw-r--r--src/qmlcompiler/qqmljscompiler.cpp41
5 files changed, 55 insertions, 25 deletions
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 9fefa2a38c..bea301c6e3 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -489,9 +489,12 @@ ReturnedValue VME::exec(CppStackFrame *frame, ExecutionEngine *engine)
Scope scope(engine);
Scoped<QmlContext> qmlContext(scope, engine->qmlContext());
- function->aotFunction->functionPtr(
- qmlContext->qmlContext()->asQQmlContext(), qmlContext->qmlScope(),
- returnValue, argumentPtrs);
+ QQmlPrivate::AOTCompiledContext aotContext;
+ aotContext.qmlContext = qmlContext ? qmlContext->qmlContext()->asQQmlContext() : nullptr;
+ aotContext.qmlScopeObject = qmlContext ? qmlContext->qmlScope() : nullptr;
+ aotContext.engine = engine->jsEngine();
+ aotContext.compilationUnit = function->executableCompilationUnit();
+ function->aotFunction->functionPtr(&aotContext, returnValue, argumentPtrs);
if (returnValue) {
result = engine->metaTypeToJS(returnType.id(), returnValue);
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp
index 40e629284b..9e71c968b8 100644
--- a/src/qml/qml/qqml.cpp
+++ b/src/qml/qml/qqml.cpp
@@ -41,6 +41,7 @@
#include <QtQml/qqmlprivate.h>
+#include <private/qjsvalue_p.h>
#include <private/qqmlengine_p.h>
#include <private/qqmlmetatype_p.h>
#include <private/qqmlmetatypedata_p.h>
@@ -561,4 +562,10 @@ namespace QQmlPrivate {
}
}
+QJSValue QQmlPrivate::AOTCompiledContext::jsMetaType(int index) const
+{
+ return QJSValuePrivate::fromReturnedValue(
+ compilationUnit->runtimeClasses[index]->asReturnedValue());
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h
index a2cd9452ac..ce83b33eaa 100644
--- a/src/qml/qml/qqmlprivate.h
+++ b/src/qml/qml/qqmlprivate.h
@@ -589,12 +589,20 @@ namespace QQmlPrivate
QVector<int> *qmlTypeIds;
};
+ struct AOTCompiledContext {
+ QQmlContext *qmlContext;
+ QObject *qmlScopeObject;
+ QJSEngine *engine;
+ QV4::CompiledData::CompilationUnit *compilationUnit;
+
+ QJSValue Q_QML_EXPORT jsMetaType(int index) const;
+ };
+
struct AOTCompiledFunction {
int index;
QMetaType returnType;
QList<QMetaType> argumentTypes;
- void (*functionPtr)(QQmlContext *context, QObject *scopeObject, void *resultPtr,
- void **arguments);
+ void (*functionPtr)(const AOTCompiledContext *context, void *resultPtr, void **arguments);
};
struct CachedQmlUnit {
diff --git a/src/qml/qml/qqmlpropertybinding.cpp b/src/qml/qml/qqmlpropertybinding.cpp
index 235d9f578f..eaf3524487 100644
--- a/src/qml/qml/qqmlpropertybinding.cpp
+++ b/src/qml/qml/qqmlpropertybinding.cpp
@@ -52,10 +52,15 @@ QUntypedPropertyBinding QQmlPropertyBinding::create(const QQmlPropertyData *pd,
aotFunction,
unit = QQmlRefPointer<QV4::ExecutableCompilationUnit>(function->executableCompilationUnit()),
scopeObject = QPointer<QObject>(obj),
- context = ctxt
+ context = ctxt,
+ engine = scope->engine()
](const QMetaType &, void *dataPtr) -> bool {
- Q_UNUSED(unit); // to keep refcount
- aotFunction->functionPtr(context->asQQmlContext(), scopeObject.data(), dataPtr, nullptr);
+ QQmlPrivate::AOTCompiledContext aotContext;
+ aotContext.qmlContext = context->asQQmlContext();
+ aotContext.qmlScopeObject = scopeObject.data();
+ aotContext.engine = engine->jsEngine();
+ aotContext.compilationUnit = unit.data();
+ aotFunction->functionPtr(&aotContext, dataPtr, nullptr);
// ### Fixme: The aotFunction should do the check whether old and new value are the same and
// return false in that case
return true;
diff --git a/src/qmlcompiler/qqmljscompiler.cpp b/src/qmlcompiler/qqmljscompiler.cpp
index bf4dc55b6d..549ee9116b 100644
--- a/src/qmlcompiler/qqmljscompiler.cpp
+++ b/src/qmlcompiler/qqmljscompiler.cpp
@@ -377,6 +377,27 @@ bool qCompileJSFile(const QString &inputFileName, const QString &inputFileUrl, Q
return saveFunction(QV4::CompiledData::SaveableUnitPointer(unit.data), empty, &error->message);
}
+static const char *wrapCallCode = R"(
+template <typename Binding>
+void wrapCall(const QQmlPrivate::AOTCompiledContext *context, void *dataPtr, void **argumentsPtr, Binding &&binding)
+{
+ using return_type = std::invoke_result_t<Binding, const QQmlPrivate::AOTCompiledContext *, void **>;
+ if constexpr (std::is_same_v<return_type, void>) {
+ Q_UNUSED(dataPtr);
+ binding(context, argumentsPtr);
+ } else {
+ new (dataPtr) return_type(binding(context, argumentsPtr));
+ }
+}
+)";
+
+static const char *funcHeaderCode = R"(
+ [](const QQmlPrivate::AOTCompiledContext *context, void *dataPtr, void **argumentsPtr) {
+ wrapCall(context, dataPtr, argumentsPtr, [](const QQmlPrivate::AOTCompiledContext *context, void **argumentsPtr) {
+Q_UNUSED(context);
+Q_UNUSED(argumentsPtr);
+)";
+
bool qSaveQmlJSUnitAsCpp(const QString &inputFileName, const QString &outputFileName, const QV4::CompiledData::SaveableUnitPointer &unit, const QQmlJSAotFunctionMap &aotFunctions, QString *errorString)
{
#if QT_CONFIG(temporaryfile)
@@ -463,22 +484,8 @@ bool qSaveQmlJSUnitAsCpp(const QString &inputFileName, const QString &outputFile
// FileScopeCodeIndex is always there, but it may be the only one.
writeStr("extern const QQmlPrivate::AOTCompiledFunction aotBuiltFunctions[] = { { 0, QMetaType::fromType<void>(), {}, nullptr } };");
} else {
- writeStr(R"(template <typename Binding>
- void wrapCall(QQmlContext *context, QObject *scopeObject, void *dataPtr, void **argumentsPtr, Binding &&binding) {
- using return_type = std::invoke_result_t<Binding, QQmlContext*, QObject*, void **>;
- if constexpr (std::is_same_v<return_type, void>) {
- Q_UNUSED(dataPtr);
- binding(context, scopeObject, argumentsPtr);
- } else {
- new (dataPtr) return_type(binding(context, scopeObject, argumentsPtr));
- }
- } )");
-
- writeStr("extern const QQmlPrivate::AOTCompiledFunction aotBuiltFunctions[] = {");
-
- QString header = QStringLiteral("[](QQmlContext *context, QObject *scopeObject, void *dataPtr, void **argumentsPtr) {\n");
- header += QStringLiteral("wrapCall(context, scopeObject, dataPtr, argumentsPtr, [](QQmlContext *context, QObject *scopeObject, void **argumentsPtr) {");
- header += QStringLiteral("Q_UNUSED(context); Q_UNUSED(scopeObject); Q_UNUSED(argumentsPtr);\n");
+ writeStr(wrapCallCode);
+ writeStr("extern const QQmlPrivate::AOTCompiledFunction aotBuiltFunctions[] = {\n");
QString footer = QStringLiteral("});}\n");
@@ -489,7 +496,7 @@ bool qSaveQmlJSUnitAsCpp(const QString &inputFileName, const QString &outputFile
if (func.key() == FileScopeCodeIndex)
continue;
- QString function = header + func.value().code + footer;
+ QString function = QString::fromUtf8(funcHeaderCode) + func.value().code + footer;
QString argumentTypes = func.value().argumentTypes.join(
QStringLiteral(">(), QMetaType::fromType<"));