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 |
