Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qv4function.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qml/qqmlprivate.h"
5#include "qv4function_p.h"
6#include "qv4managed_p.h"
7#include "qv4string_p.h"
8#include "qv4value_p.h"
9#include "qv4engine_p.h"
10#include <private/qv4mm_p.h>
11#include <private/qv4identifiertable_p.h>
12#include <private/qv4functiontable_p.h>
13#include <assembler/MacroAssemblerCodeRef.h>
14#include <private/qv4vme_moth_p.h>
15#include <private/qqmlglobal_p.h>
16#include <private/qv4jscall_p.h>
17#include <private/qqmlpropertycachecreator_p.h>
18
20
21namespace QV4 {
22
23bool Function::call(QObject *thisObject, void **a, const QMetaType *types, int argc,
25{
26 if (kind != AotCompiled) {
28 context->engine(), thisObject, a, types, argc,
29 [this, context](const Value *thisObject, const Value *argv, int argc) {
30 return call(thisObject, argv, argc, context);
31 });
32 }
33
34 ExecutionEngine *engine = context->engine();
36 frame.init(this, thisObject, context, a, types, argc);
37 frame.push(engine);
39 frame.pop(engine);
40 return !frame.isReturnValueUndefined();
41}
42
44 QV4::Function *self, const QV4::Value *thisObject, const QV4::Value *argv, int argc,
46{
47 ExecutionEngine *engine = context->engine();
49 frame.init(self, argv, argc);
50 frame.setupJSFrame(engine->jsStackTop, Value::undefinedValue(), context->d(),
51 thisObject ? *thisObject : Value::undefinedValue());
52 engine->jsStackTop += frame.requiredJSStackFrameSize();
53 frame.push(engine);
55 frame.pop(engine);
56 return result;
57}
58
60 const Value *thisObject, const Value *argv, int argc, ExecutionContext *context) {
61 switch (kind) {
62 case AotCompiled:
64 context->engine(), aotCompiledFunction, thisObject, argv, argc,
65 [this, context](
66 QObject *thisObject, void **a, const QMetaType *types, int argc) {
67 call(thisObject, a, types, argc, context);
68 });
69 case JsTyped:
70 return QV4::coerceAndCall(
71 context->engine(), jsTypedFunction, compiledFunction, thisObject, argv, argc,
72 [this, context](const Value *thisObject, const Value *argv, int argc) {
73 return doCall(this, thisObject, argv, argc, context);
74 });
75 default:
76 break;
77 }
78
79 return doCall(this, thisObject, argv, argc, context);
80}
81
83 const CompiledData::Function *function,
84 const QQmlPrivate::AOTCompiledFunction *aotFunction)
85{
86 return new Function(engine, unit, function, aotFunction);
87}
88
90{
91 delete this;
92}
93
95{
96 return type.typeNameIndexOrCommonType()
97 != (type.indexIsCommonType() ? quint32(CompiledData::CommonType::Invalid) : 0);
98}
99
101 const CompiledData::Function *function,
102 const QQmlPrivate::AOTCompiledFunction *aotFunction)
103 : FunctionData(unit)
104 , compiledFunction(function)
105 , codeData(function->code())
106 , jittedCode(nullptr)
107 , codeRef(nullptr)
108 , aotCompiledFunction(aotFunction)
109 , kind(aotFunction ? AotCompiled : JsUntyped)
110{
111 Scope scope(engine);
113
114 // first locals
115 const quint32_le *localsIndices = compiledFunction->localsTable();
116 for (quint32 i = 0; i < compiledFunction->nLocals; ++i)
117 ic = ic->addMember(engine->identifierTable->asPropertyKey(compilationUnit->runtimeStrings[localsIndices[i]]), Attr_NotConfigurable);
118
119 const CompiledData::Parameter *formalsIndices = compiledFunction->formalsTable();
120 bool enforceJsTypes = !aotFunction && !unit->ignoresFunctionSignature();
121
122 for (quint32 i = 0; i < compiledFunction->nFormals; ++i) {
123 ic = ic->addMember(engine->identifierTable->asPropertyKey(compilationUnit->runtimeStrings[formalsIndices[i].nameIndex]), Attr_NotConfigurable);
124 if (enforceJsTypes && !isSpecificType(formalsIndices[i].type))
125 enforceJsTypes = false;
126 }
127 internalClass = ic->d();
128
130
131 // If a function has any typed arguments, but an untyped return value, the return value is void.
132 // If it doesn't have any arguments at all and the return value is untyped, the function is
133 // untyped. Users can specifically set the return type to "void" to have it enforced.
134 if (!enforceJsTypes || (nFormals == 0 && !isSpecificType(compiledFunction->returnType)))
135 return;
136
137 JSTypedFunction *synthesized = new JSTypedFunction;
138
139 QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine->qmlEngine());
140 auto findQmlType = [&](const CompiledData::ParameterType &param) {
141 const quint32 type = param.typeNameIndexOrCommonType();
142 if (param.indexIsCommonType()) {
145 }
146
147 if (type == 0)
148 return QQmlType();
149
151 unit->stringAt(type)).type;
152 if (!qmltype.isValid() || qmltype.typeId().isValid())
153 return qmltype;
154
155 if (!qmltype.isComposite()) {
156 return qmltype.isInlineComponentType()
157 ? unit->qmlTypeForComponent(qmltype.elementName())
158 : QQmlType();
159 }
160
161 return enginePrivate->typeLoader.getType(qmltype.sourceUrl())->compilationUnit()->qmlType;
162 };
163
164 for (quint16 i = 0; i < nFormals; ++i)
165 synthesized->argumentTypes.append(findQmlType(formalsIndices[i].type));
166
167 synthesized->returnType = findQmlType(compiledFunction->returnType);
168 jsTypedFunction = synthesized;
169 kind = JsTyped;
170}
171
173{
174 if (codeRef) {
176 delete codeRef;
177 }
178 if (kind == JsTyped)
179 delete jsTypedFunction;
180}
181
183{
184 QStringList parameterNames;
185
186 // Resolve duplicate parameter names:
187 for (int i = 0, ei = parameters.size(); i != ei; ++i) {
188 const QByteArray &param = parameters.at(i);
189 int duplicate = -1;
190
191 for (int j = i - 1; j >= 0; --j) {
192 const QByteArray &prevParam = parameters.at(j);
193 if (param == prevParam) {
194 duplicate = j;
195 break;
196 }
197 }
198
199 if (duplicate == -1) {
200 parameterNames.append(QString::fromUtf8(param));
201 } else {
202 const QString dup = parameterNames[duplicate];
203 parameterNames.append(dup);
204 parameterNames[duplicate] =
205 QString(QChar(0xfffe)) + QString::number(duplicate) + dup;
206 }
207
208 }
209
211
212 // first locals
213 const quint32_le *localsIndices = compiledFunction->localsTable();
214 for (quint32 i = 0; i < compiledFunction->nLocals; ++i) {
216 engine->identifierTable->asPropertyKey(compilationUnit->runtimeStrings[localsIndices[i]]),
218 }
219
220 Scope scope(engine);
221 ScopedString arg(scope);
222 for (const QString &parameterName : parameterNames) {
223 arg = engine->newIdentifier(parameterName);
225 }
226 nFormals = parameters.size();
227}
228
229QString Function::prettyName(const Function *function, const void *code)
230{
231 QString prettyName = function ? function->name()->toQString() : QString();
232 if (prettyName.isEmpty()) {
233 prettyName = QString::number(reinterpret_cast<quintptr>(code), 16);
234 prettyName.prepend(QLatin1String("QV4::Function(0x"));
236 }
237 return prettyName;
238}
239
241{
242 return QQmlSourceLocation(
244}
245
246} // namespace QV4
247
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore
Definition qchar.h:48
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
void append(parameter_type t)
Definition qlist.h:441
\inmodule QtCore
Definition qmetatype.h:320
bool isValid() const
\inmodule QtCore
Definition qobject.h:90
QQmlTypeLoader typeLoader
static QQmlEnginePrivate * get(QQmlEngine *e)
static QQmlType qmlType(const QString &qualifiedName, QTypeRevision version)
Returns the type (if any) of URI-qualified named qualifiedName and version specified by version_major...
QV4::ExecutableCompilationUnit * compilationUnit() const
QQmlRefPointer< QQmlTypeData > getType(const QUrl &unNormalizedUrl, Mode mode=PreferSynchronous)
Returns a QQmlTypeData for the specified url.
Result query(const QHashedStringRef &key) const
QMetaType typeId() const
Definition qqmltype.cpp:643
QUrl sourceUrl() const
Definition qqmltype.cpp:743
bool isComposite() const
Definition qqmltype.cpp:614
bool isValid() const
Definition qqmltype_p.h:58
bool isInlineComponentType() const
Definition qqmltype.cpp:739
QString elementName() const
Definition qqmltype.cpp:442
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:7822
QString & append(QChar c)
Definition qstring.cpp:3227
QString & prepend(QChar c)
Definition qstring.h:411
QQmlRefPointer< QQmlTypeNameCache > typeNameCache
QQmlType qmlTypeForComponent(const QString &inlineComponentName=QString()) const
static void exec(MetaTypesStackFrame *frame, ExecutionEngine *engine)
Combined button and popup list for selecting options.
\qmltype Particle \inqmlmodule QtQuick.Particles
ReturnedValue convertAndCall(ExecutionEngine *engine, const QQmlPrivate::AOTCompiledFunction *aotFunction, const Value *thisObject, const Value *argv, int argc, Callable call)
quint64 ReturnedValue
ReturnedValue coerceAndCall(ExecutionEngine *engine, const Function::JSTypedFunction *typedFunction, const CompiledData::Function *compiledFunction, const Value *thisObject, const Value *argv, int argc, Callable call)
static ReturnedValue doCall(QV4::Function *self, const QV4::Value *thisObject, const QV4::Value *argv, int argc, QV4::ExecutionContext *context)
@ Attr_NotConfigurable
void destroyFunctionTable(Function *function, JSC::MacroAssemblerCodeRef *codeRef)
static bool isSpecificType(const CompiledData::ParameterType &type)
static void * context
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction function
GLboolean GLboolean GLboolean GLboolean a
[7]
GLsizei GLenum GLenum * types
GLenum type
GLenum const GLint * param
GLuint64EXT * result
[6]
SSL_CTX int(*) void arg)
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
unsigned int quint32
Definition qtypes.h:45
unsigned short quint16
Definition qtypes.h:43
size_t quintptr
Definition qtypes.h:72
QObject::connect nullptr
QFrame frame
[0]
QJSEngine engine
[0]
\inmodule QtCore \reentrant
Definition qchar.h:17
static QMetaType metaTypeForPropertyType(QV4::CompiledData::CommonType type)
const quint32_le * localsTable() const
const Parameter * formalsTable() const
CompiledData::CompilationUnitBase * compilationUnit
QList< QQmlType > argumentTypes
static Function * create(ExecutionEngine *engine, ExecutableCompilationUnit *unit, const CompiledData::Function *function, const QQmlPrivate::AOTCompiledFunction *aotFunction)
Function(ExecutionEngine *engine, ExecutableCompilationUnit *unit, const CompiledData::Function *function, const QQmlPrivate::AOTCompiledFunction *aotFunction)
QString sourceFile() const
static QString prettyName(const Function *function, const void *address)
const JSTypedFunction * jsTypedFunction
const CompiledData::Function * compiledFunction
JSC::MacroAssemblerCodeRef * codeRef
const QQmlPrivate::AOTCompiledFunction * aotCompiledFunction
void updateInternalClass(ExecutionEngine *engine, const QList< QByteArray > &parameters)
QQmlSourceLocation sourceLocation() const
bool call(QObject *thisObject, void **a, const QMetaType *types, int argc, ExecutionContext *context)
Heap::InternalClass * internalClass
static void addMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, InternalClassEntry *entry)
static constexpr Value undefinedValue()
Definition qv4value_p.h:191