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_p.h
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
5#ifndef QV4INSTR_MOTH_P_H
6#define QV4INSTR_MOTH_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/qv4staticvalue_p.h>
20#include <private/qv4compileddata_p.h> // for CompiledData::CodeOffsetToLine used by the dumper
21#include <qendian.h>
22
24
25#define INSTRUCTION(op, name, nargs, ...)
26 op##_INSTRUCTION(name, nargs, __VA_ARGS__)
27
28/* for all jump instructions, the offset has to come last, to simplify the job of the bytecode generator */
29#define INSTR_Nop(op) INSTRUCTION(op, Nop, 0)
30#define INSTR_Ret(op) INSTRUCTION(op, Ret, 0)
31#define INSTR_Debug(op) INSTRUCTION(op, Debug, 0)
32#define INSTR_LoadConst(op) INSTRUCTION(op, LoadConst, 1, index)
33#define INSTR_LoadZero(op) INSTRUCTION(op, LoadZero, 0)
34#define INSTR_LoadTrue(op) INSTRUCTION(op, LoadTrue, 0)
35#define INSTR_LoadFalse(op) INSTRUCTION(op, LoadFalse, 0)
36#define INSTR_LoadNull(op) INSTRUCTION(op, LoadNull, 0)
37#define INSTR_LoadUndefined(op) INSTRUCTION(op, LoadUndefined, 0)
38#define INSTR_LoadInt(op) INSTRUCTION(op, LoadInt, 1, value)
39#define INSTR_MoveConst(op) INSTRUCTION(op, MoveConst, 2, constIndex, destTemp)
40#define INSTR_LoadReg(op) INSTRUCTION(op, LoadReg, 1, reg)
41#define INSTR_StoreReg(op) INSTRUCTION(op, StoreReg, 1, reg)
42#define INSTR_MoveReg(op) INSTRUCTION(op, MoveReg, 2, srcReg, destReg)
43#define INSTR_LoadImport(op) INSTRUCTION(op, LoadImport, 1, index)
44#define INSTR_LoadLocal(op) INSTRUCTION(op, LoadLocal, 1, index)
45#define INSTR_StoreLocal(op) INSTRUCTION(op, StoreLocal, 1, index)
46#define INSTR_LoadScopedLocal(op) INSTRUCTION(op, LoadScopedLocal, 2, scope, index)
47#define INSTR_StoreScopedLocal(op) INSTRUCTION(op, StoreScopedLocal, 2, scope, index)
48#define INSTR_LoadRuntimeString(op) INSTRUCTION(op, LoadRuntimeString, 1, stringId)
49#define INSTR_MoveRegExp(op) INSTRUCTION(op, MoveRegExp, 2, regExpId, destReg)
50#define INSTR_LoadClosure(op) INSTRUCTION(op, LoadClosure, 1, value)
51#define INSTR_LoadName(op) INSTRUCTION(op, LoadName, 1, name)
52#define INSTR_LoadGlobalLookup(op) INSTRUCTION(op, LoadGlobalLookup, 1, index)
53#define INSTR_LoadQmlContextPropertyLookup(op) INSTRUCTION(op, LoadQmlContextPropertyLookup, 1, index)
54#define INSTR_StoreNameSloppy(op) INSTRUCTION(op, StoreNameSloppy, 1, name)
55#define INSTR_StoreNameStrict(op) INSTRUCTION(op, StoreNameStrict, 1, name)
56#define INSTR_LoadProperty(op) INSTRUCTION(op, LoadProperty, 1, name)
57#define INSTR_LoadOptionalProperty(op) INSTRUCTION(op, LoadOptionalProperty, 2, name, offset)
58#define INSTR_GetLookup(op) INSTRUCTION(op, GetLookup, 1, index)
59#define INSTR_GetOptionalLookup(op) INSTRUCTION(op, GetOptionalLookup, 2, index, offset)
60#define INSTR_Yield(op) INSTRUCTION(op, Yield, 0)
61#define INSTR_YieldStar(op) INSTRUCTION(op, YieldStar, 0)
62#define INSTR_Resume(op) INSTRUCTION(op, Resume, 1, offset)
63#define INSTR_IteratorNextForYieldStar(op) INSTRUCTION(op, IteratorNextForYieldStar, 3, iterator, object, offset)
64#define INSTR_StoreProperty(op) INSTRUCTION(op, StoreProperty, 2, name, base)
65#define INSTR_SetLookup(op) INSTRUCTION(op, SetLookup, 2, index, base)
66#define INSTR_LoadSuperProperty(op) INSTRUCTION(op, LoadSuperProperty, 1, property)
67#define INSTR_StoreSuperProperty(op) INSTRUCTION(op, StoreSuperProperty, 1, property)
68#define INSTR_LoadElement(op) INSTRUCTION(op, LoadElement, 1, base)
69#define INSTR_StoreElement(op) INSTRUCTION(op, StoreElement, 2, base, index)
70#define INSTR_CallValue(op) INSTRUCTION(op, CallValue, 3, name, argc, argv)
71#define INSTR_CallWithReceiver(op) INSTRUCTION(op, CallWithReceiver, 4, name, thisObject, argc, argv)
72#define INSTR_CallProperty(op) INSTRUCTION(op, CallProperty, 4, name, base, argc, argv)
73#define INSTR_CallPropertyLookup(op) INSTRUCTION(op, CallPropertyLookup, 4, lookupIndex, base, argc, argv)
74#define INSTR_CallName(op) INSTRUCTION(op, CallName, 3, name, argc, argv)
75#define INSTR_CallPossiblyDirectEval(op) INSTRUCTION(op, CallPossiblyDirectEval, 2, argc, argv)
76#define INSTR_CallGlobalLookup(op) INSTRUCTION(op, CallGlobalLookup, 3, index, argc, argv)
77#define INSTR_CallQmlContextPropertyLookup(op) INSTRUCTION(op, CallQmlContextPropertyLookup, 3, index, argc, argv)
78#define INSTR_CallWithSpread(op) INSTRUCTION(op, CallWithSpread, 4, func, thisObject, argc, argv)
79#define INSTR_Construct(op) INSTRUCTION(op, Construct, 3, func, argc, argv)
80#define INSTR_ConstructWithSpread(op) INSTRUCTION(op, ConstructWithSpread, 3, func, argc, argv)
81#define INSTR_SetUnwindHandler(op) INSTRUCTION(op, SetUnwindHandler, 1, offset)
82#define INSTR_UnwindDispatch(op) INSTRUCTION(op, UnwindDispatch, 0)
83#define INSTR_UnwindToLabel(op) INSTRUCTION(op, UnwindToLabel, 2, level, offset)
84#define INSTR_DeadTemporalZoneCheck(op) INSTRUCTION(op, DeadTemporalZoneCheck, 1, name)
85#define INSTR_ThrowException(op) INSTRUCTION(op, ThrowException, 0)
86#define INSTR_GetException(op) INSTRUCTION(op, GetException, 0)
87#define INSTR_SetException(op) INSTRUCTION(op, SetException, 0)
88#define INSTR_CreateCallContext(op) INSTRUCTION(op, CreateCallContext, 0)
89#define INSTR_PushCatchContext(op) INSTRUCTION(op, PushCatchContext, 2, index, name)
90#define INSTR_PushWithContext(op) INSTRUCTION(op, PushWithContext, 0)
91#define INSTR_PushBlockContext(op) INSTRUCTION(op, PushBlockContext, 1, index)
92#define INSTR_CloneBlockContext(op) INSTRUCTION(op, CloneBlockContext, 0)
93#define INSTR_PushScriptContext(op) INSTRUCTION(op, PushScriptContext, 1, index)
94#define INSTR_PopScriptContext(op) INSTRUCTION(op, PopScriptContext, 0)
95#define INSTR_PopContext(op) INSTRUCTION(op, PopContext, 0)
96#define INSTR_GetIterator(op) INSTRUCTION(op, GetIterator, 1, iterator)
97#define INSTR_IteratorNext(op) INSTRUCTION(op, IteratorNext, 2, value, offset)
98#define INSTR_IteratorClose(op) INSTRUCTION(op, IteratorClose, 0)
99#define INSTR_DestructureRestElement(op) INSTRUCTION(op, DestructureRestElement, 0)
100#define INSTR_DeleteProperty(op) INSTRUCTION(op, DeleteProperty, 2, base, index)
101#define INSTR_DeleteName(op) INSTRUCTION(op, DeleteName, 1, name)
102#define INSTR_TypeofName(op) INSTRUCTION(op, TypeofName, 1, name)
103#define INSTR_TypeofValue(op) INSTRUCTION(op, TypeofValue, 0)
104#define INSTR_DeclareVar(op) INSTRUCTION(op, DeclareVar, 2, varName, isDeletable)
105#define INSTR_DefineArray(op) INSTRUCTION(op, DefineArray, 2, argc, args)
106#define INSTR_DefineObjectLiteral(op) INSTRUCTION(op, DefineObjectLiteral, 3, internalClassId, argc, args)
107#define INSTR_CreateClass(op) INSTRUCTION(op, CreateClass, 3, classIndex, heritage, computedNames)
108#define INSTR_CreateMappedArgumentsObject(op) INSTRUCTION(op, CreateMappedArgumentsObject, 0)
109#define INSTR_CreateUnmappedArgumentsObject(op) INSTRUCTION(op, CreateUnmappedArgumentsObject, 0)
110#define INSTR_CreateRestParameter(op) INSTRUCTION(op, CreateRestParameter, 1, argIndex)
111#define INSTR_ConvertThisToObject(op) INSTRUCTION(op, ConvertThisToObject, 0)
112#define INSTR_LoadSuperConstructor(op) INSTRUCTION(op, LoadSuperConstructor, 0)
113#define INSTR_ToObject(op) INSTRUCTION(op, ToObject, 0)
114#define INSTR_Jump(op) INSTRUCTION(op, Jump, 1, offset)
115#define INSTR_JumpTrue(op) INSTRUCTION(op, JumpTrue, 1, offset)
116#define INSTR_JumpFalse(op) INSTRUCTION(op, JumpFalse, 1, offset)
117#define INSTR_JumpNotUndefined(op) INSTRUCTION(op, JumpNotUndefined, 1, offset)
118#define INSTR_JumpNoException(op) INSTRUCTION(op, JumpNoException, 1, offset)
119#define INSTR_CheckException(op) INSTRUCTION(op, CheckException, 0)
120#define INSTR_CmpEqNull(op) INSTRUCTION(op, CmpEqNull, 0)
121#define INSTR_CmpNeNull(op) INSTRUCTION(op, CmpNeNull, 0)
122#define INSTR_CmpEqInt(op) INSTRUCTION(op, CmpEqInt, 1, lhs)
123#define INSTR_CmpNeInt(op) INSTRUCTION(op, CmpNeInt, 1, lhs)
124#define INSTR_CmpEq(op) INSTRUCTION(op, CmpEq, 1, lhs)
125#define INSTR_CmpNe(op) INSTRUCTION(op, CmpNe, 1, lhs)
126#define INSTR_CmpGt(op) INSTRUCTION(op, CmpGt, 1, lhs)
127#define INSTR_CmpGe(op) INSTRUCTION(op, CmpGe, 1, lhs)
128#define INSTR_CmpLt(op) INSTRUCTION(op, CmpLt, 1, lhs)
129#define INSTR_CmpLe(op) INSTRUCTION(op, CmpLe, 1, lhs)
130#define INSTR_CmpStrictEqual(op) INSTRUCTION(op, CmpStrictEqual, 1, lhs)
131#define INSTR_CmpStrictNotEqual(op) INSTRUCTION(op, CmpStrictNotEqual, 1, lhs)
132#define INSTR_CmpIn(op) INSTRUCTION(op, CmpIn, 1, lhs)
133#define INSTR_CmpInstanceOf(op) INSTRUCTION(op, CmpInstanceOf, 1, lhs)
134#define INSTR_UNot(op) INSTRUCTION(op, UNot, 0)
135#define INSTR_UPlus(op) INSTRUCTION(op, UPlus, 0)
136#define INSTR_UMinus(op) INSTRUCTION(op, UMinus, 0)
137#define INSTR_UCompl(op) INSTRUCTION(op, UCompl, 0)
138#define INSTR_Increment(op) INSTRUCTION(op, Increment, 0)
139#define INSTR_Decrement(op) INSTRUCTION(op, Decrement, 0)
140#define INSTR_Add(op) INSTRUCTION(op, Add, 1, lhs)
141#define INSTR_BitAnd(op) INSTRUCTION(op, BitAnd, 1, lhs)
142#define INSTR_BitOr(op) INSTRUCTION(op, BitOr, 1, lhs)
143#define INSTR_BitXor(op) INSTRUCTION(op, BitXor, 1, lhs)
144#define INSTR_UShr(op) INSTRUCTION(op, UShr, 1, lhs)
145#define INSTR_Shr(op) INSTRUCTION(op, Shr, 1, lhs)
146#define INSTR_Shl(op) INSTRUCTION(op, Shl, 1, lhs)
147#define INSTR_BitAndConst(op) INSTRUCTION(op, BitAndConst, 1, rhs)
148#define INSTR_BitOrConst(op) INSTRUCTION(op, BitOrConst, 1, rhs)
149#define INSTR_BitXorConst(op) INSTRUCTION(op, BitXorConst, 1, rhs)
150#define INSTR_UShrConst(op) INSTRUCTION(op, UShrConst, 1, rhs)
151#define INSTR_ShrConst(op) INSTRUCTION(op, ShrConst, 1, rhs)
152#define INSTR_ShlConst(op) INSTRUCTION(op, ShlConst, 1, rhs)
153#define INSTR_Exp(op) INSTRUCTION(op, Exp, 1, lhs)
154#define INSTR_Mul(op) INSTRUCTION(op, Mul, 1, lhs)
155#define INSTR_Div(op) INSTRUCTION(op, Div, 1, lhs)
156#define INSTR_Mod(op) INSTRUCTION(op, Mod, 1, lhs)
157#define INSTR_Sub(op) INSTRUCTION(op, Sub, 1, lhs)
158#define INSTR_As(op) INSTRUCTION(op, As, 1, lhs)
159#define INSTR_InitializeBlockDeadTemporalZone(op) INSTRUCTION(op, InitializeBlockDeadTemporalZone, 2, firstReg, count)
160#define INSTR_ThrowOnNullOrUndefined(op) INSTRUCTION(op, ThrowOnNullOrUndefined, 0)
161#define INSTR_GetTemplateObject(op) INSTRUCTION(op, GetTemplateObject, 1, index)
162#define INSTR_TailCall(op) INSTRUCTION(op, TailCall, 4, func, thisObject, argc, argv)
163
164#define FOR_EACH_MOTH_INSTR_ALL(F)
165 F(Nop)
167
168#define FOR_EACH_MOTH_INSTR(F)
169 F(Ret)
170 F(LoadConst)
171 F(LoadZero)
172 F(LoadTrue)
173 F(LoadFalse)
174 F(LoadNull)
175 F(LoadUndefined)
176 F(LoadInt)
177 F(LoadRuntimeString)
178 F(MoveConst)
179 F(LoadReg)
180 F(StoreReg)
181 F(MoveReg)
182 F(LoadImport)
183 F(LoadLocal)
184 F(StoreLocal)
185 F(LoadScopedLocal)
186 F(StoreScopedLocal)
187 F(MoveRegExp)
188 F(LoadClosure)
189 F(LoadName)
190 F(LoadGlobalLookup)
191 F(LoadQmlContextPropertyLookup)
192 F(StoreNameSloppy)
193 F(StoreNameStrict)
194 F(LoadElement)
195 F(StoreElement)
196 F(LoadProperty)
197 F(LoadOptionalProperty)
198 F(GetLookup)
199 F(GetOptionalLookup)
200 F(StoreProperty)
201 F(SetLookup)
202 F(LoadSuperProperty)
203 F(StoreSuperProperty)
204 F(ConvertThisToObject)
205 F(ToObject)
206 F(Jump)
207 F(JumpTrue)
208 F(JumpFalse)
209 F(JumpNoException)
210 F(JumpNotUndefined)
211 F(CheckException)
212 F(CmpEqNull)
213 F(CmpNeNull)
214 F(CmpEqInt)
215 F(CmpNeInt)
216 F(CmpEq)
217 F(CmpNe)
218 F(CmpGt)
219 F(CmpGe)
220 F(CmpLt)
221 F(CmpLe)
222 F(CmpStrictEqual)
223 F(CmpStrictNotEqual)
224 F(CmpIn)
225 F(CmpInstanceOf)
226 F(UNot)
227 F(UPlus)
228 F(UMinus)
229 F(UCompl)
230 F(Increment)
231 F(Decrement)
232 F(Add)
233 F(BitAnd)
234 F(BitOr)
235 F(BitXor)
236 F(UShr)
237 F(Shr)
238 F(Shl)
239 F(BitAndConst)
240 F(BitOrConst)
241 F(BitXorConst)
242 F(UShrConst)
243 F(ShrConst)
244 F(ShlConst)
245 F(Exp)
246 F(Mul)
247 F(Div)
248 F(Mod)
249 F(Sub)
250 F(As)
251 F(CallValue)
252 F(CallWithReceiver)
253 F(CallProperty)
254 F(CallPropertyLookup)
255 F(CallName)
256 F(CallPossiblyDirectEval)
257 F(CallGlobalLookup)
258 F(CallQmlContextPropertyLookup)
259 F(CallWithSpread)
260 F(Construct)
261 F(ConstructWithSpread)
262 F(SetUnwindHandler)
263 F(UnwindDispatch)
264 F(UnwindToLabel)
265 F(DeadTemporalZoneCheck)
266 F(ThrowException)
267 F(GetException)
268 F(SetException)
269 F(CreateCallContext)
270 F(PushCatchContext)
271 F(PushWithContext)
272 F(PushBlockContext)
273 F(CloneBlockContext)
274 F(PopContext)
275 F(GetIterator)
276 F(IteratorNext)
277 F(IteratorClose)
278 F(DestructureRestElement)
279 F(DeleteProperty)
280 F(DeleteName)
281 F(TypeofName)
282 F(TypeofValue)
283 F(DeclareVar)
284 F(DefineArray)
285 F(DefineObjectLiteral)
286 F(CreateMappedArgumentsObject)
287 F(CreateUnmappedArgumentsObject)
288 F(CreateRestParameter)
289 F(Yield)
290 F(YieldStar)
291 F(Resume)
292 F(IteratorNextForYieldStar)
293 F(CreateClass)
294 F(LoadSuperConstructor)
295 F(PushScriptContext)
296 F(PopScriptContext)
297 F(InitializeBlockDeadTemporalZone)
298 F(ThrowOnNullOrUndefined)
299 F(GetTemplateObject)
300 F(TailCall)
301 F(Debug)
302
303#define MOTH_NUM_INSTRUCTIONS() (static_cast<int>(Moth::Instr::Type::Debug_Wide) + 1)
304
305#if defined(Q_CC_GNU)
306#if defined(Q_OS_WASM) && !defined(__asmjs)
307// Upstream llvm does not support computed goto for the wasm target, unlike the 'fastcomp' llvm fork
308// shipped with the emscripten SDK. Disable computed goto usage for non-fastcomp llvm on Wasm.
309#else
310# define MOTH_COMPUTED_GOTO
311#endif
312#endif
313
314#define MOTH_INSTR_ALIGN_MASK (alignof(QV4::Moth::Instr) - 1)
315
316#define MOTH_INSTR_ENUM(I) I, I##_Wide,
317#define MOTH_INSTR_SIZE(I) (sizeof(QV4::Moth::Instr::instr_##I))
318
319#define MOTH_EXPAND_FOR_MSVC(x) x
320#define MOTH_DEFINE_ARGS(nargs, ...)
321 MOTH_EXPAND_FOR_MSVC(MOTH_DEFINE_ARGS##nargs(__VA_ARGS__))
322
323#define MOTH_DEFINE_ARGS0()
324#define MOTH_DEFINE_ARGS1(arg)
325 int arg;
326#define MOTH_DEFINE_ARGS2(arg1, arg2)
327 int arg1;
328 int arg2;
329#define MOTH_DEFINE_ARGS3(arg1, arg2, arg3)
330 int arg1;
331 int arg2;
332 int arg3;
333#define MOTH_DEFINE_ARGS4(arg1, arg2, arg3, arg4)
334 int arg1;
335 int arg2;
336 int arg3;
337 int arg4;
338#define MOTH_DEFINE_ARGS5(arg1, arg2, arg3, arg4, arg5)
339 int arg1;
340 int arg2;
341 int arg3;
342 int arg4;
343 int arg5;
344
345#define MOTH_COLLECT_ENUMS(instr)
346 INSTR_##instr(MOTH_GET_ENUM)
347#define MOTH_GET_ENUM_INSTRUCTION(name, ...)
348 name,
349
350#define MOTH_EMIT_STRUCTS(instr)
351 INSTR_##instr(MOTH_EMIT_STRUCT)
352#define MOTH_EMIT_STRUCT_INSTRUCTION(name, nargs, ...)
353 struct instr_##name {
354 MOTH_DEFINE_ARGS(nargs, __VA_ARGS__)
355 };
356
357#define MOTH_EMIT_INSTR_MEMBERS(instr)
358 INSTR_##instr(MOTH_EMIT_INSTR_MEMBER)
359#define MOTH_EMIT_INSTR_MEMBER_INSTRUCTION(name, nargs, ...)
360 instr_##name name;
361
362#define MOTH_COLLECT_NARGS(instr)
363 INSTR_##instr(MOTH_COLLECT_ARG_COUNT)
364#define MOTH_COLLECT_ARG_COUNT_INSTRUCTION(name, nargs, ...)
365 nargs, nargs,
366
367#define MOTH_DECODE_ARG(arg, type, nargs, offset)
368 arg = qFromLittleEndian<type>(qFromUnaligned<type>(reinterpret_cast<const type *>(code) - nargs + offset));
369#define MOTH_ADJUST_CODE(type, nargs)
370 code += static_cast<quintptr>(nargs*sizeof(type) + 1)
371
372#define MOTH_DECODE_INSTRUCTION(name, nargs, ...)
373 MOTH_DEFINE_ARGS(nargs, __VA_ARGS__)
374 op_int_##name:
375 MOTH_ADJUST_CODE(int, nargs);
376 MOTH_DECODE_ARGS(name, int, nargs, __VA_ARGS__)
377 goto op_main_##name;
378 op_byte_##name:
379 MOTH_ADJUST_CODE(qint8, nargs);
380 MOTH_DECODE_ARGS(name, qint8, nargs, __VA_ARGS__)
381 op_main_##name:
382 ;
383
384#define MOTH_DECODE_WITH_BASE_INSTRUCTION(name, nargs, ...)
385 MOTH_DEFINE_ARGS(nargs, __VA_ARGS__)
386 const char *base_ptr;
387 op_int_##name:
388 base_ptr = code;
389 MOTH_ADJUST_CODE(int, nargs);
390 MOTH_DECODE_ARGS(name, int, nargs, __VA_ARGS__)
391 goto op_main_##name;
392 op_byte_##name:
393 base_ptr = code;
394 MOTH_ADJUST_CODE(qint8, nargs);
395 MOTH_DECODE_ARGS(name, qint8, nargs, __VA_ARGS__)
396 op_main_##name:
397 ;
398
399#define MOTH_DECODE_ARGS(name, type, nargs, ...)
400 MOTH_EXPAND_FOR_MSVC(MOTH_DECODE_ARGS##nargs(name, type, nargs, __VA_ARGS__))
401
402#define MOTH_DECODE_ARGS0(name, type, nargs, dummy)
403#define MOTH_DECODE_ARGS1(name, type, nargs, arg)
404 MOTH_DECODE_ARG(arg, type, nargs, 0);
405#define MOTH_DECODE_ARGS2(name, type, nargs, arg1, arg2)
406 MOTH_DECODE_ARGS1(name, type, nargs, arg1);
407 MOTH_DECODE_ARG(arg2, type, nargs, 1);
408#define MOTH_DECODE_ARGS3(name, type, nargs, arg1, arg2, arg3)
409 MOTH_DECODE_ARGS2(name, type, nargs, arg1, arg2);
410 MOTH_DECODE_ARG(arg3, type, nargs, 2);
411#define MOTH_DECODE_ARGS4(name, type, nargs, arg1, arg2, arg3, arg4)
412 MOTH_DECODE_ARGS3(name, type, nargs, arg1, arg2, arg3);
413 MOTH_DECODE_ARG(arg4, type, nargs, 3);
414#define MOTH_DECODE_ARGS5(name, type, nargs, arg1, arg2, arg3, arg4, arg5)
415 MOTH_DECODE_ARGS4(name, type, nargs, arg1, arg2, arg3, arg4);
416 MOTH_DECODE_ARG(arg5, type, nargs, 4);
417
418#ifdef MOTH_COMPUTED_GOTO
419/* collect jump labels */
420#define COLLECT_LABELS(instr)
421 INSTR_##instr(GET_LABEL)
422 INSTR_##instr(GET_LABEL_WIDE)
423#define GET_LABEL_INSTRUCTION(name, ...)
424 &&op_byte_##name,
425#define GET_LABEL_WIDE_INSTRUCTION(name, ...)
426 &&op_int_##name,
427
428#define MOTH_JUMP_TABLE
429 static const void *jumpTable[] = {
430 FOR_EACH_MOTH_INSTR_ALL(COLLECT_LABELS)
431 };
432
433#define MOTH_DISPATCH_SINGLE()
434 goto *jumpTable[*reinterpret_cast<const uchar *>(code)];
435
436#define MOTH_DISPATCH()
437 MOTH_DISPATCH_SINGLE()
438 op_byte_Nop:
439 ++code;
440 MOTH_DISPATCH_SINGLE()
441 op_int_Nop: /* wide prefix */
442 ++code;
443 goto *jumpTable[0x100 | *reinterpret_cast<const uchar *>(code)];
444#else
445#define MOTH_JUMP_TABLE
446
447#define MOTH_INSTR_CASE_AND_JUMP(instr)
448 INSTR_##instr(GET_CASE_AND_JUMP)
449 INSTR_##instr(GET_CASE_AND_JUMP_WIDE)
450#define GET_CASE_AND_JUMP_INSTRUCTION(name, ...)
451 case Instr::Type::name: goto op_byte_##name;
452#define GET_CASE_AND_JUMP_WIDE_INSTRUCTION(name, ...)
453 case Instr::Type::name##_Wide: goto op_int_##name;
454
455#define MOTH_DISPATCH()
456 Instr::Type type = Instr::Type(static_cast<uchar>(*code));
457 dispatch:
458 switch (type) {
459 case Instr::Type::Nop:
460 ++code;
461 type = Instr::Type(static_cast<uchar>(*code));
462 goto dispatch;
463 case Instr::Type::Nop_Wide: /* wide prefix */
464 ++code;
465 type = Instr::Type(0x100 | static_cast<uchar>(*code));
466 goto dispatch;
468 }
469#endif
470
471namespace QV4 {
472
473namespace CompiledData {
475}
476
477namespace Moth {
478
480 int index;
481
482public:
483 static StackSlot createRegister(int index) {
484 Q_ASSERT(index >= 0);
485 StackSlot t;
486 t.index = index;
487 return t;
488 }
489
490 int stackSlot() const { return index; }
491 operator int() const { return index; }
492};
493
494inline bool operator==(const StackSlot &l, const StackSlot &r) { return l.stackSlot() == r.stackSlot(); }
495inline bool operator!=(const StackSlot &l, const StackSlot &r) { return l.stackSlot() != r.stackSlot(); }
496
497// When making changes to the instructions, make sure to bump QV4_DATA_STRUCTURE_VERSION in qv4compileddata_p.h
498
499Q_QML_EXPORT
500QString dumpBytecode(
501 const char *bytecode, int len, int nLocals, int nFormals, int beginOffset, int endOffset,
505 const char *bytecode, int len, int nLocals, int nFormals, int startLine = 1,
506 const QList<CompiledData::CodeOffsetToLineAndStatement> &lineAndStatementNumberMapping =
509 const QByteArray &bytecode, int nLocals, int nFormals, int startLine = 1,
510 const QList<CompiledData::CodeOffsetToLineAndStatement> &lineAndStatementNumberMapping =
512{
513 return dumpBytecode(bytecode.constData(), bytecode.size(), nLocals, nFormals, startLine,
514 lineAndStatementNumberMapping);
515}
516
517union Instr
518{
522
523 static Type wideInstructionType(Type t) { return Type(int(t) | 1); }
524 static Type narrowInstructionType(Type t) { return Type(int(t) & ~1); }
525 static bool isWide(Type t) { return int(t) & 1; }
526 static bool isNarrow(Type t) { return !(int(t) & 1); }
527 static int encodedLength(Type t) { return int(t) >= 256 ? 2 : 1; }
528
529 /*!
530 * \internal
531 *
532 * Bytecode format:
533 *
534 * Instructions are compacted in the bytecode to save space. Every instruction gets compacted
535 * independently. There are many possible layouts coming in 4 main varieties based on two
536 * factors:
537 *
538 * If the instruction's Type <= 255, the OP code is encoded using only one byte.
539 * Otherwise, the first byte is 0x1 and the second byte is Type & 0xff.
540 *
541 * If the instruction takes arguments and they each fit in one byte, encode them this way.
542 * Otherwise, each argument is encoded using 4 bytes in little endian. In both cases, only
543 * the arguments actually needed by the instruction are encoded.
544 * Each instruction type receives two consecutive values in Instr::Type. The even variant has
545 * narrow arguments and the odd one has wide arguments and gets the suffix "_Wide".
546 *
547 * The 4 main formats with arg counts ranging from 0 to 4 (x: OP code bits, abcd: argument bits):
548 * 1. 00000001 xxxxxxx0 aaaaaaaa bbbbbbbb cccccccc dddddddd
549 * 2. 00000001 xxxxxxx1 aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa bbbbbbbb bbbbbbbb bbbbbbbb bbbbbbbb cccccccc cccccccc cccccccc cccccccc dddddddd dddddddd dddddddd dddddddd
550 * 3. xxxxxxx0 aaaaaaaa bbbbbbbb cccccccc dddddddd
551 * 4. xxxxxxx1 aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa bbbbbbbb bbbbbbbb bbbbbbbb bbbbbbbb cccccccc cccccccc cccccccc cccccccc dddddddd dddddddd dddddddd dddddddd
552 *
553 * 1. Wide instruction OP code, Narrow arguments
554 * 2. Wide instruction OP code, Wide arguments
555 * 3. Narrow instruction OP code, Narrow arguments
556 * 4. Narrow instruction OP code, Wide arguments
557 *
558 *
559 * The current design has a few nice properties:
560 * -The argument encoding width can be determined by simply checking for the lowest bit of the
561 * instruction Type.
562 * -The 127 first instructions (Nop is first and each instruction has a normal and Wide
563 * argument encoding variant) will have their OP code encoded on 1 byte. This is currently the
564 * vast majority of them. All but the rarest or slowest instructions can therefore have a
565 * compact encoding of their OP code.
566 *
567 *
568 * Examples:
569 *
570 * LoadInt 127:
571 * LoadInt is the 8th instruction added after Nop. Its value in Type is <= 255 so its OP code
572 * is encoded on 1 byte. It takes one argument which can be encoded losslessly in a signed
573 * byte. It therefore uses narrow argument encoding. Its bytecode encoding in HEX is thus:
574 * 10 7f
575 * | |
576 * | --> ARG1: 127
577 * -----> OP: 8th instruction; each comes in normal and _Wide variant => 2*8=16 or 0x10
578 *
579 * LoadInt 128:
580 * This time, not all arguments fit in one byte. Wide argument encoding is used.
581 * The bytecode encoding in HEX is thus.
582 * 11 80 00 00 00
583 * | | | | |
584 * | -----------> ARG1: Little endian representation of 128 (not in two's complement form)
585 * --------------> OP: The instruction became LoadInt_Wide.
586 *
587 * InitializeBlockDeadTemporalZone r1, 1
588 * This instruction is the 129th instruction added after Nop. Its value is > 255 so its OP
589 * code is encoded on 2 bytes. It takes 2 arguments which each fit in one byte.
590 * The bytecode encoding in HEX is thus:
591 * 01 02 07 01
592 * | | | |
593 * | | | --> ARG2
594 * | | -----> ARG1
595 * | --------> OP: 2-byte OP code -> Type value 258 & 0xff = 2
596 * -----------> OP: 2-byte OP code -> 0x1 prefix
597 *
598 *
599 * See also: QV4_SHOW_BYTECODE and dumpBytecode for much easier debugging
600 */
601 static Type unpack(const uchar *c) { if (c[0] == 0x1) return Type(0x100 + c[1]); return Type(c[0]); }
602 static uchar *pack(uchar *c, Type t) {
603 if (uint(t) >= 256) {
604 c[0] = 0x1;
605 c[1] = uint(t) &0xff;
606 return c + 2;
607 }
608 c[0] = uchar(uint(t));
609 return c + 1;
610 }
611
613
615
617};
618
620{
621 static const int argumentCount[];
622 static int size(Instr::Type type);
623};
624
625template<int N>
626struct InstrMeta {
627};
628
629QT_WARNING_PUSH
630QT_WARNING_DISABLE_GCC("-Wuninitialized")
631QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized")
632#define MOTH_INSTR_META_TEMPLATE(I)
633 template<> struct InstrMeta<int(Instr::Type::I)> {
634 enum { Size = MOTH_INSTR_SIZE(I) };
635 typedef Instr::instr_##I DataType;
636 static const DataType &data(const Instr &instr) { return instr.I; }
637 static void setData(Instr &instr, const DataType &v)
638 { memcpy(reinterpret_cast<char *>(&instr.I),
639 reinterpret_cast<const char *>(&v),
640 Size); }
641 };
643#undef MOTH_INSTR_META_TEMPLATE
645
646template<int InstrType>
648{
649};
650
652#define MOTH_INSTR_DATA_TYPEDEF(I) typedef InstrData<int(Instr::Type::I)> I;
654#undef MOTH_INSTR_DATA_TYPEDEF
655private:
656 Instruction();
657};
658
659} // namespace Moth
660} // namespace QV4
661
662QT_END_NAMESPACE
663
664#endif // QV4INSTR_MOTH_P_H
static StackSlot createRegister(int index)
Combined button and popup list for selecting options.
QString dumpBytecode(const char *code, int len, int nLocals, int nFormals, int, const QList< CompiledData::CodeOffsetToLineAndStatement > &lineAndStatementNumberMapping)
bool operator==(const StackSlot &l, const StackSlot &r)
QString dumpRegister(int reg, int nFormals)
QString dumpBytecode(const char *code, int len, int nLocals, int nFormals, int beginOffset, int endOffset, const QList< CompiledData::CodeOffsetToLineAndStatement > &lineAndStatementNumberMapping)
QString dumpBytecode(const QByteArray &bytecode, int nLocals, int nFormals, int startLine=1, const QList< CompiledData::CodeOffsetToLineAndStatement > &lineAndStatementNumberMapping=QList< CompiledData::CodeOffsetToLineAndStatement >())
bool operator!=(const StackSlot &l, const StackSlot &r)
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 MOTH_ADJUST_CODE(type, nargs)
#define INSTRUCTION(op, name, nargs,...)
#define MOTH_DECODE_ARG(arg, type, nargs, offset)
#define MOTH_INSTR_SIZE(I)
#define MOTH_DECODE_ARGS3(name, type, nargs, arg1, arg2, arg3)
#define MOTH_DECODE_ARGS1(name, type, nargs, arg)
#define MOTH_DECODE_ARGS2(name, type, nargs, arg1, arg2)
#define FOR_EACH_MOTH_INSTR_ALL(F)
#define MOTH_DECODE_ARGS4(name, type, nargs, arg1, arg2, arg3, arg4)
#define MOTH_DECODE_ARGS(name, type, nargs,...)
#define FOR_EACH_MOTH_INSTR(F)
#define MOTH_DEFINE_ARGS(nargs,...)
#define MOTH_JUMP_TABLE
#define MOTH_INSTR_CASE_AND_JUMP(instr)
#define MOTH_EXPAND_FOR_MSVC(x)
#define MOTH_DISPATCH()
static const int argumentCount[]
static int size(Instr::Type type)
static int encodedLength(Type t)
static Type wideInstructionType(Type t)
static Type unpack(const uchar *c)
static bool isNarrow(Type t)
static uchar * pack(uchar *c, Type t)
static bool isWide(Type t)
static Type narrowInstructionType(Type t)