aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <[email protected]>2021-03-17 10:03:47 +0100
committerUlf Hermann <[email protected]>2021-03-23 06:51:57 +0100
commit4333dded89ce2e49f9ef3ef50ff474ec04e284dd (patch)
tree4f0f4f9214a0e0be147141de0992d4453644807e
parentf8f31dd0e1f9425ba272691c79e719ebc4bcfb94 (diff)
Expose lookups to AOT compiled functions
This is based on QJSValue for now, but can be extended to operate on QMetaType/void* later. Change-Id: Ic63d4c9081090998afcca63ff3253963ff5096a2 Reviewed-by: Fabian Kosmale <[email protected]>
-rw-r--r--src/qml/compiler/qv4compiler_p.h2
-rw-r--r--src/qml/qml/qqml.cpp104
-rw-r--r--src/qml/qml/qqmlprivate.h13
3 files changed, 117 insertions, 2 deletions
diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h
index 4f3c718175..5155c25c06 100644
--- a/src/qml/compiler/qv4compiler_p.h
+++ b/src/qml/compiler/qv4compiler_p.h
@@ -125,6 +125,8 @@ struct Q_QMLCOMPILER_PRIVATE_EXPORT JSUnitGenerator {
int registerSetterLookup(int nameIndex);
int registerGlobalGetterLookup(int nameIndex);
int registerQmlContextPropertyGetterLookup(int nameIndex);
+ int lookupNameIndex(int index) const { return lookups[index].nameIndex; }
+ QString lookupName(int index) const { return stringForIndex(lookupNameIndex(index)); }
int registerRegExp(QQmlJS::AST::RegExpLiteral *regexp);
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp
index ae8cde8a87..26efb493d3 100644
--- a/src/qml/qml/qqml.cpp
+++ b/src/qml/qml/qqml.cpp
@@ -49,6 +49,7 @@
#include <private/qqmltypemodule_p.h>
#include <private/qqmltypenotavailable_p.h>
#include <private/qqmlcomponent_p.h>
+#include <private/qv4lookup_p.h>
#include <QtCore/qmutex.h>
@@ -696,4 +697,107 @@ void QQmlPrivate::AOTCompiledContext::setInstructionPointer(int offset) const
frame->instructionPointer = offset;
}
+QJSValue QQmlPrivate::AOTCompiledContext::loadQmlContextPropertyLookup(uint index) const
+{
+ QV4::Lookup *l = compilationUnit->runtimeLookups + index;
+ return QJSValuePrivate::fromReturnedValue(l->qmlContextPropertyGetter(
+ l, engine->handle(), nullptr));
+}
+
+QJSValue QQmlPrivate::AOTCompiledContext::callQmlContextPropertyLookup(
+ uint index, const QJSValueList &args) const
+{
+ QV4::Scope scope(engine->handle());
+ const int argc = args.length();
+ QV4::Value *argv = scope.alloc(args.length());
+ for (int i = 0; i < argc; ++i)
+ argv[i] = QJSValuePrivate::convertToReturnedValue(scope.engine, args.at(i));
+ return QJSValuePrivate::fromReturnedValue(QV4::Runtime::CallQmlContextPropertyLookup::call(
+ engine->handle(), index, argv, argc));
+}
+
+QJSValue QQmlPrivate::AOTCompiledContext::getLookup(uint index, const QJSValue &object) const
+{
+ QV4::Lookup *l = compilationUnit->runtimeLookups + index;
+
+ if (object.isNull() || object.isUndefined()) {
+ QString message = QStringLiteral("Cannot read property '%1' of %2")
+ .arg(compilationUnit->runtimeStrings[l->nameIndex]->toQString(), object.toString());
+ return QJSValuePrivate::fromReturnedValue(engine->handle()->throwTypeError(message));
+ }
+
+ return QJSValuePrivate::fromReturnedValue(
+ l->getter(l, engine->handle(),
+ QJSValuePrivate::convertToReturnedValue(engine->handle(), object)));
+}
+
+void QQmlPrivate::AOTCompiledContext::setLookup(
+ uint index, const QJSValue &object, const QJSValue &value) const
+{
+ QV4::Lookup *l = compilationUnit->runtimeLookups + index;
+ QV4::Scope scope(engine->handle());
+ QV4::ScopedValue o(scope, QJSValuePrivate::convertToReturnedValue(scope.engine, object));
+ if (!l->setter(l, engine->handle(), *o,
+ QJSValuePrivate::convertToReturnedValue(engine->handle(), value))) {
+ engine->handle()->throwTypeError();
+ }
+}
+
+QJSValue QQmlPrivate::AOTCompiledContext::callPropertyLookup(
+ uint index, const QJSValue &object, const QJSValueList &args) const
+{
+ QV4::Lookup *l = compilationUnit->runtimeLookups + index;
+ QV4::Scope scope(engine->handle());
+ QV4::ScopedValue o(scope, QJSValuePrivate::convertToReturnedValue(scope.engine, object));
+
+ // ok to have the value on the stack here
+ QV4::Value f = QV4::Value::fromReturnedValue(l->getter(l, engine->handle(), o));
+
+ if (Q_UNLIKELY(!f.isFunctionObject())) {
+ QString message = QStringLiteral("Property '%1' of object %2 is not a function")
+ .arg(compilationUnit->runtimeStrings[l->nameIndex]->toQString(),
+ object.toString());
+ engine->handle()->throwTypeError(message);
+ return QJSValue();
+ }
+
+ const int argc = args.length();
+ QV4::Value *argv = scope.alloc(args.length());
+ for (int i = 0; i < argc; ++i)
+ argv[i] = QJSValuePrivate::convertToReturnedValue(scope.engine, args.at(i));
+
+ return QJSValuePrivate::fromReturnedValue(
+ static_cast<QV4::FunctionObject &>(f).call(o, argv, argc));
+}
+
+QJSValue QQmlPrivate::AOTCompiledContext::callGlobalLookup(
+ uint index, const QJSValueList &args) const
+{
+ QV4::Scope scope(engine->handle());
+ QV4::Lookup *l = compilationUnit->runtimeLookups + index;
+ QV4::Value function = QV4::Value::fromReturnedValue(l->globalGetter(l, scope.engine));
+ if (!function.isFunctionObject()) {
+ const QString msg = QStringLiteral("Property '%1' of object [null] is not a function")
+ .arg(compilationUnit->runtimeStrings[l->nameIndex]->toQString());
+ return QJSValuePrivate::fromReturnedValue(scope.engine->throwTypeError(msg));
+ }
+
+ const int argc = args.length();
+ QV4::Value *argv = scope.alloc(args.length());
+ for (int i = 0; i < argc; ++i)
+ argv[i] = QJSValuePrivate::convertToReturnedValue(scope.engine, args.at(i));
+
+ QV4::Value thisObject = QV4::Value::undefinedValue();
+ QV4::ReturnedValue result = static_cast<QV4::FunctionObject &>(function).call(
+ &thisObject, argv, argc);
+
+ return scope.engine->hasException ? QJSValue() : QJSValuePrivate::fromReturnedValue(result);
+}
+
+QJSValue QQmlPrivate::AOTCompiledContext::loadGlobalLookup(uint index) const
+{
+ QV4::Lookup *l = compilationUnit->runtimeLookups + index;
+ return QJSValuePrivate::fromReturnedValue(l->globalGetter(l, engine->handle()));
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h
index fb2d80b3df..8c47c71305 100644
--- a/src/qml/qml/qqmlprivate.h
+++ b/src/qml/qml/qqmlprivate.h
@@ -83,9 +83,9 @@ using QQmlAttachedPropertiesFunc = A *(*)(QObject *);
namespace QV4 {
struct ExecutionEngine;
+class ExecutableCompilationUnit;
namespace CompiledData {
struct Unit;
-struct CompilationUnit;
}
}
namespace QmlIR {
@@ -606,10 +606,19 @@ namespace QQmlPrivate
QQmlContext *qmlContext;
QObject *qmlScopeObject;
QJSEngine *engine;
- QV4::CompiledData::CompilationUnit *compilationUnit;
+ QV4::ExecutableCompilationUnit *compilationUnit;
QJSValue jsMetaType(int index) const;
void setInstructionPointer(int offset) const;
+
+ QJSValue loadQmlContextPropertyLookup(uint index) const;
+ QJSValue callQmlContextPropertyLookup(uint index, const QJSValueList &args) const;
+ QJSValue getLookup(uint index, const QJSValue &object) const;
+ void setLookup(uint index, const QJSValue &object, const QJSValue &value) const;
+ QJSValue callPropertyLookup(uint index, const QJSValue &object,
+ const QJSValueList &args) const;
+ QJSValue callGlobalLookup(uint index, const QJSValueList &args) const;
+ QJSValue loadGlobalLookup(uint index) const;
};
struct AOTCompiledFunction {