diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-07-15 15:38:16 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-07-15 15:38:16 -0300 |
| commit | 11d7ba79f2a84a4feda8013a7fb270e479b785f8 (patch) | |
| tree | 6d5b4fcab65af6f5b24e10d7fc9b1bcda13664eb | |
| parent | bd5fa9cc8fdd966edc46c3de2cc420a72240ead3 (diff) | |
| download | lua-11d7ba79f2a84a4feda8013a7fb270e479b785f8.tar.gz lua-11d7ba79f2a84a4feda8013a7fb270e479b785f8.tar.bz2 lua-11d7ba79f2a84a4feda8013a7fb270e479b785f8.zip | |
tail calls do not need to move whole new frame down, only its slice
up to last parameter (the rest has not been used yet)
| -rw-r--r-- | lvm.c | 20 |
1 files changed, 12 insertions, 8 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 2.93 2009/06/17 17:50:09 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.94 2009/07/01 20:31:25 roberto Exp roberto $ |
| 3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -461,7 +461,7 @@ void luaV_execute (lua_State *L) { | |||
| 461 | /* warning!! several calls may realloc the stack and invalidate `ra' */ | 461 | /* warning!! several calls may realloc the stack and invalidate `ra' */ |
| 462 | ra = RA(i); | 462 | ra = RA(i); |
| 463 | lua_assert(base == ci->u.l.base); | 463 | lua_assert(base == ci->u.l.base); |
| 464 | lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); | 464 | lua_assert(base <= L->top && L->top < L->stack + L->stacksize); |
| 465 | switch (GET_OPCODE(i)) { | 465 | switch (GET_OPCODE(i)) { |
| 466 | case OP_MOVE: { | 466 | case OP_MOVE: { |
| 467 | setobjs2s(L, ra, RB(i)); | 467 | setobjs2s(L, ra, RB(i)); |
| @@ -658,18 +658,22 @@ void luaV_execute (lua_State *L) { | |||
| 658 | /* tail call: put called frame (n) in place of caller one (o) */ | 658 | /* tail call: put called frame (n) in place of caller one (o) */ |
| 659 | CallInfo *nci = L->ci; /* called frame */ | 659 | CallInfo *nci = L->ci; /* called frame */ |
| 660 | CallInfo *oci = nci->previous; /* caller frame */ | 660 | CallInfo *oci = nci->previous; /* caller frame */ |
| 661 | StkId nfunc = nci->func; /* called function index */ | 661 | StkId nfunc = nci->func; /* called function */ |
| 662 | StkId ofunc = oci->func; | 662 | StkId ofunc = oci->func; /* caller function */ |
| 663 | /* last stack slot filled by 'precall' */ | ||
| 664 | StkId lim = nci->u.l.base + getproto(nfunc)->numparams; | ||
| 663 | int aux; | 665 | int aux; |
| 666 | /* close all upvalues from previous call */ | ||
| 664 | if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base); | 667 | if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base); |
| 665 | oci->u.l.base = ofunc + (nci->u.l.base - nfunc); | 668 | /* move new frame into old one */ |
| 666 | for (aux = 0; nfunc+aux < L->top; aux++) /* move frame down */ | 669 | for (aux = 0; nfunc + aux < lim; aux++) |
| 667 | setobjs2s(L, ofunc + aux, nfunc + aux); | 670 | setobjs2s(L, ofunc + aux, nfunc + aux); |
| 668 | oci->top = L->top = ofunc + aux; /* correct top */ | 671 | oci->u.l.base = ofunc + (nci->u.l.base - nfunc); /* correct base */ |
| 669 | lua_assert(L->top == oci->u.l.base + clvalue(ofunc)->l.p->maxstacksize); | 672 | oci->top = L->top = ofunc + (L->top - nfunc); /* correct top */ |
| 670 | oci->u.l.savedpc = nci->u.l.savedpc; | 673 | oci->u.l.savedpc = nci->u.l.savedpc; |
| 671 | oci->u.l.tailcalls++; /* one more call lost */ | 674 | oci->u.l.tailcalls++; /* one more call lost */ |
| 672 | ci = L->ci = oci; /* remove new frame */ | 675 | ci = L->ci = oci; /* remove new frame */ |
| 676 | lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize); | ||
| 673 | break; /* restart luaV_execute over new Lua function */ | 677 | break; /* restart luaV_execute over new Lua function */ |
| 674 | } | 678 | } |
| 675 | } | 679 | } |
