lua

A copy of the Lua development repository
Log | Files | Refs | README

commit 15231d4fb2f6984b25e0353ff46eda1a180b686d
parent f407b3c4a1bc9667867ec51e835c20d97aab55a2
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date:   Sun, 21 Jul 2024 14:56:32 -0300

'nresults' moved into 'callstatus'

That gives us more free bits in 'callstatus', for future use.

Diffstat:
Mlapi.c | 4+---
Mldebug.c | 4++--
Mldo.c | 72++++++++++++++++++++++++++++++++++++++----------------------------------
Mlstate.c | 1-
Mlstate.h | 54+++++++++++++++++++++++++++++++++++-------------------
Mlvm.c | 6+++---
6 files changed, 79 insertions(+), 62 deletions(-)

diff --git a/lapi.c b/lapi.c @@ -1103,7 +1103,7 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, ci->u2.funcidx = cast_int(savestack(L, c.func)); ci->u.c.old_errfunc = L->errfunc; L->errfunc = func; - setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */ + setoah(ci, L->allowhook); /* save value of 'allowhook' */ ci->callstatus |= CIST_YPCALL; /* function can do error recovery */ luaD_call(L, c.func, nresults); /* do the call */ ci->callstatus &= ~CIST_YPCALL; @@ -1280,11 +1280,9 @@ LUA_API int lua_next (lua_State *L, int idx) { LUA_API void lua_toclose (lua_State *L, int idx) { - int nresults; StkId o; lua_lock(L); o = index2stack(L, idx); - nresults = L->ci->nresults; api_check(L, L->tbclist.p < o, "given index below or equal a marked one"); luaF_newtbcupval(L, o); /* create new to-be-closed upvalue */ L->ci->callstatus |= CIST_CLSRET; /* mark that function has TBC slots */ diff --git a/ldebug.c b/ldebug.c @@ -346,13 +346,13 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, ar->nparams = 0; } else { - ar->isvararg = f->l.p->flag & PF_ISVARARG; + ar->isvararg = (f->l.p->flag & PF_ISVARARG) ? 1 : 0; ar->nparams = f->l.p->numparams; } break; } case 't': { - ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0; + ar->istailcall = (ci != NULL && (ci->callstatus & CIST_TAIL)); break; } case 'n': { diff --git a/ldo.c b/ldo.c @@ -452,16 +452,31 @@ static StkId tryfuncTM (lua_State *L, StkId func) { } +/* Generic case for 'moveresult */ +l_sinline void genmoveresults (lua_State *L, StkId res, int nres, + int wanted) { + StkId firstresult = L->top.p - nres; /* index of first result */ + int i; + if (nres > wanted) /* extra results? */ + nres = wanted; /* don't need them */ + for (i = 0; i < nres; i++) /* move all results to correct place */ + setobjs2s(L, res + i, firstresult + i); + for (; i < wanted; i++) /* complete wanted number of results */ + setnilvalue(s2v(res + i)); + L->top.p = res + wanted; /* top points after the last result */ +} + + /* -** Given 'nres' results at 'firstResult', move 'wanted' of them to 'res'. -** Handle most typical cases (zero results for commands, one result for -** expressions, multiple results for tail calls/single parameters) -** separated. +** Given 'nres' results at 'firstResult', move 'fwanted-1' of them +** to 'res'. Handle most typical cases (zero results for commands, +** one result for expressions, multiple results for tail calls/single +** parameters) separated. The flag CIST_CLSRET in 'fwanted', if set, +** forces the swicth to go to the default case. */ -l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) { - StkId firstresult; - int i; - switch (wanted) { /* handle typical cases separately */ +l_sinline void moveresults (lua_State *L, StkId res, int nres, + l_uint32 fwanted) { + switch (fwanted) { /* handle typical cases separately */ case 0 + 1: /* no values needed */ L->top.p = res; return; @@ -473,12 +488,11 @@ l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) { L->top.p = res + 1; return; case LUA_MULTRET + 1: - wanted = nres; /* we want all results */ + genmoveresults(L, res, nres, nres); /* we want all results */ break; - default: /* two/more results and/or to-be-closed variables */ - if (!(wanted & CIST_CLSRET)) - wanted--; - else { /* to-be-closed variables? */ + default: { /* two/more results and/or to-be-closed variables */ + int wanted = get_nresults(fwanted); + if (fwanted & CIST_CLSRET) { /* to-be-closed variables? */ L->ci->u2.nres = nres; res = luaF_close(L, res, CLOSEKTOP, 1); L->ci->callstatus &= ~CIST_CLSRET; @@ -487,21 +501,13 @@ l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) { rethook(L, L->ci, nres); res = restorestack(L, savedres); /* hook can move stack */ } - wanted = (wanted & ~CIST_CLSRET) - 1; if (wanted == LUA_MULTRET) wanted = nres; /* we want all results */ } + genmoveresults(L, res, nres, wanted); break; + } } - /* generic case */ - firstresult = L->top.p - nres; /* index of first result */ - if (nres > wanted) /* extra results? */ - nres = wanted; /* don't need them */ - for (i = 0; i < nres; i++) /* move all results to correct place */ - setobjs2s(L, res + i, firstresult + i); - for (; i < wanted; i++) /* complete wanted number of results */ - setnilvalue(s2v(res + i)); - L->top.p = res + wanted; /* top points after the last result */ } @@ -512,13 +518,11 @@ l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) { ** that. */ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { - int wanted = ci->nresults + 1; - if (ci->callstatus & CIST_CLSRET) - wanted |= CIST_CLSRET; /* don't check hook in this case */ - else if (l_unlikely(L->hookmask)) + l_uint32 fwanted = ci->callstatus & (CIST_CLSRET | CIST_NRESULTS); + if (l_unlikely(L->hookmask) && !(fwanted & CIST_CLSRET)) rethook(L, ci, nres); /* move results to proper place */ - moveresults(L, ci->func.p, nres, wanted); + moveresults(L, ci->func.p, nres, fwanted); /* function cannot be in any of these cases when returning */ lua_assert(!(ci->callstatus & (CIST_HOOKED | CIST_YPCALL | CIST_FIN | CIST_TRAN | CIST_CLSRET))); @@ -530,12 +534,12 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { #define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L)) -l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret, - int mask, StkId top) { +l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nresults, + l_uint32 mask, StkId top) { CallInfo *ci = L->ci = next_ci(L); /* new frame */ ci->func.p = func; - ci->nresults = nret; - ci->callstatus = mask; + lua_assert(((nresults + 1) & ~CIST_NRESULTS) == 0); + ci->callstatus = mask | cast(l_uint32, nresults + 1); ci->top.p = top; return ci; } @@ -664,7 +668,7 @@ l_sinline void ccall (lua_State *L, StkId func, int nResults, l_uint32 inc) { luaE_checkcstack(L); } if ((ci = luaD_precall(L, func, nResults)) != NULL) { /* Lua function? */ - ci->callstatus = CIST_FRESH; /* mark that it is a "fresh" execute */ + ci->callstatus |= CIST_FRESH; /* mark that it is a "fresh" execute */ luaV_execute(L, ci); /* call it */ } L->nCcalls -= inc; @@ -709,7 +713,7 @@ static int finishpcallk (lua_State *L, CallInfo *ci) { status = LUA_YIELD; /* was interrupted by an yield */ else { /* error */ StkId func = restorestack(L, ci->u2.funcidx); - L->allowhook = getoah(ci->callstatus); /* restore 'allowhook' */ + L->allowhook = getoah(ci); /* restore 'allowhook' */ func = luaF_close(L, func, status, 1); /* can yield or raise an error */ luaD_seterrorobj(L, status, func); luaD_shrinkstack(L); /* restore stack size in case of overflow */ diff --git a/lstate.c b/lstate.c @@ -177,7 +177,6 @@ static void stack_init (lua_State *L1, lua_State *L) { ci->callstatus = CIST_C; ci->func.p = L1->top.p; ci->u.c.k = NULL; - ci->nresults = 0; setnilvalue(s2v(L1->top.p)); /* 'function' entry for this 'ci' */ L1->top.p++; ci->top.p = L1->top.p + LUA_MINSTACK; diff --git a/lstate.h b/lstate.h @@ -211,31 +211,45 @@ struct CallInfo { int ntransfer; /* number of values transferred */ } transferinfo; } u2; - short nresults; /* expected number of results from this function */ - unsigned short callstatus; + l_uint32 callstatus; }; /* ** Bits in CallInfo status */ -#define CIST_OAH (1<<0) /* original value of 'allowhook' */ -#define CIST_C (1<<1) /* call is running a C function */ -#define CIST_FRESH (1<<2) /* call is on a fresh "luaV_execute" frame */ -#define CIST_HOOKED (1<<3) /* call is running a debug hook */ -#define CIST_YPCALL (1<<4) /* doing a yieldable protected call */ -#define CIST_TAIL (1<<5) /* call was tail called */ -#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */ -#define CIST_FIN (1<<7) /* function "called" a finalizer */ -#define CIST_TRAN (1<<8) /* 'ci' has transfer information */ -#define CIST_CLSRET (1<<9) /* function is closing tbc variables */ -/* Bits 10-12 are used for CIST_RECST (see below) */ -#define CIST_RECST 10 +/* bits 0-7 are the expected number of results from this function + 1 */ +#define CIST_NRESULTS 0xff +/* original value of 'allowhook' */ +#define CIST_OAH (cast(l_uint32, 1) << 8) +/* call is running a C function */ +#define CIST_C (cast(l_uint32, 1) << 9) +/* call is on a fresh "luaV_execute" frame */ +#define CIST_FRESH (cast(l_uint32, 1) << 10) +/* call is running a debug hook */ +#define CIST_HOOKED (cast(l_uint32, 1) << 11) +/* doing a yieldable protected call */ +#define CIST_YPCALL (cast(l_uint32, 1) << 12) +/* call was tail called */ +#define CIST_TAIL (cast(l_uint32, 1) << 13) +/* last hook called yielded */ +#define CIST_HOOKYIELD (cast(l_uint32, 1) << 14) +/* function "called" a finalizer */ +#define CIST_FIN (cast(l_uint32, 1) << 15) +/* 'ci' has transfer information */ +#define CIST_TRAN (cast(l_uint32, 1) << 16) + /* function is closing tbc variables */ +#define CIST_CLSRET (cast(l_uint32, 1) << 17) +/* Bits 18-20 are used for CIST_RECST (see below) */ +#define CIST_RECST 18 /* the offset, not the mask */ #if defined(LUA_COMPAT_LT_LE) -#define CIST_LEQ (1<<13) /* using __lt for __le */ +/* using __lt for __le */ +#define CIST_LEQ (cast(l_uint32, 1) << 21) #endif +#define get_nresults(cs) (cast_int((cs) & CIST_NRESULTS) - 1) + /* ** Field CIST_RECST stores the "recover status", used to keep the error ** status while closing to-be-closed variables in coroutines, so that @@ -246,7 +260,7 @@ struct CallInfo { #define setcistrecst(ci,st) \ check_exp(((st) & 7) == (st), /* status must fit in three bits */ \ ((ci)->callstatus = ((ci)->callstatus & ~(7 << CIST_RECST)) \ - | ((st) << CIST_RECST))) + | (cast(l_uint32, st) << CIST_RECST))) /* active function is a Lua function */ @@ -255,9 +269,11 @@ struct CallInfo { /* call is running Lua code (not a hook) */ #define isLuacode(ci) (!((ci)->callstatus & (CIST_C | CIST_HOOKED))) -/* assume that CIST_OAH has offset 0 and that 'v' is strictly 0/1 */ -#define setoah(st,v) ((st) = ((st) & ~CIST_OAH) | (v)) -#define getoah(st) ((st) & CIST_OAH) + +#define setoah(ci,v) \ + ((ci)->callstatus = ((v) ? (ci)->callstatus | CIST_OAH \ + : (ci)->callstatus & ~CIST_OAH)) +#define getoah(ci) (((ci)->callstatus & CIST_OAH) ? 1 : 0) /* diff --git a/lvm.c b/lvm.c @@ -1742,10 +1742,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) { trap = 1; } else { /* do the 'poscall' here */ - int nres; + int nres = get_nresults(ci->callstatus); L->ci = ci->previous; /* back to caller */ L->top.p = base - 1; - for (nres = ci->nresults; l_unlikely(nres > 0); nres--) + for (; l_unlikely(nres > 0); nres--) setnilvalue(s2v(L->top.p++)); /* all results are nil */ } goto ret; @@ -1759,7 +1759,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { trap = 1; } else { /* do the 'poscall' here */ - int nres = ci->nresults; + int nres = get_nresults(ci->callstatus); L->ci = ci->previous; /* back to caller */ if (nres == 0) L->top.p = base - 1; /* asked for no results */