summaryrefslogtreecommitdiff
path: root/src/lvm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lvm.c')
-rw-r--r--src/lvm.c334
1 files changed, 137 insertions, 197 deletions
diff --git a/src/lvm.c b/src/lvm.c
index a3150888..518a16ba 100644
--- a/src/lvm.c
+++ b/src/lvm.c
@@ -1,5 +1,5 @@
/*
-** $Id: lvm.c,v 2.102 2009/12/17 16:20:01 roberto Exp $
+** $Id: lvm.c,v 2.120 2010/05/13 19:53:05 roberto Exp $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -50,8 +50,8 @@ int luaV_tostring (lua_State *L, StkId obj) {
else {
char s[LUAI_MAXNUMBER2STR];
lua_Number n = nvalue(obj);
- lua_number2str(s, n);
- setsvalue2s(L, obj, luaS_new(L, s));
+ int l = lua_number2str(s, n);
+ setsvalue2s(L, obj, luaS_newlstr(L, s, l));
return 1;
}
}
@@ -74,6 +74,10 @@ static void traceexec (lua_State *L) {
luaD_hook(L, LUA_HOOKLINE, newline);
}
L->oldpc = ci->u.l.savedpc;
+ if (L->status == LUA_YIELD) { /* did hook yield? */
+ ci->u.l.savedpc--; /* undo increment (resume will increment it again) */
+ luaD_throw(L, LUA_YIELD);
+ }
}
@@ -102,7 +106,7 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
if (ttistable(t)) { /* `t' is a table? */
Table *h = hvalue(t);
const TValue *res = luaH_get(h, key); /* do a primitive get */
- if (!ttisnil(res) || /* result is no nil? */
+ if (!ttisnil(res) || /* result is not nil? */
(tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
setobj2s(L, val, res);
return;
@@ -129,7 +133,7 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
if (ttistable(t)) { /* `t' is a table? */
Table *h = hvalue(t);
TValue *oldval = luaH_set(L, h, key); /* do a primitive set */
- if (!ttisnil(oldval) || /* result is no nil? */
+ if (!ttisnil(oldval) || /* result is not nil? */
(tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
setobj2t(L, oldval, val);
luaC_barriert(L, h, val);
@@ -157,12 +161,13 @@ static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2,
if (ttisnil(tm))
tm = luaT_gettmbyobj(L, p2, event); /* try second operand */
if (ttisnil(tm)) return 0;
+ if (event == TM_UNM) p2 = luaO_nilobject;
callTM(L, tm, p1, p2, res, 1);
return 1;
}
-static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2,
+static const TValue *get_equalTM (lua_State *L, Table *mt1, Table *mt2,
TMS event) {
const TValue *tm1 = fasttm(L, mt1, event);
const TValue *tm2;
@@ -178,14 +183,10 @@ static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2,
static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2,
TMS event) {
- const TValue *tm1 = luaT_gettmbyobj(L, p1, event);
- const TValue *tm2;
- if (ttisnil(tm1)) return -1; /* no metamethod? */
- tm2 = luaT_gettmbyobj(L, p2, event);
- if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */
- return -1;
- callTM(L, tm1, p1, p2, L->top, 1);
- return !l_isfalse(L->top);
+ if (!call_binTM(L, p1, p2, L->top, event))
+ return -1; /* no metamethod */
+ else
+ return !l_isfalse(L->top);
}
@@ -213,11 +214,9 @@ static int l_strcmp (const TString *ls, const TString *rs) {
int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
int res;
- if (ttype(l) != ttype(r))
- return luaG_ordererror(L, l, r);
- else if (ttisnumber(l))
+ if (ttisnumber(l) && ttisnumber(r))
return luai_numlt(L, nvalue(l), nvalue(r));
- else if (ttisstring(l))
+ else if (ttisstring(l) && ttisstring(r))
return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
return res;
@@ -227,11 +226,9 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {
int res;
- if (ttype(l) != ttype(r))
- return luaG_ordererror(L, l, r);
- else if (ttisnumber(l))
+ if (ttisnumber(l) && ttisnumber(r))
return luai_numle(L, nvalue(l), nvalue(r));
- else if (ttisstring(l))
+ else if (ttisstring(l) && ttisstring(r))
return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */
return res;
@@ -249,14 +246,16 @@ int luaV_equalval_ (lua_State *L, const TValue *t1, const TValue *t2) {
case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));
case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */
case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
+ case LUA_TLCF: return fvalue(t1) == fvalue(t2);
+ case LUA_TSTRING: return eqstr(rawtsvalue(t1), rawtsvalue(t2));
case LUA_TUSERDATA: {
if (uvalue(t1) == uvalue(t2)) return 1;
- tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, TM_EQ);
+ tm = get_equalTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, TM_EQ);
break; /* will try TM */
}
case LUA_TTABLE: {
if (hvalue(t1) == hvalue(t2)) return 1;
- tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
+ tm = get_equalTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
break; /* will try TM */
}
default: return gcvalue(t1) == gcvalue(t2);
@@ -354,14 +353,10 @@ void luaV_finishOp (lua_State *L) {
StkId base = ci->u.l.base;
Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */
OpCode op = GET_OPCODE(inst);
- if (op == OP_EXTRAARG) { /* extra argument? */
- inst = *(ci->u.l.savedpc - 2); /* get its 'main' instruction */
- op = GET_OPCODE(inst);
- }
switch (op) { /* finish its execution */
case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV:
case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN:
- case OP_GETGLOBAL: case OP_GETTABLE: case OP_SELF: {
+ case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: {
setobjs2s(L, base + GETARG_A(inst), --L->top);
break;
}
@@ -402,7 +397,7 @@ void luaV_finishOp (lua_State *L) {
L->top = ci->top; /* adjust results */
break;
}
- case OP_TAILCALL: case OP_SETGLOBAL: case OP_SETTABLE:
+ case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE:
break;
default: lua_assert(0);
}
@@ -426,11 +421,13 @@ void luaV_finishOp (lua_State *L) {
(k + (GETARG_Bx(i) != 0 ? GETARG_Bx(i) - 1 : GETARG_Ax(*ci->u.l.savedpc++)))
-#define dojump(i) { ci->u.l.savedpc += (i); luai_threadyield(L);}
+#define dojump(i) (ci->u.l.savedpc += (i))
#define Protect(x) { {x;}; base = ci->u.l.base; }
+#define checkGC(L) Protect(luaC_checkGC(L); luai_threadyield(L);)
+
#define arith_op(op,tm) { \
TValue *rb = RKB(i); \
@@ -439,133 +436,109 @@ void luaV_finishOp (lua_State *L) {
lua_Number nb = nvalue(rb), nc = nvalue(rc); \
setnvalue(ra, op(L, nb, nc)); \
} \
- else \
- Protect(luaV_arith(L, ra, rb, rc, tm)); \
- }
+ else { Protect(luaV_arith(L, ra, rb, rc, tm)); } }
+#define vmdispatch(o) switch(o)
+#define vmcase(l,b) case l: {b} break;
void luaV_execute (lua_State *L) {
CallInfo *ci = L->ci;
- LClosure *cl = &clvalue(ci->func)->l;
- TValue *k = cl->p->k;
- StkId base = ci->u.l.base;
+ LClosure *cl;
+ TValue *k;
+ StkId base;
+ newframe: /* reentry point when frame changes (call/return) */
lua_assert(isLua(ci));
+ lua_assert(ci == L->ci);
+ cl = &clvalue(ci->func)->l;
+ k = cl->p->k;
+ base = ci->u.l.base;
/* main loop of interpreter */
for (;;) {
Instruction i = *(ci->u.l.savedpc++);
StkId ra;
if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
- traceexec(L);
- if (L->status == LUA_YIELD) { /* did hook yield? */
- ci->u.l.savedpc--; /* undo increment */
- luaD_throw(L, LUA_YIELD);
- }
- base = ci->u.l.base;
+ Protect(traceexec(L));
}
/* warning!! several calls may realloc the stack and invalidate `ra' */
ra = RA(i);
lua_assert(base == ci->u.l.base);
lua_assert(base <= L->top && L->top < L->stack + L->stacksize);
- switch (GET_OPCODE(i)) {
- case OP_MOVE: {
+ vmdispatch (GET_OPCODE(i)) {
+ vmcase(OP_MOVE,
setobjs2s(L, ra, RB(i));
- continue;
- }
- case OP_LOADK: {
+ )
+ vmcase(OP_LOADK,
TValue *rb = KBx(i);
setobj2s(L, ra, rb);
- continue;
- }
- case OP_LOADBOOL: {
+ )
+ vmcase(OP_LOADBOOL,
setbvalue(ra, GETARG_B(i));
if (GETARG_C(i)) ci->u.l.savedpc++; /* skip next instruction (if C) */
- continue;
- }
- case OP_LOADNIL: {
+ )
+ vmcase(OP_LOADNIL,
TValue *rb = RB(i);
do {
setnilvalue(rb--);
} while (rb >= ra);
- continue;
- }
- case OP_GETUPVAL: {
+ )
+ vmcase(OP_GETUPVAL,
int b = GETARG_B(i);
setobj2s(L, ra, cl->upvals[b]->v);
- continue;
- }
- case OP_GETGLOBAL: {
- TValue g;
- TValue *rb = KBx(i);
- sethvalue(L, &g, cl->env);
- lua_assert(ttisstring(rb));
- Protect(luaV_gettable(L, &g, rb, ra));
- continue;
- }
- case OP_GETTABLE: {
+ )
+ vmcase(OP_GETTABUP,
+ int b = GETARG_B(i);
+ Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra));
+ )
+ vmcase(OP_GETTABLE,
Protect(luaV_gettable(L, RB(i), RKC(i), ra));
- continue;
- }
- case OP_SETGLOBAL: {
- TValue g;
- TValue *rb = KBx(i);
- sethvalue(L, &g, cl->env);
- lua_assert(ttisstring(rb));
- Protect(luaV_settable(L, &g, rb, ra));
- continue;
- }
- case OP_SETUPVAL: {
+ )
+ vmcase(OP_SETTABUP,
+ int a = GETARG_A(i);
+ Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i)));
+ )
+ vmcase(OP_SETUPVAL,
UpVal *uv = cl->upvals[GETARG_B(i)];
setobj(L, uv->v, ra);
luaC_barrier(L, uv, ra);
- continue;
- }
- case OP_SETTABLE: {
+ )
+ vmcase(OP_SETTABLE,
Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
- continue;
- }
- case OP_NEWTABLE: {
+ )
+ vmcase(OP_NEWTABLE,
int b = GETARG_B(i);
int c = GETARG_C(i);
Table *t = luaH_new(L);
sethvalue(L, ra, t);
if (b != 0 || c != 0)
luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c));
- Protect(luaC_checkGC(L));
- continue;
- }
- case OP_SELF: {
+ checkGC(L);
+ )
+ vmcase(OP_SELF,
StkId rb = RB(i);
setobjs2s(L, ra+1, rb);
Protect(luaV_gettable(L, rb, RKC(i), ra));
- continue;
- }
- case OP_ADD: {
+ )
+ vmcase(OP_ADD,
arith_op(luai_numadd, TM_ADD);
- continue;
- }
- case OP_SUB: {
+ )
+ vmcase(OP_SUB,
arith_op(luai_numsub, TM_SUB);
- continue;
- }
- case OP_MUL: {
+ )
+ vmcase(OP_MUL,
arith_op(luai_nummul, TM_MUL);
- continue;
- }
- case OP_DIV: {
+ )
+ vmcase(OP_DIV,
arith_op(luai_numdiv, TM_DIV);
- continue;
- }
- case OP_MOD: {
+ )
+ vmcase(OP_MOD,
arith_op(luai_nummod, TM_MOD);
- continue;
- }
- case OP_POW: {
+ )
+ vmcase(OP_POW,
arith_op(luai_numpow, TM_POW);
- continue;
- }
- case OP_UNM: {
+ )
+ vmcase(OP_UNM,
TValue *rb = RB(i);
if (ttisnumber(rb)) {
lua_Number nb = nvalue(rb);
@@ -574,31 +547,26 @@ void luaV_execute (lua_State *L) {
else {
Protect(luaV_arith(L, ra, rb, rb, TM_UNM));
}
- continue;
- }
- case OP_NOT: {
+ )
+ vmcase(OP_NOT,
int res = l_isfalse(RB(i)); /* next assignment may change this value */
setbvalue(ra, res);
- continue;
- }
- case OP_LEN: {
+ )
+ vmcase(OP_LEN,
Protect(luaV_objlen(L, ra, RB(i)));
- continue;
- }
- case OP_CONCAT: {
+ )
+ vmcase(OP_CONCAT,
int b = GETARG_B(i);
int c = GETARG_C(i);
L->top = base + c + 1; /* mark the end of concat operands */
- Protect(luaV_concat(L, c-b+1); luaC_checkGC(L));
+ Protect(luaV_concat(L, c-b+1); checkGC(L);)
L->top = ci->top; /* restore top */
setobjs2s(L, RA(i), base+b);
- continue;
- }
- case OP_JMP: {
+ )
+ vmcase(OP_JMP,
dojump(GETARG_sBx(i));
- continue;
- }
- case OP_EQ: {
+ )
+ vmcase(OP_EQ,
TValue *rb = RKB(i);
TValue *rc = RKC(i);
Protect(
@@ -606,62 +574,54 @@ void luaV_execute (lua_State *L) {
dojump(GETARG_sBx(*ci->u.l.savedpc));
)
ci->u.l.savedpc++;
- continue;
- }
- case OP_LT: {
+ )
+ vmcase(OP_LT,
Protect(
if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i))
dojump(GETARG_sBx(*ci->u.l.savedpc));
)
ci->u.l.savedpc++;
- continue;
- }
- case OP_LE: {
+ )
+ vmcase(OP_LE,
Protect(
if (luaV_lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))
dojump(GETARG_sBx(*ci->u.l.savedpc));
)
ci->u.l.savedpc++;
- continue;
- }
- case OP_TEST: {
+ )
+ vmcase(OP_TEST,
if (GETARG_C(i) ? !l_isfalse(ra) : l_isfalse(ra))
dojump(GETARG_sBx(*ci->u.l.savedpc));
ci->u.l.savedpc++;
- continue;
- }
- case OP_TESTSET: {
+ )
+ vmcase(OP_TESTSET,
TValue *rb = RB(i);
if (GETARG_C(i) ? !l_isfalse(rb) : l_isfalse(rb)) {
setobjs2s(L, ra, rb);
dojump(GETARG_sBx(*ci->u.l.savedpc));
}
ci->u.l.savedpc++;
- continue;
- }
- case OP_CALL: {
+ )
+ vmcase(OP_CALL,
int b = GETARG_B(i);
int nresults = GETARG_C(i) - 1;
if (b != 0) L->top = ra+b; /* else previous instruction set top */
if (luaD_precall(L, ra, nresults)) { /* C function? */
if (nresults >= 0) L->top = ci->top; /* adjust results */
base = ci->u.l.base;
- continue;
}
else { /* Lua function */
ci = L->ci;
ci->callstatus |= CIST_REENTRY;
- break; /* restart luaV_execute over new Lua function */
+ goto newframe; /* restart luaV_execute over new Lua function */
}
- }
- case OP_TAILCALL: {
+ )
+ vmcase(OP_TAILCALL,
int b = GETARG_B(i);
if (b != 0) L->top = ra+b; /* else previous instruction set top */
lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
- if (luaD_precall(L, ra, LUA_MULTRET)) { /* C function? */
+ if (luaD_precall(L, ra, LUA_MULTRET)) /* C function? */
base = ci->u.l.base;
- continue;
- }
else {
/* tail call: put called frame (n) in place of caller one (o) */
CallInfo *nci = L->ci; /* called frame */
@@ -682,10 +642,10 @@ void luaV_execute (lua_State *L) {
oci->callstatus |= CIST_TAIL; /* function was tail called */
ci = L->ci = oci; /* remove new frame */
lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize);
- break; /* restart luaV_execute over new Lua function */
+ goto newframe; /* restart luaV_execute over new Lua function */
}
- }
- case OP_RETURN: {
+ )
+ vmcase(OP_RETURN,
int b = GETARG_B(i);
if (b != 0) L->top = ra+b-1;
if (cl->p->sizep > 0) luaF_close(L, base);
@@ -697,10 +657,10 @@ void luaV_execute (lua_State *L) {
if (b) L->top = ci->top;
lua_assert(isLua(ci));
lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL);
- break; /* restart luaV_execute over new Lua function */
+ goto newframe; /* restart luaV_execute over new Lua function */
}
- }
- case OP_FORLOOP: {
+ )
+ vmcase(OP_FORLOOP,
lua_Number step = nvalue(ra+2);
lua_Number idx = luai_numadd(L, nvalue(ra), step); /* increment index */
lua_Number limit = nvalue(ra+1);
@@ -710,9 +670,8 @@ void luaV_execute (lua_State *L) {
setnvalue(ra, idx); /* update internal index... */
setnvalue(ra+3, idx); /* ...and external index */
}
- continue;
- }
- case OP_FORPREP: {
+ )
+ vmcase(OP_FORPREP,
const TValue *init = ra;
const TValue *plimit = ra+1;
const TValue *pstep = ra+2;
@@ -724,9 +683,8 @@ void luaV_execute (lua_State *L) {
luaG_runerror(L, LUA_QL("for") " step must be a number");
setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep)));
dojump(GETARG_sBx(i));
- continue;
- }
- case OP_TFORCALL: {
+ )
+ vmcase(OP_TFORCALL,
StkId cb = ra + 3; /* call base */
setobjs2s(L, cb+2, ra+2);
setobjs2s(L, cb+1, ra+1);
@@ -737,16 +695,16 @@ void luaV_execute (lua_State *L) {
i = *(ci->u.l.savedpc++); /* go to next instruction */
ra = RA(i);
lua_assert(GET_OPCODE(i) == OP_TFORLOOP);
- /* go through */
- }
- case OP_TFORLOOP: {
+ goto l_tforloop;
+ )
+ vmcase(OP_TFORLOOP,
+ l_tforloop:
if (!ttisnil(ra + 1)) { /* continue loop? */
setobjs2s(L, ra, ra + 1); /* save control variable */
dojump(GETARG_sBx(i)); /* jump back */
}
- continue;
- }
- case OP_SETLIST: {
+ )
+ vmcase(OP_SETLIST,
int n = GETARG_B(i);
int c = GETARG_C(i);
int last;
@@ -759,45 +717,34 @@ void luaV_execute (lua_State *L) {
h = hvalue(ra);
last = ((c-1)*LFIELDS_PER_FLUSH) + n;
if (last > h->sizearray) /* needs more space? */
- luaH_resizearray(L, h, last); /* pre-alloc it at once */
+ luaH_resizearray(L, h, last); /* pre-allocate it at once */
for (; n > 0; n--) {
TValue *val = ra+n;
setobj2t(L, luaH_setint(L, h, last--), val);
luaC_barriert(L, h, val);
}
L->top = ci->top; /* correct top (in case of previous open call) */
- continue;
- }
- case OP_CLOSE: {
+ )
+ vmcase(OP_CLOSE,
luaF_close(L, ra);
- continue;
- }
- case OP_CLOSURE: {
+ )
+ vmcase(OP_CLOSURE,
Proto *p = cl->p->p[GETARG_Bx(i)]; /* prototype for new closure */
int nup = p->sizeupvalues;
- Closure *ncl = luaF_newLclosure(L, nup, cl->env);
+ Closure *ncl = luaF_newLclosure(L, nup);
Upvaldesc *uv = p->upvalues;
int j;
ncl->l.p = p;
setclvalue(L, ra, ncl); /* anchor new closure in stack */
- if (p->envreg != NO_REG) { /* lexical environment? */
- StkId env = base + p->envreg;
- if (!ttistable(env))
- luaG_runerror(L, "environment is not a table: "
- "cannot create closure");
- else
- ncl->l.env = hvalue(env);
- }
for (j = 0; j < nup; j++) { /* fill in upvalues */
if (uv[j].instack) /* upvalue refers to local variable? */
ncl->l.upvals[j] = luaF_findupval(L, base + uv[j].idx);
else /* get upvalue from enclosing function */
ncl->l.upvals[j] = cl->upvals[uv[j].idx];
}
- Protect(luaC_checkGC(L));
- continue;
- }
- case OP_VARARG: {
+ checkGC(L);
+ )
+ vmcase(OP_VARARG,
int b = GETARG_B(i) - 1;
int j;
int n = cast_int(base - ci->func) - cl->p->numparams - 1;
@@ -815,18 +762,11 @@ void luaV_execute (lua_State *L) {
setnilvalue(ra + j);
}
}
- continue;
- }
- case OP_EXTRAARG: {
- luaG_runerror(L, "bad opcode");
- return;
- }
+ )
+ vmcase(OP_EXTRAARG,
+ lua_assert(0);
+ )
}
- /* function changed (call/return): update pointers */
- lua_assert(ci == L->ci);
- cl = &clvalue(ci->func)->l;
- k = cl->p->k;
- base = ci->u.l.base;
}
}