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