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