diff options
| -rw-r--r-- | ldo.c | 81 | ||||
| -rw-r--r-- | ldo.h | 2 | ||||
| -rw-r--r-- | lvm.c | 19 |
3 files changed, 58 insertions, 44 deletions
| @@ -475,30 +475,6 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { | |||
| 475 | #define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L)) | 475 | #define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L)) |
| 476 | 476 | ||
| 477 | 477 | ||
| 478 | /* | ||
| 479 | ** Prepare a function for a tail call, building its call info on top | ||
| 480 | ** of the current call info. 'narg1' is the number of arguments plus 1 | ||
| 481 | ** (so that it includes the function itself). | ||
| 482 | */ | ||
| 483 | void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) { | ||
| 484 | Proto *p = clLvalue(s2v(func))->p; | ||
| 485 | int fsize = p->maxstacksize; /* frame size */ | ||
| 486 | int nfixparams = p->numparams; | ||
| 487 | int i; | ||
| 488 | for (i = 0; i < narg1; i++) /* move down function and arguments */ | ||
| 489 | setobjs2s(L, ci->func + i, func + i); | ||
| 490 | checkstackGC(L, fsize); | ||
| 491 | func = ci->func; /* moved-down function */ | ||
| 492 | for (; narg1 <= nfixparams; narg1++) | ||
| 493 | setnilvalue(s2v(func + narg1)); /* complete missing arguments */ | ||
| 494 | ci->top = func + 1 + fsize; /* top for new function */ | ||
| 495 | lua_assert(ci->top <= L->stack_last); | ||
| 496 | ci->u.l.savedpc = p->code; /* starting point */ | ||
| 497 | ci->callstatus |= CIST_TAIL; | ||
| 498 | L->top = func + narg1; /* set top */ | ||
| 499 | } | ||
| 500 | |||
| 501 | |||
| 502 | l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret, | 478 | l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret, |
| 503 | int mask, StkId top) { | 479 | int mask, StkId top) { |
| 504 | CallInfo *ci = L->ci = next_ci(L); /* new frame */ | 480 | CallInfo *ci = L->ci = next_ci(L); /* new frame */ |
| @@ -513,7 +489,7 @@ l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret, | |||
| 513 | /* | 489 | /* |
| 514 | ** precall for C functions | 490 | ** precall for C functions |
| 515 | */ | 491 | */ |
| 516 | l_sinline CallInfo *precallC (lua_State *L, StkId func, int nresults, | 492 | l_sinline int precallC (lua_State *L, StkId func, int nresults, |
| 517 | lua_CFunction f) { | 493 | lua_CFunction f) { |
| 518 | int n; /* number of returns */ | 494 | int n; /* number of returns */ |
| 519 | CallInfo *ci; | 495 | CallInfo *ci; |
| @@ -530,7 +506,50 @@ l_sinline CallInfo *precallC (lua_State *L, StkId func, int nresults, | |||
| 530 | lua_lock(L); | 506 | lua_lock(L); |
| 531 | api_checknelems(L, n); | 507 | api_checknelems(L, n); |
| 532 | luaD_poscall(L, ci, n); | 508 | luaD_poscall(L, ci, n); |
| 533 | return NULL; | 509 | return n; |
| 510 | } | ||
| 511 | |||
| 512 | |||
| 513 | /* | ||
| 514 | ** Prepare a function for a tail call, building its call info on top | ||
| 515 | ** of the current call info. 'narg1' is the number of arguments plus 1 | ||
| 516 | ** (so that it includes the function itself). Return the number of | ||
| 517 | ** results, if it was a C function, or -1 for a Lua function. | ||
| 518 | */ | ||
| 519 | int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, | ||
| 520 | int narg1, int delta) { | ||
| 521 | retry: | ||
| 522 | switch (ttypetag(s2v(func))) { | ||
| 523 | case LUA_VCCL: /* C closure */ | ||
| 524 | return precallC(L, func, LUA_MULTRET, clCvalue(s2v(func))->f); | ||
| 525 | case LUA_VLCF: /* light C function */ | ||
| 526 | return precallC(L, func, LUA_MULTRET, fvalue(s2v(func))); | ||
| 527 | case LUA_VLCL: { /* Lua function */ | ||
| 528 | Proto *p = clLvalue(s2v(func))->p; | ||
| 529 | int fsize = p->maxstacksize; /* frame size */ | ||
| 530 | int nfixparams = p->numparams; | ||
| 531 | int i; | ||
| 532 | ci->func -= delta; /* restore 'func' (if vararg) */ | ||
| 533 | for (i = 0; i < narg1; i++) /* move down function and arguments */ | ||
| 534 | setobjs2s(L, ci->func + i, func + i); | ||
| 535 | checkstackGC(L, fsize); | ||
| 536 | func = ci->func; /* moved-down function */ | ||
| 537 | for (; narg1 <= nfixparams; narg1++) | ||
| 538 | setnilvalue(s2v(func + narg1)); /* complete missing arguments */ | ||
| 539 | ci->top = func + 1 + fsize; /* top for new function */ | ||
| 540 | lua_assert(ci->top <= L->stack_last); | ||
| 541 | ci->u.l.savedpc = p->code; /* starting point */ | ||
| 542 | ci->callstatus |= CIST_TAIL; | ||
| 543 | L->top = func + narg1; /* set top */ | ||
| 544 | return -1; | ||
| 545 | } | ||
| 546 | default: { /* not a function */ | ||
| 547 | func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */ | ||
| 548 | /* return luaD_pretailcall(L, ci, func, narg1 + 1, delta); */ | ||
| 549 | narg1++; | ||
| 550 | goto retry; /* try again */ | ||
| 551 | } | ||
| 552 | } | ||
| 534 | } | 553 | } |
| 535 | 554 | ||
| 536 | 555 | ||
| @@ -543,11 +562,14 @@ l_sinline CallInfo *precallC (lua_State *L, StkId func, int nresults, | |||
| 543 | ** original function position. | 562 | ** original function position. |
| 544 | */ | 563 | */ |
| 545 | CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { | 564 | CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { |
| 565 | retry: | ||
| 546 | switch (ttypetag(s2v(func))) { | 566 | switch (ttypetag(s2v(func))) { |
| 547 | case LUA_VCCL: /* C closure */ | 567 | case LUA_VCCL: /* C closure */ |
| 548 | return precallC(L, func, nresults, clCvalue(s2v(func))->f); | 568 | precallC(L, func, nresults, clCvalue(s2v(func))->f); |
| 569 | return NULL; | ||
| 549 | case LUA_VLCF: /* light C function */ | 570 | case LUA_VLCF: /* light C function */ |
| 550 | return precallC(L, func, nresults, fvalue(s2v(func))); | 571 | precallC(L, func, nresults, fvalue(s2v(func))); |
| 572 | return NULL; | ||
| 551 | case LUA_VLCL: { /* Lua function */ | 573 | case LUA_VLCL: { /* Lua function */ |
| 552 | CallInfo *ci; | 574 | CallInfo *ci; |
| 553 | Proto *p = clLvalue(s2v(func))->p; | 575 | Proto *p = clLvalue(s2v(func))->p; |
| @@ -564,7 +586,8 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { | |||
| 564 | } | 586 | } |
| 565 | default: { /* not a function */ | 587 | default: { /* not a function */ |
| 566 | func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */ | 588 | func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */ |
| 567 | return luaD_precall(L, func, nresults); /* try again with metamethod */ | 589 | /* return luaD_precall(L, func, nresults); */ |
| 590 | goto retry; /* try again with metamethod */ | ||
| 568 | } | 591 | } |
| 569 | } | 592 | } |
| 570 | } | 593 | } |
| @@ -58,7 +58,7 @@ LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, | |||
| 58 | LUAI_FUNC void luaD_hook (lua_State *L, int event, int line, | 58 | LUAI_FUNC void luaD_hook (lua_State *L, int event, int line, |
| 59 | int fTransfer, int nTransfer); | 59 | int fTransfer, int nTransfer); |
| 60 | LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci); | 60 | LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci); |
| 61 | LUAI_FUNC void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n); | 61 | LUAI_FUNC int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1, int delta); |
| 62 | LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults); | 62 | LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults); |
| 63 | LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); | 63 | LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); |
| 64 | LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults); | 64 | LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults); |
| @@ -1643,6 +1643,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1643 | } | 1643 | } |
| 1644 | vmcase(OP_TAILCALL) { | 1644 | vmcase(OP_TAILCALL) { |
| 1645 | int b = GETARG_B(i); /* number of arguments + 1 (function) */ | 1645 | int b = GETARG_B(i); /* number of arguments + 1 (function) */ |
| 1646 | int n; /* number of results when calling a C function */ | ||
| 1646 | int nparams1 = GETARG_C(i); | 1647 | int nparams1 = GETARG_C(i); |
| 1647 | /* delta is virtual 'func' - real 'func' (vararg functions) */ | 1648 | /* delta is virtual 'func' - real 'func' (vararg functions) */ |
| 1648 | int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0; | 1649 | int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0; |
| @@ -1656,24 +1657,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1656 | lua_assert(L->tbclist < base); /* no pending tbc variables */ | 1657 | lua_assert(L->tbclist < base); /* no pending tbc variables */ |
| 1657 | lua_assert(base == ci->func + 1); | 1658 | lua_assert(base == ci->func + 1); |
| 1658 | } | 1659 | } |
| 1659 | while (!ttisfunction(s2v(ra))) { /* not a function? */ | 1660 | if ((n = luaD_pretailcall(L, ci, ra, b, delta)) < 0) /* Lua function? */ |
| 1660 | ra = luaD_tryfuncTM(L, ra); /* try '__call' metamethod */ | 1661 | goto startfunc; /* execute the callee */ |
| 1661 | b++; /* there is now one extra argument */ | 1662 | else { /* C function? */ |
| 1662 | } | ||
| 1663 | if (!ttisLclosure(s2v(ra))) { /* C function? */ | ||
| 1664 | luaD_precall(L, ra, LUA_MULTRET); /* call it */ | ||
| 1665 | updatetrap(ci); | ||
| 1666 | updatestack(ci); /* stack may have been relocated */ | ||
| 1667 | ci->func -= delta; /* restore 'func' (if vararg) */ | 1663 | ci->func -= delta; /* restore 'func' (if vararg) */ |
| 1668 | luaD_poscall(L, ci, cast_int(L->top - ra)); /* finish caller */ | 1664 | luaD_poscall(L, ci, n); /* finish caller */ |
| 1669 | updatetrap(ci); /* 'luaD_poscall' can change hooks */ | 1665 | updatetrap(ci); /* 'luaD_poscall' can change hooks */ |
| 1670 | goto ret; /* caller returns after the tail call */ | 1666 | goto ret; /* caller returns after the tail call */ |
| 1671 | } | 1667 | } |
| 1672 | else { /* Lua function */ | ||
| 1673 | ci->func -= delta; /* restore 'func' (if vararg) */ | ||
| 1674 | luaD_pretailcall(L, ci, ra, b); /* prepare call frame */ | ||
| 1675 | goto startfunc; /* execute the callee */ | ||
| 1676 | } | ||
| 1677 | } | 1668 | } |
| 1678 | vmcase(OP_RETURN) { | 1669 | vmcase(OP_RETURN) { |
| 1679 | int n = GETARG_B(i) - 1; /* number of results */ | 1670 | int n = GETARG_B(i) - 1; /* number of results */ |
