diff options
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 66 |
1 files changed, 32 insertions, 34 deletions
@@ -474,33 +474,36 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { | |||
474 | 474 | ||
475 | 475 | ||
476 | /* | 476 | /* |
477 | ** In a tail call, move function and parameters to previous call frame. | 477 | ** Prepare a function for a tail call, building its call info on top |
478 | ** (This is done only when no more errors can occur before entering the | 478 | ** of the current call info. 'narg1' is the number of arguments plus 1 |
479 | ** new function, to keep debug information always consistent.) | 479 | ** (so that it includes the function itself). |
480 | */ | 480 | */ |
481 | static void moveparams (lua_State *L, StkId prevf, StkId func) { | 481 | void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) { |
482 | Proto *p = clLvalue(s2v(func))->p; | ||
483 | int fsize = p->maxstacksize; /* frame size */ | ||
484 | int nfixparams = p->numparams; | ||
482 | int i; | 485 | int i; |
483 | for (i = 0; func + i < L->top; i++) /* move down function and arguments */ | 486 | for (i = 0; i < narg1; i++) /* move down function and arguments */ |
484 | setobjs2s(L, prevf + i, func + i); | 487 | setobjs2s(L, ci->func + i, func + i); |
485 | L->top = prevf + i; /* correct top */ | 488 | checkstackGC(L, fsize); |
486 | } | 489 | func = ci->func; /* moved-down function */ |
487 | 490 | for (; narg1 <= nfixparams; narg1++) | |
488 | 491 | setnilvalue(s2v(func + narg1)); /* complete missing arguments */ | |
489 | static CallInfo *prepCallInfo (lua_State *L, StkId func, int retdel, | 492 | ci->top = func + 1 + fsize; /* top for new function */ |
490 | int mask) { | 493 | lua_assert(ci->top <= L->stack_last); |
491 | CallInfo *ci; | 494 | ci->u.l.savedpc = p->code; /* starting point */ |
492 | if (isdelta(retdel)) { /* tail call? */ | 495 | ci->callstatus |= CIST_TAIL; |
493 | ci = L->ci; /* reuse stack frame */ | 496 | L->top = func + narg1; /* set top */ |
494 | ci->func -= retdel2delta(retdel); /* correct 'func' */ | 497 | } |
495 | ci->callstatus |= mask | CIST_TAIL; | 498 | |
496 | moveparams(L, ci->func, func); | 499 | |
497 | } | 500 | static CallInfo *prepCallInfo (lua_State *L, StkId func, int nret, |
498 | else { /* regular call */ | 501 | int mask, StkId top) { |
499 | ci = L->ci = next_ci(L); /* new frame */ | 502 | CallInfo *ci = L->ci = next_ci(L); /* new frame */ |
500 | ci->func = func; | 503 | ci->func = func; |
501 | ci->nresults = retdel; | 504 | ci->nresults = nret; |
502 | ci->callstatus = mask; | 505 | ci->callstatus = mask; |
503 | } | 506 | ci->top = top; |
504 | return ci; | 507 | return ci; |
505 | } | 508 | } |
506 | 509 | ||
@@ -512,12 +515,8 @@ static CallInfo *prepCallInfo (lua_State *L, StkId func, int retdel, | |||
512 | ** to be executed, if it was a Lua function. Otherwise (a C function) | 515 | ** to be executed, if it was a Lua function. Otherwise (a C function) |
513 | ** returns NULL, with all the results on the stack, starting at the | 516 | ** returns NULL, with all the results on the stack, starting at the |
514 | ** original function position. | 517 | ** original function position. |
515 | ** For regular calls, 'delta1' is 0. For tail calls, 'delta1' is the | ||
516 | ** 'delta' (correction of base for vararg functions) plus 1, so that it | ||
517 | ** cannot be zero. Like 'moveparams', this correction can only be done | ||
518 | ** when no more errors can occur in the call. | ||
519 | */ | 518 | */ |
520 | CallInfo *luaD_precall (lua_State *L, StkId func, int retdel) { | 519 | CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { |
521 | lua_CFunction f; | 520 | lua_CFunction f; |
522 | retry: | 521 | retry: |
523 | switch (ttypetag(s2v(func))) { | 522 | switch (ttypetag(s2v(func))) { |
@@ -530,8 +529,8 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int retdel) { | |||
530 | int n; /* number of returns */ | 529 | int n; /* number of returns */ |
531 | CallInfo *ci; | 530 | CallInfo *ci; |
532 | checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ | 531 | checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ |
533 | ci = prepCallInfo(L, func, retdel, CIST_C); | 532 | L->ci = ci = prepCallInfo(L, func, nresults, CIST_C, |
534 | ci->top = L->top + LUA_MINSTACK; | 533 | L->top + LUA_MINSTACK); |
535 | lua_assert(ci->top <= L->stack_last); | 534 | lua_assert(ci->top <= L->stack_last); |
536 | if (l_unlikely(L->hookmask & LUA_MASKCALL)) { | 535 | if (l_unlikely(L->hookmask & LUA_MASKCALL)) { |
537 | int narg = cast_int(L->top - func) - 1; | 536 | int narg = cast_int(L->top - func) - 1; |
@@ -551,9 +550,8 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int retdel) { | |||
551 | int nfixparams = p->numparams; | 550 | int nfixparams = p->numparams; |
552 | int fsize = p->maxstacksize; /* frame size */ | 551 | int fsize = p->maxstacksize; /* frame size */ |
553 | checkstackGCp(L, fsize, func); | 552 | checkstackGCp(L, fsize, func); |
554 | ci = prepCallInfo(L, func, retdel, 0); | 553 | L->ci = ci = prepCallInfo(L, func, nresults, 0, func + 1 + fsize); |
555 | ci->u.l.savedpc = p->code; /* starting point */ | 554 | ci->u.l.savedpc = p->code; /* starting point */ |
556 | ci->top = func + 1 + fsize; | ||
557 | for (; narg < nfixparams; narg++) | 555 | for (; narg < nfixparams; narg++) |
558 | setnilvalue(s2v(L->top++)); /* complete missing arguments */ | 556 | setnilvalue(s2v(L->top++)); /* complete missing arguments */ |
559 | lua_assert(ci->top <= L->stack_last); | 557 | lua_assert(ci->top <= L->stack_last); |