Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/qtdeclarative/src/qtdeclarative/src/qml/compiler/qv4codegen_p.h |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||
---|---|---|---|---|---|---|---|---|
1 | /**************************************************************************** | - | ||||||
2 | ** | - | ||||||
3 | ** Copyright (C) 2017 The Qt Company Ltd. | - | ||||||
4 | ** Contact: https://www.qt.io/licensing/ | - | ||||||
5 | ** | - | ||||||
6 | ** This file is part of the QtQml module of the Qt Toolkit. | - | ||||||
7 | ** | - | ||||||
8 | ** $QT_BEGIN_LICENSE:LGPL$ | - | ||||||
9 | ** Commercial License Usage | - | ||||||
10 | ** Licensees holding valid commercial Qt licenses may use this file in | - | ||||||
11 | ** accordance with the commercial license agreement provided with the | - | ||||||
12 | ** Software or, alternatively, in accordance with the terms contained in | - | ||||||
13 | ** a written agreement between you and The Qt Company. For licensing terms | - | ||||||
14 | ** and conditions see https://www.qt.io/terms-conditions. For further | - | ||||||
15 | ** information use the contact form at https://www.qt.io/contact-us. | - | ||||||
16 | ** | - | ||||||
17 | ** GNU Lesser General Public License Usage | - | ||||||
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - | ||||||
19 | ** General Public License version 3 as published by the Free Software | - | ||||||
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | - | ||||||
21 | ** packaging of this file. Please review the following information to | - | ||||||
22 | ** ensure the GNU Lesser General Public License version 3 requirements | - | ||||||
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | - | ||||||
24 | ** | - | ||||||
25 | ** GNU General Public License Usage | - | ||||||
26 | ** Alternatively, this file may be used under the terms of the GNU | - | ||||||
27 | ** General Public License version 2.0 or (at your option) the GNU General | - | ||||||
28 | ** Public license version 3 or any later version approved by the KDE Free | - | ||||||
29 | ** Qt Foundation. The licenses are as published by the Free Software | - | ||||||
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | - | ||||||
31 | ** included in the packaging of this file. Please review the following | - | ||||||
32 | ** information to ensure the GNU General Public License requirements will | - | ||||||
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | - | ||||||
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | - | ||||||
35 | ** | - | ||||||
36 | ** $QT_END_LICENSE$ | - | ||||||
37 | ** | - | ||||||
38 | ****************************************************************************/ | - | ||||||
39 | #ifndef QV4CODEGEN_P_H | - | ||||||
40 | #define QV4CODEGEN_P_H | - | ||||||
41 | - | |||||||
42 | // | - | ||||||
43 | // W A R N I N G | - | ||||||
44 | // ------------- | - | ||||||
45 | // | - | ||||||
46 | // This file is not part of the Qt API. It exists purely as an | - | ||||||
47 | // implementation detail. This header file may change from version to | - | ||||||
48 | // version without notice, or even be removed. | - | ||||||
49 | // | - | ||||||
50 | // We mean it. | - | ||||||
51 | // | - | ||||||
52 | - | |||||||
53 | #include "private/qv4global_p.h" | - | ||||||
54 | #include <private/qqmljsastvisitor_p.h> | - | ||||||
55 | #include <private/qqmljsast_p.h> | - | ||||||
56 | #include <private/qqmljsengine_p.h> | - | ||||||
57 | #include <private/qv4instr_moth_p.h> | - | ||||||
58 | #include <private/qv4compiler_p.h> | - | ||||||
59 | #include <private/qv4compilercontext_p.h> | - | ||||||
60 | #include <private/qqmlrefcount_p.h> | - | ||||||
61 | #include <QtCore/QStringList> | - | ||||||
62 | #include <QtCore/QDateTime> | - | ||||||
63 | #include <QStack> | - | ||||||
64 | #ifndef V4_BOOTSTRAP | - | ||||||
65 | #include <qqmlerror.h> | - | ||||||
66 | #endif | - | ||||||
67 | #include <private/qv4util_p.h> | - | ||||||
68 | #include <private/qv4bytecodegenerator_p.h> | - | ||||||
69 | #include <private/qv4stackframe_p.h> | - | ||||||
70 | - | |||||||
71 | QT_BEGIN_NAMESPACE | - | ||||||
72 | - | |||||||
73 | using namespace QQmlJS; | - | ||||||
74 | - | |||||||
75 | namespace QV4 { | - | ||||||
76 | - | |||||||
77 | namespace Moth { | - | ||||||
78 | struct Instruction; | - | ||||||
79 | } | - | ||||||
80 | - | |||||||
81 | namespace CompiledData { | - | ||||||
82 | struct CompilationUnit; | - | ||||||
83 | } | - | ||||||
84 | - | |||||||
85 | namespace Compiler { | - | ||||||
86 | - | |||||||
87 | struct ControlFlow; | - | ||||||
88 | struct ControlFlowCatch; | - | ||||||
89 | struct ControlFlowFinally; | - | ||||||
90 | - | |||||||
91 | class Q_QML_PRIVATE_EXPORT Codegen: protected QQmlJS::AST::Visitor | - | ||||||
92 | { | - | ||||||
93 | protected: | - | ||||||
94 | using BytecodeGenerator = QV4::Moth::BytecodeGenerator; | - | ||||||
95 | using Instruction = QV4::Moth::Instruction; | - | ||||||
96 | public: | - | ||||||
97 | Codegen(QV4::Compiler::JSUnitGenerator *jsUnitGenerator, bool strict); | - | ||||||
98 | - | |||||||
99 | - | |||||||
100 | void generateFromProgram(const QString &fileName, | - | ||||||
101 | const QString &finalUrl, | - | ||||||
102 | const QString &sourceCode, | - | ||||||
103 | AST::Program *ast, | - | ||||||
104 | Module *module, | - | ||||||
105 | ContextType contextType = ContextType::Global); | - | ||||||
106 | - | |||||||
107 | public: | - | ||||||
108 | class VolatileMemoryLocationScanner; | - | ||||||
109 | class VolatileMemoryLocations { | - | ||||||
110 | friend VolatileMemoryLocationScanner; | - | ||||||
111 | bool allVolatile = false; | - | ||||||
112 | QVector<QStringView> specificLocations; | - | ||||||
113 | public: | - | ||||||
114 | bool isVolatile(const QStringView &name) { | - | ||||||
115 | if (allVolatile)
| 2643278-4727544 | ||||||
116 | return true; executed 2638398 times by 58 tests: return true; Executed by:
| 2638398 | ||||||
117 | return specificLocations.contains(name); executed 4716022 times by 65 tests: return specificLocations.contains(name); Executed by:
| 4716022 | ||||||
118 | } | - | ||||||
119 | - | |||||||
120 | void add(const QStringRef &name) { if (!allVolatile) specificLocations.append(name); } never executed: end of block never executed: specificLocations.append(name);
| 0 | ||||||
121 | void setAllVolatile() { allVolatile = true; } executed 5668968 times by 113 tests: end of block Executed by:
| 5668968 | ||||||
122 | }; | - | ||||||
123 | class RValue { | - | ||||||
124 | Codegen *codegen; | - | ||||||
125 | enum Type { | - | ||||||
126 | Invalid, | - | ||||||
127 | Accumulator, | - | ||||||
128 | StackSlot, | - | ||||||
129 | Const | - | ||||||
130 | } type; | - | ||||||
131 | union { | - | ||||||
132 | Moth::StackSlot theStackSlot; | - | ||||||
133 | QV4::ReturnedValue constant; | - | ||||||
134 | }; | - | ||||||
135 | - | |||||||
136 | public: | - | ||||||
137 | static RValue fromStackSlot(Codegen *codegen, Moth::StackSlot stackSlot) { | - | ||||||
138 | RValue r; | - | ||||||
139 | r.codegen = codegen; | - | ||||||
140 | r.type = StackSlot; | - | ||||||
141 | r.theStackSlot = stackSlot; | - | ||||||
142 | return r; executed 1863990 times by 95 tests: return r; Executed by:
| 1863990 | ||||||
143 | } | - | ||||||
144 | static RValue fromAccumulator(Codegen *codegen) { | - | ||||||
145 | RValue r; | - | ||||||
146 | r.codegen = codegen; | - | ||||||
147 | r.type = Accumulator; | - | ||||||
148 | return r; executed 2217958 times by 113 tests: return r; Executed by:
| 2217958 | ||||||
149 | } | - | ||||||
150 | static RValue fromConst(Codegen *codegen, QV4::ReturnedValue value) { | - | ||||||
151 | RValue r; | - | ||||||
152 | r.codegen = codegen; | - | ||||||
153 | r.type = Const; | - | ||||||
154 | r.constant = value; | - | ||||||
155 | return r; executed 32357 times by 18 tests: return r; Executed by:
| 32357 | ||||||
156 | } | - | ||||||
157 | - | |||||||
158 | bool operator==(const RValue &other) const; | - | ||||||
159 | - | |||||||
160 | bool isValid() const { return type != Invalid; } never executed: return type != Invalid; | 0 | ||||||
161 | bool isAccumulator() const { return type == Accumulator; } never executed: return type == Accumulator; | 0 | ||||||
162 | bool isStackSlot() const { return type == StackSlot; } executed 2887279 times by 95 tests: return type == StackSlot; Executed by:
| 2887279 | ||||||
163 | bool isConst() const { return type == Const; } never executed: return type == Const; | 0 | ||||||
164 | - | |||||||
165 | Moth::StackSlot stackSlot() const { | - | ||||||
166 | Q_ASSERT(isStackSlot()); | - | ||||||
167 | return theStackSlot; executed 1449085 times by 95 tests: return theStackSlot; Executed by:
| 1449085 | ||||||
168 | } | - | ||||||
169 | - | |||||||
170 | QV4::ReturnedValue constantValue() const { | - | ||||||
171 | Q_ASSERT(isConst()); | - | ||||||
172 | return constant; never executed: return constant; | 0 | ||||||
173 | } | - | ||||||
174 | - | |||||||
175 | Q_REQUIRED_RESULT RValue storeOnStack() const; | - | ||||||
176 | void loadInAccumulator() const; | - | ||||||
177 | }; | - | ||||||
178 | struct Reference { | - | ||||||
179 | enum Type { | - | ||||||
180 | Invalid, | - | ||||||
181 | Accumulator, | - | ||||||
182 | Super, | - | ||||||
183 | SuperProperty, | - | ||||||
184 | StackSlot, | - | ||||||
185 | ScopedLocal, | - | ||||||
186 | Name, | - | ||||||
187 | Member, | - | ||||||
188 | Subscript, | - | ||||||
189 | QmlScopeObject, | - | ||||||
190 | QmlContextObject, | - | ||||||
191 | LastLValue = QmlContextObject, | - | ||||||
192 | Const | - | ||||||
193 | } type = Invalid; | - | ||||||
194 | - | |||||||
195 | bool isLValue() const { return !isReadonly && type > Accumulator; } executed 1850318 times by 92 tests: return !isReadonly && type > Accumulator; Executed by:
| 1850318 | ||||||
196 | - | |||||||
197 | Reference(Codegen *cg, Type type = Invalid) : type(type), codegen(cg) {} executed 43837670 times by 140 tests: end of block Executed by:
| 43837670 | ||||||
198 | Reference() {} | - | ||||||
199 | Reference(const Reference &other); | - | ||||||
200 | - | |||||||
201 | Reference &operator =(const Reference &other); | - | ||||||
202 | - | |||||||
203 | bool operator==(const Reference &other) const; | - | ||||||
204 | bool operator!=(const Reference &other) const | - | ||||||
205 | { return !(*this == other); } executed 33727 times by 12 tests: return !(*this == other); Executed by:
| 33727 | ||||||
206 | - | |||||||
207 | bool isValid() const { return type != Invalid; } executed 845203 times by 73 tests: return type != Invalid; Executed by:
| 845203 | ||||||
208 | bool loadTriggersSideEffect() const { | - | ||||||
209 | switch (type) { | - | ||||||
210 | case Name: executed 3463 times by 4 tests: case Name: Executed by:
| 3463 | ||||||
211 | case Member: executed 364 times by 8 tests: case Member: Executed by:
| 364 | ||||||
212 | case Subscript: executed 36 times by 1 test: case Subscript: Executed by:
| 36 | ||||||
213 | return true; executed 3864 times by 9 tests: return true; Executed by:
| 3864 | ||||||
214 | default: executed 3567372 times by 97 tests: default: Executed by:
| 3567372 | ||||||
215 | return false; executed 3567716 times by 97 tests: return false; Executed by:
| 3567716 | ||||||
216 | } | - | ||||||
217 | } | - | ||||||
218 | bool isConstant() const { return type == Const; } executed 10226511 times by 140 tests: return type == Const; Executed by:
| 10226511 | ||||||
219 | bool isAccumulator() const { return type == Accumulator; } executed 493596 times by 50 tests: return type == Accumulator; Executed by:
| 493596 | ||||||
220 | bool isSuper() const { return type == Super; } executed 3623899 times by 114 tests: return type == Super; Executed by:
| 3623899 | ||||||
221 | bool isSuperProperty() const { return type == SuperProperty; } never executed: return type == SuperProperty; | 0 | ||||||
222 | bool isStackSlot() const { return type == StackSlot; } executed 54343143 times by 139 tests: return type == StackSlot; Executed by:
| 54343143 | ||||||
223 | bool isRegister() const { | - | ||||||
224 | return isStackSlot(); executed 808554 times by 1 test: return isStackSlot(); Executed by:
| 808554 | ||||||
225 | } | - | ||||||
226 | - | |||||||
227 | enum PropertyCapturePolicy { | - | ||||||
228 | /* | - | ||||||
229 | We're reading a property from the scope or context object, but it's a CONSTANT property, | - | ||||||
230 | so we don't need to register a dependency at all. | - | ||||||
231 | */ | - | ||||||
232 | DontCapture, | - | ||||||
233 | /* | - | ||||||
234 | We're reading the property of a QObject, and we know that it's the | - | ||||||
235 | scope object or context object, which we know very well. Instead of registering a | - | ||||||
236 | property capture every time, we can do that ahead of time and then register all those | - | ||||||
237 | captures in one shot in registerQmlDependencies(). | - | ||||||
238 | */ | - | ||||||
239 | CaptureAheadOfTime, | - | ||||||
240 | /* | - | ||||||
241 | We're reading the property of a QObject, and we're not quite sure where | - | ||||||
242 | the QObject comes from or what it is. So, when reading that property at run-time, | - | ||||||
243 | make sure that we capture where we read that property so that if it changes we can | - | ||||||
244 | re-evaluate the entire expression. | - | ||||||
245 | */ | - | ||||||
246 | CaptureAtRuntime | - | ||||||
247 | }; | - | ||||||
248 | - | |||||||
249 | static Reference fromAccumulator(Codegen *cg) { | - | ||||||
250 | return Reference(cg, Accumulator); executed 12267331 times by 118 tests: return Reference(cg, Accumulator); Executed by:
| 12267331 | ||||||
251 | } | - | ||||||
252 | static Reference fromSuper(Codegen *cg) { | - | ||||||
253 | return Reference(cg, Super); executed 883 times by 1 test: return Reference(cg, Super); Executed by:
| 883 | ||||||
254 | } | - | ||||||
255 | static Reference fromStackSlot(Codegen *cg, int tempIndex = -1, bool isLocal = false) { | - | ||||||
256 | Reference r(cg, StackSlot); | - | ||||||
257 | if (tempIndex == -1)
| 6554105-13318013 | ||||||
258 | tempIndex = cg->bytecodeGenerator->newRegister(); executed 6562219 times by 105 tests: tempIndex = cg->bytecodeGenerator->newRegister(); Executed by:
| 6562219 | ||||||
259 | r.theStackSlot = Moth::StackSlot::createRegister(tempIndex); | - | ||||||
260 | r.stackSlotIsLocalOrArgument = isLocal; | - | ||||||
261 | return r; executed 19885953 times by 139 tests: return r; Executed by:
| 19885953 | ||||||
262 | } | - | ||||||
263 | static Reference fromArgument(Codegen *cg, int index, bool isVolatile) { | - | ||||||
264 | Reference r(cg, StackSlot); | - | ||||||
265 | r.theStackSlot = Moth::StackSlot::createRegister(index + sizeof(CallData)/sizeof(Value) - 1); | - | ||||||
266 | r.stackSlotIsLocalOrArgument = true; | - | ||||||
267 | r.isVolatile = isVolatile; | - | ||||||
268 | return r; never executed: return r; | 0 | ||||||
269 | } | - | ||||||
270 | static Reference fromScopedLocal(Codegen *cg, int index, int scope) { | - | ||||||
271 | Reference r(cg, ScopedLocal); | - | ||||||
272 | r.index = index; | - | ||||||
273 | r.scope = scope; | - | ||||||
274 | return r; executed 894378 times by 21 tests: return r; Executed by:
| 894378 | ||||||
275 | } | - | ||||||
276 | static Reference fromName(Codegen *cg, const QString &name) { | - | ||||||
277 | Reference r(cg, Name); | - | ||||||
278 | r.name = name; | - | ||||||
279 | return r; executed 5488528 times by 52 tests: return r; Executed by:
| 5488528 | ||||||
280 | } | - | ||||||
281 | static Reference fromMember(const Reference &baseRef, const QString &name) { | - | ||||||
282 | Reference r(baseRef.codegen, Member); | - | ||||||
283 | r.propertyBase = baseRef.asRValue(); | - | ||||||
284 | r.propertyNameIndex = r.codegen->registerString(name); | - | ||||||
285 | return r; executed 2728017 times by 113 tests: return r; Executed by:
| 2728017 | ||||||
286 | } | - | ||||||
287 | static Reference fromSuperProperty(const Reference &property) { | - | ||||||
288 | Q_ASSERT(property.isStackSlot()); | - | ||||||
289 | Reference r(property.codegen, SuperProperty); | - | ||||||
290 | r.property = property.stackSlot(); | - | ||||||
291 | return r; executed 428 times by 1 test: return r; Executed by:
| 428 | ||||||
292 | } | - | ||||||
293 | static Reference fromSubscript(const Reference &baseRef, const Reference &subscript) { | - | ||||||
294 | Q_ASSERT(baseRef.isStackSlot()); | - | ||||||
295 | Reference r(baseRef.codegen, Subscript); | - | ||||||
296 | r.elementBase = baseRef.stackSlot(); | - | ||||||
297 | r.elementSubscript = subscript.asRValue(); | - | ||||||
298 | return r; executed 122613 times by 33 tests: return r; Executed by:
| 122613 | ||||||
299 | } | - | ||||||
300 | static Reference fromConst(Codegen *cg, QV4::ReturnedValue constant) { | - | ||||||
301 | Reference r(cg, Const); | - | ||||||
302 | r.constant = constant; | - | ||||||
303 | r.isReadonly = true; | - | ||||||
304 | return r; executed 2579074 times by 109 tests: return r; Executed by:
| 2579074 | ||||||
305 | } | - | ||||||
306 | static Reference fromQmlScopeObject(const Reference &base, qint16 coreIndex, qint16 notifyIndex, PropertyCapturePolicy capturePolicy) { | - | ||||||
307 | Reference r(base.codegen, QmlScopeObject); | - | ||||||
308 | r.qmlBase = base.storeOnStack().stackSlot(); | - | ||||||
309 | r.qmlCoreIndex = coreIndex; | - | ||||||
310 | r.qmlNotifyIndex = notifyIndex; | - | ||||||
311 | r.capturePolicy = capturePolicy; | - | ||||||
312 | return r; never executed: return r; | 0 | ||||||
313 | } | - | ||||||
314 | static Reference fromQmlContextObject(const Reference &base, qint16 coreIndex, qint16 notifyIndex, PropertyCapturePolicy capturePolicy) { | - | ||||||
315 | Reference r(base.codegen, QmlContextObject); | - | ||||||
316 | r.qmlBase = base.storeOnStack().stackSlot(); | - | ||||||
317 | r.qmlCoreIndex = coreIndex; | - | ||||||
318 | r.qmlNotifyIndex = notifyIndex; | - | ||||||
319 | r.capturePolicy = capturePolicy; | - | ||||||
320 | return r; never executed: return r; | 0 | ||||||
321 | } | - | ||||||
322 | static Reference fromThis(Codegen *cg) { | - | ||||||
323 | Reference r = fromStackSlot(cg, CallData::This); | - | ||||||
324 | r.isReadonly = true; | - | ||||||
325 | return r; executed 173742 times by 16 tests: return r; Executed by:
| 173742 | ||||||
326 | } | - | ||||||
327 | - | |||||||
328 | RValue asRValue() const; | - | ||||||
329 | Reference asLValue() const; | - | ||||||
330 | - | |||||||
331 | Q_REQUIRED_RESULT static Reference storeConstOnStack(Codegen *cg, QV4::ReturnedValue constant) | - | ||||||
332 | { return Reference::fromConst(cg, constant).storeOnStack(); } executed 12427 times by 9 tests: return Reference::fromConst(cg, constant).storeOnStack(); Executed by:
| 12427 | ||||||
333 | - | |||||||
334 | static void storeConstOnStack(Codegen *cg, QV4::ReturnedValue constant, int stackSlot) | - | ||||||
335 | { Reference::fromConst(cg, constant).storeOnStack(stackSlot); } executed 88 times by 1 test: end of block Executed by:
| 88 | ||||||
336 | - | |||||||
337 | Q_REQUIRED_RESULT Reference storeOnStack() const; | - | ||||||
338 | void storeOnStack(int tempIndex) const; | - | ||||||
339 | Q_REQUIRED_RESULT Reference storeRetainAccumulator() const; | - | ||||||
340 | Reference storeConsumeAccumulator() const; | - | ||||||
341 | - | |||||||
342 | Q_REQUIRED_RESULT Reference baseObject() const; | - | ||||||
343 | - | |||||||
344 | bool storeWipesAccumulator() const; | - | ||||||
345 | void loadInAccumulator() const; | - | ||||||
346 | - | |||||||
347 | int nameAsIndex() const { | - | ||||||
348 | Q_ASSERT(type == Name); | - | ||||||
349 | return codegen->registerString(name); executed 5376202 times by 108 tests: return codegen->registerString(name); Executed by:
| 5376202 | ||||||
350 | } | - | ||||||
351 | - | |||||||
352 | Moth::StackSlot stackSlot() const { | - | ||||||
353 | if (Q_UNLIKELY(!isStackSlot()))
| 0-17116942 | ||||||
354 | Q_UNREACHABLE(); never executed: end of block | 0 | ||||||
355 | return theStackSlot; executed 17115736 times by 107 tests: return theStackSlot; Executed by:
| 17115736 | ||||||
356 | } | - | ||||||
357 | - | |||||||
358 | union { | - | ||||||
359 | Moth::StackSlot theStackSlot; | - | ||||||
360 | QV4::ReturnedValue constant; | - | ||||||
361 | struct { // Scoped arguments/Local | - | ||||||
362 | int index; | - | ||||||
363 | int scope; | - | ||||||
364 | }; | - | ||||||
365 | struct { | - | ||||||
366 | RValue propertyBase; | - | ||||||
367 | int propertyNameIndex; | - | ||||||
368 | }; | - | ||||||
369 | struct { | - | ||||||
370 | Moth::StackSlot elementBase; | - | ||||||
371 | RValue elementSubscript; | - | ||||||
372 | }; | - | ||||||
373 | struct { // QML scope/context object case | - | ||||||
374 | Moth::StackSlot qmlBase; | - | ||||||
375 | qint16 qmlCoreIndex; | - | ||||||
376 | qint16 qmlNotifyIndex; | - | ||||||
377 | PropertyCapturePolicy capturePolicy; | - | ||||||
378 | }; | - | ||||||
379 | Moth::StackSlot property; // super property | - | ||||||
380 | }; | - | ||||||
381 | QString name; | - | ||||||
382 | mutable bool isArgOrEval = false; | - | ||||||
383 | bool isReadonly = false; | - | ||||||
384 | bool isReferenceToConst = false; | - | ||||||
385 | bool stackSlotIsLocalOrArgument = false; | - | ||||||
386 | bool isVolatile = false; | - | ||||||
387 | bool global = false; | - | ||||||
388 | Codegen *codegen = nullptr; | - | ||||||
389 | - | |||||||
390 | private: | - | ||||||
391 | void storeAccumulator() const; | - | ||||||
392 | Reference doStoreOnStack(int tempIndex) const; | - | ||||||
393 | }; | - | ||||||
394 | - | |||||||
395 | struct RegisterScope { | - | ||||||
396 | RegisterScope(Codegen *cg) | - | ||||||
397 | : generator(cg->bytecodeGenerator), | - | ||||||
398 | regCountForScope(generator->currentReg) {} executed 35234639 times by 140 tests: end of block Executed by:
| 35234639 | ||||||
399 | ~RegisterScope() { | - | ||||||
400 | generator->currentReg = regCountForScope; | - | ||||||
401 | } executed 35278453 times by 140 tests: end of block Executed by:
| 35278453 | ||||||
402 | BytecodeGenerator *generator; | - | ||||||
403 | int regCountForScope; | - | ||||||
404 | }; | - | ||||||
405 | - | |||||||
406 | struct ObjectPropertyValue { | - | ||||||
407 | ObjectPropertyValue() {} | - | ||||||
408 | - | |||||||
409 | Reference rvalue; | - | ||||||
410 | int getter = -1; // index in _module->functions or -1 if not set | - | ||||||
411 | int setter = -1; | - | ||||||
412 | uint keyAsIndex = UINT_MAX; | - | ||||||
413 | - | |||||||
414 | bool hasGetter() const { return getter >= 0; } never executed: return getter >= 0; | 0 | ||||||
415 | bool hasSetter() const { return setter >= 0; } never executed: return setter >= 0; | 0 | ||||||
416 | }; | - | ||||||
417 | protected: | - | ||||||
418 | - | |||||||
419 | enum Format { ex, cx, nx }; | - | ||||||
420 | class Result { | - | ||||||
421 | Reference _result; | - | ||||||
422 | - | |||||||
423 | const BytecodeGenerator::Label *_iftrue = nullptr; | - | ||||||
424 | const BytecodeGenerator::Label *_iffalse = nullptr; | - | ||||||
425 | Format _format = ex; | - | ||||||
426 | Format _requested; | - | ||||||
427 | bool _trueBlockFollowsCondition = false; | - | ||||||
428 | - | |||||||
429 | public: | - | ||||||
430 | explicit Result(const Reference &lrvalue) | - | ||||||
431 | : _result(lrvalue) | - | ||||||
432 | , _requested(ex) | - | ||||||
433 | {} never executed: end of block | 0 | ||||||
434 | - | |||||||
435 | explicit Result(Format requested = ex) | - | ||||||
436 | : _requested(requested) {} executed 30855790 times by 147 tests: end of block Executed by:
| 30855790 | ||||||
437 | - | |||||||
438 | explicit Result(const BytecodeGenerator::Label *iftrue, | - | ||||||
439 | const BytecodeGenerator::Label *iffalse, | - | ||||||
440 | bool trueBlockFollowsCondition) | - | ||||||
441 | : _iftrue(iftrue) | - | ||||||
442 | , _iffalse(iffalse) | - | ||||||
443 | , _requested(cx) | - | ||||||
444 | , _trueBlockFollowsCondition(trueBlockFollowsCondition) | - | ||||||
445 | { | - | ||||||
446 | Q_ASSERT(iftrue); | - | ||||||
447 | Q_ASSERT(iffalse); | - | ||||||
448 | } executed 1487495 times by 71 tests: end of block Executed by:
| 1487495 | ||||||
449 | - | |||||||
450 | const BytecodeGenerator::Label *iftrue() const { | - | ||||||
451 | Q_ASSERT(_requested == cx); | - | ||||||
452 | return _iftrue; executed 1608640 times by 71 tests: return _iftrue; Executed by:
| 1608640 | ||||||
453 | } | - | ||||||
454 | - | |||||||
455 | const BytecodeGenerator::Label *iffalse() const { | - | ||||||
456 | Q_ASSERT(_requested == cx); | - | ||||||
457 | return _iffalse; executed 1863873 times by 71 tests: return _iffalse; Executed by:
| 1863873 | ||||||
458 | } | - | ||||||
459 | - | |||||||
460 | Format format() const { | - | ||||||
461 | return _format; executed 1494892 times by 71 tests: return _format; Executed by:
| 1494892 | ||||||
462 | } | - | ||||||
463 | - | |||||||
464 | bool accept(Format f) | - | ||||||
465 | { | - | ||||||
466 | if (_requested == f) {
| 748559-2596774 | ||||||
467 | _format = f; | - | ||||||
468 | return true; executed 2597207 times by 95 tests: return true; Executed by:
| 2597207 | ||||||
469 | } | - | ||||||
470 | return false; executed 750143 times by 59 tests: return false; Executed by:
| 750143 | ||||||
471 | } | - | ||||||
472 | - | |||||||
473 | bool trueBlockFollowsCondition() const { | - | ||||||
474 | return _trueBlockFollowsCondition; executed 1495369 times by 71 tests: return _trueBlockFollowsCondition; Executed by:
| 1495369 | ||||||
475 | } | - | ||||||
476 | - | |||||||
477 | const Reference &result() const { | - | ||||||
478 | return _result; executed 29500502 times by 140 tests: return _result; Executed by:
| 29500502 | ||||||
479 | } | - | ||||||
480 | - | |||||||
481 | void setResult(const Reference &result) { | - | ||||||
482 | _result = result; | - | ||||||
483 | } executed 29872629 times by 140 tests: end of block Executed by:
| 29872629 | ||||||
484 | }; | - | ||||||
485 | - | |||||||
486 | void enterContext(AST::Node *node); | - | ||||||
487 | int leaveContext(); | - | ||||||
488 | public: | - | ||||||
489 | Context *enterBlock(AST::Node *node); | - | ||||||
490 | int leaveBlock() { return leaveContext(); } executed 1783985 times by 77 tests: return leaveContext(); Executed by:
| 1783985 | ||||||
491 | protected: | - | ||||||
492 | void leaveLoop(); | - | ||||||
493 | - | |||||||
494 | enum UnaryOperation { | - | ||||||
495 | UPlus, | - | ||||||
496 | UMinus, | - | ||||||
497 | PreIncrement, | - | ||||||
498 | PreDecrement, | - | ||||||
499 | PostIncrement, | - | ||||||
500 | PostDecrement, | - | ||||||
501 | Not, | - | ||||||
502 | Compl | - | ||||||
503 | }; | - | ||||||
504 | - | |||||||
505 | Reference unop(UnaryOperation op, const Reference &expr); | - | ||||||
506 | - | |||||||
507 | void addCJump(); | - | ||||||
508 | - | |||||||
509 | public: | - | ||||||
510 | int registerString(const QString &name) { | - | ||||||
511 | return jsUnitGenerator->registerString(name); executed 11974724 times by 125 tests: return jsUnitGenerator->registerString(name); Executed by:
| 11974724 | ||||||
512 | } | - | ||||||
513 | int registerConstant(QV4::ReturnedValue v) { return jsUnitGenerator->registerConstant(v); } executed 651833 times by 69 tests: return jsUnitGenerator->registerConstant(v); Executed by:
| 651833 | ||||||
514 | int registerGetterLookup(int nameIndex) { return jsUnitGenerator->registerGetterLookup(nameIndex); } executed 1910141 times by 7 tests: return jsUnitGenerator->registerGetterLookup(nameIndex); Executed by:
| 1910141 | ||||||
515 | int registerSetterLookup(int nameIndex) { return jsUnitGenerator->registerSetterLookup(nameIndex); } executed 593502 times by 1 test: return jsUnitGenerator->registerSetterLookup(nameIndex); Executed by:
| 593502 | ||||||
516 | int registerGlobalGetterLookup(int nameIndex) { return jsUnitGenerator->registerGlobalGetterLookup(nameIndex); } executed 3392539 times by 7 tests: return jsUnitGenerator->registerGlobalGetterLookup(nameIndex); Executed by:
| 3392539 | ||||||
517 | - | |||||||
518 | // Returns index in _module->functions | - | ||||||
519 | virtual int defineFunction(const QString &name, AST::Node *ast, | - | ||||||
520 | AST::FormalParameterList *formals, | - | ||||||
521 | AST::StatementList *body); | - | ||||||
522 | - | |||||||
523 | protected: | - | ||||||
524 | void statement(AST::Statement *ast); | - | ||||||
525 | void statement(AST::ExpressionNode *ast); | - | ||||||
526 | void condition(AST::ExpressionNode *ast, const BytecodeGenerator::Label *iftrue, | - | ||||||
527 | const BytecodeGenerator::Label *iffalse, | - | ||||||
528 | bool trueBlockFollowsCondition); | - | ||||||
529 | Reference expression(AST::ExpressionNode *ast); | - | ||||||
530 | - | |||||||
531 | void accept(AST::Node *node); | - | ||||||
532 | - | |||||||
533 | void program(AST::Program *ast); | - | ||||||
534 | void statementList(AST::StatementList *ast); | - | ||||||
535 | void variableDeclaration(AST::PatternElement *ast); | - | ||||||
536 | void variableDeclarationList(AST::VariableDeclarationList *ast); | - | ||||||
537 | - | |||||||
538 | Reference targetForPatternElement(AST::PatternElement *p); | - | ||||||
539 | void initializeAndDestructureBindingElement(AST::PatternElement *e, const Reference &baseRef = Reference(), bool isDefinition = false); | - | ||||||
540 | void destructurePropertyList(const Reference &object, AST::PatternPropertyList *bindingList, bool isDefinition = false); | - | ||||||
541 | void destructureElementList(const Reference &array, AST::PatternElementList *bindingList, bool isDefinition = false); | - | ||||||
542 | void destructurePattern(AST::Pattern *p, const Reference &rhs); | - | ||||||
543 | - | |||||||
544 | Reference referenceForPropertyName(const Codegen::Reference &object, AST::PropertyName *name); | - | ||||||
545 | - | |||||||
546 | // Hook provided to implement QML lookup semantics | - | ||||||
547 | virtual Reference fallbackNameLookup(const QString &name); | - | ||||||
548 | virtual void beginFunctionBodyHook() {} | - | ||||||
549 | - | |||||||
550 | void emitReturn(const Reference &expr); | - | ||||||
551 | - | |||||||
552 | // nodes | - | ||||||
553 | bool visit(AST::ArgumentList *ast) override; | - | ||||||
554 | bool visit(AST::CaseBlock *ast) override; | - | ||||||
555 | bool visit(AST::CaseClause *ast) override; | - | ||||||
556 | bool visit(AST::CaseClauses *ast) override; | - | ||||||
557 | bool visit(AST::Catch *ast) override; | - | ||||||
558 | bool visit(AST::DefaultClause *ast) override; | - | ||||||
559 | bool visit(AST::Elision *ast) override; | - | ||||||
560 | bool visit(AST::Finally *ast) override; | - | ||||||
561 | bool visit(AST::FormalParameterList *ast) override; | - | ||||||
562 | bool visit(AST::Program *ast) override; | - | ||||||
563 | bool visit(AST::StatementList *ast) override; | - | ||||||
564 | bool visit(AST::UiArrayMemberList *ast) override; | - | ||||||
565 | bool visit(AST::UiImport *ast) override; | - | ||||||
566 | bool visit(AST::UiHeaderItemList *ast) override; | - | ||||||
567 | bool visit(AST::UiPragma *ast) override; | - | ||||||
568 | bool visit(AST::UiObjectInitializer *ast) override; | - | ||||||
569 | bool visit(AST::UiObjectMemberList *ast) override; | - | ||||||
570 | bool visit(AST::UiParameterList *ast) override; | - | ||||||
571 | bool visit(AST::UiProgram *ast) override; | - | ||||||
572 | bool visit(AST::UiQualifiedId *ast) override; | - | ||||||
573 | bool visit(AST::UiQualifiedPragmaId *ast) override; | - | ||||||
574 | bool visit(AST::VariableDeclarationList *ast) override; | - | ||||||
575 | - | |||||||
576 | bool visit(AST::PatternElement *ast) override; | - | ||||||
577 | bool visit(AST::PatternElementList *ast) override; | - | ||||||
578 | bool visit(AST::PatternProperty *ast) override; | - | ||||||
579 | bool visit(AST::PatternPropertyList *ast) override; | - | ||||||
580 | - | |||||||
581 | // expressions | - | ||||||
582 | bool visit(AST::Expression *ast) override; | - | ||||||
583 | bool visit(AST::ArrayPattern *ast) override; | - | ||||||
584 | bool visit(AST::ArrayMemberExpression *ast) override; | - | ||||||
585 | bool visit(AST::BinaryExpression *ast) override; | - | ||||||
586 | bool visit(AST::CallExpression *ast) override; | - | ||||||
587 | bool visit(AST::ConditionalExpression *ast) override; | - | ||||||
588 | bool visit(AST::DeleteExpression *ast) override; | - | ||||||
589 | bool visit(AST::FalseLiteral *ast) override; | - | ||||||
590 | bool visit(AST::SuperLiteral *ast) override; | - | ||||||
591 | bool visit(AST::FieldMemberExpression *ast) override; | - | ||||||
592 | bool visit(AST::TaggedTemplate *ast) override; | - | ||||||
593 | bool visit(AST::FunctionExpression *ast) override; | - | ||||||
594 | bool visit(AST::IdentifierExpression *ast) override; | - | ||||||
595 | bool visit(AST::NestedExpression *ast) override; | - | ||||||
596 | bool visit(AST::NewExpression *ast) override; | - | ||||||
597 | bool visit(AST::NewMemberExpression *ast) override; | - | ||||||
598 | bool visit(AST::NotExpression *ast) override; | - | ||||||
599 | bool visit(AST::NullExpression *ast) override; | - | ||||||
600 | bool visit(AST::NumericLiteral *ast) override; | - | ||||||
601 | bool visit(AST::ObjectPattern *ast) override; | - | ||||||
602 | bool visit(AST::PostDecrementExpression *ast) override; | - | ||||||
603 | bool visit(AST::PostIncrementExpression *ast) override; | - | ||||||
604 | bool visit(AST::PreDecrementExpression *ast) override; | - | ||||||
605 | bool visit(AST::PreIncrementExpression *ast) override; | - | ||||||
606 | bool visit(AST::RegExpLiteral *ast) override; | - | ||||||
607 | bool visit(AST::StringLiteral *ast) override; | - | ||||||
608 | bool visit(AST::TemplateLiteral *ast) override; | - | ||||||
609 | bool visit(AST::ThisExpression *ast) override; | - | ||||||
610 | bool visit(AST::TildeExpression *ast) override; | - | ||||||
611 | bool visit(AST::TrueLiteral *ast) override; | - | ||||||
612 | bool visit(AST::TypeOfExpression *ast) override; | - | ||||||
613 | bool visit(AST::UnaryMinusExpression *ast) override; | - | ||||||
614 | bool visit(AST::UnaryPlusExpression *ast) override; | - | ||||||
615 | bool visit(AST::VoidExpression *ast) override; | - | ||||||
616 | bool visit(AST::FunctionDeclaration *ast) override; | - | ||||||
617 | bool visit(AST::YieldExpression *ast) override; | - | ||||||
618 | bool visit(AST::ClassExpression *ast) override; | - | ||||||
619 | bool visit(AST::ClassDeclaration *ast) override; | - | ||||||
620 | - | |||||||
621 | // statements | - | ||||||
622 | bool visit(AST::Block *ast) override; | - | ||||||
623 | bool visit(AST::BreakStatement *ast) override; | - | ||||||
624 | bool visit(AST::ContinueStatement *ast) override; | - | ||||||
625 | bool visit(AST::DebuggerStatement *ast) override; | - | ||||||
626 | bool visit(AST::DoWhileStatement *ast) override; | - | ||||||
627 | bool visit(AST::EmptyStatement *ast) override; | - | ||||||
628 | bool visit(AST::ExpressionStatement *ast) override; | - | ||||||
629 | bool visit(AST::ForEachStatement *ast) override; | - | ||||||
630 | bool visit(AST::ForStatement *ast) override; | - | ||||||
631 | bool visit(AST::IfStatement *ast) override; | - | ||||||
632 | bool visit(AST::LabelledStatement *ast) override; | - | ||||||
633 | bool visit(AST::ReturnStatement *ast) override; | - | ||||||
634 | bool visit(AST::SwitchStatement *ast) override; | - | ||||||
635 | bool visit(AST::ThrowStatement *ast) override; | - | ||||||
636 | bool visit(AST::TryStatement *ast) override; | - | ||||||
637 | bool visit(AST::VariableStatement *ast) override; | - | ||||||
638 | bool visit(AST::WhileStatement *ast) override; | - | ||||||
639 | bool visit(AST::WithStatement *ast) override; | - | ||||||
640 | - | |||||||
641 | // ui object members | - | ||||||
642 | bool visit(AST::UiArrayBinding *ast) override; | - | ||||||
643 | bool visit(AST::UiObjectBinding *ast) override; | - | ||||||
644 | bool visit(AST::UiObjectDefinition *ast) override; | - | ||||||
645 | bool visit(AST::UiPublicMember *ast) override; | - | ||||||
646 | bool visit(AST::UiScriptBinding *ast) override; | - | ||||||
647 | bool visit(AST::UiSourceElement *ast) override; | - | ||||||
648 | - | |||||||
649 | bool throwSyntaxErrorOnEvalOrArgumentsInStrictMode(const Reference &r, const AST::SourceLocation &loc); | - | ||||||
650 | virtual void throwSyntaxError(const AST::SourceLocation &loc, const QString &detail); | - | ||||||
651 | virtual void throwReferenceError(const AST::SourceLocation &loc, const QString &detail); | - | ||||||
652 | - | |||||||
653 | public: | - | ||||||
654 | QList<DiagnosticMessage> errors() const; | - | ||||||
655 | #ifndef V4_BOOTSTRAP | - | ||||||
656 | QList<QQmlError> qmlErrors() const; | - | ||||||
657 | #endif | - | ||||||
658 | - | |||||||
659 | Reference binopHelper(QSOperator::Op oper, Reference &left, Reference &right); | - | ||||||
660 | Reference jumpBinop(QSOperator::Op oper, Reference &left, Reference &right); | - | ||||||
661 | struct Arguments { int argc; int argv; bool hasSpread; }; | - | ||||||
662 | Arguments pushArgs(AST::ArgumentList *args); | - | ||||||
663 | void handleCall(Reference &base, Arguments calldata); | - | ||||||
664 | - | |||||||
665 | Arguments pushTemplateArgs(AST::TemplateLiteral *args); | - | ||||||
666 | int createTemplateArray(AST::TemplateLiteral *t); | - | ||||||
667 | - | |||||||
668 | void setUseFastLookups(bool b) { useFastLookups = b; } executed 1726449 times by 146 tests: end of block Executed by:
| 1726449 | ||||||
669 | - | |||||||
670 | void handleTryCatch(AST::TryStatement *ast); | - | ||||||
671 | void handleTryFinally(AST::TryStatement *ast); | - | ||||||
672 | - | |||||||
673 | - | |||||||
674 | Reference referenceForName(const QString &name, bool lhs); | - | ||||||
675 | - | |||||||
676 | QQmlRefPointer<QV4::CompiledData::CompilationUnit> generateCompilationUnit(bool generateUnitData = true); | - | ||||||
677 | static QQmlRefPointer<QV4::CompiledData::CompilationUnit> createUnitForLoading(); | - | ||||||
678 | - | |||||||
679 | Context *currentContext() const { return _context; } executed 585529 times by 49 tests: return _context; Executed by:
| 585529 | ||||||
680 | BytecodeGenerator *generator() const { return bytecodeGenerator; } executed 10351298 times by 140 tests: return bytecodeGenerator; Executed by:
| 10351298 | ||||||
681 | - | |||||||
682 | void loadClosure(int index); | - | ||||||
683 | - | |||||||
684 | Module *module() const { return _module; } executed 437241 times by 33 tests: return _module; Executed by:
| 437241 | ||||||
685 | - | |||||||
686 | BytecodeGenerator::Label returnLabel() { | - | ||||||
687 | if (!_returnLabel)
| 85042-419646 | ||||||
688 | _returnLabel = new BytecodeGenerator::Label(bytecodeGenerator->newLabel()); executed 419963 times by 27 tests: _returnLabel = new BytecodeGenerator::Label(bytecodeGenerator->newLabel()); Executed by:
| 419963 | ||||||
689 | return *_returnLabel; executed 507695 times by 27 tests: return *_returnLabel; Executed by:
| 507695 | ||||||
690 | } | - | ||||||
691 | - | |||||||
692 | protected: | - | ||||||
693 | friend class ScanFunctions; | - | ||||||
694 | friend struct ControlFlow; | - | ||||||
695 | friend struct ControlFlowCatch; | - | ||||||
696 | friend struct ControlFlowFinally; | - | ||||||
697 | Result _expr; | - | ||||||
698 | VolatileMemoryLocations _volatileMemoryLocations; | - | ||||||
699 | Module *_module; | - | ||||||
700 | int _returnAddress; | - | ||||||
701 | Context *_context; | - | ||||||
702 | Context *_functionContext = nullptr; | - | ||||||
703 | AST::LabelledStatement *_labelledStatement; | - | ||||||
704 | QV4::Compiler::JSUnitGenerator *jsUnitGenerator; | - | ||||||
705 | BytecodeGenerator *bytecodeGenerator = nullptr; | - | ||||||
706 | Moth::BytecodeGenerator::Label *_returnLabel = nullptr; | - | ||||||
707 | bool _strictMode; | - | ||||||
708 | bool useFastLookups = true; | - | ||||||
709 | bool requiresReturnValue = false; | - | ||||||
710 | bool insideSwitch = false; | - | ||||||
711 | bool inFormalParameterList = false; | - | ||||||
712 | bool functionEndsWithReturn = false; | - | ||||||
713 | ControlFlow *controlFlow = nullptr; | - | ||||||
714 | - | |||||||
715 | bool _fileNameIsUrl; | - | ||||||
716 | bool hasError; | - | ||||||
717 | QList<QQmlJS::DiagnosticMessage> _errors; | - | ||||||
718 | - | |||||||
719 | private: | - | ||||||
720 | VolatileMemoryLocations scanVolatileMemoryLocations(AST::Node *ast) const; | - | ||||||
721 | void handleConstruct(const Reference &base, AST::ArgumentList *args); | - | ||||||
722 | }; | - | ||||||
723 | - | |||||||
724 | } | - | ||||||
725 | - | |||||||
726 | } | - | ||||||
727 | - | |||||||
728 | QT_END_NAMESPACE | - | ||||||
729 | - | |||||||
730 | #endif // QV4CODEGEN_P_H | - | ||||||
Source code | Switch to Preprocessed file |