mirror of
https://github.com/lua/lua.git
synced 2025-01-28 06:03:00 +08:00
Fixed wrong trace of vararg functions
Trace of vararg functions was skipping an instruction when returning from a call. (Bug introduced by commit 5d8ce05b3.)
This commit is contained in:
parent
f07de22576
commit
e4a38eb0e8
45
lvm.c
45
lvm.c
@ -1092,15 +1092,11 @@ void luaV_finishOp (lua_State *L) {
|
|||||||
#define ProtectNT(exp) (savepc(L), (exp), updatetrap(ci))
|
#define ProtectNT(exp) (savepc(L), (exp), updatetrap(ci))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Protect code that will finish the loop (returns) or can only raise
|
** Protect code that can only raise errors. (That is, it cannnot change
|
||||||
** errors. (That is, it will not return to the interpreter main loop
|
** the stack or hooks.)
|
||||||
** after changing the stack or hooks.)
|
|
||||||
*/
|
*/
|
||||||
#define halfProtect(exp) (savestate(L,ci), (exp))
|
#define halfProtect(exp) (savestate(L,ci), (exp))
|
||||||
|
|
||||||
/* idem, but without changing the stack */
|
|
||||||
#define halfProtectNT(exp) (savepc(L), (exp))
|
|
||||||
|
|
||||||
/* 'c' is the limit of live values in the stack */
|
/* 'c' is the limit of live values in the stack */
|
||||||
#define checkGC(L,c) \
|
#define checkGC(L,c) \
|
||||||
{ luaC_condGC(L, (savepc(L), L->top = (c)), \
|
{ luaC_condGC(L, (savepc(L), L->top = (c)), \
|
||||||
@ -1132,17 +1128,20 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
#if LUA_USE_JUMPTABLE
|
#if LUA_USE_JUMPTABLE
|
||||||
#include "ljumptab.h"
|
#include "ljumptab.h"
|
||||||
#endif
|
#endif
|
||||||
execute:
|
startfunc:
|
||||||
trap = L->hookmask;
|
trap = L->hookmask;
|
||||||
|
returning: /* trap already set */
|
||||||
cl = clLvalue(s2v(ci->func));
|
cl = clLvalue(s2v(ci->func));
|
||||||
k = cl->p->k;
|
k = cl->p->k;
|
||||||
pc = ci->u.l.savedpc;
|
pc = ci->u.l.savedpc;
|
||||||
if (trap) {
|
if (trap) {
|
||||||
if (cl->p->is_vararg)
|
if (pc == cl->p->code) { /* first instruction (not resuming)? */
|
||||||
trap = 0; /* hooks will start after VARARGPREP instruction */
|
if (cl->p->is_vararg)
|
||||||
else if (pc == cl->p->code) /* first instruction (not resuming)? */
|
trap = 0; /* hooks will start after VARARGPREP instruction */
|
||||||
luaD_hookcall(L, ci);
|
else /* check 'call' hook */
|
||||||
ci->u.l.trap = 1; /* there may be other hooks */
|
luaD_hookcall(L, ci);
|
||||||
|
}
|
||||||
|
ci->u.l.trap = 1; /* assume trap is on, for now */
|
||||||
}
|
}
|
||||||
base = ci->func + 1;
|
base = ci->func + 1;
|
||||||
/* main loop of interpreter */
|
/* main loop of interpreter */
|
||||||
@ -1615,10 +1614,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
savepc(L); /* in case of errors */
|
savepc(L); /* in case of errors */
|
||||||
if ((newci = luaD_precall(L, ra, nresults)) == NULL)
|
if ((newci = luaD_precall(L, ra, nresults)) == NULL)
|
||||||
updatetrap(ci); /* C call; nothing else to be done */
|
updatetrap(ci); /* C call; nothing else to be done */
|
||||||
else { /* Lua call: run function in this same invocation */
|
else { /* Lua call: run function in this same C frame */
|
||||||
ci = newci;
|
ci = newci;
|
||||||
ci->callstatus = 0; /* call re-uses 'luaV_execute' */
|
ci->callstatus = 0; /* call re-uses 'luaV_execute' */
|
||||||
goto execute;
|
goto startfunc;
|
||||||
}
|
}
|
||||||
vmbreak;
|
vmbreak;
|
||||||
}
|
}
|
||||||
@ -1631,7 +1630,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
L->top = ra + b;
|
L->top = ra + b;
|
||||||
else /* previous instruction set top */
|
else /* previous instruction set top */
|
||||||
b = cast_int(L->top - ra);
|
b = cast_int(L->top - ra);
|
||||||
savepc(ci); /* some calls here can raise errors */
|
savepc(ci); /* several calls here can raise errors */
|
||||||
if (TESTARG_k(i)) {
|
if (TESTARG_k(i)) {
|
||||||
/* close upvalues from current call; the compiler ensures
|
/* close upvalues from current call; the compiler ensures
|
||||||
that there are no to-be-closed variables here, so this
|
that there are no to-be-closed variables here, so this
|
||||||
@ -1650,11 +1649,12 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
updatestack(ci); /* stack may have been relocated */
|
updatestack(ci); /* stack may have been relocated */
|
||||||
ci->func -= delta; /* restore 'func' (if vararg) */
|
ci->func -= delta; /* restore 'func' (if vararg) */
|
||||||
luaD_poscall(L, ci, cast_int(L->top - ra)); /* finish caller */
|
luaD_poscall(L, ci, cast_int(L->top - ra)); /* finish caller */
|
||||||
|
updatetrap(ci); /* 'luaD_poscall' can change hooks */
|
||||||
goto ret; /* caller returns after the tail call */
|
goto ret; /* caller returns after the tail call */
|
||||||
}
|
}
|
||||||
ci->func -= delta; /* restore 'func' (if vararg) */
|
ci->func -= delta; /* restore 'func' (if vararg) */
|
||||||
luaD_pretailcall(L, ci, ra, b); /* prepare call frame */
|
luaD_pretailcall(L, ci, ra, b); /* prepare call frame */
|
||||||
goto execute; /* execute the callee */
|
goto startfunc; /* execute the callee */
|
||||||
}
|
}
|
||||||
vmcase(OP_RETURN) {
|
vmcase(OP_RETURN) {
|
||||||
int n = GETARG_B(i) - 1; /* number of results */
|
int n = GETARG_B(i) - 1; /* number of results */
|
||||||
@ -1673,12 +1673,15 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
ci->func -= ci->u.l.nextraargs + nparams1;
|
ci->func -= ci->u.l.nextraargs + nparams1;
|
||||||
L->top = ra + n; /* set call for 'luaD_poscall' */
|
L->top = ra + n; /* set call for 'luaD_poscall' */
|
||||||
luaD_poscall(L, ci, n);
|
luaD_poscall(L, ci, n);
|
||||||
|
updatetrap(ci); /* 'luaD_poscall' can change hooks */
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
vmcase(OP_RETURN0) {
|
vmcase(OP_RETURN0) {
|
||||||
if (L->hookmask) {
|
if (L->hookmask) {
|
||||||
L->top = ra;
|
L->top = ra;
|
||||||
halfProtectNT(luaD_poscall(L, ci, 0)); /* no hurry... */
|
savepc(ci);
|
||||||
|
luaD_poscall(L, ci, 0); /* no hurry... */
|
||||||
|
trap = 1;
|
||||||
}
|
}
|
||||||
else { /* do the 'poscall' here */
|
else { /* do the 'poscall' here */
|
||||||
int nres = ci->nresults;
|
int nres = ci->nresults;
|
||||||
@ -1692,7 +1695,9 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
vmcase(OP_RETURN1) {
|
vmcase(OP_RETURN1) {
|
||||||
if (L->hookmask) {
|
if (L->hookmask) {
|
||||||
L->top = ra + 1;
|
L->top = ra + 1;
|
||||||
halfProtectNT(luaD_poscall(L, ci, 1)); /* no hurry... */
|
savepc(ci);
|
||||||
|
luaD_poscall(L, ci, 1); /* no hurry... */
|
||||||
|
trap = 1;
|
||||||
}
|
}
|
||||||
else { /* do the 'poscall' here */
|
else { /* do the 'poscall' here */
|
||||||
int nres = ci->nresults;
|
int nres = ci->nresults;
|
||||||
@ -1706,12 +1711,12 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
setnilvalue(s2v(L->top++));
|
setnilvalue(s2v(L->top++));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret:
|
ret: /* return from a Lua function */
|
||||||
if (ci->callstatus & CIST_FRESH)
|
if (ci->callstatus & CIST_FRESH)
|
||||||
return; /* end this frame */
|
return; /* end this frame */
|
||||||
else {
|
else {
|
||||||
ci = ci->previous;
|
ci = ci->previous;
|
||||||
goto execute; /* continue running caller in this frame */
|
goto returning; /* continue running caller in this frame */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vmcase(OP_FORLOOP) {
|
vmcase(OP_FORLOOP) {
|
||||||
|
@ -119,6 +119,16 @@ else
|
|||||||
end
|
end
|
||||||
]], {2,3,4,7})
|
]], {2,3,4,7})
|
||||||
|
|
||||||
|
test([[
|
||||||
|
local function foo()
|
||||||
|
end
|
||||||
|
foo()
|
||||||
|
A = 1
|
||||||
|
A = 2
|
||||||
|
A = 3
|
||||||
|
]], {2, 3, 2, 4, 5, 6})
|
||||||
|
|
||||||
|
|
||||||
test([[--
|
test([[--
|
||||||
if nil then
|
if nil then
|
||||||
a=1
|
a=1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user