diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-07-21 14:56:59 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-07-21 14:56:59 -0300 |
| commit | 15231d4fb2f6984b25e0353ff46eda1a180b686d (patch) | |
| tree | fea343d493f04539a2a9ebe46c838cc5b8a01cd5 | |
| parent | f407b3c4a1bc9667867ec51e835c20d97aab55a2 (diff) | |
| download | lua-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.c | 4 | ||||
| -rw-r--r-- | ldebug.c | 4 | ||||
| -rw-r--r-- | ldo.c | 72 | ||||
| -rw-r--r-- | lstate.c | 1 | ||||
| -rw-r--r-- | lstate.h | 54 | ||||
| -rw-r--r-- | lvm.c | 6 |
6 files changed, 79 insertions, 62 deletions
| @@ -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 | ||
| 1282 | LUA_API void lua_toclose (lua_State *L, int idx) { | 1282 | LUA_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 */ |
| @@ -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': { |
| @@ -452,16 +452,31 @@ static StkId tryfuncTM (lua_State *L, StkId func) { | |||
| 452 | } | 452 | } |
| 453 | 453 | ||
| 454 | 454 | ||
| 455 | /* Generic case for 'moveresult */ | ||
| 456 | l_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 | */ |
| 461 | l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) { | 477 | l_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 | */ |
| 514 | void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { | 520 | void 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 | ||
| 533 | l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret, | 537 | l_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 */ |
| @@ -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; |
| @@ -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 | /* |
| @@ -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 */ |
