diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-02-07 13:18:04 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-02-07 13:18:04 -0200 |
commit | 318a9a5859826d7af0294664e206236fc8814319 (patch) | |
tree | 31a00af286880036e5ef165fbbdaf7df9a04cfc1 | |
parent | 73d797ce7ea4c547cb97e39633a71a242c7356c8 (diff) | |
download | lua-318a9a5859826d7af0294664e206236fc8814319.tar.gz lua-318a9a5859826d7af0294664e206236fc8814319.tar.bz2 lua-318a9a5859826d7af0294664e206236fc8814319.zip |
new opcode 'PREPVARARG'
(avoids test for vararg function in all function calls)
-rw-r--r-- | ldo.c | 19 | ||||
-rw-r--r-- | lopcodes.c | 4 | ||||
-rw-r--r-- | lopcodes.h | 2 | ||||
-rw-r--r-- | lparser.c | 22 | ||||
-rw-r--r-- | ltm.c | 5 | ||||
-rw-r--r-- | ltm.h | 4 | ||||
-rw-r--r-- | lvm.c | 23 |
7 files changed, 50 insertions, 29 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 2.189 2018/01/29 16:21:35 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 2.190 2018/02/06 19:16:56 roberto Exp roberto $ |
3 | ** Stack and Call structure of Lua | 3 | ** Stack and Call structure of Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -297,15 +297,11 @@ void luaD_hook (lua_State *L, int event, int line) { | |||
297 | /* | 297 | /* |
298 | ** Executes a call hook for Lua functions. This function is called | 298 | ** Executes a call hook for Lua functions. This function is called |
299 | ** whenever 'hookmask' is not zero, so it checks whether call hooks are | 299 | ** whenever 'hookmask' is not zero, so it checks whether call hooks are |
300 | ** active. Also, this function can be called when resuming a function, | 300 | ** active. |
301 | ** so it checks whether the function is in its first instruction. | ||
302 | */ | 301 | */ |
303 | void luaD_hookcall (lua_State *L, CallInfo *ci) { | 302 | void luaD_hookcall (lua_State *L, CallInfo *ci) { |
304 | Proto *p = clLvalue(s2v(ci->func))->p; | ||
305 | int hook = (ci->callstatus & CIST_TAIL) ? LUA_HOOKTAILCALL : LUA_HOOKCALL; | 303 | int hook = (ci->callstatus & CIST_TAIL) ? LUA_HOOKTAILCALL : LUA_HOOKCALL; |
306 | ci->u.l.trap = 1; /* there may be other hooks */ | 304 | if (!(L->hookmask & LUA_MASKCALL)) /* some other hook? */ |
307 | if (!(L->hookmask & LUA_MASKCALL) || /* some other hook? */ | ||
308 | ci->u.l.savedpc != p->code) /* not 1st instruction? */ | ||
309 | return; /* don't call hook */ | 305 | return; /* don't call hook */ |
310 | L->top = ci->top; /* prepare top */ | 306 | L->top = ci->top; /* prepare top */ |
311 | ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ | 307 | ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ |
@@ -417,7 +413,7 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) { | |||
417 | int i; | 413 | int i; |
418 | for (i = 0; i < narg1; i++) /* move down function and arguments */ | 414 | for (i = 0; i < narg1; i++) /* move down function and arguments */ |
419 | setobjs2s(L, ci->func + i, func + i); | 415 | setobjs2s(L, ci->func + i, func + i); |
420 | checkstackp(L, fsize, func); | 416 | luaD_checkstackaux(L, fsize, (void)0, luaC_checkGC(L)); |
421 | func = ci->func; /* moved-down function */ | 417 | func = ci->func; /* moved-down function */ |
422 | for (; narg1 <= nfixparams; narg1++) | 418 | for (; narg1 <= nfixparams; narg1++) |
423 | setnilvalue(s2v(func + narg1)); /* complete missing arguments */ | 419 | setnilvalue(s2v(func + narg1)); /* complete missing arguments */ |
@@ -425,10 +421,7 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) { | |||
425 | lua_assert(ci->top <= L->stack_last); | 421 | lua_assert(ci->top <= L->stack_last); |
426 | ci->u.l.savedpc = p->code; /* starting point */ | 422 | ci->u.l.savedpc = p->code; /* starting point */ |
427 | ci->callstatus |= CIST_TAIL; | 423 | ci->callstatus |= CIST_TAIL; |
428 | if (p->is_vararg) { | 424 | L->top = func + narg1; /* set top */ |
429 | L->top = func + narg1; /* set top */ | ||
430 | luaT_adjustvarargs(L, nfixparams, narg1 - 1); | ||
431 | } | ||
432 | } | 425 | } |
433 | 426 | ||
434 | 427 | ||
@@ -481,8 +474,6 @@ void luaD_call (lua_State *L, StkId func, int nresults) { | |||
481 | lua_assert(ci->top <= L->stack_last); | 474 | lua_assert(ci->top <= L->stack_last); |
482 | ci->u.l.savedpc = p->code; /* starting point */ | 475 | ci->u.l.savedpc = p->code; /* starting point */ |
483 | ci->callstatus = 0; | 476 | ci->callstatus = 0; |
484 | if (p->is_vararg) | ||
485 | luaT_adjustvarargs(L, nfixparams, narg); /* may invoke GC */ | ||
486 | luaV_execute(L, ci); /* run the function */ | 477 | luaV_execute(L, ci); /* run the function */ |
487 | break; | 478 | break; |
488 | } | 479 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.c,v 1.74 2017/12/18 17:49:31 roberto Exp $ | 2 | ** $Id: lopcodes.c,v 1.75 2017/12/22 14:16:46 roberto Exp roberto $ |
3 | ** Opcodes for Lua virtual machine | 3 | ** Opcodes for Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -91,6 +91,7 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { | |||
91 | "SETLIST", | 91 | "SETLIST", |
92 | "CLOSURE", | 92 | "CLOSURE", |
93 | "VARARG", | 93 | "VARARG", |
94 | "PREPVARARG", | ||
94 | "EXTRAARG", | 95 | "EXTRAARG", |
95 | NULL | 96 | NULL |
96 | }; | 97 | }; |
@@ -171,6 +172,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { | |||
171 | ,opmode(0, 1, 0, 0, iABC) /* OP_SETLIST */ | 172 | ,opmode(0, 1, 0, 0, iABC) /* OP_SETLIST */ |
172 | ,opmode(0, 0, 0, 1, iABx) /* OP_CLOSURE */ | 173 | ,opmode(0, 0, 0, 1, iABx) /* OP_CLOSURE */ |
173 | ,opmode(1, 0, 0, 1, iABC) /* OP_VARARG */ | 174 | ,opmode(1, 0, 0, 1, iABC) /* OP_VARARG */ |
175 | ,opmode(0, 0, 0, 1, iABC) /* OP_PREPVARARG */ | ||
174 | ,opmode(0, 0, 0, 0, iAx) /* OP_EXTRAARG */ | 176 | ,opmode(0, 0, 0, 0, iAx) /* OP_EXTRAARG */ |
175 | }; | 177 | }; |
176 | 178 | ||
@@ -288,6 +288,8 @@ OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx]) */ | |||
288 | 288 | ||
289 | OP_VARARG,/* A B C R(A), R(A+1), ..., R(A+C-2) = vararg(B) */ | 289 | OP_VARARG,/* A B C R(A), R(A+1), ..., R(A+C-2) = vararg(B) */ |
290 | 290 | ||
291 | OP_PREPVARARG,/*A (adjust vararg parameters) */ | ||
292 | |||
291 | OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ | 293 | OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ |
292 | } OpCode; | 294 | } OpCode; |
293 | 295 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 2.174 2017/12/18 17:49:31 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 2.175 2017/12/22 14:16:46 roberto Exp roberto $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -759,12 +759,18 @@ static void constructor (LexState *ls, expdesc *t) { | |||
759 | /* }====================================================================== */ | 759 | /* }====================================================================== */ |
760 | 760 | ||
761 | 761 | ||
762 | static void setvararg (FuncState *fs, int nparams) { | ||
763 | fs->f->is_vararg = 1; | ||
764 | luaK_codeABC(fs, OP_PREPVARARG, nparams, 0, 0); | ||
765 | } | ||
766 | |||
762 | 767 | ||
763 | static void parlist (LexState *ls) { | 768 | static void parlist (LexState *ls) { |
764 | /* parlist -> [ param { ',' param } ] */ | 769 | /* parlist -> [ param { ',' param } ] */ |
765 | FuncState *fs = ls->fs; | 770 | FuncState *fs = ls->fs; |
766 | Proto *f = fs->f; | 771 | Proto *f = fs->f; |
767 | int nparams = 0; | 772 | int nparams = 0; |
773 | int isvararg = 0; | ||
768 | if (ls->t.token != ')') { /* is 'parlist' not empty? */ | 774 | if (ls->t.token != ')') { /* is 'parlist' not empty? */ |
769 | do { | 775 | do { |
770 | switch (ls->t.token) { | 776 | switch (ls->t.token) { |
@@ -779,17 +785,21 @@ static void parlist (LexState *ls) { | |||
779 | new_localvar(ls, str_checkname(ls)); | 785 | new_localvar(ls, str_checkname(ls)); |
780 | else | 786 | else |
781 | new_localvarliteral(ls, "_ARG"); | 787 | new_localvarliteral(ls, "_ARG"); |
782 | f->is_vararg = 1; /* declared vararg */ | ||
783 | nparams++; | 788 | nparams++; |
789 | isvararg = 1; | ||
784 | break; | 790 | break; |
785 | } | 791 | } |
786 | default: luaX_syntaxerror(ls, "<name> or '...' expected"); | 792 | default: luaX_syntaxerror(ls, "<name> or '...' expected"); |
787 | } | 793 | } |
788 | } while (!f->is_vararg && testnext(ls, ',')); | 794 | } while (!isvararg && testnext(ls, ',')); |
789 | } | 795 | } |
790 | adjustlocalvars(ls, nparams); | 796 | adjustlocalvars(ls, nparams); |
791 | f->numparams = cast_byte(fs->nactvar) - f->is_vararg; | 797 | f->numparams = cast_byte(fs->nactvar); |
792 | luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ | 798 | if (isvararg) { |
799 | f->numparams--; /* exclude vararg parameter */ | ||
800 | setvararg(fs, f->numparams); /* declared vararg */ | ||
801 | } | ||
802 | luaK_reserveregs(fs, fs->nactvar); /* reserve registers for parameters */ | ||
793 | } | 803 | } |
794 | 804 | ||
795 | 805 | ||
@@ -1692,7 +1702,7 @@ static void mainfunc (LexState *ls, FuncState *fs) { | |||
1692 | BlockCnt bl; | 1702 | BlockCnt bl; |
1693 | expdesc v; | 1703 | expdesc v; |
1694 | open_func(ls, fs, &bl); | 1704 | open_func(ls, fs, &bl); |
1695 | fs->f->is_vararg = 1; /* main function is always declared vararg */ | 1705 | setvararg(fs, 0); /* main function is always declared vararg */ |
1696 | fs->f->numparams = 0; | 1706 | fs->f->numparams = 0; |
1697 | new_localvarliteral(ls, "_ARG"); | 1707 | new_localvarliteral(ls, "_ARG"); |
1698 | adjustlocalvars(ls, 1); | 1708 | adjustlocalvars(ls, 1); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltm.c,v 2.57 2018/01/28 12:08:04 roberto Exp roberto $ | 2 | ** $Id: ltm.c,v 2.58 2018/01/28 13:39:52 roberto Exp roberto $ |
3 | ** Tag methods | 3 | ** Tag methods |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -216,10 +216,11 @@ int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, | |||
216 | } | 216 | } |
217 | 217 | ||
218 | 218 | ||
219 | void luaT_adjustvarargs (lua_State *L, int nfixparams, int actual) { | 219 | void luaT_adjustvarargs (lua_State *L, int nfixparams, StkId base) { |
220 | int i; | 220 | int i; |
221 | Table *vtab; | 221 | Table *vtab; |
222 | TValue nname; | 222 | TValue nname; |
223 | int actual = cast_int(L->top - base); /* number of arguments */ | ||
223 | int nextra = actual - nfixparams; /* number of extra arguments */ | 224 | int nextra = actual - nfixparams; /* number of extra arguments */ |
224 | vtab = luaH_new(L); /* create vararg table */ | 225 | vtab = luaH_new(L); /* create vararg table */ |
225 | sethvalue2s(L, L->top, vtab); /* anchor it for resizing */ | 226 | sethvalue2s(L, L->top, vtab); /* anchor it for resizing */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltm.h,v 2.28 2017/12/13 18:32:09 roberto Exp roberto $ | 2 | ** $Id: ltm.h,v 2.29 2018/01/28 13:39:52 roberto Exp roberto $ |
3 | ** Tag methods | 3 | ** Tag methods |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -77,7 +77,7 @@ LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1, | |||
77 | LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, | 77 | LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, |
78 | int inv, TMS event); | 78 | int inv, TMS event); |
79 | 79 | ||
80 | LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams, int actual); | 80 | LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams, StkId base); |
81 | LUAI_FUNC void luaT_getvarargs (lua_State *L, TValue *t, StkId where, | 81 | LUAI_FUNC void luaT_getvarargs (lua_State *L, TValue *t, StkId where, |
82 | int wanted); | 82 | int wanted); |
83 | 83 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.336 2018/01/29 16:21:35 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.337 2018/02/06 19:16:56 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 | */ |
@@ -835,12 +835,17 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
835 | int trap; | 835 | int trap; |
836 | tailcall: | 836 | tailcall: |
837 | trap = L->hookmask; | 837 | trap = L->hookmask; |
838 | if (trap) | ||
839 | luaD_hookcall(L, ci); | ||
840 | cl = clLvalue(s2v(ci->func)); | 838 | cl = clLvalue(s2v(ci->func)); |
841 | k = cl->p->k; | 839 | k = cl->p->k; |
842 | base = ci->func + 1; | ||
843 | pc = ci->u.l.savedpc; | 840 | pc = ci->u.l.savedpc; |
841 | if (trap) { | ||
842 | if (cl->p->is_vararg) | ||
843 | trap = 0; /* hooks will start with PREPVARARG instruction */ | ||
844 | else if (pc == cl->p->code) /* first instruction (not resuming)? */ | ||
845 | luaD_hookcall(L, ci); | ||
846 | ci->u.l.trap = 1; /* there may be other hooks */ | ||
847 | } | ||
848 | base = ci->func + 1; | ||
844 | /* main loop of interpreter */ | 849 | /* main loop of interpreter */ |
845 | for (;;) { | 850 | for (;;) { |
846 | int cond; /* flag for conditional jumps */ | 851 | int cond; /* flag for conditional jumps */ |
@@ -1701,6 +1706,16 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1701 | Protect(luaT_getvarargs(L, vtab, ra, n)); | 1706 | Protect(luaT_getvarargs(L, vtab, ra, n)); |
1702 | vmbreak; | 1707 | vmbreak; |
1703 | } | 1708 | } |
1709 | vmcase(OP_PREPVARARG) { | ||
1710 | luaT_adjustvarargs(L, GETARG_A(i), base); | ||
1711 | updatetrap(ci); | ||
1712 | if (trap) { | ||
1713 | luaD_hookcall(L, ci); | ||
1714 | L->oldpc = pc + 1; /* next opcode will be seen as a new line */ | ||
1715 | } | ||
1716 | updatebase(ci); | ||
1717 | vmbreak; | ||
1718 | } | ||
1704 | vmcase(OP_EXTRAARG) { | 1719 | vmcase(OP_EXTRAARG) { |
1705 | lua_assert(0); | 1720 | lua_assert(0); |
1706 | vmbreak; | 1721 | vmbreak; |