mirror of
https://github.com/lua/lua.git
synced 2025-01-28 06:03:00 +08:00
'luaV_execute' keeps local copy of program counter and hook mask,
to avoid excessive access to globals.
This commit is contained in:
parent
4ce8d2047c
commit
e8757a73e6
91
lvm.c
91
lvm.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lvm.c,v 2.275 2017/04/30 20:43:26 roberto Exp roberto $
|
||||
** $Id: lvm.c,v 2.276 2017/05/04 13:32:01 roberto Exp roberto $
|
||||
** Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -742,17 +742,37 @@ void luaV_finishOp (lua_State *L) {
|
||||
ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i))
|
||||
|
||||
|
||||
/* execute a jump instruction */
|
||||
|
||||
#define updatemask(L) (mask = L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT))
|
||||
|
||||
|
||||
/*
|
||||
** Execute a jump instruction. The 'updatemask' allows signals to stop
|
||||
** tight loops. (Without it, the local copy of 'mask' could never change.)
|
||||
*/
|
||||
#define dojump(ci,i,e) \
|
||||
{ int a = GETARG_A(i); \
|
||||
if (a != 0) luaF_close(L, ci->u.l.base + a - 1); \
|
||||
ci->u.l.savedpc += GETARG_sBx(i) + e; }
|
||||
pc += GETARG_sBx(i) + e; updatemask(L); }
|
||||
|
||||
|
||||
/* for test instructions, execute the jump instruction that follows it */
|
||||
#define donextjump(ci) { i = *ci->u.l.savedpc; dojump(ci, i, 1); }
|
||||
#define donextjump(ci) { i = *pc; dojump(ci, i, 1); }
|
||||
|
||||
/*
|
||||
** Whenever code can raise errors (including memory errors), the global
|
||||
** 'pc' must be correct to report occasional errors.
|
||||
*/
|
||||
#define savepc(L) (ci->u.l.savedpc = pc)
|
||||
|
||||
|
||||
#define Protect(x) { {x;}; base = ci->u.l.base; }
|
||||
/*
|
||||
** Protect code that, in general, can raise errors, reallocate the
|
||||
** stack, and change the hooks.
|
||||
*/
|
||||
#define Protect(code) \
|
||||
{ savepc(L); {code;}; base = ci->u.l.base; updatemask(L); }
|
||||
|
||||
|
||||
#define checkGC(L,c) \
|
||||
{ luaC_condGC(L, L->top = (c), /* limit of live values */ \
|
||||
@ -762,12 +782,9 @@ void luaV_finishOp (lua_State *L) {
|
||||
|
||||
/* fetch an instruction and prepare its execution */
|
||||
#define vmfetch() { \
|
||||
i = *(ci->u.l.savedpc++); \
|
||||
if (L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) \
|
||||
Protect(luaG_traceexec(L)); \
|
||||
i = *(pc++); \
|
||||
if (mask) Protect(luaG_traceexec(L)); \
|
||||
ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \
|
||||
lua_assert(base == ci->u.l.base); \
|
||||
lua_assert(base <= L->top && L->top < L->stack + L->stacksize); \
|
||||
}
|
||||
|
||||
#define vmdispatch(o) switch(o)
|
||||
@ -795,18 +812,24 @@ void luaV_execute (lua_State *L) {
|
||||
CallInfo *ci = L->ci;
|
||||
LClosure *cl;
|
||||
TValue *k;
|
||||
StkId base;
|
||||
StkId base; /* local copy of 'ci->u.l.base' */
|
||||
int mask; /* local copy of 'L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)' */
|
||||
const Instruction *pc; /* local copy of 'ci->u.l.savedpc' */
|
||||
ci->callstatus |= CIST_FRESH; /* fresh invocation of 'luaV_execute" */
|
||||
newframe: /* reentry point when frame changes (call/return) */
|
||||
lua_assert(ci == L->ci);
|
||||
cl = clLvalue(ci->func); /* local reference to function's closure */
|
||||
k = cl->p->k; /* local reference to function's constant table */
|
||||
base = ci->u.l.base; /* local copy of function's base */
|
||||
updatemask(L);
|
||||
base = ci->u.l.base;
|
||||
pc = ci->u.l.savedpc;
|
||||
/* main loop of interpreter */
|
||||
for (;;) {
|
||||
Instruction i;
|
||||
StkId ra;
|
||||
vmfetch();
|
||||
lua_assert(base == ci->u.l.base);
|
||||
lua_assert(base <= L->top && L->top < L->stack + L->stacksize);
|
||||
vmdispatch (GET_OPCODE(i)) {
|
||||
vmcase(OP_MOVE) {
|
||||
setobjs2s(L, ra, RB(i));
|
||||
@ -824,14 +847,14 @@ void luaV_execute (lua_State *L) {
|
||||
}
|
||||
vmcase(OP_LOADKX) {
|
||||
TValue *rb;
|
||||
lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG);
|
||||
rb = k + GETARG_Ax(*ci->u.l.savedpc++);
|
||||
lua_assert(GET_OPCODE(*pc) == OP_EXTRAARG);
|
||||
rb = k + GETARG_Ax(*pc++);
|
||||
setobj2s(L, ra, rb);
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_LOADBOOL) {
|
||||
setbvalue(ra, GETARG_B(i));
|
||||
if (GETARG_C(i)) ci->u.l.savedpc++; /* skip next instruction (if C) */
|
||||
if (GETARG_C(i)) pc++; /* skip next instruction (if C) */
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_LOADNIL) {
|
||||
@ -933,7 +956,9 @@ void luaV_execute (lua_State *L) {
|
||||
vmcase(OP_NEWTABLE) {
|
||||
int b = GETARG_B(i);
|
||||
int c = GETARG_C(i);
|
||||
Table *t = luaH_new(L);
|
||||
Table *t;
|
||||
savepc(L); /* in case of allocation errors */
|
||||
t = luaH_new(L);
|
||||
sethvalue(L, ra, t);
|
||||
if (b != 0 || c != 0)
|
||||
luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c));
|
||||
@ -1173,7 +1198,7 @@ void luaV_execute (lua_State *L) {
|
||||
TValue *rc = RKC(i);
|
||||
Protect(
|
||||
if (luaV_equalobj(L, rb, rc) != GETARG_A(i))
|
||||
ci->u.l.savedpc++;
|
||||
pc++;
|
||||
else
|
||||
donextjump(ci);
|
||||
)
|
||||
@ -1182,7 +1207,7 @@ void luaV_execute (lua_State *L) {
|
||||
vmcase(OP_LT) {
|
||||
Protect(
|
||||
if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i))
|
||||
ci->u.l.savedpc++;
|
||||
pc++;
|
||||
else
|
||||
donextjump(ci);
|
||||
)
|
||||
@ -1191,7 +1216,7 @@ void luaV_execute (lua_State *L) {
|
||||
vmcase(OP_LE) {
|
||||
Protect(
|
||||
if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i))
|
||||
ci->u.l.savedpc++;
|
||||
pc++;
|
||||
else
|
||||
donextjump(ci);
|
||||
)
|
||||
@ -1199,7 +1224,7 @@ void luaV_execute (lua_State *L) {
|
||||
}
|
||||
vmcase(OP_TEST) {
|
||||
if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra))
|
||||
ci->u.l.savedpc++;
|
||||
pc++;
|
||||
else
|
||||
donextjump(ci);
|
||||
vmbreak;
|
||||
@ -1207,7 +1232,7 @@ void luaV_execute (lua_State *L) {
|
||||
vmcase(OP_TESTSET) {
|
||||
TValue *rb = RB(i);
|
||||
if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb))
|
||||
ci->u.l.savedpc++;
|
||||
pc++;
|
||||
else {
|
||||
setobjs2s(L, ra, rb);
|
||||
donextjump(ci);
|
||||
@ -1218,6 +1243,7 @@ void luaV_execute (lua_State *L) {
|
||||
int b = GETARG_B(i);
|
||||
int nresults = GETARG_C(i) - 1;
|
||||
if (b != 0) L->top = ra+b; /* else previous instruction set top */
|
||||
savepc(L);
|
||||
if (luaD_precall(L, ra, nresults)) { /* C function? */
|
||||
if (nresults >= 0)
|
||||
L->top = ci->top; /* adjust results */
|
||||
@ -1233,6 +1259,7 @@ void luaV_execute (lua_State *L) {
|
||||
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);
|
||||
savepc(L);
|
||||
if (luaD_precall(L, ra, LUA_MULTRET)) { /* C function? */
|
||||
Protect((void)0); /* update 'base' */
|
||||
}
|
||||
@ -1263,6 +1290,7 @@ void luaV_execute (lua_State *L) {
|
||||
vmcase(OP_RETURN) {
|
||||
int b = GETARG_B(i);
|
||||
if (cl->p->sizep > 0) luaF_close(L, base);
|
||||
savepc(L);
|
||||
b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra)));
|
||||
if (ci->callstatus & CIST_FRESH) /* local 'ci' still from callee */
|
||||
return; /* external invocation: return */
|
||||
@ -1280,7 +1308,7 @@ void luaV_execute (lua_State *L) {
|
||||
lua_Integer idx = intop(+, ivalue(ra), step); /* increment index */
|
||||
lua_Integer limit = ivalue(ra + 1);
|
||||
if ((0 < step) ? (idx <= limit) : (limit <= idx)) {
|
||||
ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
|
||||
pc += GETARG_sBx(i); /* jump back */
|
||||
chgivalue(ra, idx); /* update internal index... */
|
||||
setivalue(ra + 3, idx); /* ...and external index */
|
||||
}
|
||||
@ -1291,11 +1319,12 @@ void luaV_execute (lua_State *L) {
|
||||
lua_Number limit = fltvalue(ra + 1);
|
||||
if (luai_numlt(0, step) ? luai_numle(idx, limit)
|
||||
: luai_numle(limit, idx)) {
|
||||
ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
|
||||
pc += GETARG_sBx(i); /* jump back */
|
||||
chgfltvalue(ra, idx); /* update internal index... */
|
||||
setfltvalue(ra + 3, idx); /* ...and external index */
|
||||
}
|
||||
}
|
||||
updatemask(L);
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_FORPREP) {
|
||||
@ -1313,6 +1342,7 @@ void luaV_execute (lua_State *L) {
|
||||
}
|
||||
else { /* try making all values floats */
|
||||
lua_Number ninit; lua_Number nlimit; lua_Number nstep;
|
||||
savepc(L); /* in case of errors */
|
||||
if (!tonumber(plimit, &nlimit))
|
||||
luaG_runerror(L, "'for' limit must be a number");
|
||||
setfltvalue(plimit, nlimit);
|
||||
@ -1323,7 +1353,7 @@ void luaV_execute (lua_State *L) {
|
||||
luaG_runerror(L, "'for' initial value must be a number");
|
||||
setfltvalue(init, luai_numsub(L, ninit, nstep));
|
||||
}
|
||||
ci->u.l.savedpc += GETARG_sBx(i);
|
||||
pc += GETARG_sBx(i);
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_TFORCALL) {
|
||||
@ -1334,7 +1364,7 @@ void luaV_execute (lua_State *L) {
|
||||
L->top = cb + 3; /* func. + 2 args (state and index) */
|
||||
Protect(luaD_call(L, cb, GETARG_C(i)));
|
||||
L->top = ci->top;
|
||||
i = *(ci->u.l.savedpc++); /* go to next instruction */
|
||||
i = *(pc++); /* go to next instruction */
|
||||
ra = RA(i);
|
||||
lua_assert(GET_OPCODE(i) == OP_TFORLOOP);
|
||||
goto l_tforloop;
|
||||
@ -1343,7 +1373,7 @@ void luaV_execute (lua_State *L) {
|
||||
l_tforloop:
|
||||
if (!ttisnil(ra + 1)) { /* continue loop? */
|
||||
setobjs2s(L, ra, ra + 1); /* save control variable */
|
||||
ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
|
||||
pc += GETARG_sBx(i); /* jump back */
|
||||
}
|
||||
vmbreak;
|
||||
}
|
||||
@ -1354,11 +1384,12 @@ void luaV_execute (lua_State *L) {
|
||||
Table *h;
|
||||
if (n == 0) n = cast_int(L->top - ra) - 1;
|
||||
if (c == 0) {
|
||||
lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG);
|
||||
c = GETARG_Ax(*ci->u.l.savedpc++);
|
||||
lua_assert(GET_OPCODE(*pc) == OP_EXTRAARG);
|
||||
c = GETARG_Ax(*pc++);
|
||||
}
|
||||
h = hvalue(ra);
|
||||
last = ((c-1)*LFIELDS_PER_FLUSH) + n;
|
||||
savepc(L); /* in case of allocation errors */
|
||||
if (last > h->sizearray) /* needs more space? */
|
||||
luaH_resizearray(L, h, last); /* preallocate it at once */
|
||||
for (; n > 0; n--) {
|
||||
@ -1372,8 +1403,10 @@ void luaV_execute (lua_State *L) {
|
||||
vmcase(OP_CLOSURE) {
|
||||
Proto *p = cl->p->p[GETARG_Bx(i)];
|
||||
LClosure *ncl = getcached(p, cl->upvals, base); /* cached closure */
|
||||
if (ncl == NULL) /* no match? */
|
||||
if (ncl == NULL) { /* no match? */
|
||||
savepc(L); /* in case of allocation errors */
|
||||
pushclosure(L, p, cl->upvals, base, ra); /* create a new one */
|
||||
}
|
||||
else
|
||||
setclLvalue(L, ra, ncl); /* push cashed closure */
|
||||
checkGC(L, ra + 1);
|
||||
|
Loading…
x
Reference in New Issue
Block a user