aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-02-07 13:18:04 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-02-07 13:18:04 -0200
commit318a9a5859826d7af0294664e206236fc8814319 (patch)
tree31a00af286880036e5ef165fbbdaf7df9a04cfc1
parent73d797ce7ea4c547cb97e39633a71a242c7356c8 (diff)
downloadlua-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.c19
-rw-r--r--lopcodes.c4
-rw-r--r--lopcodes.h2
-rw-r--r--lparser.c22
-rw-r--r--ltm.c5
-rw-r--r--ltm.h4
-rw-r--r--lvm.c23
7 files changed, 50 insertions, 29 deletions
diff --git a/ldo.c b/ldo.c
index d627941c..89c63350 100644
--- a/ldo.c
+++ b/ldo.c
@@ -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*/
303void luaD_hookcall (lua_State *L, CallInfo *ci) { 302void 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 }
diff --git a/lopcodes.c b/lopcodes.c
index a5867d23..cd85f1a9 100644
--- a/lopcodes.c
+++ b/lopcodes.c
@@ -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
diff --git a/lopcodes.h b/lopcodes.h
index 31bd12f8..47c72c69 100644
--- a/lopcodes.h
+++ b/lopcodes.h
@@ -288,6 +288,8 @@ OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx]) */
288 288
289OP_VARARG,/* A B C R(A), R(A+1), ..., R(A+C-2) = vararg(B) */ 289OP_VARARG,/* A B C R(A), R(A+1), ..., R(A+C-2) = vararg(B) */
290 290
291OP_PREPVARARG,/*A (adjust vararg parameters) */
292
291OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ 293OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
292} OpCode; 294} OpCode;
293 295
diff --git a/lparser.c b/lparser.c
index e99b33ff..aab03dc8 100644
--- a/lparser.c
+++ b/lparser.c
@@ -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
762static 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
763static void parlist (LexState *ls) { 768static 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);
diff --git a/ltm.c b/ltm.c
index 64622f20..f36f4625 100644
--- a/ltm.c
+++ b/ltm.c
@@ -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
219void luaT_adjustvarargs (lua_State *L, int nfixparams, int actual) { 219void 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 */
diff --git a/ltm.h b/ltm.h
index fbba067a..a0f4f92e 100644
--- a/ltm.h
+++ b/ltm.h
@@ -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,
77LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, 77LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2,
78 int inv, TMS event); 78 int inv, TMS event);
79 79
80LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams, int actual); 80LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams, StkId base);
81LUAI_FUNC void luaT_getvarargs (lua_State *L, TValue *t, StkId where, 81LUAI_FUNC void luaT_getvarargs (lua_State *L, TValue *t, StkId where,
82 int wanted); 82 int wanted);
83 83
diff --git a/lvm.c b/lvm.c
index d9814b62..7f2e2492 100644
--- a/lvm.c
+++ b/lvm.c
@@ -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;