--- a/src/lvm.c +++ b/src/lvm.c @@ -31,6 +31,9 @@ /* limit for table tag-method chains (to avoid loops) */ #define MAXTAGLOOP 100 +#ifdef __GNUC__ +#define COMPUTED_GOTO 1 +#endif /* * If 'obj' is a string, it is tried to be interpreted as a number. @@ -566,12 +569,63 @@ static inline int arith_mode( const TVal ARITH_OP1_END #endif +#ifdef COMPUTED_GOTO +#define OPCODE_TARGET(op) DO_OP_##op: +#define CALL_OPCODE(op) goto *opcodes[op]; +#define OPCODE_PTR(op) [OP_##op] = &&DO_OP_##op +#else +#define OPCODE_TARGET(op) case OP_##op: +#define CALL_OPCODE(op) switch (op) +#endif + void luaV_execute (lua_State *L, int nexeccalls) { LClosure *cl; StkId base; TValue *k; const Instruction *pc; +#ifdef COMPUTED_GOTO + static const void *opcodes[] = { + OPCODE_PTR(MOVE), + OPCODE_PTR(LOADK), + OPCODE_PTR(LOADBOOL), + OPCODE_PTR(LOADNIL), + OPCODE_PTR(GETUPVAL), + OPCODE_PTR(GETGLOBAL), + OPCODE_PTR(GETTABLE), + OPCODE_PTR(SETGLOBAL), + OPCODE_PTR(SETUPVAL), + OPCODE_PTR(SETTABLE), + OPCODE_PTR(NEWTABLE), + OPCODE_PTR(SELF), + OPCODE_PTR(ADD), + OPCODE_PTR(SUB), + OPCODE_PTR(MUL), + OPCODE_PTR(DIV), + OPCODE_PTR(MOD), + OPCODE_PTR(POW), + OPCODE_PTR(UNM), + OPCODE_PTR(NOT), + OPCODE_PTR(LEN), + OPCODE_PTR(CONCAT), + OPCODE_PTR(JMP), + OPCODE_PTR(EQ), + OPCODE_PTR(LT), + OPCODE_PTR(LE), + OPCODE_PTR(TEST), + OPCODE_PTR(TESTSET), + OPCODE_PTR(CALL), + OPCODE_PTR(TAILCALL), + OPCODE_PTR(RETURN), + OPCODE_PTR(FORLOOP), + OPCODE_PTR(FORPREP), + OPCODE_PTR(TFORLOOP), + OPCODE_PTR(SETLIST), + OPCODE_PTR(CLOSE), + OPCODE_PTR(CLOSURE), + OPCODE_PTR(VARARG) + }; +#endif reentry: /* entry point */ lua_assert(isLua(L->ci)); pc = L->savedpc; @@ -596,33 +650,33 @@ void luaV_execute (lua_State *L, int nex lua_assert(base == L->base && L->base == L->ci->base); lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); - switch (GET_OPCODE(i)) { - case OP_MOVE: { + CALL_OPCODE(GET_OPCODE(i)) { + OPCODE_TARGET(MOVE) { setobjs2s(L, ra, RB(i)); continue; } - case OP_LOADK: { + OPCODE_TARGET(LOADK) { setobj2s(L, ra, KBx(i)); continue; } - case OP_LOADBOOL: { + OPCODE_TARGET(LOADBOOL) { setbvalue(ra, GETARG_B(i)); if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ continue; } - case OP_LOADNIL: { + OPCODE_TARGET(LOADNIL) { TValue *rb = RB(i); do { setnilvalue(rb--); } while (rb >= ra); continue; } - case OP_GETUPVAL: { + OPCODE_TARGET(GETUPVAL) { int b = GETARG_B(i); setobj2s(L, ra, cl->upvals[b]->v); continue; } - case OP_GETGLOBAL: { + OPCODE_TARGET(GETGLOBAL) { TValue g; TValue *rb = KBx(i); sethvalue(L, &g, cl->env); @@ -630,88 +684,88 @@ void luaV_execute (lua_State *L, int nex Protect(luaV_gettable(L, &g, rb, ra)); continue; } - case OP_GETTABLE: { + OPCODE_TARGET(GETTABLE) { Protect(luaV_gettable(L, RB(i), RKC(i), ra)); continue; } - case OP_SETGLOBAL: { + OPCODE_TARGET(SETGLOBAL) { TValue g; sethvalue(L, &g, cl->env); lua_assert(ttisstring(KBx(i))); Protect(luaV_settable(L, &g, KBx(i), ra)); continue; } - case OP_SETUPVAL: { + OPCODE_TARGET(SETUPVAL) { UpVal *uv = cl->upvals[GETARG_B(i)]; setobj(L, uv->v, ra); luaC_barrier(L, uv, ra); continue; } - case OP_SETTABLE: { + OPCODE_TARGET(SETTABLE) { Protect(luaV_settable(L, ra, RKB(i), RKC(i))); continue; } - case OP_NEWTABLE: { + OPCODE_TARGET(NEWTABLE) { int b = GETARG_B(i); int c = GETARG_C(i); sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); Protect(luaC_checkGC(L)); continue; } - case OP_SELF: { + OPCODE_TARGET(SELF) { StkId rb = RB(i); setobjs2s(L, ra+1, rb); Protect(luaV_gettable(L, rb, RKC(i), ra)); continue; } - case OP_ADD: { + OPCODE_TARGET(ADD) { TValue *rb = RKB(i), *rc= RKC(i); arith_op_continue( luai_numadd, try_addint, luai_vectadd ); Protect(Arith(L, ra, rb, rc, TM_ADD)); \ continue; } - case OP_SUB: { + OPCODE_TARGET(SUB) { TValue *rb = RKB(i), *rc= RKC(i); arith_op_continue( luai_numsub, try_subint, luai_vectsub ); Protect(Arith(L, ra, rb, rc, TM_SUB)); continue; } - case OP_MUL: { + OPCODE_TARGET(MUL) { TValue *rb = RKB(i), *rc= RKC(i); arith_op_continue(luai_nummul, try_mulint, luai_vectmul); Protect(Arith(L, ra, rb, rc, TM_MUL)); continue; } - case OP_DIV: { + OPCODE_TARGET(DIV) { TValue *rb = RKB(i), *rc= RKC(i); arith_op_continue(luai_numdiv, try_divint, luai_vectdiv); Protect(Arith(L, ra, rb, rc, TM_DIV)); continue; } - case OP_MOD: { + OPCODE_TARGET(MOD) { TValue *rb = RKB(i), *rc= RKC(i); arith_op_continue_scalar(luai_nummod, try_modint); /* scalars only */ Protect(Arith(L, ra, rb, rc, TM_MOD)); continue; } - case OP_POW: { + OPCODE_TARGET(POW) { TValue *rb = RKB(i), *rc= RKC(i); arith_op_continue(luai_numpow, try_powint, luai_vectpow); Protect(Arith(L, ra, rb, rc, TM_POW)); continue; } - case OP_UNM: { + OPCODE_TARGET(UNM) { TValue *rb = RB(i); arith_op1_continue(luai_numunm, try_unmint, luai_vectunm); Protect(Arith(L, ra, rb, rb, TM_UNM)); continue; } - case OP_NOT: { + OPCODE_TARGET(NOT) { int res = l_isfalse(RB(i)); /* next assignment may change this value */ setbvalue(ra, res); continue; } - case OP_LEN: { + OPCODE_TARGET(LEN) { const TValue *rb = RB(i); switch (ttype(rb)) { case LUA_TTABLE: { @@ -731,18 +785,18 @@ void luaV_execute (lua_State *L, int nex } continue; } - case OP_CONCAT: { + OPCODE_TARGET(CONCAT) { int b = GETARG_B(i); int c = GETARG_C(i); Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); setobjs2s(L, RA(i), base+b); continue; } - case OP_JMP: { + OPCODE_TARGET(JMP) { dojump(L, pc, GETARG_sBx(i)); continue; } - case OP_EQ: { + OPCODE_TARGET(EQ) { TValue *rb = RKB(i); TValue *rc = RKC(i); Protect( @@ -752,7 +806,7 @@ void luaV_execute (lua_State *L, int nex pc++; continue; } - case OP_LT: { + OPCODE_TARGET(LT) { Protect( if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) dojump(L, pc, GETARG_sBx(*pc)); @@ -760,7 +814,7 @@ void luaV_execute (lua_State *L, int nex pc++; continue; } - case OP_LE: { + OPCODE_TARGET(LE) { Protect( if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) dojump(L, pc, GETARG_sBx(*pc)); @@ -768,13 +822,13 @@ void luaV_execute (lua_State *L, int nex pc++; continue; } - case OP_TEST: { + OPCODE_TARGET(TEST) { if (l_isfalse(ra) != GETARG_C(i)) dojump(L, pc, GETARG_sBx(*pc)); pc++; continue; } - case OP_TESTSET: { + OPCODE_TARGET(TESTSET) { TValue *rb = RB(i); if (l_isfalse(rb) != GETARG_C(i)) { setobjs2s(L, ra, rb); @@ -783,7 +837,7 @@ void luaV_execute (lua_State *L, int nex pc++; continue; } - case OP_CALL: { + OPCODE_TARGET(CALL) { int b = GETARG_B(i); int nresults = GETARG_C(i) - 1; if (b != 0) L->top = ra+b; /* else previous instruction set top */ @@ -804,7 +858,7 @@ void luaV_execute (lua_State *L, int nex } } } - case OP_TAILCALL: { + OPCODE_TARGET(TAILCALL) { int b = GETARG_B(i); if (b != 0) L->top = ra+b; /* else previous instruction set top */ L->savedpc = pc; @@ -836,7 +890,7 @@ void luaV_execute (lua_State *L, int nex } } } - case OP_RETURN: { + OPCODE_TARGET(RETURN) { int b = GETARG_B(i); if (b != 0) L->top = ra+b-1; if (L->openupval) luaF_close(L, base); @@ -851,7 +905,7 @@ void luaV_execute (lua_State *L, int nex goto reentry; } } - case OP_FORLOOP: { + OPCODE_TARGET(FORLOOP) { /* If start,step and limit are all integers, we don't need to check * against overflow in the looping. */ @@ -879,7 +933,7 @@ void luaV_execute (lua_State *L, int nex } continue; } - case OP_FORPREP: { + OPCODE_TARGET(FORPREP) { const TValue *init = ra; const TValue *plimit = ra+1; const TValue *pstep = ra+2; @@ -902,7 +956,7 @@ void luaV_execute (lua_State *L, int nex dojump(L, pc, GETARG_sBx(i)); continue; } - case OP_TFORLOOP: { + OPCODE_TARGET(TFORLOOP) { StkId cb = ra + 3; /* call base */ setobjs2s(L, cb+2, ra+2); setobjs2s(L, cb+1, ra+1); @@ -918,7 +972,7 @@ void luaV_execute (lua_State *L, int nex pc++; continue; } - case OP_SETLIST: { + OPCODE_TARGET(SETLIST) { int n = GETARG_B(i); int c = GETARG_C(i); int last; @@ -940,11 +994,11 @@ void luaV_execute (lua_State *L, int nex } continue; } - case OP_CLOSE: { + OPCODE_TARGET(CLOSE) { luaF_close(L, ra); continue; } - case OP_CLOSURE: { + OPCODE_TARGET(CLOSURE) { Proto *p; Closure *ncl; int nup, j; @@ -964,7 +1018,7 @@ void luaV_execute (lua_State *L, int nex Protect(luaC_checkGC(L)); continue; } - case OP_VARARG: { + OPCODE_TARGET(VARARG) { int b = GETARG_B(i) - 1; int j; CallInfo *ci = L->ci;