diff options
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 48 |
1 files changed, 24 insertions, 24 deletions
@@ -474,26 +474,16 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { | |||
474 | 474 | ||
475 | 475 | ||
476 | /* | 476 | /* |
477 | ** Prepare a function for a tail call, building its call info on top | 477 | ** In a tail call, move function and parameters to previous call frame. |
478 | ** of the current call info. 'narg1' is the number of arguments plus 1 | 478 | ** (This is done only when no more errors can occur before entering the |
479 | ** (so that it includes the function itself). | 479 | ** new function, to keep debug information always consistent.) |
480 | */ | 480 | */ |
481 | void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) { | 481 | static void moveparams (lua_State *L, StkId prevf, StkId func, int narg) { |
482 | Proto *p = clLvalue(s2v(func))->p; | ||
483 | int fsize = p->maxstacksize; /* frame size */ | ||
484 | int nfixparams = p->numparams; | ||
485 | int i; | 482 | int i; |
486 | for (i = 0; i < narg1; i++) /* move down function and arguments */ | 483 | narg++; /* function itself will be moved, too */ |
487 | setobjs2s(L, ci->func + i, func + i); | 484 | for (i = 0; i < narg; i++) /* move down function and arguments */ |
488 | checkstackGC(L, fsize); | 485 | setobjs2s(L, prevf + i, func + i); |
489 | func = ci->func; /* moved-down function */ | 486 | L->top = prevf + narg; /* correct top */ |
490 | for (; narg1 <= nfixparams; narg1++) | ||
491 | setnilvalue(s2v(func + narg1)); /* complete missing arguments */ | ||
492 | ci->top = func + 1 + fsize; /* top for new function */ | ||
493 | lua_assert(ci->top <= L->stack_last); | ||
494 | ci->u.l.savedpc = p->code; /* starting point */ | ||
495 | ci->callstatus |= CIST_TAIL; | ||
496 | L->top = func + narg1; /* set top */ | ||
497 | } | 487 | } |
498 | 488 | ||
499 | 489 | ||
@@ -504,8 +494,12 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) { | |||
504 | ** to be executed, if it was a Lua function. Otherwise (a C function) | 494 | ** to be executed, if it was a Lua function. Otherwise (a C function) |
505 | ** returns NULL, with all the results on the stack, starting at the | 495 | ** returns NULL, with all the results on the stack, starting at the |
506 | ** original function position. | 496 | ** original function position. |
497 | ** For regular calls, 'delta1' is 0. For tail calls, 'delta1' is the | ||
498 | ** 'delta' (correction of base for vararg functions) plus 1, so that it | ||
499 | ** cannot be zero. Like 'moveparams', this correction can only be done | ||
500 | ** when no more errors can occur in the call. | ||
507 | */ | 501 | */ |
508 | CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { | 502 | CallInfo *luaD_precall (lua_State *L, StkId func, int nresults, int delta1) { |
509 | lua_CFunction f; | 503 | lua_CFunction f; |
510 | retry: | 504 | retry: |
511 | switch (ttypetag(s2v(func))) { | 505 | switch (ttypetag(s2v(func))) { |
@@ -542,12 +536,18 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { | |||
542 | int nfixparams = p->numparams; | 536 | int nfixparams = p->numparams; |
543 | int fsize = p->maxstacksize; /* frame size */ | 537 | int fsize = p->maxstacksize; /* frame size */ |
544 | checkstackGCp(L, fsize, func); | 538 | checkstackGCp(L, fsize, func); |
545 | L->ci = ci = next_ci(L); | 539 | if (delta1) { /* tail call? */ |
546 | ci->nresults = nresults; | 540 | ci = L->ci; /* reuse stack frame */ |
541 | ci->func -= delta1 - 1; /* correct 'func' */ | ||
542 | moveparams(L, ci->func, func, narg); | ||
543 | } | ||
544 | else { /* regular call */ | ||
545 | L->ci = ci = next_ci(L); /* new frame */ | ||
546 | ci->func = func; | ||
547 | ci->nresults = nresults; | ||
548 | } | ||
547 | ci->u.l.savedpc = p->code; /* starting point */ | 549 | ci->u.l.savedpc = p->code; /* starting point */ |
548 | ci->top = func + 1 + fsize; | 550 | ci->top = func + 1 + fsize; |
549 | ci->func = func; | ||
550 | L->ci = ci; | ||
551 | for (; narg < nfixparams; narg++) | 551 | for (; narg < nfixparams; narg++) |
552 | setnilvalue(s2v(L->top++)); /* complete missing arguments */ | 552 | setnilvalue(s2v(L->top++)); /* complete missing arguments */ |
553 | lua_assert(ci->top <= L->stack_last); | 553 | lua_assert(ci->top <= L->stack_last); |
@@ -572,7 +572,7 @@ static void ccall (lua_State *L, StkId func, int nResults, int inc) { | |||
572 | L->nCcalls += inc; | 572 | L->nCcalls += inc; |
573 | if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) | 573 | if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) |
574 | luaE_checkcstack(L); | 574 | luaE_checkcstack(L); |
575 | if ((ci = luaD_precall(L, func, nResults)) != NULL) { /* Lua function? */ | 575 | if ((ci = luaD_precall(L, func, nResults, 0)) != NULL) { /* Lua function? */ |
576 | ci->callstatus = CIST_FRESH; /* mark that it is a "fresh" execute */ | 576 | ci->callstatus = CIST_FRESH; /* mark that it is a "fresh" execute */ |
577 | luaV_execute(L, ci); /* call it */ | 577 | luaV_execute(L, ci); /* call it */ |
578 | } | 578 | } |