In the generic for loop, it is simpler for OP_TFORLOOP to use the
same 'ra' as OP_TFORCALL. Moreover, the internal names of the loop
temporaries "(for ...)" don't need to leak internal details (even
because the numerical for loop doesn't have a fixed role for each of
its temporaries).
This commit is contained in:
Roberto Ierusalimschy 2019-07-10 14:58:31 -03:00
parent 3d296304ef
commit be8445d7e4
3 changed files with 13 additions and 13 deletions

View File

@ -1527,7 +1527,6 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isgen) {
if (isgen) { /* generic for? */ if (isgen) { /* generic for? */
luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars);
luaK_fixline(fs, line); luaK_fixline(fs, line);
base += 2; /* base for 'OP_TFORLOOP' (skips function and state) */
} }
endfor = luaK_codeABx(fs, forloop[isgen], base, 0); endfor = luaK_codeABx(fs, forloop[isgen], base, 0);
fixforjump(fs, endfor, prep + 1, 1); fixforjump(fs, endfor, prep + 1, 1);
@ -1539,9 +1538,9 @@ static void fornum (LexState *ls, TString *varname, int line) {
/* fornum -> NAME = exp,exp[,exp] forbody */ /* fornum -> NAME = exp,exp[,exp] forbody */
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
int base = fs->freereg; int base = fs->freereg;
new_localvarliteral(ls, "(for index)"); new_localvarliteral(ls, "(for state)");
new_localvarliteral(ls, "(for limit)"); new_localvarliteral(ls, "(for state)");
new_localvarliteral(ls, "(for step)"); new_localvarliteral(ls, "(for state)");
new_localvar(ls, varname); new_localvar(ls, varname);
checknext(ls, '='); checknext(ls, '=');
exp1(ls); /* initial value */ exp1(ls); /* initial value */
@ -1566,10 +1565,10 @@ static void forlist (LexState *ls, TString *indexname) {
int line; int line;
int base = fs->freereg; int base = fs->freereg;
/* create control variables */ /* create control variables */
new_localvarliteral(ls, "(for generator)");
new_localvarliteral(ls, "(for state)"); new_localvarliteral(ls, "(for state)");
new_localvarliteral(ls, "(for control)"); new_localvarliteral(ls, "(for state)");
new_localvarliteral(ls, "(for toclose)"); new_localvarliteral(ls, "(for state)");
new_localvarliteral(ls, "(for state)");
/* create declared variables */ /* create declared variables */
new_localvar(ls, indexname); new_localvar(ls, indexname);
while (testnext(ls, ',')) { while (testnext(ls, ',')) {

5
lvm.c
View File

@ -1746,14 +1746,13 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
Protect(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */ Protect(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */
updatestack(ci); /* stack may have changed */ updatestack(ci); /* stack may have changed */
i = *(pc++); /* go to next instruction */ i = *(pc++); /* go to next instruction */
ra += 2; /* adjust for next instruction */
lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i)); lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i));
goto l_tforloop; goto l_tforloop;
} }
vmcase(OP_TFORLOOP) { vmcase(OP_TFORLOOP) {
l_tforloop: l_tforloop:
if (!ttisnil(s2v(ra + 2))) { /* continue loop? */ if (!ttisnil(s2v(ra + 4))) { /* continue loop? */
setobjs2s(L, ra, ra + 2); /* save control variable */ setobjs2s(L, ra + 2, ra + 4); /* save control variable */
pc -= GETARG_Bx(i); /* jump back */ pc -= GETARG_Bx(i); /* jump back */
} }
vmbreak; vmbreak;

View File

@ -427,10 +427,12 @@ do -- testing closing file in line iteration
-- get the to-be-closed variable from a loop -- get the to-be-closed variable from a loop
local function gettoclose (lv) local function gettoclose (lv)
lv = lv + 1 lv = lv + 1
for i = 1, math.maxinteger do local stvar = 0 -- to-be-closed is 4th state variable in the loop
for i = 1, 1000 do
local n, v = debug.getlocal(lv, i) local n, v = debug.getlocal(lv, i)
if n == "(for toclose)" then if n == "(for state)" then
return v stvar = stvar + 1
if stvar == 4 then return v end
end end
end end
end end