1// Copyright (C) 2019 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#ifndef QV4EXECUTABLECOMPILATIONUNIT_P_H
5#define QV4EXECUTABLECOMPILATIONUNIT_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <private/qintrusivelist_p.h>
19#include <private/qqmlmetatype_p.h>
20#include <private/qqmlnullablevalue_p.h>
21#include <private/qqmlpropertycachevector_p.h>
22#include <private/qqmlrefcount_p.h>
23#include <private/qqmltype_p.h>
24#include <private/qqmltypenamecache_p.h>
25#include <private/qv4compileddata_p.h>
26#include <private/qv4identifierhash_p.h>
27
28#include <memory>
29
30QT_BEGIN_NAMESPACE
31
32class QQmlScriptData;
33class QQmlEnginePrivate;
34
35namespace QV4 {
36
37class CompilationUnitMapper;
38
39struct CompilationUnitRuntimeData
40{
41 Heap::String **runtimeStrings = nullptr; // Array
42
43 // pointers either to data->constants() or little-endian memory copy.
44 // We keep this member twice so that the JIT can access it via standard layout.
45 const StaticValue *constants = nullptr;
46
47 QV4::StaticValue *runtimeRegularExpressions = nullptr;
48 Heap::InternalClass **runtimeClasses = nullptr;
49 const StaticValue **imports = nullptr;
50
51 QV4::Lookup *runtimeLookups = nullptr;
52 QVector<QV4::Function *> runtimeFunctions;
53 QVector<QV4::Heap::InternalClass *> runtimeBlocks;
54 mutable QVector<QV4::Heap::Object *> templateObjects;
55};
56
57static_assert(std::is_standard_layout_v<CompilationUnitRuntimeData>);
58static_assert(offsetof(CompilationUnitRuntimeData, runtimeStrings) == 0);
59static_assert(offsetof(CompilationUnitRuntimeData, constants) == sizeof(QV4::Heap::String **));
60static_assert(offsetof(CompilationUnitRuntimeData, runtimeRegularExpressions) == offsetof(CompilationUnitRuntimeData, constants) + sizeof(const StaticValue *));
61static_assert(offsetof(CompilationUnitRuntimeData, runtimeClasses) == offsetof(CompilationUnitRuntimeData, runtimeRegularExpressions) + sizeof(const StaticValue *));
62static_assert(offsetof(CompilationUnitRuntimeData, imports) == offsetof(CompilationUnitRuntimeData, runtimeClasses) + sizeof(const StaticValue *));
63
64class Q_QML_EXPORT ExecutableCompilationUnit final
65 : public CompilationUnitRuntimeData,
66 public QQmlRefCounted<ExecutableCompilationUnit>
67{
68 Q_DISABLE_COPY_MOVE(ExecutableCompilationUnit)
69public:
70 friend class QQmlRefCounted<ExecutableCompilationUnit>;
71 friend class QQmlRefPointer<ExecutableCompilationUnit>;
72 friend struct ExecutionEngine;
73
74 ExecutionEngine *engine = nullptr;
75
76 QString finalUrlString() const { return m_compilationUnit->finalUrlString(); }
77 QString fileName() const { return m_compilationUnit->fileName(); }
78
79 QUrl url() const { return m_compilationUnit->url(); }
80 QUrl finalUrl() const { return m_compilationUnit->finalUrl(); }
81
82 QQmlRefPointer<QQmlTypeNameCache> typeNameCache() const
83 {
84 return m_compilationUnit->typeNameCache;
85 }
86
87 QQmlPropertyCacheVector *propertyCachesPtr()
88 {
89 return &m_compilationUnit->propertyCaches;
90 }
91
92 QQmlPropertyCache::ConstPtr rootPropertyCache() const
93 {
94 return m_compilationUnit->rootPropertyCache();
95 }
96
97 // mapping from component object index (CompiledData::Unit object index that points to component) to identifier hash of named objects
98 // this is initialized on-demand by QQmlContextData
99 QHash<int, IdentifierHash> namedObjectsPerComponentCache;
100 inline IdentifierHash namedObjectsPerComponent(int componentObjectIndex);
101
102 ResolvedTypeReference *resolvedType(int id) const
103 {
104 return m_compilationUnit->resolvedType(id);
105 }
106
107 QQmlType qmlTypeForComponent(const QString &inlineComponentName = QString()) const
108 {
109 return m_compilationUnit->qmlTypeForComponent(inlineComponentName);
110 }
111
112 QMetaType metaType() const { return m_compilationUnit->qmlType.typeId(); }
113
114 int inlineComponentId(const QString &inlineComponentName) const
115 {
116 return m_compilationUnit->inlineComponentId(inlineComponentName);
117 }
118
119 // --- interface for QQmlPropertyCacheCreator
120 using CompiledObject = CompiledData::CompilationUnit::CompiledObject;
121 using CompiledFunction = CompiledData::CompilationUnit::CompiledFunction;
122 using CompiledBinding = CompiledData::CompilationUnit::CompiledBinding;
123 using IdToObjectMap = CompiledData::CompilationUnit::IdToObjectMap;
124
125 bool nativeMethodsAcceptThisObjects() const
126 {
127 return m_compilationUnit->nativeMethodsAcceptThisObjects();
128 }
129
130 bool ignoresFunctionSignature() const { return m_compilationUnit->ignoresFunctionSignature(); }
131 bool valueTypesAreCopied() const { return m_compilationUnit->valueTypesAreCopied(); }
132 bool valueTypesAreAddressable() const { return m_compilationUnit->valueTypesAreAddressable(); }
133 bool valueTypesAreAssertable() const { return m_compilationUnit->valueTypesAreAssertable(); }
134 bool componentsAreBound() const { return m_compilationUnit->componentsAreBound(); }
135 bool isESModule() const { return m_compilationUnit->isESModule(); }
136
137 int objectCount() const { return m_compilationUnit->objectCount(); }
138 const CompiledObject *objectAt(int index) const
139 {
140 return m_compilationUnit->objectAt(index);
141 }
142
143 Heap::Object *templateObjectAt(int index) const;
144
145 Heap::Module *instantiate();
146 const Value *resolveExport(QV4::String *exportName)
147 {
148 QVector<ResolveSetEntry> resolveSet;
149 return resolveExportRecursively(exportName, resolveSet: &resolveSet);
150 }
151
152 QStringList exportedNames() const
153 {
154 QStringList names;
155 QVector<const ExecutableCompilationUnit*> exportNameSet;
156 getExportedNamesRecursively(names: &names, exportNameSet: &exportNameSet);
157 names.sort();
158 auto last = std::unique(first: names.begin(), last: names.end());
159 names.erase(abegin: last, aend: names.end());
160 return names;
161 }
162
163 void evaluate();
164 void evaluateModuleRequests();
165
166 void mark(MarkStack *markStack) const { markObjects(markStack); }
167 void markObjects(MarkStack *markStack) const;
168
169 QString bindingValueAsString(const CompiledData::Binding *binding) const;
170 double bindingValueAsNumber(const CompiledData::Binding *binding) const
171 {
172 return m_compilationUnit->bindingValueAsNumber(binding);
173 }
174 QString bindingValueAsScriptString(const CompiledData::Binding *binding) const
175 {
176 return m_compilationUnit->bindingValueAsScriptString(binding);
177 }
178
179 struct TranslationDataIndex
180 {
181 uint index;
182 bool byId;
183 };
184
185 QString translateFrom(TranslationDataIndex index) const;
186
187 Heap::Module *module() const;
188 void setModule(Heap::Module *module);
189
190 ReturnedValue value() const { return m_valueOrModule.asReturnedValue(); }
191 void setValue(const QV4::Value &value) { m_valueOrModule = value; }
192
193 const CompiledData::Unit *unitData() const { return m_compilationUnit->data; }
194
195 QString stringAt(uint index) const { return m_compilationUnit->stringAt(index); }
196
197 const QVector<QQmlRefPointer<QQmlScriptData>> *dependentScriptsPtr() const
198 {
199 return &m_compilationUnit->dependentScripts;
200 }
201
202 const CompiledData::BindingPropertyData *bindingPropertyDataPerObjectAt(
203 qsizetype objectIndex) const
204 {
205 return &m_compilationUnit->bindingPropertyDataPerObject.at(i: objectIndex);
206 }
207
208 const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &baseCompilationUnit() const
209 {
210 return m_compilationUnit;
211 }
212
213 QV4::Function *rootFunction()
214 {
215 if (!runtimeStrings)
216 populate();
217
218 const auto *data = unitData();
219 return data->indexOfRootFunction != -1
220 ? runtimeFunctions[data->indexOfRootFunction]
221 : nullptr;
222 }
223
224 void populate();
225 void clear();
226
227protected:
228 quint32 totalStringCount() const
229 { return unitData()->stringTableSize; }
230
231private:
232 friend struct ExecutionEngine;
233
234 QQmlRefPointer<CompiledData::CompilationUnit> m_compilationUnit;
235 Value m_valueOrModule = QV4::Value::emptyValue();
236
237 struct ResolveSetEntry
238 {
239 ResolveSetEntry() {}
240 ResolveSetEntry(ExecutableCompilationUnit *module, QV4::String *exportName)
241 : module(module), exportName(exportName) {}
242 ExecutableCompilationUnit *module = nullptr;
243 QV4::String *exportName = nullptr;
244 };
245
246 ExecutableCompilationUnit();
247 ExecutableCompilationUnit(QQmlRefPointer<CompiledData::CompilationUnit> &&compilationUnit);
248 ~ExecutableCompilationUnit();
249
250 static QQmlRefPointer<ExecutableCompilationUnit> create(
251 QQmlRefPointer<CompiledData::CompilationUnit> &&compilationUnit,
252 ExecutionEngine *engine);
253
254 const Value *resolveExportRecursively(QV4::String *exportName,
255 QVector<ResolveSetEntry> *resolveSet);
256
257 QUrl urlAt(int index) const { return QUrl(stringAt(index)); }
258
259 Q_NEVER_INLINE IdentifierHash createNamedObjectsPerComponent(int componentObjectIndex);
260 const CompiledData::ExportEntry *lookupNameInExportTable(
261 const CompiledData::ExportEntry *firstExportEntry, int tableSize,
262 QV4::String *name) const;
263
264 void getExportedNamesRecursively(
265 QStringList *names, QVector<const ExecutableCompilationUnit *> *exportNameSet,
266 bool includeDefaultExport = true) const;
267};
268
269IdentifierHash ExecutableCompilationUnit::namedObjectsPerComponent(int componentObjectIndex)
270{
271 auto it = namedObjectsPerComponentCache.constFind(key: componentObjectIndex);
272 if (Q_UNLIKELY(it == namedObjectsPerComponentCache.cend()))
273 return createNamedObjectsPerComponent(componentObjectIndex);
274 Q_ASSERT(!it->isEmpty());
275 return *it;
276}
277
278} // namespace QV4
279
280QT_END_NAMESPACE
281
282#endif // QV4EXECUTABLECOMPILATIONUNIT_P_H
283

source code of qtdeclarative/src/qml/jsruntime/qv4executablecompilationunit_p.h