aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lcode.c32
-rw-r--r--ldo.c24
-rw-r--r--ldo.h5
-rw-r--r--lopcodes.c4
-rw-r--r--lopcodes.h22
-rw-r--r--ltm.c10
-rw-r--r--lvm.c60
7 files changed, 80 insertions, 77 deletions
diff --git a/lcode.c b/lcode.c
index 25fb0770..eb5a2c82 100644
--- a/lcode.c
+++ b/lcode.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lcode.c,v 2.152 2018/01/28 15:13:26 roberto Exp roberto $ 2** $Id: lcode.c,v 2.153 2018/02/09 15:16:06 roberto Exp roberto $
3** Code generator for Lua 3** Code generator for Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -158,16 +158,12 @@ int luaK_jump (FuncState *fs) {
158*/ 158*/
159void luaK_ret (FuncState *fs, int first, int nret) { 159void luaK_ret (FuncState *fs, int first, int nret) {
160 OpCode op; 160 OpCode op;
161 if (fs->f->is_vararg) 161 switch (nret) {
162 op = OP_RETVARARG; 162 case 0: op = OP_RETURN0; break;
163 else { 163 case 1: op = OP_RETURN1; break;
164 switch (nret) { 164 default: op = OP_RETURN; break;
165 case 0: op = OP_RETURN0; break;
166 case 1: op = OP_RETURN1; break;
167 default: op = OP_RETURN; break;
168 }
169 } 165 }
170 luaK_codeABC(fs, op, first, nret + 1, fs->f->numparams); 166 luaK_codeABC(fs, op, first, nret + 1, 0);
171} 167}
172 168
173 169
@@ -1646,10 +1642,18 @@ void luaK_finish (FuncState *fs) {
1646 Instruction *pc = &p->code[i]; 1642 Instruction *pc = &p->code[i];
1647 lua_assert(i == 0 || isOT(*(pc - 1)) == isIT(*pc)); 1643 lua_assert(i == 0 || isOT(*(pc - 1)) == isIT(*pc));
1648 switch (GET_OPCODE(*pc)) { 1644 switch (GET_OPCODE(*pc)) {
1649 case OP_RETURN: case OP_RETURN0: case OP_RETURN1: 1645 case OP_RETURN0: case OP_RETURN1: {
1650 case OP_RETVARARG: case OP_TAILCALL: { 1646 if (p->sizep == 0 && !p->is_vararg)
1651 if (p->sizep > 0) 1647 break; /* no extra work */
1652 SETARG_k(*pc, 1); /* signal that they must close upvalues */ 1648 /* else use OP_RETURN to do the extra work */
1649 SET_OPCODE(*pc, OP_RETURN);
1650 /* FALLTHROUGH */
1651 }
1652 case OP_RETURN: case OP_TAILCALL: {
1653 if (p->sizep > 0 || p->is_vararg) {
1654 SETARG_C(*pc, p->is_vararg ? p->numparams + 1 : 0);
1655 SETARG_k(*pc, 1); /* signal that there is extra work */
1656 }
1653 break; 1657 break;
1654 } 1658 }
1655 case OP_JMP: { 1659 case OP_JMP: {
diff --git a/ldo.c b/ldo.c
index 64512487..19d6aefd 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.c,v 2.192 2018/02/07 15:55:18 roberto Exp roberto $ 2** $Id: ldo.c,v 2.193 2018/02/09 15:16:06 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*/
@@ -310,11 +310,19 @@ void luaD_hookcall (lua_State *L, CallInfo *ci) {
310} 310}
311 311
312 312
313void luaD_rethook (lua_State *L, CallInfo *ci) { 313static void rethook (lua_State *L, CallInfo *ci) {
314 if (isLuacode(ci)) 314 int delta = 0;
315 if (isLuacode(ci)) {
316 Proto *p = clLvalue(s2v(ci->func))->p;
317 if (p->is_vararg)
318 delta = ci->u.l.nextraargs + p->numparams + 1;
315 L->top = ci->top; /* prepare top */ 319 L->top = ci->top; /* prepare top */
316 if (L->hookmask & LUA_MASKRET) /* is return hook on? */ 320 }
321 if (L->hookmask & LUA_MASKRET) { /* is return hook on? */
322 ci->func += delta; /* if vararg, back to virtual 'func' */
317 luaD_hook(L, LUA_HOOKRET, -1); /* call it */ 323 luaD_hook(L, LUA_HOOKRET, -1); /* call it */
324 ci->func -= delta;
325 }
318 if (isLua(ci->previous)) 326 if (isLua(ci->previous))
319 L->oldpc = ci->previous->u.l.savedpc; /* update 'oldpc' */ 327 L->oldpc = ci->previous->u.l.savedpc; /* update 'oldpc' */
320} 328}
@@ -343,8 +351,8 @@ void luaD_tryfuncTM (lua_State *L, StkId func) {
343** expressions, multiple results for tail calls/single parameters) 351** expressions, multiple results for tail calls/single parameters)
344** separated. 352** separated.
345*/ 353*/
346void luaD_moveresults (lua_State *L, StkId firstResult, StkId res, 354static void moveresults (lua_State *L, StkId firstResult, StkId res,
347 int nres, int wanted) { 355 int nres, int wanted) {
348 switch (wanted) { /* handle typical cases separately */ 356 switch (wanted) { /* handle typical cases separately */
349 case 0: break; /* nothing to move */ 357 case 0: break; /* nothing to move */
350 case 1: { /* one result needed */ 358 case 1: { /* one result needed */
@@ -387,12 +395,12 @@ void luaD_moveresults (lua_State *L, StkId firstResult, StkId res,
387void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { 395void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) {
388 if (L->hookmask) { 396 if (L->hookmask) {
389 ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ 397 ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */
390 luaD_rethook(L, ci); 398 rethook(L, ci);
391 firstResult = restorestack(L, fr); 399 firstResult = restorestack(L, fr);
392 } 400 }
393 L->ci = ci->previous; /* back to caller */ 401 L->ci = ci->previous; /* back to caller */
394 /* move results to proper place */ 402 /* move results to proper place */
395 luaD_moveresults(L, firstResult, ci->func, nres, ci->nresults); 403 moveresults(L, firstResult, ci->func, nres, ci->nresults);
396} 404}
397 405
398 406
diff --git a/ldo.h b/ldo.h
index 864cf3e6..9d976b32 100644
--- a/ldo.h
+++ b/ldo.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.h,v 2.40 2018/02/06 19:16:56 roberto Exp roberto $ 2** $Id: ldo.h,v 2.41 2018/02/09 15:16:06 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*/
@@ -62,10 +62,7 @@ LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
62 ptrdiff_t oldtop, ptrdiff_t ef); 62 ptrdiff_t oldtop, ptrdiff_t ef);
63LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, 63LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult,
64 int nres); 64 int nres);
65LUAI_FUNC void luaD_rethook (lua_State *L, CallInfo *ci);
66LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror); 65LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror);
67LUAI_FUNC void luaD_moveresults (lua_State *L, StkId firstResult, StkId res,
68 int nres, int wanted);
69LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror); 66LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror);
70LUAI_FUNC void luaD_shrinkstack (lua_State *L); 67LUAI_FUNC void luaD_shrinkstack (lua_State *L);
71LUAI_FUNC void luaD_inctop (lua_State *L); 68LUAI_FUNC void luaD_inctop (lua_State *L);
diff --git a/lopcodes.c b/lopcodes.c
index d04e707f..aa3055be 100644
--- a/lopcodes.c
+++ b/lopcodes.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lopcodes.c,v 1.76 2018/02/07 15:18:04 roberto Exp roberto $ 2** $Id: lopcodes.c,v 1.77 2018/02/09 15:16:06 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*/
@@ -80,7 +80,6 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
80 "CALL", 80 "CALL",
81 "TAILCALL", 81 "TAILCALL",
82 "RETURN", 82 "RETURN",
83 "RETVARARG",
84 "RETURN0", 83 "RETURN0",
85 "RETURN1", 84 "RETURN1",
86 "FORLOOP1", 85 "FORLOOP1",
@@ -162,7 +161,6 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
162 ,opmode(1, 1, 0, 1, iABC) /* OP_CALL */ 161 ,opmode(1, 1, 0, 1, iABC) /* OP_CALL */
163 ,opmode(1, 1, 0, 1, iABC) /* OP_TAILCALL */ 162 ,opmode(1, 1, 0, 1, iABC) /* OP_TAILCALL */
164 ,opmode(0, 1, 0, 0, iABC) /* OP_RETURN */ 163 ,opmode(0, 1, 0, 0, iABC) /* OP_RETURN */
165 ,opmode(0, 1, 0, 0, iABC) /* OP_RETVARARG */
166 ,opmode(0, 0, 0, 0, iABC) /* OP_RETURN0 */ 164 ,opmode(0, 0, 0, 0, iABC) /* OP_RETURN0 */
167 ,opmode(0, 0, 0, 0, iABC) /* OP_RETURN1 */ 165 ,opmode(0, 0, 0, 0, iABC) /* OP_RETURN1 */
168 ,opmode(0, 0, 0, 1, iABx) /* OP_FORLOOP1 */ 166 ,opmode(0, 0, 0, 1, iABx) /* OP_FORLOOP1 */
diff --git a/lopcodes.h b/lopcodes.h
index 3c7a9573..b2e22c27 100644
--- a/lopcodes.h
+++ b/lopcodes.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lopcodes.h,v 1.186 2018/02/07 15:18:04 roberto Exp roberto $ 2** $Id: lopcodes.h,v 1.187 2018/02/09 15:16:06 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*/
@@ -267,8 +267,7 @@ OP_TESTSET,/* A B if (not R(B) == k) then R(A) := R(B) else pc++ */
267OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ 267OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
268OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ 268OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
269 269
270OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ 270OP_RETURN,/* A B C return R(A), ... ,R(A+B-2) (see note) */
271OP_RETVARARG,/* A B return R(A), ... ,R(A+B-2) (see note) */
272OP_RETURN0,/* return */ 271OP_RETURN0,/* return */
273OP_RETURN1,/* A return R(A) */ 272OP_RETURN1,/* A return R(A) */
274 273
@@ -302,14 +301,13 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
302/*=========================================================================== 301/*===========================================================================
303 Notes: 302 Notes:
304 (*) In OP_CALL, if (B == 0) then B = top. If (C == 0), then 'top' is 303 (*) In OP_CALL, if (B == 0) then B = top. If (C == 0), then 'top' is
305 set to last_result+1, so next open instruction (OP_CALL, OP_RETURN, 304 set to last_result+1, so next open instruction (OP_CALL, OP_RETURN*,
306 OP_SETLIST) may use 'top'. 305 OP_SETLIST) may use 'top'.
307 306
308 (*) In OP_VARARG, if (C == 0) then use actual number of varargs and 307 (*) In OP_VARARG, if (C == 0) then use actual number of varargs and
309 set top (like in OP_CALL with C == 0). 308 set top (like in OP_CALL with C == 0).
310 309
311 (*) In OP_RETURN/OP_RETVARARG, if (B == 0) then return up to 'top'. 310 (*) In OP_RETURN, if (B == 0) then return up to 'top'.
312 (OP_RETVARARG is the return instruction for vararg functions.)
313 311
314 (*) In OP_SETLIST, if (B == 0) then real B = 'top'; if (C == 0) then 312 (*) In OP_SETLIST, if (B == 0) then real B = 'top'; if (C == 0) then
315 next 'instruction' is EXTRAARG(real C). 313 next 'instruction' is EXTRAARG(real C).
@@ -326,9 +324,11 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
326 324
327 (*) All 'skips' (pc++) assume that next instruction is a jump. 325 (*) All 'skips' (pc++) assume that next instruction is a jump.
328 326
329 (*) In instructions ending a function (OP_RETURN*, OP_TAILCALL), k 327 (*) In instructions OP_RETURN/OP_TAILCALL, 'k' specifies that the
330 specifies that the function builds upvalues, which may need to be 328 function either builds upvalues, which may need to be closed, or is
331 closed. 329 vararg, which must be corrected before returning. When 'k' is true,
330 C > 0 means the function is vararg and (C - 1) is its number of
331 fixed parameters.
332 332
333===========================================================================*/ 333===========================================================================*/
334 334
@@ -351,7 +351,9 @@ LUAI_DDEC const lu_byte luaP_opmodes[NUM_OPCODES];
351#define testOTMode(m) (luaP_opmodes[m] & (1 << 6)) 351#define testOTMode(m) (luaP_opmodes[m] & (1 << 6))
352 352
353/* "out top" (set top for next instruction) */ 353/* "out top" (set top for next instruction) */
354#define isOT(i) (testOTMode(GET_OPCODE(i)) && GETARG_C(i) == 0) 354#define isOT(i) \
355 ((testOTMode(GET_OPCODE(i)) && GETARG_C(i) == 0) || \
356 GET_OPCODE(i) == OP_TAILCALL)
355 357
356/* "in top" (uses top from previous instruction) */ 358/* "in top" (uses top from previous instruction) */
357#define isIT(i) (testITMode(GET_OPCODE(i)) && GETARG_B(i) == 0) 359#define isIT(i) (testITMode(GET_OPCODE(i)) && GETARG_B(i) == 0)
diff --git a/ltm.c b/ltm.c
index d88b636b..be7dc4f0 100644
--- a/ltm.c
+++ b/ltm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltm.c,v 2.59 2018/02/07 15:18:04 roberto Exp roberto $ 2** $Id: ltm.c,v 2.60 2018/02/09 15:16:06 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*/
@@ -222,10 +222,12 @@ void luaT_adjustvarargs (lua_State *L, int nfixparams, CallInfo *ci) {
222 int nextra = actual - nfixparams; /* number of extra arguments */ 222 int nextra = actual - nfixparams; /* number of extra arguments */
223 ci->u.l.nextraargs = nextra; 223 ci->u.l.nextraargs = nextra;
224 checkstackGC(L, nfixparams + 1); 224 checkstackGC(L, nfixparams + 1);
225 /* copy function and fixed parameters to the top of the stack */ 225 /* copy function to the top of the stack */
226 for (i = 0; i <= nfixparams; i++) { 226 setobjs2s(L, L->top++, ci->func);
227 /* move fixed parameters to the top of the stack */
228 for (i = 1; i <= nfixparams; i++) {
227 setobjs2s(L, L->top++, ci->func + i); 229 setobjs2s(L, L->top++, ci->func + i);
228 setnilvalue(s2v(ci->func + i)); /* erase original copy (for GC) */ 230 setnilvalue(s2v(ci->func + i)); /* erase original parameter (for GC) */
229 } 231 }
230 ci->func += actual + 1; 232 ci->func += actual + 1;
231 ci->top += actual + 1; 233 ci->top += actual + 1;
diff --git a/lvm.c b/lvm.c
index 2d01e4c1..0cc3a0b9 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 2.338 2018/02/07 15:18:04 roberto Exp roberto $ 2** $Id: lvm.c,v 2.339 2018/02/09 15:16:06 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*/
@@ -1493,23 +1493,35 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1493 } 1493 }
1494 vmcase(OP_TAILCALL) { 1494 vmcase(OP_TAILCALL) {
1495 int b = GETARG_B(i); /* number of arguments + 1 (function) */ 1495 int b = GETARG_B(i); /* number of arguments + 1 (function) */
1496 int delta = 0; /* virtual 'func' - real 'func' (vararg functions) */
1496 if (b != 0) 1497 if (b != 0)
1497 L->top = ra + b; 1498 L->top = ra + b;
1498 else /* previous instruction set top */ 1499 else /* previous instruction set top */
1499 b = cast_int(L->top - ra); 1500 b = cast_int(L->top - ra);
1500 lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); 1501 savepc(ci);
1502 if (TESTARG_k(i)) {
1503 int nparams1 = GETARG_C(i);
1504 if (nparams1) /* vararg function? */
1505 delta = ci->u.l.nextraargs + nparams1;
1506 luaF_close(L, base); /* close upvalues from current call */
1507 }
1501 if (!ttisfunction(vra)) { /* not a function? */ 1508 if (!ttisfunction(vra)) { /* not a function? */
1502 ProtectNT(luaD_tryfuncTM(L, ra)); /* try '__call' metamethod */ 1509 luaD_tryfuncTM(L, ra); /* try '__call' metamethod */
1503 b++; /* there is now one extra argument */ 1510 b++; /* there is now one extra argument */
1504 } 1511 }
1505 if (TESTARG_k(i))
1506 luaF_close(L, base); /* close upvalues from current call */
1507 if (!ttisLclosure(vra)) { /* C function? */ 1512 if (!ttisLclosure(vra)) { /* C function? */
1508 ProtectNT(luaD_call(L, ra, LUA_MULTRET)); /* call it */ 1513 luaD_call(L, ra, LUA_MULTRET); /* call it */
1514 updatetrap(ci);
1515 if (trap) { /* stack may have been relocated */
1516 updatebase(ci);
1517 ra = RA(i);
1518 }
1519 ci->func -= delta;
1520 luaD_poscall(L, ci, ra, cast_int(L->top - ra));
1521 return;
1509 } 1522 }
1510 else { /* Lua tail call */ 1523 else { /* Lua tail call */
1511 if (cl->p->is_vararg) 1524 ci->func -= delta;
1512 ci->func -= cl->p->numparams + ci->u.l.nextraargs + 1;
1513 luaD_pretailcall(L, ci, ra, b); /* prepare call frame */ 1525 luaD_pretailcall(L, ci, ra, b); /* prepare call frame */
1514 goto tailcall; 1526 goto tailcall;
1515 } 1527 }
@@ -1518,34 +1530,16 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1518 vmcase(OP_RETURN) { 1530 vmcase(OP_RETURN) {
1519 int b = GETARG_B(i); 1531 int b = GETARG_B(i);
1520 int n = (b != 0 ? b - 1 : cast_int(L->top - ra)); 1532 int n = (b != 0 ? b - 1 : cast_int(L->top - ra));
1521 if (TESTARG_k(i)) 1533 if (TESTARG_k(i)) {
1522 luaF_close(L, base); 1534 int nparams1 = GETARG_C(i);
1523 halfProtect(luaD_poscall(L, ci, ra, n)); 1535 if (nparams1) /* vararg function? */
1524 return; 1536 ci->func -= ci->u.l.nextraargs + nparams1;
1525 } 1537 luaF_close(L, base); /* there may be open upvalues */
1526 vmcase(OP_RETVARARG) {
1527 int b = GETARG_B(i);
1528 int nparams = GETARG_C(i);
1529 int nres = (b != 0 ? b - 1 : cast_int(L->top - ra));
1530 int delta = ci->u.l.nextraargs + nparams + 2;
1531 if (TESTARG_k(i))
1532 luaF_close(L, base);
1533 savepc(L);
1534 /* code similar to 'luaD_poscall', but with a delta */
1535 if (L->hookmask) {
1536 luaD_rethook(L, ci);
1537 if (ci->u.l.trap) {
1538 updatebase(ci);
1539 ra = RA(i);
1540 }
1541 } 1538 }
1542 L->ci = ci->previous; /* back to caller */ 1539 halfProtect(luaD_poscall(L, ci, ra, n));
1543 luaD_moveresults(L, ra, base - delta, nres, ci->nresults);
1544 return; 1540 return;
1545 } 1541 }
1546 vmcase(OP_RETURN0) { 1542 vmcase(OP_RETURN0) {
1547 if (TESTARG_k(i))
1548 luaF_close(L, base);
1549 if (L->hookmask) 1543 if (L->hookmask)
1550 halfProtect(luaD_poscall(L, ci, ra, 0)); /* no hurry... */ 1544 halfProtect(luaD_poscall(L, ci, ra, 0)); /* no hurry... */
1551 else { 1545 else {
@@ -1558,8 +1552,6 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1558 return; 1552 return;
1559 } 1553 }
1560 vmcase(OP_RETURN1) { 1554 vmcase(OP_RETURN1) {
1561 if (TESTARG_k(i))
1562 luaF_close(L, base);
1563 if (L->hookmask) 1555 if (L->hookmask)
1564 halfProtect(luaD_poscall(L, ci, ra, 1)); /* no hurry... */ 1556 halfProtect(luaD_poscall(L, ci, ra, 1)); /* no hurry... */
1565 else { 1557 else {