diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-10-19 15:55:25 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-10-19 15:55:25 -0300 |
commit | e4a38eb0e828e9589c391171e2e1904a3b9698e7 (patch) | |
tree | 694af4b6797f8e8597bc87185f9718e24a349120 | |
parent | f07de225762ee0f2d5b411b948b3c6e28e0695d3 (diff) | |
download | lua-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.c | 45 | ||||
-rw-r--r-- | testes/db.lua | 10 |
2 files changed, 35 insertions, 20 deletions
@@ -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 | |||
119 | end | 119 | end |
120 | ]], {2,3,4,7}) | 120 | ]], {2,3,4,7}) |
121 | 121 | ||
122 | test([[ | ||
123 | local function foo() | ||
124 | end | ||
125 | foo() | ||
126 | A = 1 | ||
127 | A = 2 | ||
128 | A = 3 | ||
129 | ]], {2, 3, 2, 4, 5, 6}) | ||
130 | |||
131 | |||
122 | test([[-- | 132 | test([[-- |
123 | if nil then | 133 | if nil then |
124 | a=1 | 134 | a=1 |