mirror of
git://git.openwrt.org/openwrt/openwrt.git
synced 2024-12-15 03:14:50 +00:00
8f98214617
SVN-Revision: 18136
364 lines
10 KiB
Diff
364 lines
10 KiB
Diff
--- 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.
|
|
@@ -562,12 +565,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;
|
|
@@ -592,33 +646,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);
|
|
@@ -626,88 +680,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: {
|
|
@@ -727,18 +781,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(
|
|
@@ -748,7 +802,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));
|
|
@@ -756,7 +810,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));
|
|
@@ -764,13 +818,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);
|
|
@@ -779,7 +833,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 */
|
|
@@ -800,7 +854,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;
|
|
@@ -832,7 +886,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);
|
|
@@ -847,7 +901,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.
|
|
*/
|
|
@@ -875,7 +929,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;
|
|
@@ -898,7 +952,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);
|
|
@@ -914,7 +968,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;
|
|
@@ -936,11 +990,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;
|
|
@@ -960,7 +1014,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;
|