aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2020-11-17 13:41:36 +0100
committerUlf Hermann <ulf.hermann@qt.io>2020-11-20 10:36:06 +0100
commit744b277733a03e0fb5a0c25640be0f73cf3eb6c9 (patch)
treee4faf101e397dca324349223b330f92f708b673f /src
parentfe2d3a839775f64f7aad8610ea241c8760be4646 (diff)
V4: Allow passing arguments to AOT-compiled functions
Change-Id: I2340f4413ae9a44c71000e840a79e904b6a0fec9 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp37
-rw-r--r--src/qml/qml/qqmlprivate.h4
-rw-r--r--src/qml/qml/qqmlpropertybinding.cpp2
-rw-r--r--src/qmlcompiler/qqmljscompiler.cpp35
-rw-r--r--src/qmlcompiler/qqmljscompiler_p.h1
5 files changed, 52 insertions, 27 deletions
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 55c7759716..ebc018a595 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -42,6 +42,7 @@
#include <QtCore/qjsondocument.h>
#include <QtCore/qjsonobject.h>
+#include <private/qv4alloca_p.h>
#include <private/qv4instr_moth_p.h>
#include <private/qv4value_p.h>
#include <private/qv4debugging_p.h>
@@ -460,21 +461,33 @@ ReturnedValue VME::exec(CppStackFrame *frame, ExecutionEngine *engine)
if (function->jittedCode != nullptr && debugger == nullptr) {
result = function->jittedCode(frame, engine);
} else if (function->aotFunction) {
+ const qsizetype numFunctionArguments = function->aotFunction->argumentTypes.size();
+ Q_ALLOCA_VAR(void *, argumentPtrs, numFunctionArguments * sizeof(void *));
+
+ for (qsizetype i = 0; i < numFunctionArguments; ++i) {
+ const QMetaType argumentType = function->aotFunction->argumentTypes[i];
+ Q_ALLOCA_VAR(void, argument, argumentType.sizeOf());
+ if (i < frame->originalArgumentsCount)
+ engine->metaTypeFromJS(frame->originalArguments[i], argumentType.id(), argument);
+ else
+ argumentType.construct(argument);
+ argumentPtrs[i] = argument;
+ }
+
+ const QMetaType returnType = function->aotFunction->returnType;
+ Q_ALLOCA_VAR(void, returnValue, returnType.sizeOf());
+
Scope scope(engine);
Scoped<QmlContext> qmlContext(scope, engine->qmlContext());
+ function->aotFunction->functionPtr(
+ qmlContext->qmlContext()->asQQmlContext(), qmlContext->qmlScope(),
+ returnValue, const_cast<const void **>(argumentPtrs)); // We're adding const here
- QVariant resultVariant;
- if (function->aotFunction->returnType.id() == QMetaType::QVariant) {
- function->aotFunction->functionPtr(
- qmlContext->qmlContext()->asQQmlContext(), qmlContext->qmlScope(),
- &resultVariant);
- } else {
- resultVariant = QVariant(function->aotFunction->returnType, nullptr);
- function->aotFunction->functionPtr(
- qmlContext->qmlContext()->asQQmlContext(), qmlContext->qmlScope(),
- resultVariant.data());
- }
- result = engine->fromVariant(resultVariant);
+ result = engine->metaTypeToJS(returnType.id(), returnValue);
+
+ returnType.destruct(returnValue);
+ for (qsizetype i = 0; i < numFunctionArguments; ++i)
+ function->aotFunction->argumentTypes[i].destruct(argumentPtrs[i]);
} else {
// interpreter
result = interpret(frame, engine, function->codeData);
diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h
index feee3f8686..654ae35c57 100644
--- a/src/qml/qml/qqmlprivate.h
+++ b/src/qml/qml/qqmlprivate.h
@@ -592,7 +592,9 @@ namespace QQmlPrivate
struct AOTCompiledFunction {
int index;
QMetaType returnType;
- void (*functionPtr)(QQmlContext *context, QObject *scopeObject, void *resultPtr);
+ QList<QMetaType> argumentTypes;
+ void (*functionPtr)(QQmlContext *context, QObject *scopeObject, void *resultPtr,
+ const void **arguments);
};
struct CachedQmlUnit {
diff --git a/src/qml/qml/qqmlpropertybinding.cpp b/src/qml/qml/qqmlpropertybinding.cpp
index 656e2788c4..e950de5d48 100644
--- a/src/qml/qml/qqmlpropertybinding.cpp
+++ b/src/qml/qml/qqmlpropertybinding.cpp
@@ -55,7 +55,7 @@ QUntypedPropertyBinding QQmlPropertyBinding::create(const QQmlPropertyData *pd,
context = ctxt
](const QMetaType &, void *dataPtr) -> bool {
Q_UNUSED(unit); // to keep refcount
- aotFunction->functionPtr(context->asQQmlContext(), scopeObject.data(), dataPtr);
+ aotFunction->functionPtr(context->asQQmlContext(), scopeObject.data(), 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 7d780b21a1..d69eacaa29 100644
--- a/src/qmlcompiler/qqmljscompiler.cpp
+++ b/src/qmlcompiler/qqmljscompiler.cpp
@@ -451,25 +451,24 @@ bool qSaveQmlJSUnitAsCpp(const QString &inputFileName, const QString &outputFile
writeStr(aotFunctions[FileScopeCodeIndex].code.toUtf8().constData());
if (aotFunctions.size() <= 1) {
// FileScopeCodeIndex is always there, but it may be the only one.
- writeStr("extern const QQmlPrivate::AOTCompiledFunction aotBuiltFunctions[] = { { 0, QMetaType::fromType<void>(), nullptr } };");
+ 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, Binding &&binding) {
- using return_type = std::invoke_result_t<Binding, QQmlContext*, QObject*>;
+ void wrapCall(QQmlContext *context, QObject *scopeObject, void *dataPtr, const void **argumentsPtr, Binding &&binding) {
+ using return_type = std::invoke_result_t<Binding, QQmlContext*, QObject*, const void **>;
if constexpr (std::is_same_v<return_type, void>) {
- Q_UNUSED(dataPtr);
- binding(context, scopeObject);
+ Q_UNUSED(dataPtr);
+ binding(context, scopeObject, argumentsPtr);
} else {
- auto result = binding(context, scopeObject);
- *reinterpret_cast<return_type *>(dataPtr) = std::move(result);
+ new (dataPtr) return_type(binding(context, scopeObject, argumentsPtr));
}
} )");
writeStr("extern const QQmlPrivate::AOTCompiledFunction aotBuiltFunctions[] = {");
- QString header = QStringLiteral("[](QQmlContext *context, QObject *scopeObject, void *dataPtr) {\n");
- header += QStringLiteral("wrapCall(context, scopeObject, dataPtr, [](QQmlContext *context, QObject *scopeObject) {");
- header += QStringLiteral("Q_UNUSED(context); Q_UNUSED(scopeObject);\n");
+ QString header = QStringLiteral("[](QQmlContext *context, QObject *scopeObject, void *dataPtr, const void **argumentsPtr) {\n");
+ header += QStringLiteral("wrapCall(context, scopeObject, dataPtr, argumentsPtr, [](QQmlContext *context, QObject *scopeObject, const void **argumentsPtr) {");
+ header += QStringLiteral("Q_UNUSED(context); Q_UNUSED(scopeObject); Q_UNUSED(argumentsPtr);\n");
QString footer = QStringLiteral("});}\n");
@@ -482,13 +481,23 @@ bool qSaveQmlJSUnitAsCpp(const QString &inputFileName, const QString &outputFile
QString function = header + func.value().code + footer;
- writeStr(QStringLiteral("{ %1, QMetaType::fromType<%2>(), %3 },")
- .arg(func.key()).arg(func.value().returnType).arg(function)
+ QString argumentTypes = func.value().argumentTypes.join(
+ QStringLiteral(">(), QMetaType::fromType<"));
+ if (!argumentTypes.isEmpty()) {
+ argumentTypes = QStringLiteral("QMetaType::fromType<")
+ + argumentTypes + QStringLiteral(">()");
+ }
+
+ writeStr(QStringLiteral("{ %1, QMetaType::fromType<%2>(), { %3 }, %4 },")
+ .arg(func.key())
+ .arg(func.value().returnType)
+ .arg(argumentTypes)
+ .arg(function)
.toUtf8().constData());
}
// Conclude the list with a nullptr
- writeStr("{ 0, QMetaType::fromType<void>(), nullptr }");
+ writeStr("{ 0, QMetaType::fromType<void>(), {}, nullptr }");
writeStr("};\n");
}
diff --git a/src/qmlcompiler/qqmljscompiler_p.h b/src/qmlcompiler/qqmljscompiler_p.h
index 1bfb1369c1..9fda257bd7 100644
--- a/src/qmlcompiler/qqmljscompiler_p.h
+++ b/src/qmlcompiler/qqmljscompiler_p.h
@@ -64,6 +64,7 @@ struct QQmlJSCompileError
struct QQmlJSAotFunction
{
QStringList includes;
+ QStringList argumentTypes;
QString code;
QString returnType;
};