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// Qt-Security score:significant
4
5#ifndef QV4COMPILERCONTEXT_P_H
6#define QV4COMPILERCONTEXT_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <private/qqmljsast_p.h>
20#include <private/qv4compileddata_p.h>
21#include <QtCore/QStringList>
22#include <QtCore/QDateTime>
23#include <QtCore/QStack>
24#include <QtCore/QHash>
25#include <QtCore/QMap>
26#include <QtCore/QSet>
27#include <QtCore/QVarLengthArray>
28
29#include <memory>
30
31QT_BEGIN_NAMESPACE
32
33namespace QV4 {
34
35namespace Moth {
37}
38
39namespace Compiler {
40
41class Codegen;
42struct ControlFlow;
43
44enum class ContextType {
48 Binding, // This is almost the same as Eval, except:
49 // * function declarations are moved to the return address when encountered
50 // * return statements are allowed everywhere (like in FunctionCode)
51 // * variable declarations are treated as true locals (like in FunctionCode)
55};
56
57struct Context;
58
76
80 bool operator==(const TemplateObject &other) {
81 return strings == other.strings && rawStrings == other.rawStrings;
82 }
83};
84
86{
92
93 static bool lessThan(const ExportEntry &lhs, const ExportEntry &rhs)
94 { return lhs.exportName < rhs.exportName; }
95};
96
104
105struct Module {
106 Module(const QString &fileName, const QString &finalUrl, bool debugMode)
109 , debugMode(debugMode)
110 {}
112 qDeleteAll(contextMap);
113 }
114
115 Context *newContext(QQmlJS::AST::Node *node, Context *parent, ContextType compilationMode);
116
126 uint unitFlags = 0; // flags merged into CompiledData::Unit::flags
127 bool debugMode = false;
133};
134
135
136struct Context {
139 int line = 0;
140 int column = 0;
143 int blockIndex = -1;
144
152
162
163 struct Member {
165 int index = -1;
167 mutable bool canEscape = false;
168 bool isInjected = false;
171
172 bool isLexicallyScoped() const { return this->scope != QQmlJS::AST::VariableScope::Var; }
173 bool requiresTDZCheck(const QQmlJS::SourceLocation &accessLocation, bool accessAcrossContextBoundaries) const;
174 };
176
181 QQmlJS::AST::Type *returnType = nullptr;
188
193 std::vector<unsigned> labelInfo;
194
195 int nRegisters = 0;
200 bool hasDirectEval = false;
201 bool allVarsEscape = false;
202 bool hasNestedFunctions = false;
203 bool isStrict = false;
204 bool isArrowFunction = false;
205 bool isGenerator = false;
206 bool usesThis = false;
209 bool returnsClosure = false;
210 mutable bool argumentsCanEscape = false;
212 bool isWithBlock = false;
213 bool isCatchBlock = false;
216
222
224
226
227 template <typename T>
228 class SmallSet: public QVarLengthArray<T, 8>
229 {
230 public:
231 void insert(int value)
232 {
233 for (auto it : *this) {
234 if (it == value)
235 return;
236 }
237 this->append(value);
238 }
239 };
240
241 // Map from meta property index (existence implies dependency) to notify signal index
243 {
246
248 KeyValuePair(quint32 key, quint32 value): _key(key), _value(value) {}
249
250 quint32 key() const { return _key; }
251 quint32 value() const { return _value; }
252 };
253
255 {
256 public:
257 void insert(quint32 key, quint32 value)
258 {
259 for (auto it = begin(), eit = end(); it != eit; ++it) {
260 if (it->_key == key) {
261 it->_value = value;
262 return;
263 }
264 }
265 append(KeyValuePair(key, value));
266 }
267 };
268
270 : parent(parent)
271 , contextType(type)
272 {
273 if (parent && parent->isStrict)
274 isStrict = true;
275 }
276
277 bool hasArgument(const QString &name) const
278 {
279 return arguments.contains(name);
280 }
281
282 int findArgument(const QString &name, bool *isInjected) const
283 {
284 // search backwards to handle duplicate argument names correctly
285 for (int i = arguments.size() - 1; i >= 0; --i) {
286 const auto &arg = arguments.at(i);
287 if (arg.id == name) {
288 *isInjected = arg.isInjected();
289 return i;
290 }
291 }
292 return -1;
293 }
294
295 Member findMember(const QString &name) const
296 {
297 MemberMap::const_iterator it = members.find(name);
298 if (it == members.end())
299 return Member();
300 Q_ASSERT(it->index != -1 || !parent);
301 return (*it);
302 }
303
304 bool memberInfo(const QString &name, const Member **m) const
305 {
306 Q_ASSERT(m);
307 MemberMap::const_iterator it = members.find(name);
308 if (it == members.end()) {
309 *m = nullptr;
310 return false;
311 }
312 *m = &(*it);
313 return true;
314 }
315
321
322 void addUsedVariable(const QString &name) {
323 usedVariables.insert(name);
324 }
325
326 bool addLocalVar(
327 const QString &name, MemberType contextType, QQmlJS::AST::VariableScope scope,
328 QQmlJS::AST::FunctionExpression *function = nullptr,
329 const QQmlJS::SourceLocation &declarationLocation = QQmlJS::SourceLocation(),
330 bool isInjected = false);
331
352 ResolvedName resolveName(const QString &name, const QQmlJS::SourceLocation &accessLocation);
353 void emitBlockHeader(Compiler::Codegen *codegen);
354 void emitBlockFooter(Compiler::Codegen *codegen);
355
356 void setupFunctionIndices(Moth::BytecodeGenerator *bytecodeGenerator);
357
358 bool canHaveTailCalls() const
359 {
360 if (!isStrict)
361 return false;
363 return !isGenerator;
366 return false;
367 }
368
369 bool isCaseBlock() const
370 {
371 return contextType == ContextType::Block && name == u"%CaseBlock";
372 }
373};
374
375
376} } // namespace QV4::Compiler
377
378QT_END_NAMESPACE
379
380#endif // QV4CODEGEN_P_H
Definition qjsvalue.h:24
QList< Method > staticMethods
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
QList< Context * > nestedContexts
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
std::unique_ptr< SourceLocationTable > sourceLocationTable
UsesArgumentsObject usesArgumentsObject
QList< CompiledData::CodeOffsetToLineAndStatement > lineAndStatementNumberMapping
QList< ImportEntry > importEntries
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
void addUsedVariable(const QString &name)
QList< ExportEntry > exportEntries
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
Context * newContext(QQmlJS::AST::Node *node, Context *parent, ContextType compilationMode)
QHash< QQmlJS::AST::Node *, Context * > contextMap
QList< ExportEntry > indirectExportEntries
QList< Context * > functions
Module(const QString &fileName, const QString &finalUrl, bool debugMode)
QList< ExportEntry > starExportEntries
QList< TemplateObject > templateObjects
QList< ImportEntry > importEntries
QList< ExportEntry > localExportEntries
bool operator==(const TemplateObject &other)