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
qv4instr_moth.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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
6#include <private/qv4compileddata_p.h>
7#include <private/qv4calldata_p.h>
8
9#include <QtCore/qdebug.h>
10
11using namespace QV4;
12using namespace QV4::Moth;
13
15{
16#define MOTH_RETURN_INSTR_SIZE(I) case Instr::Type::I: case Instr::Type::I##_Wide: return InstrMeta<int(Instr::Type::I)>::Size;
17 switch (type) {
18 FOR_EACH_MOTH_INSTR_ALL(MOTH_RETURN_INSTR_SIZE)
19 }
20#undef MOTH_RETURN_INSTR_SIZE
21 Q_UNREACHABLE();
22}
23
25 QByteArray number = QByteArray::number(n);
26 return number.prepend(8 - number.size(), ' ');
27}
28
29static QByteArray alignedLineNumber(int line) {
30 if (line > 0)
31 return alignedNumber(static_cast<int>(line));
32 return QByteArray(" ");
33}
34
35static QByteArray rawBytes(const char *data, int n)
36{
37 QByteArray ba;
38 while (n) {
39 uint num = *reinterpret_cast<const uchar *>(data);
40 if (num < 16)
41 ba += '0';
42 ba += QByteArray::number(num, 16) + " ";
43 ++data;
44 --n;
45 }
46 while (ba.size() < 25)
47 ba += ' ';
48 return ba;
49}
50
51#define ABSOLUTE_OFFSET()
52 (code + beginOffset - start + offset)
53
54#define MOTH_BEGIN_INSTR(instr)
55 {
56 INSTR_##instr(MOTH_DECODE_WITH_BASE)
57 if (static_cast<int>(Instr::Type::instr) >= 0x100)
58 --base_ptr;
59 s << alignedLineNumber(line) << alignedNumber(beginOffset + codeOffset).constData() << ": "
60 << rawBytes(base_ptr, int(code - base_ptr)) << #instr << " ";
61
62#define MOTH_END_INSTR(instr)
63 s << "\n";
64 continue;
65 }
66
67QT_BEGIN_NAMESPACE
68namespace QV4 {
69namespace Moth {
70
71const int InstrInfo::argumentCount[] = {
72 FOR_EACH_MOTH_INSTR_ALL(MOTH_COLLECT_NARGS)
73};
74
75QString dumpRegister(int reg, int nFormals)
76{
77 Q_STATIC_ASSERT(offsetof(CallData, function) == 0);
78 Q_STATIC_ASSERT(offsetof(CallData, context) == sizeof(StaticValue));
79 Q_STATIC_ASSERT(offsetof(CallData, accumulator) == 2*sizeof(StaticValue));
80 Q_STATIC_ASSERT(offsetof(CallData, thisObject) == 3*sizeof(StaticValue));
81 if (reg == CallData::Function)
82 return QStringLiteral("(function)");
83 else if (reg == CallData::Context)
84 return QStringLiteral("(context)");
85 else if (reg == CallData::Accumulator)
86 return QStringLiteral("(accumulator)");
87 else if (reg == CallData::NewTarget)
88 return QStringLiteral("(new.target)");
89 else if (reg == CallData::This)
90 return QStringLiteral("(this)");
91 else if (reg == CallData::Argc)
92 return QStringLiteral("(argc)");
93 reg -= CallData::HeaderSize();
94 if (reg < nFormals)
95 return QStringLiteral("a%1").arg(reg);
96 reg -= nFormals;
97 return QStringLiteral("r%1").arg(reg);
98
99}
100
101QString dumpArguments(int argc, int argv, int nFormals)
102{
103 if (!argc)
104 return QStringLiteral("()");
105 return QStringLiteral("(") + dumpRegister(argv, nFormals) + QStringLiteral(", ") + QString::number(argc) + QStringLiteral(")");
106}
107
109 const char *code, int len, int nLocals, int nFormals, int /*startLine*/,
110 const QList<CompiledData::CodeOffsetToLineAndStatement> &lineAndStatementNumberMapping)
111{
112 return dumpBytecode(code, len, nLocals, nFormals, 0, len - 1, lineAndStatementNumberMapping);
113}
114
115QT_WARNING_PUSH
116QT_WARNING_DISABLE_LARGE_STACK_FRAME // unclear how this can be shrunk...
118 const char *code, int len, int nLocals, int nFormals, int beginOffset, int endOffset,
120{
122
124
126 return entry.codeOffset < offset;
127 };
128
130 QTextStream s{ &output };
131
132 int lastLine = -1;
133 code += beginOffset;
134 const char *start = code;
135 const char *end = code + (endOffset - beginOffset) + 1;
136 while (code < end) {
137 const auto codeToLine = std::lower_bound(
140 static_cast<uint>(code - start + beginOffset) + 1, findLine) - 1;
141 int line = int(codeToLine->line);
142 if (line != lastLine)
143 lastLine = line;
144 else
145 line = -1;
146
147 int codeOffset = int(code - start);
148
150
153 MOTH_END_INSTR(LoadReg)
154
157 MOTH_END_INSTR(StoreReg)
158
161 MOTH_END_INSTR(MoveReg)
162
164 s << "i" << index;
165 MOTH_END_INSTR(LoadImport)
166
168 s << "C" << index;
169 MOTH_END_INSTR(LoadConst)
170
172 MOTH_END_INSTR(LoadNull)
173
175 MOTH_END_INSTR(LoadZero)
176
178 MOTH_END_INSTR(LoadTrue)
179
181 MOTH_END_INSTR(LoadFalse)
182
184 MOTH_END_INSTR(LoadUndefined)
185
187 s << value;
188 MOTH_END_INSTR(LoadInt)
189
191 s << "C" << constIndex << ", " << dumpRegister(destTemp, nFormals);
192 MOTH_END_INSTR(MoveConst)
193
195 if (index < nLocals)
196 s << "l" << index;
197 else
198 s << "a" << (index - nLocals);
199 MOTH_END_INSTR(LoadLocal)
200
202 if (index < nLocals)
203 s << "l" << index;
204 else
205 s << "a" << (index - nLocals);
206 MOTH_END_INSTR(StoreLocal)
207
209 if (index < nLocals)
210 s << "l" << index << "@" << scope;
211 else
212 s << "a" << (index - nLocals) << "@" << scope;
213 MOTH_END_INSTR(LoadScopedLocal)
214
216 if (index < nLocals)
217 s << ", " << "l" << index << "@" << scope;
218 else
219 s << ", " << "a" << (index - nLocals) << "@" << scope;
220 MOTH_END_INSTR(StoreScopedLocal)
221
223 s << stringId;
224 MOTH_END_INSTR(LoadRuntimeString)
225
227 s << regExpId << ", " << dumpRegister(destReg, nFormals);
228 MOTH_END_INSTR(MoveRegExp)
229
231 s << value;
232 MOTH_END_INSTR(LoadClosure)
233
235 s << name;
236 MOTH_END_INSTR(LoadName)
237
239 s << index;
240 MOTH_END_INSTR(LoadGlobalLookup)
241
243 s << index;
244 MOTH_END_INSTR(LoadQmlContextPropertyLookup)
245
247 s << name;
248 MOTH_END_INSTR(StoreNameSloppy)
249
251 s << name;
252 MOTH_END_INSTR(StoreNameStrict)
253
255 s << dumpRegister(base, nFormals) << "[acc]";
256 MOTH_END_INSTR(LoadElement)
257
259 s << dumpRegister(base, nFormals) << "[" << dumpRegister(index, nFormals) << "]";
260 MOTH_END_INSTR(StoreElement)
261
263 s << "acc[" << name << "]";
264 MOTH_END_INSTR(LoadProperty)
265
267 s << "acc[" << name << "], jump(" << ABSOLUTE_OFFSET() << ")";
268 MOTH_END_INSTR(LoadOptionalProperty)
269
271 s << "acc(" << index << ")";
272 MOTH_END_INSTR(GetLookup)
273
275 s << "acc(" << index << "), jump(" << ABSOLUTE_OFFSET() << ")";
276 MOTH_END_INSTR(GetOptionalLookup)
277
279 s << dumpRegister(base, nFormals) << "[" << name<< "]";
280 MOTH_END_INSTR(StoreProperty)
281
283 s << dumpRegister(base, nFormals) << "(" << index << ")";
284 MOTH_END_INSTR(SetLookup)
285
288 MOTH_END_INSTR(LoadSuperProperty)
289
292 MOTH_END_INSTR(StoreSuperProperty)
293
295 MOTH_END_INSTR(Yield)
296
298 MOTH_END_INSTR(YieldStar)
299
301 s << ABSOLUTE_OFFSET();
302 MOTH_END_INSTR(Resume)
303
306 MOTH_END_INSTR(CallValue)
307
311 MOTH_END_INSTR(CallWithReceiver)
312
315 ;
316 MOTH_END_INSTR(CallProperty)
317
319 s << dumpRegister(base, nFormals) << "." << lookupIndex
321 MOTH_END_INSTR(CallPropertyLookup)
322
325 MOTH_END_INSTR(CallName)
326
329 MOTH_END_INSTR(CallPossiblyDirectEval)
330
333 MOTH_END_INSTR(CallGlobalLookup)
334
337 MOTH_END_INSTR(CallQmlContextPropertyLookup)
338
342 MOTH_END_INSTR(CallWithSpread)
343
346 MOTH_END_INSTR(Construct)
347
350 MOTH_END_INSTR(ConstructWithSpread)
351
353 if (offset)
354 s << ABSOLUTE_OFFSET();
355 else
356 s << "<null>";
357 MOTH_END_INSTR(SetUnwindHandler)
358
360 MOTH_END_INSTR(UnwindDispatch)
361
363 s << "(" << level << ") " << ABSOLUTE_OFFSET();
364 MOTH_END_INSTR(UnwindToLabel)
365
367 s << name;
368 MOTH_END_INSTR(DeadTemporalZoneCheck)
369
371 MOTH_END_INSTR(ThrowException)
372
374 MOTH_END_INSTR(HasException)
375
377 MOTH_END_INSTR(SetExceptionFlag)
378
380 MOTH_END_INSTR(CreateCallContext)
381
383 s << index << ", " << name;
384 MOTH_END_INSTR(PushCatchContext)
385
387 MOTH_END_INSTR(PushWithContext)
388
390 s << index;
391 MOTH_END_INSTR(PushBlockContext)
392
394 MOTH_END_INSTR(CloneBlockContext)
395
397 s << index;
398 MOTH_END_INSTR(PushScriptContext)
399
401 MOTH_END_INSTR(PopScriptContext)
402
404 MOTH_END_INSTR(PopContext)
405
407 s << iterator;
408 MOTH_END_INSTR(GetIterator)
409
411 s << dumpRegister(value, nFormals) << ", " << ABSOLUTE_OFFSET();
412 MOTH_END_INSTR(IteratorNext)
413
416 << ABSOLUTE_OFFSET();
417 MOTH_END_INSTR(IteratorNextForYieldStar)
418
420 MOTH_END_INSTR(IteratorClose)
421
423 MOTH_END_INSTR(DestructureRestElement)
424
426 s << dumpRegister(base, nFormals) << "[" << dumpRegister(index, nFormals) << "]";
427 MOTH_END_INSTR(DeleteProperty)
428
430 s << name;
431 MOTH_END_INSTR(DeleteName)
432
434 s << name;
435 MOTH_END_INSTR(TypeofName)
436
438 MOTH_END_INSTR(TypeofValue)
439
441 s << isDeletable << ", " << varName;
442 MOTH_END_INSTR(DeclareVar)
443
445 s << dumpRegister(args, nFormals) << ", " << argc;
446 MOTH_END_INSTR(DefineArray)
447
450 << ", " << argc
451 << ", " << dumpRegister(args, nFormals);
452 MOTH_END_INSTR(DefineObjectLiteral)
453
455 s << classIndex
456 << ", " << dumpRegister(heritage, nFormals)
458 MOTH_END_INSTR(CreateClass)
459
461 MOTH_END_INSTR(CreateMappedArgumentsObject)
462
464 MOTH_END_INSTR(CreateUnmappedArgumentsObject)
465
467 s << argIndex;
468 MOTH_END_INSTR(CreateRestParameter)
469
471 MOTH_END_INSTR(ConvertThisToObject)
472
474 MOTH_END_INSTR(LoadSuperConstructor)
475
477 MOTH_END_INSTR(ToObject)
478
480 s << ABSOLUTE_OFFSET();
481 MOTH_END_INSTR(Jump)
482
484 s << ABSOLUTE_OFFSET();
485 MOTH_END_INSTR(JumpTrue)
486
488 s << ABSOLUTE_OFFSET();
489 MOTH_END_INSTR(JumpFalse)
490
492 s << ABSOLUTE_OFFSET();
493 MOTH_END_INSTR(JumpNotUndefined)
494
496 s << ABSOLUTE_OFFSET();
497 MOTH_END_INSTR(JumpNoException)
498
500 MOTH_END_INSTR(CheckException)
501
503 MOTH_END_INSTR(CmpEqNull)
504
506 MOTH_END_INSTR(CmpNeNull)
507
509 s << lhs;
510 MOTH_END_INSTR(CmpEq)
511
513 s << lhs;
514 MOTH_END_INSTR(CmpNeInt)
515
518 MOTH_END_INSTR(CmpEq)
519
522 MOTH_END_INSTR(CmpNe)
523
526 MOTH_END_INSTR(CmpGt)
527
530 MOTH_END_INSTR(CmpGe)
531
534 MOTH_END_INSTR(CmpLt)
535
538 MOTH_END_INSTR(CmpLe)
539
542 MOTH_END_INSTR(CmpStrictEqual)
543
546 MOTH_END_INSTR(CmpStrictNotEqual)
547
549 MOTH_END_INSTR(UNot)
550
552 MOTH_END_INSTR(UPlus)
553
555 MOTH_END_INSTR(UMinus)
556
558 MOTH_END_INSTR(UCompl)
559
561 MOTH_END_INSTR(Increment)
562
564 MOTH_END_INSTR(Decrement)
565
567 s << dumpRegister(lhs, nFormals) << ", acc";
568 MOTH_END_INSTR(Add)
569
571 s << dumpRegister(lhs, nFormals) << ", acc";
572 MOTH_END_INSTR(BitAnd)
573
575 s << dumpRegister(lhs, nFormals) << ", acc";
576 MOTH_END_INSTR(BitOr)
577
579 s << dumpRegister(lhs, nFormals) << ", acc";
580 MOTH_END_INSTR(BitXor)
581
583 s << dumpRegister(lhs, nFormals) << ", acc";
584 MOTH_END_INSTR(UShr)
585
587 s << dumpRegister(lhs, nFormals) << ", acc";
588 MOTH_END_INSTR(Shr)
589
591 s << dumpRegister(lhs, nFormals) << ", acc";
592 MOTH_END_INSTR(Shl)
593
595 s << "acc, " << rhs;
596 MOTH_END_INSTR(BitAndConst)
597
599 s << "acc, " << rhs;
600 MOTH_END_INSTR(BitOr)
601
603 s << "acc, " << rhs;
604 MOTH_END_INSTR(BitXor)
605
607 s << "acc, " << rhs;
608 MOTH_END_INSTR(UShrConst)
609
611 s << "acc, " << rhs;
612 MOTH_END_INSTR(ShrConst)
613
615 s << "acc, " << rhs;
616 MOTH_END_INSTR(ShlConst)
617
619 s << dumpRegister(lhs, nFormals) << ", acc";
620 MOTH_END_INSTR(Exp)
621
623 s << dumpRegister(lhs, nFormals) << ", acc";
624 MOTH_END_INSTR(Mul)
625
627 s << dumpRegister(lhs, nFormals) << ", acc";
628 MOTH_END_INSTR(Div)
629
631 s << dumpRegister(lhs, nFormals) << ", acc";
632 MOTH_END_INSTR(Mod)
633
635 s << dumpRegister(lhs, nFormals) << ", acc";
636 MOTH_END_INSTR(Sub)
637
639 s << dumpRegister(lhs, nFormals) << ", acc";
640 MOTH_END_INSTR(Sub)
641
643 s << dumpRegister(lhs, nFormals) << ", acc";
644 MOTH_END_INSTR(CmpIn)
645
647 s << dumpRegister(lhs, nFormals) << ", acc";
648 MOTH_END_INSTR(CmpInstanceOf)
649
651 MOTH_END_INSTR(Ret)
652
654 MOTH_END_INSTR(Debug)
655
657 s << dumpRegister(firstReg, nFormals) << ", " << count;
658 MOTH_END_INSTR(InitializeBlockDeadTemporalZone)
659
661 MOTH_END_INSTR(ThrowOnNullOrUndefined)
662
664 s << index;
665 MOTH_END_INSTR(GetTemplateObject)
666
669 MOTH_END_INSTR(TailCall)
670 }
671 return output;
672}
673QT_WARNING_POP // DISABLE_LARGE_STACK_FRAME
674
675}
676}
677QT_END_NAMESPACE
QString dumpBytecode(const char *code, int len, int nLocals, int nFormals, int, const QList< CompiledData::CodeOffsetToLineAndStatement > &lineAndStatementNumberMapping)
QString dumpRegister(int reg, int nFormals)
QString dumpArguments(int argc, int argv, int nFormals)
Definition qjsvalue.h:24
#define ABSOLUTE_OFFSET()
static QByteArray rawBytes(const char *data, int n)
static QByteArray alignedLineNumber(int line)
#define MOTH_BEGIN_INSTR(instr)
#define MOTH_END_INSTR(instr)
static QByteArray alignedNumber(int n)
#define FOR_EACH_MOTH_INSTR_ALL(F)
#define MOTH_JUMP_TABLE
#define MOTH_DISPATCH()
static const int argumentCount[]
static int size(Instr::Type type)