diff options
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 72 |
1 files changed, 38 insertions, 34 deletions
@@ -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 */ |