aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2024-07-21 14:56:59 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2024-07-21 14:56:59 -0300
commit15231d4fb2f6984b25e0353ff46eda1a180b686d (patch)
treefea343d493f04539a2a9ebe46c838cc5b8a01cd5
parentf407b3c4a1bc9667867ec51e835c20d97aab55a2 (diff)
downloadlua-15231d4fb2f6984b25e0353ff46eda1a180b686d.tar.gz
lua-15231d4fb2f6984b25e0353ff46eda1a180b686d.tar.bz2
lua-15231d4fb2f6984b25e0353ff46eda1a180b686d.zip
'nresults' moved into 'callstatus'
That gives us more free bits in 'callstatus', for future use.
-rw-r--r--lapi.c4
-rw-r--r--ldebug.c4
-rw-r--r--ldo.c72
-rw-r--r--lstate.c1
-rw-r--r--lstate.h54
-rw-r--r--lvm.c6
6 files changed, 79 insertions, 62 deletions
diff --git a/lapi.c b/lapi.c
index 70e2a44a..a9ab1d08 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1103,7 +1103,7 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,
1103 ci->u2.funcidx = cast_int(savestack(L, c.func)); 1103 ci->u2.funcidx = cast_int(savestack(L, c.func));
1104 ci->u.c.old_errfunc = L->errfunc; 1104 ci->u.c.old_errfunc = L->errfunc;
1105 L->errfunc = func; 1105 L->errfunc = func;
1106 setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */ 1106 setoah(ci, L->allowhook); /* save value of 'allowhook' */
1107 ci->callstatus |= CIST_YPCALL; /* function can do error recovery */ 1107 ci->callstatus |= CIST_YPCALL; /* function can do error recovery */
1108 luaD_call(L, c.func, nresults); /* do the call */ 1108 luaD_call(L, c.func, nresults); /* do the call */
1109 ci->callstatus &= ~CIST_YPCALL; 1109 ci->callstatus &= ~CIST_YPCALL;
@@ -1280,11 +1280,9 @@ LUA_API int lua_next (lua_State *L, int idx) {
1280 1280
1281 1281
1282LUA_API void lua_toclose (lua_State *L, int idx) { 1282LUA_API void lua_toclose (lua_State *L, int idx) {
1283 int nresults;
1284 StkId o; 1283 StkId o;
1285 lua_lock(L); 1284 lua_lock(L);
1286 o = index2stack(L, idx); 1285 o = index2stack(L, idx);
1287 nresults = L->ci->nresults;
1288 api_check(L, L->tbclist.p < o, "given index below or equal a marked one"); 1286 api_check(L, L->tbclist.p < o, "given index below or equal a marked one");
1289 luaF_newtbcupval(L, o); /* create new to-be-closed upvalue */ 1287 luaF_newtbcupval(L, o); /* create new to-be-closed upvalue */
1290 L->ci->callstatus |= CIST_CLSRET; /* mark that function has TBC slots */ 1288 L->ci->callstatus |= CIST_CLSRET; /* mark that function has TBC slots */
diff --git a/ldebug.c b/ldebug.c
index 202d6417..1c8b57c8 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -346,13 +346,13 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
346 ar->nparams = 0; 346 ar->nparams = 0;
347 } 347 }
348 else { 348 else {
349 ar->isvararg = f->l.p->flag & PF_ISVARARG; 349 ar->isvararg = (f->l.p->flag & PF_ISVARARG) ? 1 : 0;
350 ar->nparams = f->l.p->numparams; 350 ar->nparams = f->l.p->numparams;
351 } 351 }
352 break; 352 break;
353 } 353 }
354 case 't': { 354 case 't': {
355 ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0; 355 ar->istailcall = (ci != NULL && (ci->callstatus & CIST_TAIL));
356 break; 356 break;
357 } 357 }
358 case 'n': { 358 case 'n': {
diff --git a/ldo.c b/ldo.c
index 6eaa31a0..933a55bf 100644
--- a/ldo.c
+++ b/ldo.c
@@ -452,16 +452,31 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
452} 452}
453 453
454 454
455/* Generic case for 'moveresult */
456l_sinline void genmoveresults (lua_State *L, StkId res, int nres,
457 int wanted) {
458 StkId firstresult = L->top.p - nres; /* index of first result */
459 int i;
460 if (nres > wanted) /* extra results? */
461 nres = wanted; /* don't need them */
462 for (i = 0; i < nres; i++) /* move all results to correct place */
463 setobjs2s(L, res + i, firstresult + i);
464 for (; i < wanted; i++) /* complete wanted number of results */
465 setnilvalue(s2v(res + i));
466 L->top.p = res + wanted; /* top points after the last result */
467}
468
469
455/* 470/*
456** Given 'nres' results at 'firstResult', move 'wanted' of them to 'res'. 471** Given 'nres' results at 'firstResult', move 'fwanted-1' of them
457** Handle most typical cases (zero results for commands, one result for 472** to 'res'. Handle most typical cases (zero results for commands,
458** expressions, multiple results for tail calls/single parameters) 473** one result for expressions, multiple results for tail calls/single
459** separated. 474** parameters) separated. The flag CIST_CLSRET in 'fwanted', if set,
475** forces the swicth to go to the default case.
460*/ 476*/
461l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) { 477l_sinline void moveresults (lua_State *L, StkId res, int nres,
462 StkId firstresult; 478 l_uint32 fwanted) {
463 int i; 479 switch (fwanted) { /* handle typical cases separately */
464 switch (wanted) { /* handle typical cases separately */
465 case 0 + 1: /* no values needed */ 480 case 0 + 1: /* no values needed */
466 L->top.p = res; 481 L->top.p = res;
467 return; 482 return;
@@ -473,12 +488,11 @@ l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) {
473 L->top.p = res + 1; 488 L->top.p = res + 1;
474 return; 489 return;
475 case LUA_MULTRET + 1: 490 case LUA_MULTRET + 1:
476 wanted = nres; /* we want all results */ 491 genmoveresults(L, res, nres, nres); /* we want all results */
477 break; 492 break;
478 default: /* two/more results and/or to-be-closed variables */ 493 default: { /* two/more results and/or to-be-closed variables */
479 if (!(wanted & CIST_CLSRET)) 494 int wanted = get_nresults(fwanted);
480 wanted--; 495 if (fwanted & CIST_CLSRET) { /* to-be-closed variables? */
481 else { /* to-be-closed variables? */
482 L->ci->u2.nres = nres; 496 L->ci->u2.nres = nres;
483 res = luaF_close(L, res, CLOSEKTOP, 1); 497 res = luaF_close(L, res, CLOSEKTOP, 1);
484 L->ci->callstatus &= ~CIST_CLSRET; 498 L->ci->callstatus &= ~CIST_CLSRET;
@@ -487,21 +501,13 @@ l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) {
487 rethook(L, L->ci, nres); 501 rethook(L, L->ci, nres);
488 res = restorestack(L, savedres); /* hook can move stack */ 502 res = restorestack(L, savedres); /* hook can move stack */
489 } 503 }
490 wanted = (wanted & ~CIST_CLSRET) - 1;
491 if (wanted == LUA_MULTRET) 504 if (wanted == LUA_MULTRET)
492 wanted = nres; /* we want all results */ 505 wanted = nres; /* we want all results */
493 } 506 }
507 genmoveresults(L, res, nres, wanted);
494 break; 508 break;
509 }
495 } 510 }
496 /* generic case */
497 firstresult = L->top.p - nres; /* index of first result */
498 if (nres > wanted) /* extra results? */
499 nres = wanted; /* don't need them */
500 for (i = 0; i < nres; i++) /* move all results to correct place */
501 setobjs2s(L, res + i, firstresult + i);
502 for (; i < wanted; i++) /* complete wanted number of results */
503 setnilvalue(s2v(res + i));
504 L->top.p = res + wanted; /* top points after the last result */
505} 511}
506 512
507 513
@@ -512,13 +518,11 @@ l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) {
512** that. 518** that.
513*/ 519*/
514void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { 520void luaD_poscall (lua_State *L, CallInfo *ci, int nres) {
515 int wanted = ci->nresults + 1; 521 l_uint32 fwanted = ci->callstatus & (CIST_CLSRET | CIST_NRESULTS);
516 if (ci->callstatus & CIST_CLSRET) 522 if (l_unlikely(L->hookmask) && !(fwanted & CIST_CLSRET))
517 wanted |= CIST_CLSRET; /* don't check hook in this case */
518 else if (l_unlikely(L->hookmask))
519 rethook(L, ci, nres); 523 rethook(L, ci, nres);
520 /* move results to proper place */ 524 /* move results to proper place */
521 moveresults(L, ci->func.p, nres, wanted); 525 moveresults(L, ci->func.p, nres, fwanted);
522 /* function cannot be in any of these cases when returning */ 526 /* function cannot be in any of these cases when returning */
523 lua_assert(!(ci->callstatus & 527 lua_assert(!(ci->callstatus &
524 (CIST_HOOKED | CIST_YPCALL | CIST_FIN | CIST_TRAN | CIST_CLSRET))); 528 (CIST_HOOKED | CIST_YPCALL | CIST_FIN | CIST_TRAN | CIST_CLSRET)));
@@ -530,12 +534,12 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) {
530#define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L)) 534#define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L))
531 535
532 536
533l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret, 537l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nresults,
534 int mask, StkId top) { 538 l_uint32 mask, StkId top) {
535 CallInfo *ci = L->ci = next_ci(L); /* new frame */ 539 CallInfo *ci = L->ci = next_ci(L); /* new frame */
536 ci->func.p = func; 540 ci->func.p = func;
537 ci->nresults = nret; 541 lua_assert(((nresults + 1) & ~CIST_NRESULTS) == 0);
538 ci->callstatus = mask; 542 ci->callstatus = mask | cast(l_uint32, nresults + 1);
539 ci->top.p = top; 543 ci->top.p = top;
540 return ci; 544 return ci;
541} 545}
@@ -664,7 +668,7 @@ l_sinline void ccall (lua_State *L, StkId func, int nResults, l_uint32 inc) {
664 luaE_checkcstack(L); 668 luaE_checkcstack(L);
665 } 669 }
666 if ((ci = luaD_precall(L, func, nResults)) != NULL) { /* Lua function? */ 670 if ((ci = luaD_precall(L, func, nResults)) != NULL) { /* Lua function? */
667 ci->callstatus = CIST_FRESH; /* mark that it is a "fresh" execute */ 671 ci->callstatus |= CIST_FRESH; /* mark that it is a "fresh" execute */
668 luaV_execute(L, ci); /* call it */ 672 luaV_execute(L, ci); /* call it */
669 } 673 }
670 L->nCcalls -= inc; 674 L->nCcalls -= inc;
@@ -709,7 +713,7 @@ static int finishpcallk (lua_State *L, CallInfo *ci) {
709 status = LUA_YIELD; /* was interrupted by an yield */ 713 status = LUA_YIELD; /* was interrupted by an yield */
710 else { /* error */ 714 else { /* error */
711 StkId func = restorestack(L, ci->u2.funcidx); 715 StkId func = restorestack(L, ci->u2.funcidx);
712 L->allowhook = getoah(ci->callstatus); /* restore 'allowhook' */ 716 L->allowhook = getoah(ci); /* restore 'allowhook' */
713 func = luaF_close(L, func, status, 1); /* can yield or raise an error */ 717 func = luaF_close(L, func, status, 1); /* can yield or raise an error */
714 luaD_seterrorobj(L, status, func); 718 luaD_seterrorobj(L, status, func);
715 luaD_shrinkstack(L); /* restore stack size in case of overflow */ 719 luaD_shrinkstack(L); /* restore stack size in case of overflow */
diff --git a/lstate.c b/lstate.c
index 8df86bf5..4511bc00 100644
--- a/lstate.c
+++ b/lstate.c
@@ -177,7 +177,6 @@ static void stack_init (lua_State *L1, lua_State *L) {
177 ci->callstatus = CIST_C; 177 ci->callstatus = CIST_C;
178 ci->func.p = L1->top.p; 178 ci->func.p = L1->top.p;
179 ci->u.c.k = NULL; 179 ci->u.c.k = NULL;
180 ci->nresults = 0;
181 setnilvalue(s2v(L1->top.p)); /* 'function' entry for this 'ci' */ 180 setnilvalue(s2v(L1->top.p)); /* 'function' entry for this 'ci' */
182 L1->top.p++; 181 L1->top.p++;
183 ci->top.p = L1->top.p + LUA_MINSTACK; 182 ci->top.p = L1->top.p + LUA_MINSTACK;
diff --git a/lstate.h b/lstate.h
index e5056abe..ff86d825 100644
--- a/lstate.h
+++ b/lstate.h
@@ -211,31 +211,45 @@ struct CallInfo {
211 int ntransfer; /* number of values transferred */ 211 int ntransfer; /* number of values transferred */
212 } transferinfo; 212 } transferinfo;
213 } u2; 213 } u2;
214 short nresults; /* expected number of results from this function */ 214 l_uint32 callstatus;
215 unsigned short callstatus;
216}; 215};
217 216
218 217
219/* 218/*
220** Bits in CallInfo status 219** Bits in CallInfo status
221*/ 220*/
222#define CIST_OAH (1<<0) /* original value of 'allowhook' */ 221/* bits 0-7 are the expected number of results from this function + 1 */
223#define CIST_C (1<<1) /* call is running a C function */ 222#define CIST_NRESULTS 0xff
224#define CIST_FRESH (1<<2) /* call is on a fresh "luaV_execute" frame */ 223/* original value of 'allowhook' */
225#define CIST_HOOKED (1<<3) /* call is running a debug hook */ 224#define CIST_OAH (cast(l_uint32, 1) << 8)
226#define CIST_YPCALL (1<<4) /* doing a yieldable protected call */ 225/* call is running a C function */
227#define CIST_TAIL (1<<5) /* call was tail called */ 226#define CIST_C (cast(l_uint32, 1) << 9)
228#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */ 227/* call is on a fresh "luaV_execute" frame */
229#define CIST_FIN (1<<7) /* function "called" a finalizer */ 228#define CIST_FRESH (cast(l_uint32, 1) << 10)
230#define CIST_TRAN (1<<8) /* 'ci' has transfer information */ 229/* call is running a debug hook */
231#define CIST_CLSRET (1<<9) /* function is closing tbc variables */ 230#define CIST_HOOKED (cast(l_uint32, 1) << 11)
232/* Bits 10-12 are used for CIST_RECST (see below) */ 231/* doing a yieldable protected call */
233#define CIST_RECST 10 232#define CIST_YPCALL (cast(l_uint32, 1) << 12)
233/* call was tail called */
234#define CIST_TAIL (cast(l_uint32, 1) << 13)
235/* last hook called yielded */
236#define CIST_HOOKYIELD (cast(l_uint32, 1) << 14)
237/* function "called" a finalizer */
238#define CIST_FIN (cast(l_uint32, 1) << 15)
239/* 'ci' has transfer information */
240#define CIST_TRAN (cast(l_uint32, 1) << 16)
241 /* function is closing tbc variables */
242#define CIST_CLSRET (cast(l_uint32, 1) << 17)
243/* Bits 18-20 are used for CIST_RECST (see below) */
244#define CIST_RECST 18 /* the offset, not the mask */
234#if defined(LUA_COMPAT_LT_LE) 245#if defined(LUA_COMPAT_LT_LE)
235#define CIST_LEQ (1<<13) /* using __lt for __le */ 246/* using __lt for __le */
247#define CIST_LEQ (cast(l_uint32, 1) << 21)
236#endif 248#endif
237 249
238 250
251#define get_nresults(cs) (cast_int((cs) & CIST_NRESULTS) - 1)
252
239/* 253/*
240** Field CIST_RECST stores the "recover status", used to keep the error 254** Field CIST_RECST stores the "recover status", used to keep the error
241** status while closing to-be-closed variables in coroutines, so that 255** status while closing to-be-closed variables in coroutines, so that
@@ -246,7 +260,7 @@ struct CallInfo {
246#define setcistrecst(ci,st) \ 260#define setcistrecst(ci,st) \
247 check_exp(((st) & 7) == (st), /* status must fit in three bits */ \ 261 check_exp(((st) & 7) == (st), /* status must fit in three bits */ \
248 ((ci)->callstatus = ((ci)->callstatus & ~(7 << CIST_RECST)) \ 262 ((ci)->callstatus = ((ci)->callstatus & ~(7 << CIST_RECST)) \
249 | ((st) << CIST_RECST))) 263 | (cast(l_uint32, st) << CIST_RECST)))
250 264
251 265
252/* active function is a Lua function */ 266/* active function is a Lua function */
@@ -255,9 +269,11 @@ struct CallInfo {
255/* call is running Lua code (not a hook) */ 269/* call is running Lua code (not a hook) */
256#define isLuacode(ci) (!((ci)->callstatus & (CIST_C | CIST_HOOKED))) 270#define isLuacode(ci) (!((ci)->callstatus & (CIST_C | CIST_HOOKED)))
257 271
258/* assume that CIST_OAH has offset 0 and that 'v' is strictly 0/1 */ 272
259#define setoah(st,v) ((st) = ((st) & ~CIST_OAH) | (v)) 273#define setoah(ci,v) \
260#define getoah(st) ((st) & CIST_OAH) 274 ((ci)->callstatus = ((v) ? (ci)->callstatus | CIST_OAH \
275 : (ci)->callstatus & ~CIST_OAH))
276#define getoah(ci) (((ci)->callstatus & CIST_OAH) ? 1 : 0)
261 277
262 278
263/* 279/*
diff --git a/lvm.c b/lvm.c
index d8fe55e5..5771c31a 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1742,10 +1742,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1742 trap = 1; 1742 trap = 1;
1743 } 1743 }
1744 else { /* do the 'poscall' here */ 1744 else { /* do the 'poscall' here */
1745 int nres; 1745 int nres = get_nresults(ci->callstatus);
1746 L->ci = ci->previous; /* back to caller */ 1746 L->ci = ci->previous; /* back to caller */
1747 L->top.p = base - 1; 1747 L->top.p = base - 1;
1748 for (nres = ci->nresults; l_unlikely(nres > 0); nres--) 1748 for (; l_unlikely(nres > 0); nres--)
1749 setnilvalue(s2v(L->top.p++)); /* all results are nil */ 1749 setnilvalue(s2v(L->top.p++)); /* all results are nil */
1750 } 1750 }
1751 goto ret; 1751 goto ret;
@@ -1759,7 +1759,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1759 trap = 1; 1759 trap = 1;
1760 } 1760 }
1761 else { /* do the 'poscall' here */ 1761 else { /* do the 'poscall' here */
1762 int nres = ci->nresults; 1762 int nres = get_nresults(ci->callstatus);
1763 L->ci = ci->previous; /* back to caller */ 1763 L->ci = ci->previous; /* back to caller */
1764 if (nres == 0) 1764 if (nres == 0)
1765 L->top.p = base - 1; /* asked for no results */ 1765 L->top.p = base - 1; /* asked for no results */