aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-10-19 15:55:25 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-10-19 15:55:25 -0300
commite4a38eb0e828e9589c391171e2e1904a3b9698e7 (patch)
tree694af4b6797f8e8597bc87185f9718e24a349120
parentf07de225762ee0f2d5b411b948b3c6e28e0695d3 (diff)
downloadlua-e4a38eb0e828e9589c391171e2e1904a3b9698e7.tar.gz
lua-e4a38eb0e828e9589c391171e2e1904a3b9698e7.tar.bz2
lua-e4a38eb0e828e9589c391171e2e1904a3b9698e7.zip
Fixed wrong trace of vararg functions
Trace of vararg functions was skipping an instruction when returning from a call. (Bug introduced by commit 5d8ce05b3.)
-rw-r--r--lvm.c45
-rw-r--r--testes/db.lua10
2 files changed, 35 insertions, 20 deletions
diff --git a/lvm.c b/lvm.c
index 72d3e695..aa3b22bf 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1092,15 +1092,11 @@ void luaV_finishOp (lua_State *L) {
1092#define ProtectNT(exp) (savepc(L), (exp), updatetrap(ci)) 1092#define ProtectNT(exp) (savepc(L), (exp), updatetrap(ci))
1093 1093
1094/* 1094/*
1095** Protect code that will finish the loop (returns) or can only raise 1095** Protect code that can only raise errors. (That is, it cannnot change
1096** errors. (That is, it will not return to the interpreter main loop 1096** the stack or hooks.)
1097** after changing the stack or hooks.)
1098*/ 1097*/
1099#define halfProtect(exp) (savestate(L,ci), (exp)) 1098#define halfProtect(exp) (savestate(L,ci), (exp))
1100 1099
1101/* idem, but without changing the stack */
1102#define halfProtectNT(exp) (savepc(L), (exp))
1103
1104/* 'c' is the limit of live values in the stack */ 1100/* 'c' is the limit of live values in the stack */
1105#define checkGC(L,c) \ 1101#define checkGC(L,c) \
1106 { luaC_condGC(L, (savepc(L), L->top = (c)), \ 1102 { luaC_condGC(L, (savepc(L), L->top = (c)), \
@@ -1132,17 +1128,20 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1132#if LUA_USE_JUMPTABLE 1128#if LUA_USE_JUMPTABLE
1133#include "ljumptab.h" 1129#include "ljumptab.h"
1134#endif 1130#endif
1135 execute: 1131 startfunc:
1136 trap = L->hookmask; 1132 trap = L->hookmask;
1133 returning: /* trap already set */
1137 cl = clLvalue(s2v(ci->func)); 1134 cl = clLvalue(s2v(ci->func));
1138 k = cl->p->k; 1135 k = cl->p->k;
1139 pc = ci->u.l.savedpc; 1136 pc = ci->u.l.savedpc;
1140 if (trap) { 1137 if (trap) {
1141 if (cl->p->is_vararg) 1138 if (pc == cl->p->code) { /* first instruction (not resuming)? */
1142 trap = 0; /* hooks will start after VARARGPREP instruction */ 1139 if (cl->p->is_vararg)
1143 else if (pc == cl->p->code) /* first instruction (not resuming)? */ 1140 trap = 0; /* hooks will start after VARARGPREP instruction */
1144 luaD_hookcall(L, ci); 1141 else /* check 'call' hook */
1145 ci->u.l.trap = 1; /* there may be other hooks */ 1142 luaD_hookcall(L, ci);
1143 }
1144 ci->u.l.trap = 1; /* assume trap is on, for now */
1146 } 1145 }
1147 base = ci->func + 1; 1146 base = ci->func + 1;
1148 /* main loop of interpreter */ 1147 /* main loop of interpreter */
@@ -1615,10 +1614,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1615 savepc(L); /* in case of errors */ 1614 savepc(L); /* in case of errors */
1616 if ((newci = luaD_precall(L, ra, nresults)) == NULL) 1615 if ((newci = luaD_precall(L, ra, nresults)) == NULL)
1617 updatetrap(ci); /* C call; nothing else to be done */ 1616 updatetrap(ci); /* C call; nothing else to be done */
1618 else { /* Lua call: run function in this same invocation */ 1617 else { /* Lua call: run function in this same C frame */
1619 ci = newci; 1618 ci = newci;
1620 ci->callstatus = 0; /* call re-uses 'luaV_execute' */ 1619 ci->callstatus = 0; /* call re-uses 'luaV_execute' */
1621 goto execute; 1620 goto startfunc;
1622 } 1621 }
1623 vmbreak; 1622 vmbreak;
1624 } 1623 }
@@ -1631,7 +1630,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1631 L->top = ra + b; 1630 L->top = ra + b;
1632 else /* previous instruction set top */ 1631 else /* previous instruction set top */
1633 b = cast_int(L->top - ra); 1632 b = cast_int(L->top - ra);
1634 savepc(ci); /* some calls here can raise errors */ 1633 savepc(ci); /* several calls here can raise errors */
1635 if (TESTARG_k(i)) { 1634 if (TESTARG_k(i)) {
1636 /* close upvalues from current call; the compiler ensures 1635 /* close upvalues from current call; the compiler ensures
1637 that there are no to-be-closed variables here, so this 1636 that there are no to-be-closed variables here, so this
@@ -1650,11 +1649,12 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1650 updatestack(ci); /* stack may have been relocated */ 1649 updatestack(ci); /* stack may have been relocated */
1651 ci->func -= delta; /* restore 'func' (if vararg) */ 1650 ci->func -= delta; /* restore 'func' (if vararg) */
1652 luaD_poscall(L, ci, cast_int(L->top - ra)); /* finish caller */ 1651 luaD_poscall(L, ci, cast_int(L->top - ra)); /* finish caller */
1652 updatetrap(ci); /* 'luaD_poscall' can change hooks */
1653 goto ret; /* caller returns after the tail call */ 1653 goto ret; /* caller returns after the tail call */
1654 } 1654 }
1655 ci->func -= delta; /* restore 'func' (if vararg) */ 1655 ci->func -= delta; /* restore 'func' (if vararg) */
1656 luaD_pretailcall(L, ci, ra, b); /* prepare call frame */ 1656 luaD_pretailcall(L, ci, ra, b); /* prepare call frame */
1657 goto execute; /* execute the callee */ 1657 goto startfunc; /* execute the callee */
1658 } 1658 }
1659 vmcase(OP_RETURN) { 1659 vmcase(OP_RETURN) {
1660 int n = GETARG_B(i) - 1; /* number of results */ 1660 int n = GETARG_B(i) - 1; /* number of results */
@@ -1673,12 +1673,15 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1673 ci->func -= ci->u.l.nextraargs + nparams1; 1673 ci->func -= ci->u.l.nextraargs + nparams1;
1674 L->top = ra + n; /* set call for 'luaD_poscall' */ 1674 L->top = ra + n; /* set call for 'luaD_poscall' */
1675 luaD_poscall(L, ci, n); 1675 luaD_poscall(L, ci, n);
1676 updatetrap(ci); /* 'luaD_poscall' can change hooks */
1676 goto ret; 1677 goto ret;
1677 } 1678 }
1678 vmcase(OP_RETURN0) { 1679 vmcase(OP_RETURN0) {
1679 if (L->hookmask) { 1680 if (L->hookmask) {
1680 L->top = ra; 1681 L->top = ra;
1681 halfProtectNT(luaD_poscall(L, ci, 0)); /* no hurry... */ 1682 savepc(ci);
1683 luaD_poscall(L, ci, 0); /* no hurry... */
1684 trap = 1;
1682 } 1685 }
1683 else { /* do the 'poscall' here */ 1686 else { /* do the 'poscall' here */
1684 int nres = ci->nresults; 1687 int nres = ci->nresults;
@@ -1692,7 +1695,9 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1692 vmcase(OP_RETURN1) { 1695 vmcase(OP_RETURN1) {
1693 if (L->hookmask) { 1696 if (L->hookmask) {
1694 L->top = ra + 1; 1697 L->top = ra + 1;
1695 halfProtectNT(luaD_poscall(L, ci, 1)); /* no hurry... */ 1698 savepc(ci);
1699 luaD_poscall(L, ci, 1); /* no hurry... */
1700 trap = 1;
1696 } 1701 }
1697 else { /* do the 'poscall' here */ 1702 else { /* do the 'poscall' here */
1698 int nres = ci->nresults; 1703 int nres = ci->nresults;
@@ -1706,12 +1711,12 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1706 setnilvalue(s2v(L->top++)); 1711 setnilvalue(s2v(L->top++));
1707 } 1712 }
1708 } 1713 }
1709 ret: 1714 ret: /* return from a Lua function */
1710 if (ci->callstatus & CIST_FRESH) 1715 if (ci->callstatus & CIST_FRESH)
1711 return; /* end this frame */ 1716 return; /* end this frame */
1712 else { 1717 else {
1713 ci = ci->previous; 1718 ci = ci->previous;
1714 goto execute; /* continue running caller in this frame */ 1719 goto returning; /* continue running caller in this frame */
1715 } 1720 }
1716 } 1721 }
1717 vmcase(OP_FORLOOP) { 1722 vmcase(OP_FORLOOP) {
diff --git a/testes/db.lua b/testes/db.lua
index 5377f6ec..fdb0da4a 100644
--- a/testes/db.lua
+++ b/testes/db.lua
@@ -119,6 +119,16 @@ else
119end 119end
120]], {2,3,4,7}) 120]], {2,3,4,7})
121 121
122test([[
123local function foo()
124end
125foo()
126A = 1
127A = 2
128A = 3
129]], {2, 3, 2, 4, 5, 6})
130
131
122test([[-- 132test([[--
123if nil then 133if nil then
124 a=1 134 a=1