| 1 | /**************************************************************************** | 
| 2 | ** | 
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. | 
| 4 | ** Contact: https://www.qt.io/licensing/ | 
| 5 | ** | 
| 6 | ** This file is part of the QtQml module of the Qt Toolkit. | 
| 7 | ** | 
| 8 | ** $QT_BEGIN_LICENSE:LGPL$ | 
| 9 | ** Commercial License Usage | 
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in | 
| 11 | ** accordance with the commercial license agreement provided with the | 
| 12 | ** Software or, alternatively, in accordance with the terms contained in | 
| 13 | ** a written agreement between you and The Qt Company. For licensing terms | 
| 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | 
| 15 | ** information use the contact form at https://www.qt.io/contact-us. | 
| 16 | ** | 
| 17 | ** GNU Lesser General Public License Usage | 
| 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | 
| 19 | ** General Public License version 3 as published by the Free Software | 
| 20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | 
| 21 | ** packaging of this file. Please review the following information to | 
| 22 | ** ensure the GNU Lesser General Public License version 3 requirements | 
| 23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | 
| 24 | ** | 
| 25 | ** GNU General Public License Usage | 
| 26 | ** Alternatively, this file may be used under the terms of the GNU | 
| 27 | ** General Public License version 2.0 or (at your option) the GNU General | 
| 28 | ** Public license version 3 or any later version approved by the KDE Free | 
| 29 | ** Qt Foundation. The licenses are as published by the Free Software | 
| 30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | 
| 31 | ** included in the packaging of this file. Please review the following | 
| 32 | ** information to ensure the GNU General Public License requirements will | 
| 33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | 
| 34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | 
| 35 | ** | 
| 36 | ** $QT_END_LICENSE$ | 
| 37 | ** | 
| 38 | ****************************************************************************/ | 
| 39 |  | 
| 40 | #ifndef QV4INSTR_MOTH_P_H | 
| 41 | #define QV4INSTR_MOTH_P_H | 
| 42 |  | 
| 43 | // | 
| 44 | //  W A R N I N G | 
| 45 | //  ------------- | 
| 46 | // | 
| 47 | // This file is not part of the Qt API.  It exists purely as an | 
| 48 | // implementation detail.  This header file may change from version to | 
| 49 | // version without notice, or even be removed. | 
| 50 | // | 
| 51 | // We mean it. | 
| 52 | // | 
| 53 |  | 
| 54 | #include <private/qv4staticvalue_p.h> | 
| 55 | #include <private/qv4compileddata_p.h> // for CompiledData::CodeOffsetToLine used by the dumper | 
| 56 | #include <qendian.h> | 
| 57 |  | 
| 58 | QT_BEGIN_NAMESPACE | 
| 59 |  | 
| 60 | #define INSTRUCTION(op, name, nargs, ...) \ | 
| 61 |     op##_INSTRUCTION(name, nargs, __VA_ARGS__) | 
| 62 |  | 
| 63 | /* for all jump instructions, the offset has to come last, to simplify the job of the bytecode generator */ | 
| 64 | #define INSTR_Nop(op) INSTRUCTION(op, Nop, 0) | 
| 65 | #define INSTR_Ret(op) INSTRUCTION(op, Ret, 0) | 
| 66 | #define INSTR_Debug(op) INSTRUCTION(op, Debug, 0) | 
| 67 | #define INSTR_LoadConst(op) INSTRUCTION(op, LoadConst, 1, index) | 
| 68 | #define INSTR_LoadZero(op) INSTRUCTION(op, LoadZero, 0) | 
| 69 | #define INSTR_LoadTrue(op) INSTRUCTION(op, LoadTrue, 0) | 
| 70 | #define INSTR_LoadFalse(op) INSTRUCTION(op, LoadFalse, 0) | 
| 71 | #define INSTR_LoadNull(op) INSTRUCTION(op, LoadNull, 0) | 
| 72 | #define INSTR_LoadUndefined(op) INSTRUCTION(op, LoadUndefined, 0) | 
| 73 | #define INSTR_LoadInt(op) INSTRUCTION(op, LoadInt, 1, value) | 
| 74 | #define INSTR_MoveConst(op) INSTRUCTION(op, MoveConst, 2, constIndex, destTemp) | 
| 75 | #define INSTR_LoadReg(op) INSTRUCTION(op, LoadReg, 1, reg) | 
| 76 | #define INSTR_StoreReg(op) INSTRUCTION(op, StoreReg, 1, reg) | 
| 77 | #define INSTR_MoveReg(op) INSTRUCTION(op, MoveReg, 2, srcReg, destReg) | 
| 78 | #define INSTR_LoadImport(op) INSTRUCTION(op, LoadImport, 1, index) | 
| 79 | #define INSTR_LoadLocal(op) INSTRUCTION(op, LoadLocal, 1, index) | 
| 80 | #define INSTR_StoreLocal(op) INSTRUCTION(op, StoreLocal, 1, index) | 
| 81 | #define INSTR_LoadScopedLocal(op) INSTRUCTION(op, LoadScopedLocal, 2, scope, index) | 
| 82 | #define INSTR_StoreScopedLocal(op) INSTRUCTION(op, StoreScopedLocal, 2, scope, index) | 
| 83 | #define INSTR_LoadRuntimeString(op) INSTRUCTION(op, LoadRuntimeString, 1, stringId) | 
| 84 | #define INSTR_MoveRegExp(op) INSTRUCTION(op, MoveRegExp, 2, regExpId, destReg) | 
| 85 | #define INSTR_LoadClosure(op) INSTRUCTION(op, LoadClosure, 1, value) | 
| 86 | #define INSTR_LoadName(op) INSTRUCTION(op, LoadName, 1, name) | 
| 87 | #define INSTR_LoadGlobalLookup(op) INSTRUCTION(op, LoadGlobalLookup, 1, index) | 
| 88 | #define INSTR_LoadQmlContextPropertyLookup(op) INSTRUCTION(op, LoadQmlContextPropertyLookup, 1, index) | 
| 89 | #define INSTR_StoreNameSloppy(op) INSTRUCTION(op, StoreNameSloppy, 1, name) | 
| 90 | #define INSTR_StoreNameStrict(op) INSTRUCTION(op, StoreNameStrict, 1, name) | 
| 91 | #define INSTR_LoadProperty(op) INSTRUCTION(op, LoadProperty, 1, name) | 
| 92 | #define INSTR_GetLookup(op) INSTRUCTION(op, GetLookup, 1, index) | 
| 93 | #define INSTR_LoadIdObject(op) INSTRUCTION(op, LoadIdObject, 2, index, base) | 
| 94 | #define INSTR_Yield(op) INSTRUCTION(op, Yield, 0) | 
| 95 | #define INSTR_YieldStar(op) INSTRUCTION(op, YieldStar, 0) | 
| 96 | #define INSTR_Resume(op) INSTRUCTION(op, Resume, 1, offset) | 
| 97 | #define INSTR_IteratorNextForYieldStar(op) INSTRUCTION(op, IteratorNextForYieldStar, 2, iterator, object) | 
| 98 | #define INSTR_StoreProperty(op) INSTRUCTION(op, StoreProperty, 2, name, base) | 
| 99 | #define INSTR_SetLookup(op) INSTRUCTION(op, SetLookup, 2, index, base) | 
| 100 | #define INSTR_LoadSuperProperty(op) INSTRUCTION(op, LoadSuperProperty, 1, property) | 
| 101 | #define INSTR_StoreSuperProperty(op) INSTRUCTION(op, StoreSuperProperty, 1, property) | 
| 102 | #define INSTR_LoadElement(op) INSTRUCTION(op, LoadElement, 1, base) | 
| 103 | #define INSTR_StoreElement(op) INSTRUCTION(op, StoreElement, 2, base, index) | 
| 104 | #define INSTR_CallValue(op) INSTRUCTION(op, CallValue, 3, name, argc, argv) | 
| 105 | #define INSTR_CallWithReceiver(op) INSTRUCTION(op, CallWithReceiver, 4, name, thisObject, argc, argv) | 
| 106 | #define INSTR_CallProperty(op) INSTRUCTION(op, CallProperty, 4, name, base, argc, argv) | 
| 107 | #define INSTR_CallPropertyLookup(op) INSTRUCTION(op, CallPropertyLookup, 4, lookupIndex, base, argc, argv) | 
| 108 | #define INSTR_CallElement(op) INSTRUCTION(op, CallElement, 4, base, index, argc, argv) | 
| 109 | #define INSTR_CallName(op) INSTRUCTION(op, CallName, 3, name, argc, argv) | 
| 110 | #define INSTR_CallPossiblyDirectEval(op) INSTRUCTION(op, CallPossiblyDirectEval, 2, argc, argv) | 
| 111 | #define INSTR_CallGlobalLookup(op) INSTRUCTION(op, CallGlobalLookup, 3, index, argc, argv) | 
| 112 | #define INSTR_CallQmlContextPropertyLookup(op) INSTRUCTION(op, CallQmlContextPropertyLookup, 3, index, argc, argv) | 
| 113 | #define INSTR_CallWithSpread(op) INSTRUCTION(op, CallWithSpread, 4, func, thisObject, argc, argv) | 
| 114 | #define INSTR_Construct(op) INSTRUCTION(op, Construct, 3, func, argc, argv) | 
| 115 | #define INSTR_ConstructWithSpread(op) INSTRUCTION(op, ConstructWithSpread, 3, func, argc, argv) | 
| 116 | #define INSTR_SetUnwindHandler(op) INSTRUCTION(op, SetUnwindHandler, 1, offset) | 
| 117 | #define INSTR_UnwindDispatch(op) INSTRUCTION(op, UnwindDispatch, 0) | 
| 118 | #define INSTR_UnwindToLabel(op) INSTRUCTION(op, UnwindToLabel, 2, level, offset) | 
| 119 | #define INSTR_DeadTemporalZoneCheck(op) INSTRUCTION(op, DeadTemporalZoneCheck, 1, name) | 
| 120 | #define INSTR_ThrowException(op) INSTRUCTION(op, ThrowException, 0) | 
| 121 | #define INSTR_GetException(op) INSTRUCTION(op, GetException, 0) | 
| 122 | #define INSTR_SetException(op) INSTRUCTION(op, SetException, 0) | 
| 123 | #define INSTR_CreateCallContext(op) INSTRUCTION(op, CreateCallContext, 0) | 
| 124 | #define INSTR_PushCatchContext(op) INSTRUCTION(op, PushCatchContext, 2, index, name) | 
| 125 | #define INSTR_PushWithContext(op) INSTRUCTION(op, PushWithContext, 0) | 
| 126 | #define INSTR_PushBlockContext(op) INSTRUCTION(op, PushBlockContext, 1, index) | 
| 127 | #define INSTR_CloneBlockContext(op) INSTRUCTION(op, CloneBlockContext, 0) | 
| 128 | #define INSTR_PushScriptContext(op) INSTRUCTION(op, PushScriptContext, 1, index) | 
| 129 | #define INSTR_PopScriptContext(op) INSTRUCTION(op, PopScriptContext, 0) | 
| 130 | #define INSTR_PopContext(op) INSTRUCTION(op, PopContext, 0) | 
| 131 | #define INSTR_GetIterator(op) INSTRUCTION(op, GetIterator, 1, iterator) | 
| 132 | #define INSTR_IteratorNext(op) INSTRUCTION(op, IteratorNext, 2, value, done) | 
| 133 | #define INSTR_IteratorClose(op) INSTRUCTION(op, IteratorClose, 1, done) | 
| 134 | #define INSTR_DestructureRestElement(op) INSTRUCTION(op, DestructureRestElement, 0) | 
| 135 | #define INSTR_DeleteProperty(op) INSTRUCTION(op, DeleteProperty, 2, base, index) | 
| 136 | #define INSTR_DeleteName(op) INSTRUCTION(op, DeleteName, 1, name) | 
| 137 | #define INSTR_TypeofName(op) INSTRUCTION(op, TypeofName, 1, name) | 
| 138 | #define INSTR_TypeofValue(op) INSTRUCTION(op, TypeofValue, 0) | 
| 139 | #define INSTR_DeclareVar(op) INSTRUCTION(op, DeclareVar, 2, varName, isDeletable) | 
| 140 | #define INSTR_DefineArray(op) INSTRUCTION(op, DefineArray, 2, argc, args) | 
| 141 | #define INSTR_DefineObjectLiteral(op) INSTRUCTION(op, DefineObjectLiteral, 3, internalClassId, argc, args) | 
| 142 | #define INSTR_CreateClass(op) INSTRUCTION(op, CreateClass, 3, classIndex, heritage, computedNames) | 
| 143 | #define INSTR_CreateMappedArgumentsObject(op) INSTRUCTION(op, CreateMappedArgumentsObject, 0) | 
| 144 | #define INSTR_CreateUnmappedArgumentsObject(op) INSTRUCTION(op, CreateUnmappedArgumentsObject, 0) | 
| 145 | #define INSTR_CreateRestParameter(op) INSTRUCTION(op, CreateRestParameter, 1, argIndex) | 
| 146 | #define INSTR_ConvertThisToObject(op) INSTRUCTION(op, ConvertThisToObject, 0) | 
| 147 | #define INSTR_LoadSuperConstructor(op) INSTRUCTION(op, LoadSuperConstructor, 0) | 
| 148 | #define INSTR_ToObject(op) INSTRUCTION(op, ToObject, 0) | 
| 149 | #define INSTR_Jump(op) INSTRUCTION(op, Jump, 1, offset) | 
| 150 | #define INSTR_JumpTrue(op) INSTRUCTION(op, JumpTrue, 1, offset) | 
| 151 | #define INSTR_JumpFalse(op) INSTRUCTION(op, JumpFalse, 1, offset) | 
| 152 | #define INSTR_JumpNotUndefined(op) INSTRUCTION(op, JumpNotUndefined, 1, offset) | 
| 153 | #define INSTR_JumpNoException(op) INSTRUCTION(op, JumpNoException, 1, offset) | 
| 154 | #define INSTR_CheckException(op) INSTRUCTION(op, CheckException, 0) | 
| 155 | #define INSTR_CmpEqNull(op) INSTRUCTION(op, CmpEqNull, 0) | 
| 156 | #define INSTR_CmpNeNull(op) INSTRUCTION(op, CmpNeNull, 0) | 
| 157 | #define INSTR_CmpEqInt(op) INSTRUCTION(op, CmpEqInt, 1, lhs) | 
| 158 | #define INSTR_CmpNeInt(op) INSTRUCTION(op, CmpNeInt, 1, lhs) | 
| 159 | #define INSTR_CmpEq(op) INSTRUCTION(op, CmpEq, 1, lhs) | 
| 160 | #define INSTR_CmpNe(op) INSTRUCTION(op, CmpNe, 1, lhs) | 
| 161 | #define INSTR_CmpGt(op) INSTRUCTION(op, CmpGt, 1, lhs) | 
| 162 | #define INSTR_CmpGe(op) INSTRUCTION(op, CmpGe, 1, lhs) | 
| 163 | #define INSTR_CmpLt(op) INSTRUCTION(op, CmpLt, 1, lhs) | 
| 164 | #define INSTR_CmpLe(op) INSTRUCTION(op, CmpLe, 1, lhs) | 
| 165 | #define INSTR_CmpStrictEqual(op) INSTRUCTION(op, CmpStrictEqual, 1, lhs) | 
| 166 | #define INSTR_CmpStrictNotEqual(op) INSTRUCTION(op, CmpStrictNotEqual, 1, lhs) | 
| 167 | #define INSTR_CmpIn(op) INSTRUCTION(op, CmpIn, 1, lhs) | 
| 168 | #define INSTR_CmpInstanceOf(op) INSTRUCTION(op, CmpInstanceOf, 1, lhs) | 
| 169 | #define INSTR_UNot(op) INSTRUCTION(op, UNot, 0) | 
| 170 | #define INSTR_UPlus(op) INSTRUCTION(op, UPlus, 0) | 
| 171 | #define INSTR_UMinus(op) INSTRUCTION(op, UMinus, 0) | 
| 172 | #define INSTR_UCompl(op) INSTRUCTION(op, UCompl, 0) | 
| 173 | #define INSTR_Increment(op) INSTRUCTION(op, Increment, 0) | 
| 174 | #define INSTR_Decrement(op) INSTRUCTION(op, Decrement, 0) | 
| 175 | #define INSTR_Add(op) INSTRUCTION(op, Add, 1, lhs) | 
| 176 | #define INSTR_BitAnd(op) INSTRUCTION(op, BitAnd, 1, lhs) | 
| 177 | #define INSTR_BitOr(op) INSTRUCTION(op, BitOr, 1, lhs) | 
| 178 | #define INSTR_BitXor(op) INSTRUCTION(op, BitXor, 1, lhs) | 
| 179 | #define INSTR_UShr(op) INSTRUCTION(op, UShr, 1, lhs) | 
| 180 | #define INSTR_Shr(op) INSTRUCTION(op, Shr, 1, lhs) | 
| 181 | #define INSTR_Shl(op) INSTRUCTION(op, Shl, 1, lhs) | 
| 182 | #define INSTR_BitAndConst(op) INSTRUCTION(op, BitAndConst, 1, rhs) | 
| 183 | #define INSTR_BitOrConst(op) INSTRUCTION(op, BitOrConst, 1, rhs) | 
| 184 | #define INSTR_BitXorConst(op) INSTRUCTION(op, BitXorConst, 1, rhs) | 
| 185 | #define INSTR_UShrConst(op) INSTRUCTION(op, UShrConst, 1, rhs) | 
| 186 | #define INSTR_ShrConst(op) INSTRUCTION(op, ShrConst, 1, rhs) | 
| 187 | #define INSTR_ShlConst(op) INSTRUCTION(op, ShlConst, 1, rhs) | 
| 188 | #define INSTR_Exp(op) INSTRUCTION(op, Exp, 1, lhs) | 
| 189 | #define INSTR_Mul(op) INSTRUCTION(op, Mul, 1, lhs) | 
| 190 | #define INSTR_Div(op) INSTRUCTION(op, Div, 1, lhs) | 
| 191 | #define INSTR_Mod(op) INSTRUCTION(op, Mod, 1, lhs) | 
| 192 | #define INSTR_Sub(op) INSTRUCTION(op, Sub, 1, lhs) | 
| 193 | #define INSTR_LoadQmlImportedScripts(op) INSTRUCTION(op, LoadQmlImportedScripts, 1, result) | 
| 194 | #define INSTR_InitializeBlockDeadTemporalZone(op) INSTRUCTION(op, InitializeBlockDeadTemporalZone, 2, firstReg, count) | 
| 195 | #define INSTR_ThrowOnNullOrUndefined(op) INSTRUCTION(op, ThrowOnNullOrUndefined, 0) | 
| 196 | #define INSTR_GetTemplateObject(op) INSTRUCTION(op, GetTemplateObject, 1, index) | 
| 197 | #define INSTR_TailCall(op) INSTRUCTION(op, TailCall, 4, func, thisObject, argc, argv) | 
| 198 |  | 
| 199 | #define FOR_EACH_MOTH_INSTR_ALL(F) \ | 
| 200 |     F(Nop) \ | 
| 201 |     FOR_EACH_MOTH_INSTR(F) | 
| 202 |  | 
| 203 | #define FOR_EACH_MOTH_INSTR(F) \ | 
| 204 |     F(Ret) \ | 
| 205 |     F(LoadConst) \ | 
| 206 |     F(LoadZero) \ | 
| 207 |     F(LoadTrue) \ | 
| 208 |     F(LoadFalse) \ | 
| 209 |     F(LoadNull) \ | 
| 210 |     F(LoadUndefined) \ | 
| 211 |     F(LoadInt) \ | 
| 212 |     F(LoadRuntimeString) \ | 
| 213 |     F(MoveConst) \ | 
| 214 |     F(LoadReg) \ | 
| 215 |     F(StoreReg) \ | 
| 216 |     F(MoveReg) \ | 
| 217 |     F(LoadImport) \ | 
| 218 |     F(LoadLocal) \ | 
| 219 |     F(StoreLocal) \ | 
| 220 |     F(LoadScopedLocal) \ | 
| 221 |     F(StoreScopedLocal) \ | 
| 222 |     F(MoveRegExp) \ | 
| 223 |     F(LoadClosure) \ | 
| 224 |     F(LoadName) \ | 
| 225 |     F(LoadGlobalLookup) \ | 
| 226 |     F(LoadQmlContextPropertyLookup) \ | 
| 227 |     F(StoreNameSloppy) \ | 
| 228 |     F(StoreNameStrict) \ | 
| 229 |     F(LoadElement) \ | 
| 230 |     F(StoreElement) \ | 
| 231 |     F(LoadProperty) \ | 
| 232 |     F(GetLookup) \ | 
| 233 |     F(StoreProperty) \ | 
| 234 |     F(SetLookup) \ | 
| 235 |     F(LoadSuperProperty) \ | 
| 236 |     F(StoreSuperProperty) \ | 
| 237 |     F(ConvertThisToObject) \ | 
| 238 |     F(ToObject) \ | 
| 239 |     F(Jump) \ | 
| 240 |     F(JumpTrue) \ | 
| 241 |     F(JumpFalse) \ | 
| 242 |     F(JumpNoException) \ | 
| 243 |     F(JumpNotUndefined) \ | 
| 244 |     F(CheckException) \ | 
| 245 |     F(CmpEqNull) \ | 
| 246 |     F(CmpNeNull) \ | 
| 247 |     F(CmpEqInt) \ | 
| 248 |     F(CmpNeInt) \ | 
| 249 |     F(CmpEq) \ | 
| 250 |     F(CmpNe) \ | 
| 251 |     F(CmpGt) \ | 
| 252 |     F(CmpGe) \ | 
| 253 |     F(CmpLt) \ | 
| 254 |     F(CmpLe) \ | 
| 255 |     F(CmpStrictEqual) \ | 
| 256 |     F(CmpStrictNotEqual) \ | 
| 257 |     F(CmpIn) \ | 
| 258 |     F(CmpInstanceOf) \ | 
| 259 |     F(UNot) \ | 
| 260 |     F(UPlus) \ | 
| 261 |     F(UMinus) \ | 
| 262 |     F(UCompl) \ | 
| 263 |     F(Increment) \ | 
| 264 |     F(Decrement) \ | 
| 265 |     F(Add) \ | 
| 266 |     F(BitAnd) \ | 
| 267 |     F(BitOr) \ | 
| 268 |     F(BitXor) \ | 
| 269 |     F(UShr) \ | 
| 270 |     F(Shr) \ | 
| 271 |     F(Shl) \ | 
| 272 |     F(BitAndConst) \ | 
| 273 |     F(BitOrConst) \ | 
| 274 |     F(BitXorConst) \ | 
| 275 |     F(UShrConst) \ | 
| 276 |     F(ShrConst) \ | 
| 277 |     F(ShlConst) \ | 
| 278 |     F(Exp) \ | 
| 279 |     F(Mul) \ | 
| 280 |     F(Div) \ | 
| 281 |     F(Mod) \ | 
| 282 |     F(Sub) \ | 
| 283 |     F(CallValue) \ | 
| 284 |     F(CallWithReceiver) \ | 
| 285 |     F(CallProperty) \ | 
| 286 |     F(CallPropertyLookup) \ | 
| 287 |     F(CallElement) \ | 
| 288 |     F(CallName) \ | 
| 289 |     F(CallPossiblyDirectEval) \ | 
| 290 |     F(CallGlobalLookup) \ | 
| 291 |     F(CallQmlContextPropertyLookup) \ | 
| 292 |     F(CallWithSpread) \ | 
| 293 |     F(Construct) \ | 
| 294 |     F(ConstructWithSpread) \ | 
| 295 |     F(SetUnwindHandler) \ | 
| 296 |     F(UnwindDispatch) \ | 
| 297 |     F(UnwindToLabel) \ | 
| 298 |     F(DeadTemporalZoneCheck) \ | 
| 299 |     F(ThrowException) \ | 
| 300 |     F(GetException) \ | 
| 301 |     F(SetException) \ | 
| 302 |     F(CreateCallContext) \ | 
| 303 |     F(PushCatchContext) \ | 
| 304 |     F(PushWithContext) \ | 
| 305 |     F(PushBlockContext) \ | 
| 306 |     F(CloneBlockContext) \ | 
| 307 |     F(PopContext) \ | 
| 308 |     F(GetIterator) \ | 
| 309 |     F(IteratorNext) \ | 
| 310 |     F(IteratorClose) \ | 
| 311 |     F(DestructureRestElement) \ | 
| 312 |     F(DeleteProperty) \ | 
| 313 |     F(DeleteName) \ | 
| 314 |     F(TypeofName) \ | 
| 315 |     F(TypeofValue) \ | 
| 316 |     F(DeclareVar) \ | 
| 317 |     F(DefineArray) \ | 
| 318 |     F(DefineObjectLiteral) \ | 
| 319 |     F(CreateMappedArgumentsObject) \ | 
| 320 |     F(CreateUnmappedArgumentsObject) \ | 
| 321 |     F(CreateRestParameter) \ | 
| 322 |     F(Yield) \ | 
| 323 |     F(YieldStar) \ | 
| 324 |     F(Resume) \ | 
| 325 |     F(IteratorNextForYieldStar) \ | 
| 326 |     F(CreateClass) \ | 
| 327 |     F(LoadSuperConstructor) \ | 
| 328 |     F(PushScriptContext) \ | 
| 329 |     F(PopScriptContext) \ | 
| 330 |     F(InitializeBlockDeadTemporalZone) \ | 
| 331 |     F(ThrowOnNullOrUndefined) \ | 
| 332 |     F(GetTemplateObject) \ | 
| 333 |     F(TailCall) \ | 
| 334 |     F(Debug) \ | 
| 335 |  | 
| 336 | #define MOTH_NUM_INSTRUCTIONS() (static_cast<int>(Moth::Instr::Type::Debug_Wide) + 1) | 
| 337 |  | 
| 338 | #if defined(Q_CC_GNU) | 
| 339 | #if defined(Q_CC_INTEL) | 
| 340 | // icc before version 1200 doesn't support computed goto, and at least up to version 18.0.0 the | 
| 341 | // current use results in an internal compiler error. We could enable this if/when it gets fixed | 
| 342 | // in a later version. | 
| 343 | # elif defined(Q_OS_WASM) && !defined(__asmjs) | 
| 344 | // Upstream llvm does not support computed goto for the wasm target, unlike the 'fastcomp' llvm fork | 
| 345 | // shipped with the emscripten SDK. Disable computed goto usage for non-fastcomp llvm on Wasm. | 
| 346 | #else | 
| 347 | #  define MOTH_COMPUTED_GOTO | 
| 348 | #endif | 
| 349 | #endif | 
| 350 |  | 
| 351 | #define MOTH_INSTR_ALIGN_MASK (Q_ALIGNOF(QV4::Moth::Instr) - 1) | 
| 352 |  | 
| 353 | #define MOTH_INSTR_ENUM(I)  I, I##_Wide, | 
| 354 | #define MOTH_INSTR_SIZE(I) (sizeof(QV4::Moth::Instr::instr_##I)) | 
| 355 |  | 
| 356 | #define MOTH_EXPAND_FOR_MSVC(x) x | 
| 357 | #define MOTH_DEFINE_ARGS(nargs, ...) \ | 
| 358 |     MOTH_EXPAND_FOR_MSVC(MOTH_DEFINE_ARGS##nargs(__VA_ARGS__)) | 
| 359 |  | 
| 360 | #define MOTH_DEFINE_ARGS0() | 
| 361 | #define MOTH_DEFINE_ARGS1(arg) \ | 
| 362 |     int arg; | 
| 363 | #define MOTH_DEFINE_ARGS2(arg1, arg2) \ | 
| 364 |     int arg1; \ | 
| 365 |     int arg2; | 
| 366 | #define MOTH_DEFINE_ARGS3(arg1, arg2, arg3) \ | 
| 367 |     int arg1; \ | 
| 368 |     int arg2; \ | 
| 369 |     int arg3; | 
| 370 | #define MOTH_DEFINE_ARGS4(arg1, arg2, arg3, arg4) \ | 
| 371 |     int arg1; \ | 
| 372 |     int arg2; \ | 
| 373 |     int arg3; \ | 
| 374 |     int arg4; | 
| 375 | #define MOTH_DEFINE_ARGS5(arg1, arg2, arg3, arg4, arg5) \ | 
| 376 |     int arg1; \ | 
| 377 |     int arg2; \ | 
| 378 |     int arg3; \ | 
| 379 |     int arg4; \ | 
| 380 |     int arg5; | 
| 381 |  | 
| 382 | #define MOTH_COLLECT_ENUMS(instr) \ | 
| 383 |     INSTR_##instr(MOTH_GET_ENUM) | 
| 384 | #define MOTH_GET_ENUM_INSTRUCTION(name, ...) \ | 
| 385 |     name, | 
| 386 |  | 
| 387 | #define MOTH_EMIT_STRUCTS(instr) \ | 
| 388 |     INSTR_##instr(MOTH_EMIT_STRUCT) | 
| 389 | #define MOTH_EMIT_STRUCT_INSTRUCTION(name, nargs, ...) \ | 
| 390 |     struct instr_##name { \ | 
| 391 |         MOTH_DEFINE_ARGS(nargs, __VA_ARGS__) \ | 
| 392 |     }; | 
| 393 |  | 
| 394 | #define MOTH_EMIT_INSTR_MEMBERS(instr) \ | 
| 395 |     INSTR_##instr(MOTH_EMIT_INSTR_MEMBER) | 
| 396 | #define MOTH_EMIT_INSTR_MEMBER_INSTRUCTION(name, nargs, ...) \ | 
| 397 |     instr_##name name; | 
| 398 |  | 
| 399 | #define MOTH_COLLECT_NARGS(instr) \ | 
| 400 |     INSTR_##instr(MOTH_COLLECT_ARG_COUNT) | 
| 401 | #define MOTH_COLLECT_ARG_COUNT_INSTRUCTION(name, nargs, ...) \ | 
| 402 |     nargs, nargs, | 
| 403 |  | 
| 404 | #define MOTH_DECODE_ARG(arg, type, nargs, offset) \ | 
| 405 |     arg = qFromLittleEndian<type>(qFromUnaligned<type>(reinterpret_cast<const type *>(code) - nargs + offset)); | 
| 406 | #define MOTH_ADJUST_CODE(type, nargs) \ | 
| 407 |     code += static_cast<quintptr>(nargs*sizeof(type) + 1) | 
| 408 |  | 
| 409 | #define MOTH_DECODE_INSTRUCTION(name, nargs, ...) \ | 
| 410 |         MOTH_DEFINE_ARGS(nargs, __VA_ARGS__) \ | 
| 411 |     op_int_##name: \ | 
| 412 |         MOTH_ADJUST_CODE(int, nargs); \ | 
| 413 |         MOTH_DECODE_ARGS(name, int, nargs, __VA_ARGS__) \ | 
| 414 |         goto op_main_##name; \ | 
| 415 |     op_byte_##name: \ | 
| 416 |         MOTH_ADJUST_CODE(qint8, nargs); \ | 
| 417 |         MOTH_DECODE_ARGS(name, qint8, nargs, __VA_ARGS__) \ | 
| 418 |     op_main_##name: \ | 
| 419 |         ; \ | 
| 420 |  | 
| 421 | #define MOTH_DECODE_WITH_BASE_INSTRUCTION(name, nargs, ...) \ | 
| 422 |         MOTH_DEFINE_ARGS(nargs, __VA_ARGS__) \ | 
| 423 |         const char *base_ptr; \ | 
| 424 |     op_int_##name: \ | 
| 425 |         base_ptr = code; \ | 
| 426 |         MOTH_ADJUST_CODE(int, nargs); \ | 
| 427 |         MOTH_DECODE_ARGS(name, int, nargs, __VA_ARGS__) \ | 
| 428 |         goto op_main_##name; \ | 
| 429 |     op_byte_##name: \ | 
| 430 |         base_ptr = code; \ | 
| 431 |         MOTH_ADJUST_CODE(qint8, nargs); \ | 
| 432 |         MOTH_DECODE_ARGS(name, qint8, nargs, __VA_ARGS__) \ | 
| 433 |     op_main_##name: \ | 
| 434 |         ; \ | 
| 435 |  | 
| 436 | #define MOTH_DECODE_ARGS(name, type, nargs, ...) \ | 
| 437 |     MOTH_EXPAND_FOR_MSVC(MOTH_DECODE_ARGS##nargs(name, type, nargs, __VA_ARGS__)) | 
| 438 |  | 
| 439 | #define MOTH_DECODE_ARGS0(name, type, nargs, dummy) | 
| 440 | #define MOTH_DECODE_ARGS1(name, type, nargs, arg) \ | 
| 441 |         MOTH_DECODE_ARG(arg, type, nargs, 0); | 
| 442 | #define MOTH_DECODE_ARGS2(name, type, nargs, arg1, arg2) \ | 
| 443 |         MOTH_DECODE_ARGS1(name, type, nargs, arg1); \ | 
| 444 |         MOTH_DECODE_ARG(arg2, type, nargs, 1); | 
| 445 | #define MOTH_DECODE_ARGS3(name, type, nargs, arg1, arg2, arg3) \ | 
| 446 |         MOTH_DECODE_ARGS2(name, type, nargs, arg1, arg2); \ | 
| 447 |         MOTH_DECODE_ARG(arg3, type, nargs, 2); | 
| 448 | #define MOTH_DECODE_ARGS4(name, type, nargs, arg1, arg2, arg3, arg4) \ | 
| 449 |         MOTH_DECODE_ARGS3(name, type, nargs, arg1, arg2, arg3); \ | 
| 450 |         MOTH_DECODE_ARG(arg4, type, nargs, 3); | 
| 451 | #define MOTH_DECODE_ARGS5(name, type, nargs, arg1, arg2, arg3, arg4, arg5) \ | 
| 452 |         MOTH_DECODE_ARGS4(name, type, nargs, arg1, arg2, arg3, arg4); \ | 
| 453 |         MOTH_DECODE_ARG(arg5, type, nargs, 4); | 
| 454 |  | 
| 455 | #ifdef MOTH_COMPUTED_GOTO | 
| 456 | /* collect jump labels */ | 
| 457 | #define COLLECT_LABELS(instr) \ | 
| 458 |     INSTR_##instr(GET_LABEL) \ | 
| 459 |     INSTR_##instr(GET_LABEL_WIDE) | 
| 460 | #define GET_LABEL_INSTRUCTION(name, ...) \ | 
| 461 |     &&op_byte_##name, | 
| 462 | #define GET_LABEL_WIDE_INSTRUCTION(name, ...) \ | 
| 463 |     &&op_int_##name, | 
| 464 |  | 
| 465 | #define MOTH_JUMP_TABLE \ | 
| 466 |     static const void *jumpTable[] = { \ | 
| 467 |         FOR_EACH_MOTH_INSTR_ALL(COLLECT_LABELS) \ | 
| 468 |     }; | 
| 469 |  | 
| 470 | #define MOTH_DISPATCH_SINGLE() \ | 
| 471 |     goto *jumpTable[*reinterpret_cast<const uchar *>(code)]; | 
| 472 |  | 
| 473 | #define MOTH_DISPATCH() \ | 
| 474 |     MOTH_DISPATCH_SINGLE() \ | 
| 475 |     op_byte_Nop: \ | 
| 476 |         ++code; \ | 
| 477 |         MOTH_DISPATCH_SINGLE() \ | 
| 478 |     op_int_Nop: /* wide prefix */ \ | 
| 479 |         ++code; \ | 
| 480 |         goto *jumpTable[0x100 | *reinterpret_cast<const uchar *>(code)]; | 
| 481 | #else | 
| 482 | #define MOTH_JUMP_TABLE | 
| 483 |  | 
| 484 | #define MOTH_INSTR_CASE_AND_JUMP(instr) \ | 
| 485 |     INSTR_##instr(GET_CASE_AND_JUMP) \ | 
| 486 |     INSTR_##instr(GET_CASE_AND_JUMP_WIDE) | 
| 487 | #define GET_CASE_AND_JUMP_INSTRUCTION(name, ...) \ | 
| 488 |     case Instr::Type::name: goto op_byte_##name; | 
| 489 | #define GET_CASE_AND_JUMP_WIDE_INSTRUCTION(name, ...) \ | 
| 490 |     case Instr::Type::name##_Wide: goto op_int_##name; | 
| 491 |  | 
| 492 | #define MOTH_DISPATCH() \ | 
| 493 |     Instr::Type type = Instr::Type(static_cast<uchar>(*code)); \ | 
| 494 |   dispatch: \ | 
| 495 |     switch (type) { \ | 
| 496 |         case Instr::Type::Nop: \ | 
| 497 |             ++code; \ | 
| 498 |             type = Instr::Type(static_cast<uchar>(*code)); \ | 
| 499 |             goto dispatch; \ | 
| 500 |         case Instr::Type::Nop_Wide: /* wide prefix */ \ | 
| 501 |             ++code; \ | 
| 502 |             type = Instr::Type(0x100 | static_cast<uchar>(*code)); \ | 
| 503 |             goto dispatch; \ | 
| 504 |         FOR_EACH_MOTH_INSTR(MOTH_INSTR_CASE_AND_JUMP) \ | 
| 505 |     } | 
| 506 | #endif | 
| 507 |  | 
| 508 | namespace QV4 { | 
| 509 |  | 
| 510 | namespace CompiledData { | 
| 511 | struct CodeOffsetToLine; | 
| 512 | } | 
| 513 |  | 
| 514 | namespace Moth { | 
| 515 |  | 
| 516 | class StackSlot { | 
| 517 |     int index; | 
| 518 |  | 
| 519 | public: | 
| 520 |     static StackSlot createRegister(int index) { | 
| 521 |         Q_ASSERT(index >= 0); | 
| 522 |         StackSlot t; | 
| 523 |         t.index = index; | 
| 524 |         return t; | 
| 525 |     } | 
| 526 |  | 
| 527 |     int stackSlot() const { return index; } | 
| 528 |     operator int() const { return index; } | 
| 529 | }; | 
| 530 |  | 
| 531 | inline bool operator==(const StackSlot &l, const StackSlot &r) { return l.stackSlot() == r.stackSlot(); } | 
| 532 | inline bool operator!=(const StackSlot &l, const StackSlot &r) { return l.stackSlot() != r.stackSlot(); } | 
| 533 |  | 
| 534 | // When making changes to the instructions, make sure to bump QV4_DATA_STRUCTURE_VERSION in qv4compileddata_p.h | 
| 535 |  | 
| 536 | void dumpBytecode(const char *bytecode, int len, int nLocals, int nFormals, int startLine = 1, | 
| 537 |                   const QVector<CompiledData::CodeOffsetToLine> &lineNumberMapping = QVector<CompiledData::CodeOffsetToLine>()); | 
| 538 | inline void dumpBytecode(const QByteArray &bytecode, int nLocals, int nFormals, int startLine = 1, | 
| 539 |                          const QVector<CompiledData::CodeOffsetToLine> &lineNumberMapping = QVector<CompiledData::CodeOffsetToLine>()) { | 
| 540 |     dumpBytecode(bytecode: bytecode.constData(), len: bytecode.length(), nLocals, nFormals, startLine, lineNumberMapping); | 
| 541 | } | 
| 542 |  | 
| 543 | union Instr | 
| 544 | { | 
| 545 |     enum class Type { | 
| 546 |         FOR_EACH_MOTH_INSTR_ALL(MOTH_INSTR_ENUM) | 
| 547 |     }; | 
| 548 |  | 
| 549 |     static Type wideInstructionType(Type t) { return Type(int(t) | 1); } | 
| 550 |     static Type narrowInstructionType(Type t) { return Type(int(t) & ~1); } | 
| 551 |     static bool isWide(Type t) { return int(t) & 1; } | 
| 552 |     static bool isNarrow(Type t) { return !(int(t) & 1); } | 
| 553 |     static int encodedLength(Type t) { return int(t) >= 256 ? 2 : 1; } | 
| 554 |  | 
| 555 |     static Type unpack(const uchar *c) { if (c[0] == 0x1) return Type(0x100 + c[1]); return Type(c[0]); } | 
| 556 |     static uchar *pack(uchar *c, Type t) { | 
| 557 |         if (uint(t) >= 256) { | 
| 558 |             c[0] = 0x1; | 
| 559 |             c[1] = uint(t) &0xff; | 
| 560 |             return c + 2; | 
| 561 |         } | 
| 562 |         c[0] = uchar(uint(t)); | 
| 563 |         return c + 1; | 
| 564 |     } | 
| 565 |  | 
| 566 |     FOR_EACH_MOTH_INSTR_ALL(MOTH_EMIT_STRUCTS) | 
| 567 |  | 
| 568 |     FOR_EACH_MOTH_INSTR_ALL(MOTH_EMIT_INSTR_MEMBERS) | 
| 569 |  | 
| 570 |     int argumentsAsInts[4]; | 
| 571 | }; | 
| 572 |  | 
| 573 | struct InstrInfo | 
| 574 | { | 
| 575 |     static const int argumentCount[]; | 
| 576 |     static int size(Instr::Type type); | 
| 577 | }; | 
| 578 |  | 
| 579 | template<int N> | 
| 580 | struct InstrMeta { | 
| 581 | }; | 
| 582 |  | 
| 583 | QT_WARNING_PUSH | 
| 584 | QT_WARNING_DISABLE_GCC("-Wuninitialized" ) | 
| 585 | QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized" ) | 
| 586 | #define MOTH_INSTR_META_TEMPLATE(I) \ | 
| 587 |     template<> struct InstrMeta<int(Instr::Type::I)> { \ | 
| 588 |         enum { Size = MOTH_INSTR_SIZE(I) }; \ | 
| 589 |         typedef Instr::instr_##I DataType; \ | 
| 590 |         static const DataType &data(const Instr &instr) { return instr.I; } \ | 
| 591 |         static void setData(Instr &instr, const DataType &v) \ | 
| 592 |         { memcpy(reinterpret_cast<char *>(&instr.I), \ | 
| 593 |                  reinterpret_cast<const char *>(&v), \ | 
| 594 |                  Size); } \ | 
| 595 |     }; | 
| 596 | FOR_EACH_MOTH_INSTR_ALL(MOTH_INSTR_META_TEMPLATE); | 
| 597 | #undef MOTH_INSTR_META_TEMPLATE | 
| 598 | QT_WARNING_POP | 
| 599 |  | 
| 600 | template<int InstrType> | 
| 601 | class InstrData : public InstrMeta<InstrType>::DataType | 
| 602 | { | 
| 603 | }; | 
| 604 |  | 
| 605 | struct Instruction { | 
| 606 | #define MOTH_INSTR_DATA_TYPEDEF(I) typedef InstrData<int(Instr::Type::I)> I; | 
| 607 | FOR_EACH_MOTH_INSTR_ALL(MOTH_INSTR_DATA_TYPEDEF) | 
| 608 | #undef MOTH_INSTR_DATA_TYPEDEF | 
| 609 | private: | 
| 610 |     Instruction(); | 
| 611 | }; | 
| 612 |  | 
| 613 | } // namespace Moth | 
| 614 | } // namespace QV4 | 
| 615 |  | 
| 616 | QT_END_NAMESPACE | 
| 617 |  | 
| 618 | #endif // QV4INSTR_MOTH_P_H | 
| 619 |  |