aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4function.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime/qv4function.cpp')
-rw-r--r--src/qml/jsruntime/qv4function.cpp145
1 files changed, 77 insertions, 68 deletions
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index 29e3d8d7ef..ae36b563e0 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -41,8 +41,8 @@ bool Function::call(QObject *thisObject, void **a, const QMetaType *types, int a
}
static ReturnedValue doCall(
- Function *self, const Value *thisObject, const Value *argv, int argc,
- ExecutionContext *context)
+ QV4::Function *self, const QV4::Value *thisObject, const QV4::Value *argv, int argc,
+ QV4::ExecutionContext *context)
{
ExecutionEngine *engine = context->engine();
JSTypesStackFrame frame;
@@ -61,15 +61,15 @@ ReturnedValue Function::call(
switch (kind) {
case AotCompiled:
return QV4::convertAndCall(
- context->engine(), typedFunction, thisObject, argv, argc,
+ context->engine(), &aotCompiledFunction, thisObject, argv, argc,
[this, context](
QObject *thisObject, void **a, const QMetaType *types, int argc) {
call(thisObject, a, types, argc, context);
});
case JsTyped:
return QV4::coerceAndCall(
- context->engine(), typedFunction, thisObject, argv, argc,
- [this, context](const Value *thisObject, const Value *argv, int argc) {
+ context->engine(), &jsTypedFunction, compiledFunction, argv, argc,
+ [this, context, thisObject](const Value *argv, int argc) {
return doCall(this, thisObject, argv, argc, context);
});
default:
@@ -81,7 +81,7 @@ ReturnedValue Function::call(
Function *Function::create(ExecutionEngine *engine, ExecutableCompilationUnit *unit,
const CompiledData::Function *function,
- const QQmlPrivate::TypedFunction *aotFunction)
+ const QQmlPrivate::AOTCompiledFunction *aotFunction)
{
return new Function(engine, unit, function, aotFunction);
}
@@ -91,16 +91,24 @@ void Function::destroy()
delete this;
}
+void Function::mark(MarkStack *ms)
+{
+ if (internalClass)
+ internalClass->mark(ms);
+}
+
+static bool isSpecificType(const CompiledData::ParameterType &type)
+{
+ return type.typeNameIndexOrCommonType()
+ != (type.indexIsCommonType() ? quint32(CompiledData::CommonType::Invalid) : 0);
+}
+
Function::Function(ExecutionEngine *engine, ExecutableCompilationUnit *unit,
const CompiledData::Function *function,
- const QQmlPrivate::TypedFunction *aotFunction)
- : FunctionData(unit)
+ const QQmlPrivate::AOTCompiledFunction *aotFunction)
+ : FunctionData(engine, unit)
, compiledFunction(function)
, codeData(function->code())
- , jittedCode(nullptr)
- , codeRef(nullptr)
- , typedFunction(aotFunction)
- , kind(aotFunction ? AotCompiled : JsUntyped)
{
Scope scope(engine);
Scoped<InternalClass> ic(scope, engine->internalClasses(EngineBase::Class_CallContext));
@@ -111,74 +119,59 @@ Function::Function(ExecutionEngine *engine, ExecutableCompilationUnit *unit,
ic = ic->addMember(engine->identifierTable->asPropertyKey(compilationUnit->runtimeStrings[localsIndices[i]]), Attr_NotConfigurable);
const CompiledData::Parameter *formalsIndices = compiledFunction->formalsTable();
- const bool enforcesSignature = !aotFunction && unit->enforcesFunctionSignature();
- bool hasTypes = false;
+ bool enforceJsTypes = !unit->ignoresFunctionSignature();
+
for (quint32 i = 0; i < compiledFunction->nFormals; ++i) {
ic = ic->addMember(engine->identifierTable->asPropertyKey(compilationUnit->runtimeStrings[formalsIndices[i].nameIndex]), Attr_NotConfigurable);
- if (enforcesSignature
- && !hasTypes
- && formalsIndices[i].type.typeNameIndexOrBuiltinType()
- != quint32(QV4::CompiledData::BuiltinType::InvalidBuiltin)) {
- hasTypes = true;
- }
+ if (enforceJsTypes && !isSpecificType(formalsIndices[i].type))
+ enforceJsTypes = false;
}
- internalClass = ic->d();
+ internalClass.set(engine, ic->d());
nFormals = compiledFunction->nFormals;
- if (!enforcesSignature)
+ if (!enforceJsTypes)
return;
- if (!hasTypes
- && compiledFunction->returnType.typeNameIndexOrBuiltinType()
- == quint32(QV4::CompiledData::BuiltinType::InvalidBuiltin)) {
+ if (aotFunction) {
+ aotCompiledCode = aotFunction->functionPtr;
+ new (&aotCompiledFunction) AOTCompiledFunction;
+ kind = AotCompiled;
+ aotCompiledFunction.types.resize(aotFunction->numArguments + 1);
+ aotFunction->signature(unit, aotCompiledFunction.types.data());
return;
}
- QQmlPrivate::TypedFunction *synthesized = new QQmlPrivate::TypedFunction;
- QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine->qmlEngine());
-
- auto findMetaType = [&](const CompiledData::ParameterType &param) {
- const quint32 type = param.typeNameIndexOrBuiltinType();
- if (param.indexIsBuiltinType()) {
- if (param.isList()) {
- return QQmlPropertyCacheCreatorBase::listTypeForPropertyType(
- QV4::CompiledData::BuiltinType(type));
- }
- return QQmlPropertyCacheCreatorBase::metaTypeForPropertyType(
- QV4::CompiledData::BuiltinType(type));
- }
-
- if (type == 0)
- return QMetaType();
-
- const QQmlType qmltype = unit->typeNameCache->query(unit->stringAt(type)).type;
- if (!qmltype.isValid())
- return QMetaType();
+ // If a function has any typed arguments, but an untyped return value, the return value is void.
+ // If it doesn't have any arguments at all and the return value is untyped, the function is
+ // untyped. Users can specifically set the return type to "void" to have it enforced.
+ if (nFormals == 0 && !isSpecificType(compiledFunction->returnType))
+ return;
- const QMetaType metaType = param.isList() ? qmltype.qListTypeId() : qmltype.typeId();
- if (metaType.isValid())
- return metaType;
+ QQmlTypeLoader *typeLoader = engine->typeLoader();
- if (!qmltype.isComposite()) {
- if (!qmltype.isInlineComponentType())
- return QMetaType();
- const CompositeMetaTypeIds typeIds
- = unit->typeIdsForComponent(qmltype.inlineComponentId());
- return param.isList() ? typeIds.listId : typeIds.id;
+ auto findQmlType = [&](const CompiledData::ParameterType &param) {
+ const quint32 type = param.typeNameIndexOrCommonType();
+ if (param.indexIsCommonType()) {
+ return QQmlMetaType::qmlType(QQmlPropertyCacheCreatorBase::metaTypeForPropertyType(
+ QV4::CompiledData::CommonType(type)));
}
- const CompositeMetaTypeIds typeIds = enginePrivate->typeLoader.getType(
- qmltype.sourceUrl())->compilationUnit()->typeIds;
- return param.isList() ? typeIds.listId : typeIds.id;
- };
+ if (type == 0 || !typeLoader)
+ return QQmlType();
- for (quint16 i = 0; i < nFormals; ++i)
- synthesized->argumentTypes.append(findMetaType(formalsIndices[i].type));
+ const auto &base = unit->baseCompilationUnit();
+ const QQmlType qmltype = QQmlTypePrivate::compositeQmlType(
+ base, typeLoader, base->stringAt(type));
+ return qmltype.typeId().isValid() ? qmltype : QQmlType();
+ };
- synthesized->returnType = findMetaType(compiledFunction->returnType);
- typedFunction = synthesized;
+ new (&jsTypedFunction) JSTypedFunction;
kind = JsTyped;
+ jsTypedFunction.types.reserve(nFormals + 1);
+ jsTypedFunction.types.append(findQmlType(compiledFunction->returnType));
+ for (quint16 i = 0; i < nFormals; ++i)
+ jsTypedFunction.types.append(findQmlType(formalsIndices[i].type));
}
Function::~Function()
@@ -187,8 +180,18 @@ Function::~Function()
destroyFunctionTable(this, codeRef);
delete codeRef;
}
- if (kind == JsTyped)
- delete typedFunction;
+
+ switch (kind) {
+ case JsTyped:
+ jsTypedFunction.~JSTypedFunction();
+ break;
+ case AotCompiled:
+ aotCompiledFunction.~AOTCompiledFunction();
+ break;
+ case JsUntyped:
+ case Eval:
+ break;
+ }
}
void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArray> &parameters)
@@ -219,22 +222,23 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArr
}
- internalClass = engine->internalClasses(EngineBase::Class_CallContext);
+ Scope scope(engine);
+ Scoped<InternalClass> ic(scope, engine->internalClasses(EngineBase::Class_CallContext));
// first locals
const quint32_le *localsIndices = compiledFunction->localsTable();
for (quint32 i = 0; i < compiledFunction->nLocals; ++i) {
- internalClass = internalClass->addMember(
+ ic = ic->addMember(
engine->identifierTable->asPropertyKey(compilationUnit->runtimeStrings[localsIndices[i]]),
Attr_NotConfigurable);
}
- Scope scope(engine);
ScopedString arg(scope);
for (const QString &parameterName : parameterNames) {
arg = engine->newIdentifier(parameterName);
- internalClass = internalClass->addMember(arg->propertyKey(), Attr_NotConfigurable);
+ ic = ic->addMember(arg->propertyKey(), Attr_NotConfigurable);
}
+ internalClass.set(engine, ic->d());
nFormals = parameters.size();
}
@@ -255,6 +259,11 @@ QQmlSourceLocation Function::sourceLocation() const
sourceFile(), compiledFunction->location.line(), compiledFunction->location.column());
}
+FunctionData::FunctionData(EngineBase *engine, ExecutableCompilationUnit *compilationUnit_)
+{
+ compilationUnit.set(engine, compilationUnit_);
+}
+
} // namespace QV4
QT_END_NAMESPACE