diff options
Diffstat (limited to 'src/qml/jsruntime/qv4function.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4function.cpp | 145 |
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 ¶m) { - 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 ¶m) { + 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> ¶meters) @@ -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 ¶meterName : 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 |