Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qv4compilercontext_p.h
Go to the documentation of this file.
1// Copyright (C) 2017 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#ifndef QV4COMPILERCONTEXT_P_H
4#define QV4COMPILERCONTEXT_P_H
5
6//
7// W A R N I N G
8// -------------
9//
10// This file is not part of the Qt API. It exists purely as an
11// implementation detail. This header file may change from version to
12// version without notice, or even be removed.
13//
14// We mean it.
15//
16
17#include <private/qqmljsast_p.h>
18#include <private/qv4compileddata_p.h>
19#include <QtCore/QStringList>
20#include <QtCore/QDateTime>
21#include <QtCore/QStack>
22#include <QtCore/QHash>
23#include <QtCore/QMap>
24#include <QtCore/QSet>
25#include <QtCore/QVarLengthArray>
26
27#include <memory>
28
29QT_BEGIN_NAMESPACE
30
31namespace QV4 {
32
33namespace Moth {
35}
36
37namespace Compiler {
38
39class Codegen;
40struct ControlFlow;
41
42enum class ContextType {
46 Binding, // This is almost the same as Eval, except:
47 // * function declarations are moved to the return address when encountered
48 // * return statements are allowed everywhere (like in FunctionCode)
49 // * variable declarations are treated as true locals (like in FunctionCode)
53};
54
55struct Context;
56
74
78 bool operator==(const TemplateObject &other) {
79 return strings == other.strings && rawStrings == other.rawStrings;
80 }
81};
82
84{
90
91 static bool lessThan(const ExportEntry &lhs, const ExportEntry &rhs)
92 { return lhs.exportName < rhs.exportName; }
93};
94
102
103struct Module {
104 Module(const QString &fileName, const QString &finalUrl, bool debugMode)
107 , debugMode(debugMode)
108 {}
110 qDeleteAll(contextMap);
111 }
112
113 Context *newContext(QQmlJS::AST::Node *node, Context *parent, ContextType compilationMode);
114
124 uint unitFlags = 0; // flags merged into CompiledData::Unit::flags
125 bool debugMode = false;
131};
132
133
134struct Context {
137 int line = 0;
138 int column = 0;
141 int blockIndex = -1;
142
150
160
161 struct Member {
163 int index = -1;
165 mutable bool canEscape = false;
166 bool isInjected = false;
169
170 bool isLexicallyScoped() const { return this->scope != QQmlJS::AST::VariableScope::Var; }
171 bool requiresTDZCheck(const QQmlJS::SourceLocation &accessLocation, bool accessAcrossContextBoundaries) const;
172 };
174
179 QQmlJS::AST::Type *returnType = nullptr;
186
191 std::vector<unsigned> labelInfo;
192
193 int nRegisters = 0;
198 bool hasDirectEval = false;
199 bool allVarsEscape = false;
200 bool hasNestedFunctions = false;
201 bool isStrict = false;
202 bool isArrowFunction = false;
203 bool isGenerator = false;
204 bool usesThis = false;
207 bool returnsClosure = false;
208 mutable bool argumentsCanEscape = false;
210 bool isWithBlock = false;
211 bool isCatchBlock = false;
214
220
222
224
225 template <typename T>
226 class SmallSet: public QVarLengthArray<T, 8>
227 {
228 public:
229 void insert(int value)
230 {
231 for (auto it : *this) {
232 if (it == value)
233 return;
234 }
235 this->append(value);
236 }
237 };
238
239 // Map from meta property index (existence implies dependency) to notify signal index
241 {
244
246 KeyValuePair(quint32 key, quint32 value): _key(key), _value(value) {}
247
248 quint32 key() const { return _key; }
249 quint32 value() const { return _value; }
250 };
251
253 {
254 public:
255 void insert(quint32 key, quint32 value)
256 {
257 for (auto it = begin(), eit = end(); it != eit; ++it) {
258 if (it->_key == key) {
259 it->_value = value;
260 return;
261 }
262 }
263 append(KeyValuePair(key, value));
264 }
265 };
266
268 : parent(parent)
269 , contextType(type)
270 {
271 if (parent && parent->isStrict)
272 isStrict = true;
273 }
274
275 bool hasArgument(const QString &name) const
276 {
277 return arguments.contains(name);
278 }
279
280 int findArgument(const QString &name, bool *isInjected) const
281 {
282 // search backwards to handle duplicate argument names correctly
283 for (int i = arguments.size() - 1; i >= 0; --i) {
284 const auto &arg = arguments.at(i);
285 if (arg.id == name) {
286 *isInjected = arg.isInjected();
287 return i;
288 }
289 }
290 return -1;
291 }
292
293 Member findMember(const QString &name) const
294 {
295 MemberMap::const_iterator it = members.find(name);
296 if (it == members.end())
297 return Member();
298 Q_ASSERT(it->index != -1 || !parent);
299 return (*it);
300 }
301
302 bool memberInfo(const QString &name, const Member **m) const
303 {
304 Q_ASSERT(m);
305 MemberMap::const_iterator it = members.find(name);
306 if (it == members.end()) {
307 *m = nullptr;
308 return false;
309 }
310 *m = &(*it);
311 return true;
312 }
313
319
320 void addUsedVariable(const QString &name) {
321 usedVariables.insert(name);
322 }
323
324 bool addLocalVar(
325 const QString &name, MemberType contextType, QQmlJS::AST::VariableScope scope,
326 QQmlJS::AST::FunctionExpression *function = nullptr,
327 const QQmlJS::SourceLocation &declarationLocation = QQmlJS::SourceLocation(),
328 bool isInjected = false);
329
350 ResolvedName resolveName(const QString &name, const QQmlJS::SourceLocation &accessLocation);
351 void emitBlockHeader(Compiler::Codegen *codegen);
352 void emitBlockFooter(Compiler::Codegen *codegen);
353
354 void setupFunctionIndices(Moth::BytecodeGenerator *bytecodeGenerator);
355
356 bool canHaveTailCalls() const
357 {
358 if (!isStrict)
359 return false;
361 return !isGenerator;
364 return false;
365 }
366
367 bool isCaseBlock() const
368 {
369 return contextType == ContextType::Block && name == u"%CaseBlock";
370 }
371};
372
373
374} } // namespace QV4::Compiler
375
376QT_END_NAMESPACE
377
378#endif // QV4CODEGEN_P_H
Definition qjsvalue.h:23
QVector< Method > staticMethods
QVector< Method > methods
KeyValuePair(quint32 key, quint32 value)
QQmlJS::AST::FunctionExpression * function
bool requiresTDZCheck(const QQmlJS::SourceLocation &accessLocation, bool accessAcrossContextBoundaries) const
QQmlJS::SourceLocation declarationLocation
QQmlJS::AST::VariableScope scope
bool memberInfo(const QString &name, const Member **m) const
void emitBlockFooter(Compiler::Codegen *codegen)
QQmlJS::AST::FormalParameterList * formals
bool hasArgument(const QString &name) const
void emitBlockHeader(Compiler::Codegen *codegen)
QQmlJS::AST::BoundNames arguments
QVector< Context * > nestedContexts
std::unique_ptr< SourceLocationTable > sourceLocationTable
QVector< ImportEntry > importEntries
UsesArgumentsObject usesArgumentsObject
QVector< ExportEntry > exportEntries
QMap< QString, Member > MemberMap
QQmlJS::AST::Type * returnType
Context(Context *parent, ContextType type)
ResolvedName resolveName(const QString &name, const QQmlJS::SourceLocation &accessLocation)
void setupFunctionIndices(Moth::BytecodeGenerator *bytecodeGenerator)
QQmlJS::SourceLocation lastBlockInitializerLocation
QVector< CompiledData::CodeOffsetToLineAndStatement > lineAndStatementNumberMapping
void addUsedVariable(const QString &name)
std::vector< unsigned > labelInfo
Member findMember(const QString &name) const
bool addLocalVar(const QString &name, MemberType contextType, QQmlJS::AST::VariableScope scope, QQmlJS::AST::FunctionExpression *function=nullptr, const QQmlJS::SourceLocation &declarationLocation=QQmlJS::SourceLocation(), bool isInjected=false)
int findArgument(const QString &name, bool *isInjected) const
CompiledData::Location location
static bool lessThan(const ExportEntry &lhs, const ExportEntry &rhs)
CompiledData::Location location
QVector< ImportEntry > importEntries
Context * newContext(QQmlJS::AST::Node *node, Context *parent, ContextType compilationMode)
QVector< ExportEntry > localExportEntries
QHash< QQmlJS::AST::Node *, Context * > contextMap
QList< Context * > functions
QVector< TemplateObject > templateObjects
Module(const QString &fileName, const QString &finalUrl, bool debugMode)
QVector< ExportEntry > starExportEntries
QVector< ExportEntry > indirectExportEntries
bool operator==(const TemplateObject &other)