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
qqmljscompilepass_p.h
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#ifndef QQMLJSCOMPILEPASS_P_H
5#define QQMLJSCOMPILEPASS_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/qqmljslogger_p.h>
19#include <private/qqmljsregistercontent_p.h>
20#include <private/qqmljsscope_p.h>
21#include <private/qqmljstyperesolver_p.h>
22#include <private/qv4bytecodehandler_p.h>
23#include <private/qv4compiler_p.h>
24#include <private/qflatmap_p.h>
25
27
29{
30 Q_DISABLE_COPY_MOVE(QQmlJSCompilePass)
31public:
38
40
42 {
44 bool canMove = false;
46
47 private:
48 friend bool operator==(const VirtualRegister &a, const VirtualRegister &b)
49 {
50 return a.content == b.content && a.canMove == b.canMove
51 && a.affectedBySideEffects == b.affectedBySideEffects;
52 }
53 };
54
55 // map from register index to expected type
56 using VirtualRegisters = QFlatMap<int, VirtualRegister>;
57
59 {
60 QList<int> jumpOrigins;
61 QList<int> readRegisters;
62 QList<QQmlJSScope::ConstPtr> readTypes;
63 int jumpTarget = -1;
64 bool jumpIsUnconditional = false;
65 bool isReturnBlock = false;
66 bool isThrowBlock = false;
67 };
68
69 using BasicBlocks = QFlatMap<int, BasicBlock>;
70
72 {
73 // Registers explicit read as part of the instruction.
75
76 // Registers that have to be converted for future instructions after a jump.
78
81 bool hasSideEffects = false;
82 bool isRename = false;
83 };
84
85 using InstructionAnnotations = QFlatMap<int, InstructionAnnotation>;
91
106
108 {
109 enum {
112 };
113
116 int argc = 0;
117 int argv = -1;
118 };
119
120 struct State
121 {
124
137 {
139 Q_ASSERT(it != registers.end());
140 return it.value().content;
141 };
142
148 {
149 Q_ASSERT(m_changedRegisterIndex == Accumulator);
150 return m_changedRegister;
151 };
152
153 void setRegister(int registerIndex, QQmlJSRegisterContent content)
154 {
155 const int lookupIndex = content.resultLookupIndex();
157 lookups[lookupIndex] = { content, false, false };
158
159 m_changedRegister = std::move(content);
160 m_changedRegisterIndex = registerIndex;
161 }
162
164 {
165 m_changedRegisterIndex = InvalidRegister;
166 m_changedRegister = QQmlJSRegisterContent();
167 }
168
169 int changedRegisterIndex() const { return m_changedRegisterIndex; }
170 const QQmlJSRegisterContent &changedRegister() const { return m_changedRegister; }
171
172 void addReadRegister(int registerIndex, const QQmlJSRegisterContent &reg)
173 {
174 Q_ASSERT(isRename() || reg.isConversion());
175 const VirtualRegister &source = registers[registerIndex];
176 VirtualRegister &target = m_readRegisters[registerIndex];
177 target.content = reg;
178 target.canMove = source.canMove;
179 target.affectedBySideEffects = source.affectedBySideEffects;
180 }
181
186
187 VirtualRegisters takeReadRegisters() const { return std::move(m_readRegisters); }
189 {
190 m_readRegisters = std::move(readReagisters);
191 }
192
193 QQmlJSRegisterContent readRegister(int registerIndex) const
194 {
195 Q_ASSERT(m_readRegisters.contains(registerIndex));
196 return m_readRegisters[registerIndex].content;
197 }
198
199 bool canMoveReadRegister(int registerIndex) const
200 {
201 auto it = m_readRegisters.find(registerIndex);
202 return it != m_readRegisters.end() && it->second.canMove;
203 }
204
205 bool isRegisterAffectedBySideEffects(int registerIndex) const
206 {
207 auto it = m_readRegisters.find(registerIndex);
208 return it != m_readRegisters.end() && it->second.affectedBySideEffects;
209 }
210
222
223 bool readsRegister(int registerIndex) const
224 {
225 return m_readRegisters.contains(registerIndex);
226 }
227
228 bool hasSideEffects() const { return m_hasSideEffects; }
229
230 void markSideEffects(bool hasSideEffects) { m_hasSideEffects = hasSideEffects; }
232 {
233 if (!hasSideEffects)
234 return;
235
236 for (auto it = registers.begin(), end = registers.end(); it != end; ++it)
237 it.value().affectedBySideEffects = true;
238
239 for (auto it = lookups.begin(), end = lookups.end(); it != end; ++it)
240 it.value().affectedBySideEffects = true;
241 }
242
247
248 bool isRename() const { return m_isRename; }
249 void setIsRename(bool isRename) { m_isRename = isRename; }
250
252 {
253 Q_ASSERT(m_isRename);
254 Q_ASSERT(m_readRegisters.size() == 1);
255 return m_readRegisters.begin().key();
256 }
257
258 private:
259 VirtualRegisters m_readRegisters;
260 QQmlJSRegisterContent m_changedRegister;
261 int m_changedRegisterIndex = InvalidRegister;
262 bool m_hasSideEffects = false;
263 bool m_isRename = false;
264 };
265
267 const QQmlJSTypeResolver *typeResolver, QQmlJSLogger *logger,
268 BasicBlocks basicBlocks = {}, InstructionAnnotations annotations = {})
269 : m_jsUnitGenerator(jsUnitGenerator)
270 , m_typeResolver(typeResolver)
271 , m_logger(logger)
272 , m_basicBlocks(basicBlocks)
273 , m_annotations(annotations)
274 {}
275
276protected:
280
281 const Function *m_function = nullptr;
285
287 {
289 }
290
291 bool isArgument(int registerIndex) const
292 {
293 return registerIndex >= FirstArgument && registerIndex < firstRegisterIndex();
294 }
295
296 QQmlJSRegisterContent argumentType(int registerIndex) const
297 {
298 Q_ASSERT(isArgument(registerIndex));
299 return m_function->argumentTypes[registerIndex - FirstArgument];
300 }
301
302
303 State initialState(const Function *function)
304 {
305 State state;
306 for (int i = 0, end = function->argumentTypes.size(); i < end; ++i) {
307 state.registers[FirstArgument + i].content = function->argumentTypes.at(i);
308 Q_ASSERT(state.registers[FirstArgument + i].content.isValid());
309 }
310 for (int i = 0, end = function->registerTypes.size(); i != end; ++i)
311 state.registers[firstRegisterIndex() + i].content = function->registerTypes[i];
312 return state;
313 }
314
316 const State &oldState, const InstructionAnnotations &annotations)
317 {
319
320 const auto instruction = annotations.find(currentInstructionOffset());
321 newState.registers = oldState.registers;
322 newState.lookups = oldState.lookups;
323
324 // Usually the initial accumulator type is the output of the previous instruction, but ...
325 if (oldState.changedRegisterIndex() != InvalidRegister) {
326 newState.registers[oldState.changedRegisterIndex()].affectedBySideEffects = false;
327 newState.registers[oldState.changedRegisterIndex()].content
328 = oldState.changedRegister();
329 }
330
331 // Side effects are applied at the end of an instruction: An instruction with side
332 // effects can still read its registers before the side effects happen.
333 newState.applySideEffects(oldState.hasSideEffects());
334
335 if (instruction == annotations.constEnd())
336 return newState;
337
338 newState.markSideEffects(instruction->second.hasSideEffects);
339 newState.setReadRegisters(instruction->second.readRegisters);
340 newState.setIsRename(instruction->second.isRename);
341
342 for (auto it = instruction->second.typeConversions.begin(),
343 end = instruction->second.typeConversions.end(); it != end; ++it) {
344 Q_ASSERT(it.key() != InvalidRegister);
345 newState.registers[it.key()] = it.value();
346 }
347
348 if (instruction->second.changedRegisterIndex != InvalidRegister) {
349 newState.setRegister(instruction->second.changedRegisterIndex,
350 instruction->second.changedRegister);
351 }
352
353 return newState;
354 }
355
356 QQmlJS::SourceLocation sourceLocation(int instructionOffset) const
357 {
360 const auto &entries = m_function->sourceLocations->entries;
361 auto item = std::lower_bound(entries.begin(), entries.end(), instructionOffset,
362 [](auto entry, uint offset) { return entry.offset < offset; });
363
364 Q_ASSERT(item != entries.end());
365 return item->location;
366 }
367
372
373 void setError(const QString &message, int instructionOffset)
374 {
376 if (m_error->isValid())
377 return;
379 m_error->loc = sourceLocation(instructionOffset);
380 }
381
386
388 {
390 switch (type) {
391 case Type::PopContext:
392 case Type::PopScriptContext:
393 case Type::CreateCallContext:
394 case Type::CreateCallContext_Wide:
395 case Type::PushCatchContext:
396 case Type::PushCatchContext_Wide:
397 case Type::PushWithContext:
398 case Type::PushWithContext_Wide:
399 case Type::PushBlockContext:
400 case Type::PushBlockContext_Wide:
401 case Type::CloneBlockContext:
402 case Type::CloneBlockContext_Wide:
403 case Type::PushScriptContext:
404 case Type::PushScriptContext_Wide:
405 return true;
406 default:
407 break;
408 }
409 return false;
410 }
411
412 // Stub out all the methods so that passes can choose to only implement part of them.
413 void generate_Add(int) override {}
414 void generate_As(int) override {}
415 void generate_BitAnd(int) override {}
416 void generate_BitAndConst(int) override {}
417 void generate_BitOr(int) override {}
418 void generate_BitOrConst(int) override {}
419 void generate_BitXor(int) override {}
420 void generate_BitXorConst(int) override {}
421 void generate_CallGlobalLookup(int, int, int) override {}
422 void generate_CallName(int, int, int) override {}
423 void generate_CallPossiblyDirectEval(int, int) override {}
424 void generate_CallProperty(int, int, int, int) override {}
425 void generate_CallPropertyLookup(int, int, int, int) override {}
426 void generate_CallQmlContextPropertyLookup(int, int, int) override {}
427 void generate_CallValue(int, int, int) override {}
428 void generate_CallWithReceiver(int, int, int, int) override {}
429 void generate_CallWithSpread(int, int, int, int) override {}
430 void generate_CheckException() override {}
431 void generate_CloneBlockContext() override {}
432 void generate_CmpEq(int) override {}
433 void generate_CmpEqInt(int) override {}
434 void generate_CmpEqNull() override {}
435 void generate_CmpGe(int) override {}
436 void generate_CmpGt(int) override {}
437 void generate_CmpIn(int) override {}
438 void generate_CmpInstanceOf(int) override {}
439 void generate_CmpLe(int) override {}
440 void generate_CmpLt(int) override {}
441 void generate_CmpNe(int) override {}
442 void generate_CmpNeInt(int) override {}
443 void generate_CmpNeNull() override {}
444 void generate_CmpStrictEqual(int) override {}
445 void generate_CmpStrictNotEqual(int) override {}
446 void generate_Construct(int, int, int) override {}
447 void generate_ConstructWithSpread(int, int, int) override {}
449 void generate_CreateCallContext() override {}
450 void generate_CreateClass(int, int, int) override {}
452 void generate_CreateRestParameter(int) override {}
454 void generate_DeadTemporalZoneCheck(int) override {}
455 void generate_Debug() override {}
456 void generate_DeclareVar(int, int) override {}
457 void generate_Decrement() override {}
458 void generate_DefineArray(int, int) override {}
459 void generate_DefineObjectLiteral(int, int, int) override {}
460 void generate_DeleteName(int) override {}
461 void generate_DeleteProperty(int, int) override {}
463 void generate_Div(int) override {}
464 void generate_Exp(int) override {}
465 void generate_GetException() override {}
466 void generate_GetIterator(int) override {}
467 void generate_GetLookup(int) override {}
468 void generate_GetOptionalLookup(int, int) override {}
469 void generate_GetTemplateObject(int) override {}
470 void generate_Increment() override {}
472 void generate_IteratorClose() override {}
473 void generate_IteratorNext(int, int) override {}
474 void generate_IteratorNextForYieldStar(int, int, int) override {}
475 void generate_Jump(int) override {}
476 void generate_JumpFalse(int) override {}
477 void generate_JumpNoException(int) override {}
478 void generate_JumpNotUndefined(int) override {}
479 void generate_JumpTrue(int) override {}
480 void generate_LoadClosure(int) override {}
481 void generate_LoadConst(int) override {}
482 void generate_LoadElement(int) override {}
483 void generate_LoadFalse() override {}
484 void generate_LoadGlobalLookup(int) override {}
485 void generate_LoadImport(int) override {}
486 void generate_LoadInt(int) override {}
487 void generate_LoadLocal(int) override {}
488 void generate_LoadName(int) override {}
489 void generate_LoadNull() override {}
490 void generate_LoadOptionalProperty(int, int) override {}
491 void generate_LoadProperty(int) override {}
493 void generate_LoadReg(int) override {}
494 void generate_LoadRuntimeString(int) override {}
495 void generate_LoadScopedLocal(int, int) override {}
497 void generate_LoadSuperProperty(int) override {}
498 void generate_LoadTrue() override {}
499 void generate_LoadUndefined() override {}
500 void generate_LoadZero() override {}
501 void generate_Mod(int) override {}
502 void generate_MoveConst(int, int) override {}
503 void generate_MoveReg(int, int) override {}
504 void generate_MoveRegExp(int, int) override {}
505 void generate_Mul(int) override {}
506 void generate_PopContext() override {}
507 void generate_PopScriptContext() override {}
508 void generate_PushBlockContext(int) override {}
509 void generate_PushCatchContext(int, int) override {}
510 void generate_PushScriptContext(int) override {}
511 void generate_PushWithContext() override {}
512 void generate_Resume(int) override {}
513 void generate_Ret() override {}
514 void generate_SetException() override {}
515 void generate_SetLookup(int, int) override {}
516 void generate_SetUnwindHandler(int) override {}
517 void generate_Shl(int) override {}
518 void generate_ShlConst(int) override {}
519 void generate_Shr(int) override {}
520 void generate_ShrConst(int) override {}
521 void generate_StoreElement(int, int) override {}
522 void generate_StoreLocal(int) override {}
523 void generate_StoreNameSloppy(int) override {}
524 void generate_StoreNameStrict(int) override {}
525 void generate_StoreProperty(int, int) override {}
526 void generate_StoreReg(int) override {}
527 void generate_StoreScopedLocal(int, int) override {}
528 void generate_StoreSuperProperty(int) override {}
529 void generate_Sub(int) override {}
530 void generate_TailCall(int, int, int, int) override {}
531 void generate_ThrowException() override {}
533 void generate_ToObject() override {}
534 void generate_TypeofName(int) override {}
535 void generate_TypeofValue() override {}
536 void generate_UCompl() override {}
537 void generate_UMinus() override {}
538 void generate_UNot() override {}
539 void generate_UPlus() override {}
540 void generate_UShr(int) override {}
541 void generate_UShrConst(int) override {}
542 void generate_UnwindDispatch() override {}
543 void generate_UnwindToLabel(int, int) override {}
544 void generate_Yield() override {}
545 void generate_YieldStar() override {}
546};
547
549
550#endif // QQMLJSCOMPILEPASS_P_H
\inmodule QtCore
Definition qbytearray.h:57
iterator begin()
Definition qflatmap_p.h:769
iterator end()
Definition qflatmap_p.h:773
bool contains(const Key &key) const
Definition qflatmap_p.h:625
iterator find(const Key &key)
Definition qflatmap_p.h:816
const_iterator constEnd() const
Definition qflatmap_p.h:776
size_type size() const noexcept
Definition qflatmap_p.h:577
qsizetype size() const noexcept
Definition qlist.h:397
void generate_YieldStar() override
void generate_CallValue(int, int, int) override
void generate_LoadRuntimeString(int) override
void generate_GetOptionalLookup(int, int) override
void generate_LoadImport(int) override
void generate_LoadName(int) override
void generate_Yield() override
void generate_DeleteName(int) override
void generate_DeleteProperty(int, int) override
void generate_CreateUnmappedArgumentsObject() override
const QV4::Compiler::JSUnitGenerator * m_jsUnitGenerator
void generate_CmpEqNull() override
bool isArgument(int registerIndex) const
void generate_BitAndConst(int) override
void generate_CmpEq(int) override
void generate_UnwindToLabel(int, int) override
static bool instructionManipulatesContext(QV4::Moth::Instr::Type type)
void generate_MoveRegExp(int, int) override
void generate_PopScriptContext() override
QQmlJS::SourceLocation sourceLocation(int instructionOffset) const
QFlatMap< int, InstructionAnnotation > InstructionAnnotations
void generate_UCompl() override
void generate_LoadFalse() override
void generate_CallGlobalLookup(int, int, int) override
void generate_UShrConst(int) override
void generate_CmpStrictNotEqual(int) override
void generate_CallPossiblyDirectEval(int, int) override
void generate_CmpLt(int) override
void generate_LoadQmlContextPropertyLookup(int) override
const Function * m_function
void generate_CloneBlockContext() override
void generate_UNot() override
void generate_Shl(int) override
void generate_LoadZero() override
void generate_Increment() override
void generate_CheckException() override
const QQmlJSTypeResolver * m_typeResolver
QQmlJS::DiagnosticMessage * m_error
void generate_SetUnwindHandler(int) override
void generate_InitializeBlockDeadTemporalZone(int, int) override
void generate_CreateClass(int, int, int) override
void generate_LoadClosure(int) override
void generate_TypeofValue() override
void generate_ConstructWithSpread(int, int, int) override
void generate_JumpTrue(int) override
void generate_StoreProperty(int, int) override
void generate_JumpFalse(int) override
void setError(const QString &message)
void generate_IteratorNext(int, int) override
void generate_UnwindDispatch() override
void generate_As(int) override
InstructionAnnotations m_annotations
void generate_SetLookup(int, int) override
void generate_LoadTrue() override
void generate_ShlConst(int) override
void generate_CallWithSpread(int, int, int, int) override
void generate_LoadProperty(int) override
void generate_BitXor(int) override
void generate_StoreReg(int) override
void generate_LoadUndefined() override
State initialState(const Function *function)
void generate_Sub(int) override
void generate_LoadScopedLocal(int, int) override
void generate_StoreNameStrict(int) override
void generate_CreateCallContext() override
void generate_CmpGe(int) override
void generate_LoadConst(int) override
void generate_ToObject() override
void generate_SetException() override
void generate_CmpLe(int) override
void generate_Resume(int) override
void generate_StoreNameSloppy(int) override
void generate_Construct(int, int, int) override
void generate_Jump(int) override
void generate_CreateRestParameter(int) override
void generate_LoadReg(int) override
void generate_LoadGlobalLookup(int) override
void generate_StoreElement(int, int) override
void generate_Add(int) override
void generate_UMinus() override
void generate_IteratorClose() override
void generate_CallName(int, int, int) override
void generate_Decrement() override
void generate_PushScriptContext(int) override
void generate_GetException() override
void generate_PushBlockContext(int) override
void generate_LoadInt(int) override
void generate_LoadElement(int) override
void generate_CallQmlContextPropertyLookup(int, int, int) override
void generate_Shr(int) override
void generate_PushWithContext() override
void generate_TypeofName(int) override
void generate_CallWithReceiver(int, int, int, int) override
void generate_BitXorConst(int) override
State nextStateFromAnnotations(const State &oldState, const InstructionAnnotations &annotations)
void generate_LoadLocal(int) override
void generate_CmpNeInt(int) override
QQmlJS::SourceLocation currentSourceLocation() const
void generate_MoveReg(int, int) override
void generate_Debug() override
void generate_StoreLocal(int) override
void generate_CmpNe(int) override
void generate_GetIterator(int) override
void generate_CmpGt(int) override
void generate_UPlus() override
void generate_CmpNeNull() override
void generate_DestructureRestElement() override
void generate_GetTemplateObject(int) override
void generate_CallProperty(int, int, int, int) override
void generate_StoreSuperProperty(int) override
void generate_BitOrConst(int) override
void generate_Exp(int) override
void generate_UShr(int) override
void generate_ShrConst(int) override
void generate_StoreScopedLocal(int, int) override
void generate_GetLookup(int) override
void generate_IteratorNextForYieldStar(int, int, int) override
void generate_DefineArray(int, int) override
void generate_LoadSuperProperty(int) override
void generate_JumpNotUndefined(int) override
void generate_CmpStrictEqual(int) override
void generate_CreateMappedArgumentsObject() override
void generate_BitOr(int) override
void generate_Ret() override
void generate_PushCatchContext(int, int) override
void generate_MoveConst(int, int) override
void generate_ThrowException() override
void generate_TailCall(int, int, int, int) override
void generate_DeadTemporalZoneCheck(int) override
void generate_ThrowOnNullOrUndefined() override
void generate_JumpNoException(int) override
void generate_PopContext() override
void generate_LoadNull() override
void generate_BitAnd(int) override
void generate_ConvertThisToObject() override
void generate_Mod(int) override
void generate_CmpIn(int) override
void generate_CmpInstanceOf(int) override
void setError(const QString &message, int instructionOffset)
void generate_CmpEqInt(int) override
void generate_Mul(int) override
void generate_DefineObjectLiteral(int, int, int) override
QQmlJSRegisterContent argumentType(int registerIndex) const
void generate_CallPropertyLookup(int, int, int, int) override
void generate_DeclareVar(int, int) override
void generate_Div(int) override
void generate_LoadOptionalProperty(int, int) override
QQmlJSCompilePass(const QV4::Compiler::JSUnitGenerator *jsUnitGenerator, const QQmlJSTypeResolver *typeResolver, QQmlJSLogger *logger, BasicBlocks basicBlocks={}, InstructionAnnotations annotations={})
void generate_LoadSuperConstructor() override
iterator begin()
Definition qset.h:136
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QSet< QString >::iterator it
else opt state
[0]
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
Combined button and popup list for selecting options.
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint GLuint end
GLenum type
GLenum target
GLuint GLsizei const GLchar * message
GLenum GLuint GLintptr offset
GLsizei GLsizei GLchar * source
GLuint entry
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
unsigned int uint
Definition qtypes.h:34
QGraphicsItem * item
QList< QQmlJSScope::ConstPtr > readTypes
QList< QQmlJSRegisterContent > argumentTypes
QQmlJSScope::ConstPtr qmlScope
const SourceLocationTable * sourceLocations
QQmlJSRegisterContent returnType
QList< QQmlJSRegisterContent > registerTypes
const QQmlJSRegisterContent & accumulatorIn() const
The accumulatorIn is the input register of the current instruction.
void addReadAccumulator(const QQmlJSRegisterContent &reg)
VirtualRegisters takeReadRegisters() const
bool canMoveReadRegister(int registerIndex) const
void markSideEffects(bool hasSideEffects)
bool isRegisterAffectedBySideEffects(int registerIndex) const
void setReadRegisters(VirtualRegisters readReagisters)
bool readsRegister(int registerIndex) const
QQmlJSRegisterContent readRegister(int registerIndex) const
const QQmlJSRegisterContent & changedRegister() const
void applySideEffects(bool hasSideEffects)
void setIsRename(bool isRename)
void setRegister(int registerIndex, QQmlJSRegisterContent content)
void addReadRegister(int registerIndex, const QQmlJSRegisterContent &reg)
void setHasSideEffects(bool hasSideEffects)
QQmlJSRegisterContent readAccumulator() const
The readAccumulator is the register content expected by the current instruction.
const QQmlJSRegisterContent & accumulatorOut() const
The accumulatorOut is the output register of the current instruction.
friend bool operator==(const VirtualRegister &a, const VirtualRegister &b)
Definition moc.h:23