aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-01-28 11:39:52 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-01-28 11:39:52 -0200
commit89110986d7a9e81960261ae682780d5fd06dc4ac (patch)
tree5fe3d0039b2152223b58adc33a4b6c916fc853d8
parent53979dfe0dbd7eba767ff37b1148d1e4dc9f8294 (diff)
downloadlua-89110986d7a9e81960261ae682780d5fd06dc4ac.tar.gz
lua-89110986d7a9e81960261ae682780d5fd06dc4ac.tar.bz2
lua-89110986d7a9e81960261ae682780d5fd06dc4ac.zip
bug in tailcall of vararg functions
(when adjusting missing parameters)
-rw-r--r--ldo.c29
-rw-r--r--ltm.c17
-rw-r--r--ltm.h4
3 files changed, 26 insertions, 24 deletions
diff --git a/ldo.c b/ldo.c
index 50ab0012..15bec173 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.c,v 2.186 2018/01/10 19:19:27 roberto Exp roberto $ 2** $Id: ldo.c,v 2.187 2018/01/28 12:08:04 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*/
@@ -405,25 +405,27 @@ void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) {
405 405
406/* 406/*
407** Prepare a function for a tail call, building its call info on top 407** Prepare a function for a tail call, building its call info on top
408** of the current call info. 'n' is the number of arguments plus 1 408** of the current call info. 'narg1' is the number of arguments plus 1
409** (so that it includes the function itself). 409** (so that it includes the function itself).
410*/ 410*/
411void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n) { 411void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) {
412 Proto *p = clLvalue(s2v(func))->p; 412 Proto *p = clLvalue(s2v(func))->p;
413 int fsize = p->maxstacksize; /* frame size */ 413 int fsize = p->maxstacksize; /* frame size */
414 int nfixparams = p->numparams;
414 int i; 415 int i;
415 for (i = 0; i < n; i++) /* move down function and arguments */ 416 for (i = 0; i < narg1; i++) /* move down function and arguments */
416 setobjs2s(L, ci->func + i, func + i); 417 setobjs2s(L, ci->func + i, func + i);
417 checkstackp(L, fsize, func); 418 checkstackp(L, fsize, func);
418 for (; i <= p->numparams; i++) 419 func = ci->func; /* moved-down function */
419 setnilvalue(s2v(ci->func + i)); /* complete missing arguments */ 420 for (; narg1 <= nfixparams; narg1++)
420 ci->top = ci->func + 1 + fsize; /* top for new function */ 421 setnilvalue(s2v(func + narg1)); /* complete missing arguments */
422 ci->top = func + 1 + fsize; /* top for new function */
421 lua_assert(ci->top <= L->stack_last); 423 lua_assert(ci->top <= L->stack_last);
422 ci->u.l.savedpc = p->code; /* starting point */ 424 ci->u.l.savedpc = p->code; /* starting point */
423 ci->callstatus |= CIST_TAIL; 425 ci->callstatus |= CIST_TAIL;
424 if (p->is_vararg) { 426 if (p->is_vararg) {
425 L->top -= (func - ci->func); /* move down top */ 427 L->top = func + narg1; /* set top */
426 luaT_adjustvarargs(L, p, n - 1); 428 luaT_adjustvarargs(L, nfixparams, narg1 - 1);
427 } 429 }
428 if (L->hookmask) 430 if (L->hookmask)
429 hookcall(L, ci, 1); 431 hookcall(L, ci, 1);
@@ -464,12 +466,13 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
464 luaD_poscall(L, ci, L->top - n, n); 466 luaD_poscall(L, ci, L->top - n, n);
465 break; 467 break;
466 } 468 }
467 case LUA_TLCL: { /* Lua function: prepare its call */ 469 case LUA_TLCL: { /* Lua function */
468 Proto *p = clLvalue(funcv)->p; 470 Proto *p = clLvalue(funcv)->p;
469 int n = cast_int(L->top - func) - 1; /* number of real arguments */ 471 int narg = cast_int(L->top - func) - 1; /* number of real arguments */
472 int nfixparams = p->numparams;
470 int fsize = p->maxstacksize; /* frame size */ 473 int fsize = p->maxstacksize; /* frame size */
471 checkstackp(L, fsize, func); 474 checkstackp(L, fsize, func);
472 for (; n < p->numparams; n++) 475 for (; narg < nfixparams; narg++)
473 setnilvalue(s2v(L->top++)); /* complete missing arguments */ 476 setnilvalue(s2v(L->top++)); /* complete missing arguments */
474 ci = next_ci(L); /* now 'enter' new function */ 477 ci = next_ci(L); /* now 'enter' new function */
475 ci->nresults = nresults; 478 ci->nresults = nresults;
@@ -479,7 +482,7 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
479 ci->u.l.savedpc = p->code; /* starting point */ 482 ci->u.l.savedpc = p->code; /* starting point */
480 ci->callstatus = 0; 483 ci->callstatus = 0;
481 if (p->is_vararg) 484 if (p->is_vararg)
482 luaT_adjustvarargs(L, p, n); /* may invoke GC */ 485 luaT_adjustvarargs(L, nfixparams, narg); /* may invoke GC */
483 if (L->hookmask) 486 if (L->hookmask)
484 hookcall(L, ci, 0); 487 hookcall(L, ci, 0);
485 luaV_execute(L, ci); /* run the function */ 488 luaV_execute(L, ci); /* run the function */
diff --git a/ltm.c b/ltm.c
index 8108abb2..64622f20 100644
--- a/ltm.c
+++ b/ltm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltm.c,v 2.56 2017/12/28 15:42:57 roberto Exp roberto $ 2** $Id: ltm.c,v 2.57 2018/01/28 12:08:04 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,21 +216,20 @@ int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2,
216} 216}
217 217
218 218
219void luaT_adjustvarargs (lua_State *L, Proto *p, int actual) { 219void luaT_adjustvarargs (lua_State *L, int nfixparams, int actual) {
220 int i; 220 int i;
221 Table *vtab; 221 Table *vtab;
222 TValue nname; 222 TValue nname;
223 int nfixparams = p->numparams; /* number of fixed parameters */ 223 int nextra = actual - nfixparams; /* number of extra arguments */
224 actual -= nfixparams; /* number of extra arguments */
225 vtab = luaH_new(L); /* create vararg table */ 224 vtab = luaH_new(L); /* create vararg table */
226 sethvalue2s(L, L->top, vtab); /* anchor it for resizing */ 225 sethvalue2s(L, L->top, vtab); /* anchor it for resizing */
227 L->top++; /* space ensured by caller */ 226 L->top++; /* space ensured by caller */
228 luaH_resize(L, vtab, actual, 1); 227 luaH_resize(L, vtab, nextra, 1);
229 for (i = 0; i < actual; i++) /* put extra arguments into vararg table */ 228 for (i = 0; i < nextra; i++) /* put extra arguments into vararg table */
230 setobj2n(L, &vtab->array[i], s2v(L->top - actual + i - 1)); 229 setobj2n(L, &vtab->array[i], s2v(L->top - nextra + i - 1));
231 setsvalue(L, &nname, G(L)->nfield); /* get field 'n' */ 230 setsvalue(L, &nname, G(L)->nfield); /* get field 'n' */
232 setivalue(luaH_set(L, vtab, &nname), actual); /* store counter there */ 231 setivalue(luaH_set(L, vtab, &nname), nextra); /* store counter there */
233 L->top -= actual; /* remove extra elements from the stack */ 232 L->top -= nextra; /* remove extra elements from the stack */
234 sethvalue2s(L, L->top - 1, vtab); /* move table to new top */ 233 sethvalue2s(L, L->top - 1, vtab); /* move table to new top */
235 luaC_checkGC(L); 234 luaC_checkGC(L);
236} 235}
diff --git a/ltm.h b/ltm.h
index 34dbc82c..fbba067a 100644
--- a/ltm.h
+++ b/ltm.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltm.h,v 2.27 2017/11/27 17:44:31 roberto Exp roberto $ 2** $Id: ltm.h,v 2.28 2017/12/13 18:32:09 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, Proto *p, int actual); 80LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams, int actual);
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