diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2022-09-23 16:43:58 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2022-10-14 16:36:36 +0200 |
commit | de2d7cba76bcfbe0a29271df1178c176d00bf9b4 (patch) | |
tree | 5d37fcfad0636975f8ed4292f07140fdecdd19f2 /src/qml/compiler/qqmlirbuilder.cpp | |
parent | d45925b0fdbd8055b60afbf87324325465d89568 (diff) |
Add option to enforce function signatures
By default, the QML engine does not enforce signatures given as type
annotations to functions. By passing different types than the function
declares, you can get different behavior between the interpreter/JIT and
the AOT-compiled code. In addition, in interpreted or JIT'ed mode, we
pass all non-primitive value types as references. This means, if you
modify them within the called function, the modifications are propagated
back to the place where the value was loaded from.
Enforcing the signature prevents all of this, at a run time cost. Since
we have to coerce all arguments to the desired types, the function call
overhead grows. This change introduces a pragma
"FunctionSignatureBehavior" which you can set to "Ignored" or "Enforced"
to choose one way or the other as universal way of handling type
annotations.
Fixes: QTBUG-106819
Change-Id: I50e9b2bd6702907da44974cd9e05b48a96bb609e
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/compiler/qqmlirbuilder.cpp')
-rw-r--r-- | src/qml/compiler/qqmlirbuilder.cpp | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 3832621589..8ed900e9e1 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -799,6 +799,8 @@ private: return Pragma::ComponentBehavior; } else if constexpr (std::is_same_v<Argument, Pragma::ListPropertyAssignBehaviorValue>) { return Pragma::ListPropertyAssignBehavior; + } else if constexpr (std::is_same_v<Argument, Pragma::FunctionSignatureBehaviorValue>) { + return Pragma::FunctionSignatureBehavior; } Q_UNREACHABLE(); @@ -832,6 +834,15 @@ private: pragma->listPropertyAssignBehavior = Pragma::ReplaceIfNotDefault; return true; } + } else if constexpr (std::is_same_v<Argument, Pragma::FunctionSignatureBehaviorValue>) { + if (value == "Ignored"_L1) { + pragma->functionSignatureBehavior = Pragma::Ignored; + return true; + } + if (value == "Enforced"_L1) { + pragma->functionSignatureBehavior = Pragma::Enforced; + return true; + } } return false; @@ -853,6 +864,8 @@ private: return "list property assign behavior"_L1; case Pragma::ComponentBehavior: return "component behavior"_L1; + case Pragma::FunctionSignatureBehavior: + return "function signature behavior"_L1; default: break; } @@ -876,6 +889,9 @@ bool IRBuilder::visit(QQmlJS::AST::UiPragma *node) } else if (node->name == QStringLiteral("ListPropertyAssignBehavior")) { if (!PragmaParser<Pragma::ListPropertyAssignBehaviorValue>::run(this, node, pragma)) return false; + } else if (node->name == QStringLiteral("FunctionSignatureBehavior")) { + if (!PragmaParser<Pragma::FunctionSignatureBehaviorValue>::run(this, node, pragma)) + return false; } else { recordError(node->pragmaToken, QCoreApplication::translate( "QQmlParser", "Unknown pragma '%1'").arg(node->name)); @@ -1629,6 +1645,16 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen break; } break; + case Pragma::FunctionSignatureBehavior: + switch (p->functionSignatureBehavior) { + case Pragma::Enforced: + createdUnit->flags |= Unit::FunctionSignaturesEnforced; + break; + case Pragma::Ignored: + //this is the default; + break; + } + break; } } |