Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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, argv, argc,
72 [this, context, 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 if (internalClass)
97 internalClass->mark(ms);
98}
99
101{
102 return type.typeNameIndexOrCommonType()
103 != (type.indexIsCommonType() ? quint32(CompiledData::CommonType::Invalid) : 0);
104}
105
107 const CompiledData::Function *function,
108 const QQmlPrivate::AOTCompiledFunction *aotFunction)
109 : FunctionData(engine, unit)
110 , compiledFunction(function)
111 , codeData(function->code())
112{
113 Scope scope(engine);
114 Scoped<InternalClass> ic(scope, engine->internalClasses(EngineBase::Class_CallContext));
115
116 // first locals
117 const quint32_le *localsIndices = compiledFunction->localsTable();
118 for (quint32 i = 0; i < compiledFunction->nLocals; ++i)
119 ic = ic->addMember(engine->identifierTable->asPropertyKey(compilationUnit->runtimeStrings[localsIndices[i]]), Attr_NotConfigurable);
120
121 const CompiledData::Parameter *formalsIndices = compiledFunction->formalsTable();
122 bool enforceJsTypes = !unit->ignoresFunctionSignature();
123
124 for (quint32 i = 0; i < compiledFunction->nFormals; ++i) {
125 ic = ic->addMember(engine->identifierTable->asPropertyKey(compilationUnit->runtimeStrings[formalsIndices[i].nameIndex]), Attr_NotConfigurable);
126 if (enforceJsTypes && !isSpecificType(formalsIndices[i].type))
127 enforceJsTypes = false;
128 }
129 internalClass.set(engine, ic->d());
130
132
133 if (!enforceJsTypes)
134 return;
135
136 if (aotFunction) {
137 aotCompiledCode = aotFunction->functionPtr;
140 aotCompiledFunction.types.resize(aotFunction->numArguments + 1);
141 aotFunction->signature(unit, aotCompiledFunction.types.data());
142 return;
143 }
144
145 // If a function has any typed arguments, but an untyped return value, the return value is void.
146 // If it doesn't have any arguments at all and the return value is untyped, the function is
147 // untyped. Users can specifically set the return type to "void" to have it enforced.
149 return;
150
151 QQmlTypeLoader *typeLoader = engine->typeLoader();
152
153 auto findQmlType = [&](const CompiledData::ParameterType &param) {
154 const quint32 type = param.typeNameIndexOrCommonType();
155 if (param.indexIsCommonType()) {
158 }
159
160 if (type == 0 || !typeLoader)
161 return QQmlType();
162
163 const auto &base = unit->baseCompilationUnit();
165 base, typeLoader, base->stringAt(type));
166 return qmltype.typeId().isValid() ? qmltype : QQmlType();
167 };
168
170 kind = JsTyped;
173 for (quint16 i = 0; i < nFormals; ++i)
174 jsTypedFunction.types.append(findQmlType(formalsIndices[i].type));
175}
176
178{
179 if (codeRef) {
181 delete codeRef;
182 }
183
184 switch (kind) {
185 case JsTyped:
186 jsTypedFunction.~JSTypedFunction();
187 break;
188 case AotCompiled:
189 aotCompiledFunction.~AOTCompiledFunction();
190 break;
191 case JsUntyped:
192 case Eval:
193 break;
194 }
195}
196
197void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArray> &parameters)
198{
199 QStringList parameterNames;
200
201 // Resolve duplicate parameter names:
202 for (int i = 0, ei = parameters.size(); i != ei; ++i) {
203 const QByteArray &param = parameters.at(i);
204 int duplicate = -1;
205
206 for (int j = i - 1; j >= 0; --j) {
207 const QByteArray &prevParam = parameters.at(j);
208 if (param == prevParam) {
209 duplicate = j;
210 break;
211 }
212 }
213
214 if (duplicate == -1) {
215 parameterNames.append(QString::fromUtf8(param));
216 } else {
217 const QString dup = parameterNames[duplicate];
218 parameterNames.append(dup);
219 parameterNames[duplicate] =
220 QString(QChar(0xfffe)) + QString::number(duplicate) + dup;
221 }
222
223 }
224
225 Scope scope(engine);
226 Scoped<InternalClass> ic(scope, engine->internalClasses(EngineBase::Class_CallContext));
227
228 // first locals
229 const quint32_le *localsIndices = compiledFunction->localsTable();
230 for (quint32 i = 0; i < compiledFunction->nLocals; ++i) {
231 ic = ic->addMember(
232 engine->identifierTable->asPropertyKey(compilationUnit->runtimeStrings[localsIndices[i]]),
234 }
235
236 ScopedString arg(scope);
237 for (const QString &parameterName : parameterNames) {
238 arg = engine->newIdentifier(parameterName);
239 ic = ic->addMember(arg->propertyKey(), Attr_NotConfigurable);
240 }
241 internalClass.set(engine, ic->d());
242 nFormals = parameters.size();
243}
244
245QString Function::prettyName(const Function *function, const void *code)
246{
247 QString prettyName = function ? function->name()->toQString() : QString();
248 if (prettyName.isEmpty()) {
249 prettyName = QString::number(reinterpret_cast<quintptr>(code), 16);
250 prettyName.prepend(QLatin1String("QV4::Function(0x"));
251 prettyName.append(QLatin1Char(')'));
252 }
253 return prettyName;
254}
255
261
263{
264 compilationUnit.set(engine, compilationUnit_);
265}
266
267} // namespace QV4
268
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore
\inmodule QtCore
Definition qmetatype.h:341
\inmodule QtCore
Definition qobject.h:103
static QQmlType qmlType(const QString &qualifiedName, QTypeRevision version)
Returns the type (if any) of URI-qualified named qualifiedName and version specified by version_major...
The QQmlTypeLoader class abstracts loading files and their dependencies over the network.
static QQmlType compositeQmlType(const QQmlRefPointer< QV4::CompiledData::CompilationUnit > &unit, QQmlTypeLoader *typeLoader, const QString &type)
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
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:8084
const QQmlRefPointer< QV4::CompiledData::CompilationUnit > & baseCompilationUnit() const
static void exec(MetaTypesStackFrame *frame, ExecutionEngine *engine)
void resize(qsizetype sz)
void append(const T &t)
T * data() noexcept
void reserve(qsizetype sz)
Combined button and popup list for selecting options.
ReturnedValue convertAndCall(ExecutionEngine *engine, const Function::AOTCompiledFunction *aotFunction, const Value *thisObject, const Value *argv, int argc, Callable call)
quint64 ReturnedValue
static ReturnedValue doCall(QV4::Function *self, const QV4::Value *thisObject, const QV4::Value *argv, int argc, QV4::ExecutionContext *context)
Scoped< String > ScopedString
ReturnedValue coerceAndCall(ExecutionEngine *engine, const Function::JSTypedFunction *typedFunction, const CompiledData::Function *compiledFunction, const Value *argv, int argc, Callable call)
@ Attr_NotConfigurable
void destroyFunctionTable(Function *function, JSC::MacroAssemblerCodeRef *codeRef)
static bool isSpecificType(const CompiledData::ParameterType &type)
static void * context
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:50
unsigned short quint16
Definition qtypes.h:48
size_t quintptr
Definition qtypes.h:167
static const uint base
Definition qurlidna.cpp:20
QFrame frame
[0]
QJSEngine engine
[0]
\inmodule QtCore \reentrant
Definition qchar.h:18
static QMetaType metaTypeForPropertyType(QV4::CompiledData::CommonType type)
const quint32_le * localsTable() const
const Parameter * formalsTable() const
WriteBarrier::HeapObjectWrapper< CompilationUnitRuntimeData, 1 > compilationUnit
FunctionData(EngineBase *engine, ExecutableCompilationUnit *compilationUnit_)
QVarLengthArray< QMetaType, 4 > types
QVarLengthArray< QQmlType, 4 > types
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 CompiledData::Function * compiledFunction
void mark(QV4::MarkStack *ms)
JSC::MacroAssemblerCodeRef * codeRef
JSTypedFunction jsTypedFunction
void updateInternalClass(ExecutionEngine *engine, const QList< QByteArray > &parameters)
QQmlSourceLocation sourceLocation() const
QV4::WriteBarrier::Pointer< Heap::InternalClass > internalClass
AOTCompiledFunction aotCompiledFunction
bool call(QObject *thisObject, void **a, const QMetaType *types, int argc, ExecutionContext *context)
AotCompiledCode aotCompiledCode
static constexpr Value undefinedValue()
Definition qv4value_p.h:191