b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | --- a/src/lvm.c |
| 2 | +++ b/src/lvm.c |
| 3 | @@ -31,6 +31,9 @@ |
| 4 | /* limit for table tag-method chains (to avoid loops) */ |
| 5 | #define MAXTAGLOOP 100 |
| 6 | |
| 7 | +#ifdef __GNUC__ |
| 8 | +#define COMPUTED_GOTO 1 |
| 9 | +#endif |
| 10 | |
| 11 | /* |
| 12 | * If 'obj' is a string, it is tried to be interpreted as a number. |
| 13 | @@ -568,12 +571,63 @@ static inline int arith_mode( const TVal |
| 14 | ARITH_OP1_END |
| 15 | #endif |
| 16 | |
| 17 | +#ifdef COMPUTED_GOTO |
| 18 | +#define OPCODE_TARGET(op) DO_OP_##op: |
| 19 | +#define CALL_OPCODE(op) goto *opcodes[op]; |
| 20 | +#define OPCODE_PTR(op) [OP_##op] = &&DO_OP_##op |
| 21 | +#else |
| 22 | +#define OPCODE_TARGET(op) case OP_##op: |
| 23 | +#define CALL_OPCODE(op) switch (op) |
| 24 | +#endif |
| 25 | + |
| 26 | |
| 27 | void luaV_execute (lua_State *L, int nexeccalls) { |
| 28 | LClosure *cl; |
| 29 | StkId base; |
| 30 | TValue *k; |
| 31 | const Instruction *pc; |
| 32 | +#ifdef COMPUTED_GOTO |
| 33 | + static const void *opcodes[] = { |
| 34 | + OPCODE_PTR(MOVE), |
| 35 | + OPCODE_PTR(LOADK), |
| 36 | + OPCODE_PTR(LOADBOOL), |
| 37 | + OPCODE_PTR(LOADNIL), |
| 38 | + OPCODE_PTR(GETUPVAL), |
| 39 | + OPCODE_PTR(GETGLOBAL), |
| 40 | + OPCODE_PTR(GETTABLE), |
| 41 | + OPCODE_PTR(SETGLOBAL), |
| 42 | + OPCODE_PTR(SETUPVAL), |
| 43 | + OPCODE_PTR(SETTABLE), |
| 44 | + OPCODE_PTR(NEWTABLE), |
| 45 | + OPCODE_PTR(SELF), |
| 46 | + OPCODE_PTR(ADD), |
| 47 | + OPCODE_PTR(SUB), |
| 48 | + OPCODE_PTR(MUL), |
| 49 | + OPCODE_PTR(DIV), |
| 50 | + OPCODE_PTR(MOD), |
| 51 | + OPCODE_PTR(POW), |
| 52 | + OPCODE_PTR(UNM), |
| 53 | + OPCODE_PTR(NOT), |
| 54 | + OPCODE_PTR(LEN), |
| 55 | + OPCODE_PTR(CONCAT), |
| 56 | + OPCODE_PTR(JMP), |
| 57 | + OPCODE_PTR(EQ), |
| 58 | + OPCODE_PTR(LT), |
| 59 | + OPCODE_PTR(LE), |
| 60 | + OPCODE_PTR(TEST), |
| 61 | + OPCODE_PTR(TESTSET), |
| 62 | + OPCODE_PTR(CALL), |
| 63 | + OPCODE_PTR(TAILCALL), |
| 64 | + OPCODE_PTR(RETURN), |
| 65 | + OPCODE_PTR(FORLOOP), |
| 66 | + OPCODE_PTR(FORPREP), |
| 67 | + OPCODE_PTR(TFORLOOP), |
| 68 | + OPCODE_PTR(SETLIST), |
| 69 | + OPCODE_PTR(CLOSE), |
| 70 | + OPCODE_PTR(CLOSURE), |
| 71 | + OPCODE_PTR(VARARG) |
| 72 | + }; |
| 73 | +#endif |
| 74 | reentry: /* entry point */ |
| 75 | lua_assert(isLua(L->ci)); |
| 76 | pc = L->savedpc; |
| 77 | @@ -598,33 +652,33 @@ void luaV_execute (lua_State *L, int nex |
| 78 | lua_assert(base == L->base && L->base == L->ci->base); |
| 79 | lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); |
| 80 | lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); |
| 81 | - switch (GET_OPCODE(i)) { |
| 82 | - case OP_MOVE: { |
| 83 | + CALL_OPCODE(GET_OPCODE(i)) { |
| 84 | + OPCODE_TARGET(MOVE) { |
| 85 | setobjs2s(L, ra, RB(i)); |
| 86 | continue; |
| 87 | } |
| 88 | - case OP_LOADK: { |
| 89 | + OPCODE_TARGET(LOADK) { |
| 90 | setobj2s(L, ra, KBx(i)); |
| 91 | continue; |
| 92 | } |
| 93 | - case OP_LOADBOOL: { |
| 94 | + OPCODE_TARGET(LOADBOOL) { |
| 95 | setbvalue(ra, GETARG_B(i)); |
| 96 | if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ |
| 97 | continue; |
| 98 | } |
| 99 | - case OP_LOADNIL: { |
| 100 | + OPCODE_TARGET(LOADNIL) { |
| 101 | TValue *rb = RB(i); |
| 102 | do { |
| 103 | setnilvalue(rb--); |
| 104 | } while (rb >= ra); |
| 105 | continue; |
| 106 | } |
| 107 | - case OP_GETUPVAL: { |
| 108 | + OPCODE_TARGET(GETUPVAL) { |
| 109 | int b = GETARG_B(i); |
| 110 | setobj2s(L, ra, cl->upvals[b]->v); |
| 111 | continue; |
| 112 | } |
| 113 | - case OP_GETGLOBAL: { |
| 114 | + OPCODE_TARGET(GETGLOBAL) { |
| 115 | TValue g; |
| 116 | TValue *rb = KBx(i); |
| 117 | sethvalue(L, &g, cl->env); |
| 118 | @@ -632,88 +686,88 @@ void luaV_execute (lua_State *L, int nex |
| 119 | Protect(luaV_gettable(L, &g, rb, ra)); |
| 120 | continue; |
| 121 | } |
| 122 | - case OP_GETTABLE: { |
| 123 | + OPCODE_TARGET(GETTABLE) { |
| 124 | Protect(luaV_gettable(L, RB(i), RKC(i), ra)); |
| 125 | continue; |
| 126 | } |
| 127 | - case OP_SETGLOBAL: { |
| 128 | + OPCODE_TARGET(SETGLOBAL) { |
| 129 | TValue g; |
| 130 | sethvalue(L, &g, cl->env); |
| 131 | lua_assert(ttisstring(KBx(i))); |
| 132 | Protect(luaV_settable(L, &g, KBx(i), ra)); |
| 133 | continue; |
| 134 | } |
| 135 | - case OP_SETUPVAL: { |
| 136 | + OPCODE_TARGET(SETUPVAL) { |
| 137 | UpVal *uv = cl->upvals[GETARG_B(i)]; |
| 138 | setobj(L, uv->v, ra); |
| 139 | luaC_barrier(L, uv, ra); |
| 140 | continue; |
| 141 | } |
| 142 | - case OP_SETTABLE: { |
| 143 | + OPCODE_TARGET(SETTABLE) { |
| 144 | Protect(luaV_settable(L, ra, RKB(i), RKC(i))); |
| 145 | continue; |
| 146 | } |
| 147 | - case OP_NEWTABLE: { |
| 148 | + OPCODE_TARGET(NEWTABLE) { |
| 149 | int b = GETARG_B(i); |
| 150 | int c = GETARG_C(i); |
| 151 | sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); |
| 152 | Protect(luaC_checkGC(L)); |
| 153 | continue; |
| 154 | } |
| 155 | - case OP_SELF: { |
| 156 | + OPCODE_TARGET(SELF) { |
| 157 | StkId rb = RB(i); |
| 158 | setobjs2s(L, ra+1, rb); |
| 159 | Protect(luaV_gettable(L, rb, RKC(i), ra)); |
| 160 | continue; |
| 161 | } |
| 162 | - case OP_ADD: { |
| 163 | + OPCODE_TARGET(ADD) { |
| 164 | TValue *rb = RKB(i), *rc= RKC(i); |
| 165 | arith_op_continue( luai_numadd, try_addint, luai_vectadd ); |
| 166 | Protect(Arith(L, ra, rb, rc, TM_ADD)); \ |
| 167 | continue; |
| 168 | } |
| 169 | - case OP_SUB: { |
| 170 | + OPCODE_TARGET(SUB) { |
| 171 | TValue *rb = RKB(i), *rc= RKC(i); |
| 172 | arith_op_continue( luai_numsub, try_subint, luai_vectsub ); |
| 173 | Protect(Arith(L, ra, rb, rc, TM_SUB)); |
| 174 | continue; |
| 175 | } |
| 176 | - case OP_MUL: { |
| 177 | + OPCODE_TARGET(MUL) { |
| 178 | TValue *rb = RKB(i), *rc= RKC(i); |
| 179 | arith_op_continue(luai_nummul, try_mulint, luai_vectmul); |
| 180 | Protect(Arith(L, ra, rb, rc, TM_MUL)); |
| 181 | continue; |
| 182 | } |
| 183 | - case OP_DIV: { |
| 184 | + OPCODE_TARGET(DIV) { |
| 185 | TValue *rb = RKB(i), *rc= RKC(i); |
| 186 | arith_op_continue(luai_numdiv, try_divint, luai_vectdiv); |
| 187 | Protect(Arith(L, ra, rb, rc, TM_DIV)); |
| 188 | continue; |
| 189 | } |
| 190 | - case OP_MOD: { |
| 191 | + OPCODE_TARGET(MOD) { |
| 192 | TValue *rb = RKB(i), *rc= RKC(i); |
| 193 | arith_op_continue_scalar(luai_nummod, try_modint); /* scalars only */ |
| 194 | Protect(Arith(L, ra, rb, rc, TM_MOD)); |
| 195 | continue; |
| 196 | } |
| 197 | - case OP_POW: { |
| 198 | + OPCODE_TARGET(POW) { |
| 199 | TValue *rb = RKB(i), *rc= RKC(i); |
| 200 | arith_op_continue(luai_numpow, try_powint, luai_vectpow); |
| 201 | Protect(Arith(L, ra, rb, rc, TM_POW)); |
| 202 | continue; |
| 203 | } |
| 204 | - case OP_UNM: { |
| 205 | + OPCODE_TARGET(UNM) { |
| 206 | TValue *rb = RB(i); |
| 207 | arith_op1_continue(luai_numunm, try_unmint, luai_vectunm); |
| 208 | Protect(Arith(L, ra, rb, rb, TM_UNM)); |
| 209 | continue; |
| 210 | } |
| 211 | - case OP_NOT: { |
| 212 | + OPCODE_TARGET(NOT) { |
| 213 | int res = l_isfalse(RB(i)); /* next assignment may change this value */ |
| 214 | setbvalue(ra, res); |
| 215 | continue; |
| 216 | } |
| 217 | - case OP_LEN: { |
| 218 | + OPCODE_TARGET(LEN) { |
| 219 | const TValue *rb = RB(i); |
| 220 | switch (ttype(rb)) { |
| 221 | case LUA_TTABLE: { |
| 222 | @@ -733,18 +787,18 @@ void luaV_execute (lua_State *L, int nex |
| 223 | } |
| 224 | continue; |
| 225 | } |
| 226 | - case OP_CONCAT: { |
| 227 | + OPCODE_TARGET(CONCAT) { |
| 228 | int b = GETARG_B(i); |
| 229 | int c = GETARG_C(i); |
| 230 | Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); |
| 231 | setobjs2s(L, RA(i), base+b); |
| 232 | continue; |
| 233 | } |
| 234 | - case OP_JMP: { |
| 235 | + OPCODE_TARGET(JMP) { |
| 236 | dojump(L, pc, GETARG_sBx(i)); |
| 237 | continue; |
| 238 | } |
| 239 | - case OP_EQ: { |
| 240 | + OPCODE_TARGET(EQ) { |
| 241 | TValue *rb = RKB(i); |
| 242 | TValue *rc = RKC(i); |
| 243 | Protect( |
| 244 | @@ -754,7 +808,7 @@ void luaV_execute (lua_State *L, int nex |
| 245 | pc++; |
| 246 | continue; |
| 247 | } |
| 248 | - case OP_LT: { |
| 249 | + OPCODE_TARGET(LT) { |
| 250 | Protect( |
| 251 | if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) |
| 252 | dojump(L, pc, GETARG_sBx(*pc)); |
| 253 | @@ -762,7 +816,7 @@ void luaV_execute (lua_State *L, int nex |
| 254 | pc++; |
| 255 | continue; |
| 256 | } |
| 257 | - case OP_LE: { |
| 258 | + OPCODE_TARGET(LE) { |
| 259 | Protect( |
| 260 | if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) |
| 261 | dojump(L, pc, GETARG_sBx(*pc)); |
| 262 | @@ -770,13 +824,13 @@ void luaV_execute (lua_State *L, int nex |
| 263 | pc++; |
| 264 | continue; |
| 265 | } |
| 266 | - case OP_TEST: { |
| 267 | + OPCODE_TARGET(TEST) { |
| 268 | if (l_isfalse(ra) != GETARG_C(i)) |
| 269 | dojump(L, pc, GETARG_sBx(*pc)); |
| 270 | pc++; |
| 271 | continue; |
| 272 | } |
| 273 | - case OP_TESTSET: { |
| 274 | + OPCODE_TARGET(TESTSET) { |
| 275 | TValue *rb = RB(i); |
| 276 | if (l_isfalse(rb) != GETARG_C(i)) { |
| 277 | setobjs2s(L, ra, rb); |
| 278 | @@ -785,7 +839,7 @@ void luaV_execute (lua_State *L, int nex |
| 279 | pc++; |
| 280 | continue; |
| 281 | } |
| 282 | - case OP_CALL: { |
| 283 | + OPCODE_TARGET(CALL) { |
| 284 | int b = GETARG_B(i); |
| 285 | int nresults = GETARG_C(i) - 1; |
| 286 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ |
| 287 | @@ -806,7 +860,7 @@ void luaV_execute (lua_State *L, int nex |
| 288 | } |
| 289 | } |
| 290 | } |
| 291 | - case OP_TAILCALL: { |
| 292 | + OPCODE_TARGET(TAILCALL) { |
| 293 | int b = GETARG_B(i); |
| 294 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ |
| 295 | L->savedpc = pc; |
| 296 | @@ -838,7 +892,7 @@ void luaV_execute (lua_State *L, int nex |
| 297 | } |
| 298 | } |
| 299 | } |
| 300 | - case OP_RETURN: { |
| 301 | + OPCODE_TARGET(RETURN) { |
| 302 | int b = GETARG_B(i); |
| 303 | if (b != 0) L->top = ra+b-1; |
| 304 | if (L->openupval) luaF_close(L, base); |
| 305 | @@ -853,7 +907,7 @@ void luaV_execute (lua_State *L, int nex |
| 306 | goto reentry; |
| 307 | } |
| 308 | } |
| 309 | - case OP_FORLOOP: { |
| 310 | + OPCODE_TARGET(FORLOOP) { |
| 311 | /* If start,step and limit are all integers, we don't need to check |
| 312 | * against overflow in the looping. |
| 313 | */ |
| 314 | @@ -881,7 +935,7 @@ void luaV_execute (lua_State *L, int nex |
| 315 | } |
| 316 | continue; |
| 317 | } |
| 318 | - case OP_FORPREP: { |
| 319 | + OPCODE_TARGET(FORPREP) { |
| 320 | const TValue *init = ra; |
| 321 | const TValue *plimit = ra+1; |
| 322 | const TValue *pstep = ra+2; |
| 323 | @@ -904,7 +958,7 @@ void luaV_execute (lua_State *L, int nex |
| 324 | dojump(L, pc, GETARG_sBx(i)); |
| 325 | continue; |
| 326 | } |
| 327 | - case OP_TFORLOOP: { |
| 328 | + OPCODE_TARGET(TFORLOOP) { |
| 329 | StkId cb = ra + 3; /* call base */ |
| 330 | setobjs2s(L, cb+2, ra+2); |
| 331 | setobjs2s(L, cb+1, ra+1); |
| 332 | @@ -920,7 +974,7 @@ void luaV_execute (lua_State *L, int nex |
| 333 | pc++; |
| 334 | continue; |
| 335 | } |
| 336 | - case OP_SETLIST: { |
| 337 | + OPCODE_TARGET(SETLIST) { |
| 338 | int n = GETARG_B(i); |
| 339 | int c = GETARG_C(i); |
| 340 | int last; |
| 341 | @@ -942,11 +996,11 @@ void luaV_execute (lua_State *L, int nex |
| 342 | } |
| 343 | continue; |
| 344 | } |
| 345 | - case OP_CLOSE: { |
| 346 | + OPCODE_TARGET(CLOSE) { |
| 347 | luaF_close(L, ra); |
| 348 | continue; |
| 349 | } |
| 350 | - case OP_CLOSURE: { |
| 351 | + OPCODE_TARGET(CLOSURE) { |
| 352 | Proto *p; |
| 353 | Closure *ncl; |
| 354 | int nup, j; |
| 355 | @@ -966,7 +1020,7 @@ void luaV_execute (lua_State *L, int nex |
| 356 | Protect(luaC_checkGC(L)); |
| 357 | continue; |
| 358 | } |
| 359 | - case OP_VARARG: { |
| 360 | + OPCODE_TARGET(VARARG) { |
| 361 | int b = GETARG_B(i) - 1; |
| 362 | int j; |
| 363 | CallInfo *ci = L->ci; |