diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-06-14 13:28:21 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-06-14 13:28:21 -0300 |
| commit | 04e19712a5d48b84869f9942836ff8314fb0be8e (patch) | |
| tree | 75aab8dff5bdf07026080eba0189e4025ec3b7ee /lvm.c | |
| parent | 901d76009346d76996679c02deee708bf225e91e (diff) | |
| download | lua-04e19712a5d48b84869f9942836ff8314fb0be8e.tar.gz lua-04e19712a5d48b84869f9942836ff8314fb0be8e.tar.bz2 lua-04e19712a5d48b84869f9942836ff8314fb0be8e.zip | |
C functions can be tail called, too
A tail call to a C function can have the behavior of a "real" tail
call, reusing the stack frame of the caller.
Diffstat (limited to 'lvm.c')
| -rw-r--r-- | lvm.c | 9 |
1 files changed, 1 insertions, 8 deletions
| @@ -1636,7 +1636,6 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1636 | updatetrap(ci); /* C call; nothing else to be done */ | 1636 | updatetrap(ci); /* C call; nothing else to be done */ |
| 1637 | else { /* Lua call: run function in this same C frame */ | 1637 | else { /* Lua call: run function in this same C frame */ |
| 1638 | ci = newci; | 1638 | ci = newci; |
| 1639 | ci->callstatus = 0; | ||
| 1640 | goto startfunc; | 1639 | goto startfunc; |
| 1641 | } | 1640 | } |
| 1642 | vmbreak; | 1641 | vmbreak; |
| @@ -1655,16 +1654,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1655 | lua_assert(L->tbclist < base); /* no pending tbc variables */ | 1654 | lua_assert(L->tbclist < base); /* no pending tbc variables */ |
| 1656 | lua_assert(base == ci->func + 1); | 1655 | lua_assert(base == ci->func + 1); |
| 1657 | } | 1656 | } |
| 1658 | if (luaD_precall(L, ra, LUA_MULTRET, delta + 1)) { /* Lua function? */ | 1657 | if (luaD_precall(L, ra, LUA_MULTRET, delta + 1)) /* Lua function? */ |
| 1659 | ci->callstatus |= CIST_TAIL; | ||
| 1660 | goto startfunc; /* execute the callee */ | 1658 | goto startfunc; /* execute the callee */ |
| 1661 | } | ||
| 1662 | else { /* C function */ | 1659 | else { /* C function */ |
| 1663 | updatetrap(ci); | 1660 | updatetrap(ci); |
| 1664 | updatestack(ci); /* stack may have been relocated */ | ||
| 1665 | ci->func -= delta; /* restore 'func' (if vararg) */ | ||
| 1666 | luaD_poscall(L, ci, cast_int(L->top - ra)); /* finish caller */ | ||
| 1667 | updatetrap(ci); /* 'luaD_poscall' can change hooks */ | ||
| 1668 | goto ret; /* caller returns after the tail call */ | 1661 | goto ret; /* caller returns after the tail call */ |
| 1669 | } | 1662 | } |
| 1670 | } | 1663 | } |
