aboutsummaryrefslogtreecommitdiff
path: root/ldo.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldo.c')
-rw-r--r--ldo.c72
1 files changed, 43 insertions, 29 deletions
diff --git a/ldo.c b/ldo.c
index bc7212c6..5587b602 100644
--- a/ldo.c
+++ b/ldo.c
@@ -408,24 +408,27 @@ static void moveresults (lua_State *L, StkId res, int nres, int wanted) {
408 case LUA_MULTRET: 408 case LUA_MULTRET:
409 wanted = nres; /* we want all results */ 409 wanted = nres; /* we want all results */
410 break; 410 break;
411 default: /* multiple results (or to-be-closed variables) */ 411 default: /* two/more results and/or to-be-closed variables */
412 if (hastocloseCfunc(wanted)) { /* to-be-closed variables? */ 412 if (hastocloseCfunc(wanted)) { /* to-be-closed variables? */
413 ptrdiff_t savedres = savestack(L, res); 413 ptrdiff_t savedres = savestack(L, res);
414 luaF_close(L, res, CLOSEKTOP, 0); /* may change the stack */ 414 L->ci->callstatus |= CIST_CLSRET; /* in case of yields */
415 wanted = codeNresults(wanted); /* correct value */ 415 L->ci->u2.nres = nres;
416 if (wanted == LUA_MULTRET) 416 luaF_close(L, res, CLOSEKTOP, 1);
417 wanted = nres; 417 L->ci->callstatus &= ~CIST_CLSRET;
418 if (L->hookmask) /* if needed, call hook after '__close's */ 418 if (L->hookmask) /* if needed, call hook after '__close's */
419 rethook(L, L->ci, nres); 419 rethook(L, L->ci, nres);
420 res = restorestack(L, savedres); /* close and hook can move stack */ 420 res = restorestack(L, savedres); /* close and hook can move stack */
421 wanted = decodeNresults(wanted);
422 if (wanted == LUA_MULTRET)
423 wanted = nres; /* we want all results */
421 } 424 }
422 break; 425 break;
423 } 426 }
427 /* generic case */
424 firstresult = L->top - nres; /* index of first result */ 428 firstresult = L->top - nres; /* index of first result */
425 /* move all results to correct place */ 429 if (nres > wanted) /* extra results? */
426 if (nres > wanted) 430 nres = wanted; /* don't need them */
427 nres = wanted; /* don't need more than that */ 431 for (i = 0; i < nres; i++) /* move all results to correct place */
428 for (i = 0; i < nres; i++)
429 setobjs2s(L, res + i, firstresult + i); 432 setobjs2s(L, res + i, firstresult + i);
430 for (; i < wanted; i++) /* complete wanted number of results */ 433 for (; i < wanted; i++) /* complete wanted number of results */
431 setnilvalue(s2v(res + i)); 434 setnilvalue(s2v(res + i));
@@ -445,6 +448,9 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) {
445 rethook(L, ci, nres); 448 rethook(L, ci, nres);
446 /* move results to proper place */ 449 /* move results to proper place */
447 moveresults(L, ci->func, nres, wanted); 450 moveresults(L, ci->func, nres, wanted);
451 /* function cannot be in any of these cases when returning */
452 lua_assert(!(ci->callstatus &
453 (CIST_HOOKED | CIST_YPCALL | CIST_FIN | CIST_TRAN | CIST_CLSRET)));
448 L->ci = ci->previous; /* back to caller (after closing variables) */ 454 L->ci = ci->previous; /* back to caller (after closing variables) */
449} 455}
450 456
@@ -615,28 +621,36 @@ static int finishpcallk (lua_State *L, CallInfo *ci) {
615 621
616/* 622/*
617** Completes the execution of a C function interrupted by an yield. 623** Completes the execution of a C function interrupted by an yield.
618** The interruption must have happened while the function was 624** The interruption must have happened while the function was either
619** executing 'lua_callk' or 'lua_pcallk'. In the second case, the 625** closing its tbc variables in 'moveresults' or executing
620** call to 'finishpcallk' finishes the interrupted execution of 626** 'lua_callk'/'lua_pcallk'. In the first case, it just redoes
621** 'lua_pcallk'. After that, it calls the continuation of the 627** 'luaD_poscall'. In the second case, the call to 'finishpcallk'
622** interrupted function and finally it completes the job of the 628** finishes the interrupted execution of 'lua_pcallk'. After that, it
623** 'luaD_call' that called the function. 629** calls the continuation of the interrupted function and finally it
624** In the call to 'adjustresults', we do not know the number of 630** completes the job of the 'luaD_call' that called the function. In
625** results of the function called by 'lua_callk'/'lua_pcallk', 631** the call to 'adjustresults', we do not know the number of results
626** so we are conservative and use LUA_MULTRET (always adjust). 632** of the function called by 'lua_callk'/'lua_pcallk', so we are
633** conservative and use LUA_MULTRET (always adjust).
627*/ 634*/
628static void finishCcall (lua_State *L, CallInfo *ci) { 635static void finishCcall (lua_State *L, CallInfo *ci) {
629 int n; 636 int n; /* actual number of results from C function */
630 int status = LUA_YIELD; /* default if there were no errors */ 637 if (ci->callstatus & CIST_CLSRET) { /* was returning? */
631 /* must have a continuation and must be able to call it */ 638 lua_assert(hastocloseCfunc(ci->nresults));
632 lua_assert(ci->u.c.k != NULL && yieldable(L)); 639 n = ci->u2.nres; /* just redo 'luaD_poscall' */
633 if (ci->callstatus & CIST_YPCALL) /* was inside a 'lua_pcallk'? */ 640 /* don't need to reset CIST_CLSRET, as it will be set again anyway */
634 status = finishpcallk(L, ci); /* finish it */ 641 }
635 adjustresults(L, LUA_MULTRET); /* finish 'lua_callk' */ 642 else {
636 lua_unlock(L); 643 int status = LUA_YIELD; /* default if there were no errors */
637 n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation */ 644 /* must have a continuation and must be able to call it */
638 lua_lock(L); 645 lua_assert(ci->u.c.k != NULL && yieldable(L));
639 api_checknelems(L, n); 646 if (ci->callstatus & CIST_YPCALL) /* was inside a 'lua_pcallk'? */
647 status = finishpcallk(L, ci); /* finish it */
648 adjustresults(L, LUA_MULTRET); /* finish 'lua_callk' */
649 lua_unlock(L);
650 n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation */
651 lua_lock(L);
652 api_checknelems(L, n);
653 }
640 luaD_poscall(L, ci, n); /* finish 'luaD_call' */ 654 luaD_poscall(L, ci, n); /* finish 'luaD_call' */
641} 655}
642 656