Changes in opcodes for generic 'for'
Again, as the control variable is read only, the code doesn't need to keep an internal copy of it.
This commit is contained in:
23
lparser.c
23
lparser.c
@@ -1558,6 +1558,7 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isgen) {
|
|||||||
int prep, endfor;
|
int prep, endfor;
|
||||||
checknext(ls, TK_DO);
|
checknext(ls, TK_DO);
|
||||||
prep = luaK_codeABx(fs, forprep[isgen], base, 0);
|
prep = luaK_codeABx(fs, forprep[isgen], base, 0);
|
||||||
|
fs->freereg--; /* both 'forprep' remove one register from the stack */
|
||||||
enterblock(fs, &bl, 0); /* scope for declared variables */
|
enterblock(fs, &bl, 0); /* scope for declared variables */
|
||||||
adjustlocalvars(ls, nvars);
|
adjustlocalvars(ls, nvars);
|
||||||
luaK_reserveregs(fs, nvars);
|
luaK_reserveregs(fs, nvars);
|
||||||
@@ -1591,8 +1592,7 @@ static void fornum (LexState *ls, TString *varname, int line) {
|
|||||||
luaK_int(fs, fs->freereg, 1);
|
luaK_int(fs, fs->freereg, 1);
|
||||||
luaK_reserveregs(fs, 1);
|
luaK_reserveregs(fs, 1);
|
||||||
}
|
}
|
||||||
adjustlocalvars(ls, 2); /* start scope for internal state variables */
|
adjustlocalvars(ls, 2); /* start scope for internal variables */
|
||||||
fs->freereg--; /* OP_FORPREP removes one register from the stack */
|
|
||||||
forbody(ls, base, line, 1, 0);
|
forbody(ls, base, line, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1601,14 +1601,13 @@ static void forlist (LexState *ls, TString *indexname) {
|
|||||||
/* forlist -> NAME {,NAME} IN explist forbody */
|
/* forlist -> NAME {,NAME} IN explist forbody */
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
expdesc e;
|
expdesc e;
|
||||||
int nvars = 5; /* gen, state, control, toclose, 'indexname' */
|
int nvars = 4; /* function, state, closing, control */
|
||||||
int line;
|
int line;
|
||||||
int base = fs->freereg;
|
int base = fs->freereg;
|
||||||
/* create control variables */
|
/* create internal variables */
|
||||||
new_localvarliteral(ls, "(for state)");
|
new_localvarliteral(ls, "(for state)"); /* iterator function */
|
||||||
new_localvarliteral(ls, "(for state)");
|
new_localvarliteral(ls, "(for state)"); /* state */
|
||||||
new_localvarliteral(ls, "(for state)");
|
new_localvarliteral(ls, "(for state)"); /* closing var. (after swap) */
|
||||||
new_localvarliteral(ls, "(for state)");
|
|
||||||
new_localvarkind(ls, indexname, RDKCONST); /* control variable */
|
new_localvarkind(ls, indexname, RDKCONST); /* control variable */
|
||||||
/* other declared variables */
|
/* other declared variables */
|
||||||
while (testnext(ls, ',')) {
|
while (testnext(ls, ',')) {
|
||||||
@@ -1618,10 +1617,10 @@ static void forlist (LexState *ls, TString *indexname) {
|
|||||||
checknext(ls, TK_IN);
|
checknext(ls, TK_IN);
|
||||||
line = ls->linenumber;
|
line = ls->linenumber;
|
||||||
adjust_assign(ls, 4, explist(ls, &e), &e);
|
adjust_assign(ls, 4, explist(ls, &e), &e);
|
||||||
adjustlocalvars(ls, 4); /* control variables */
|
adjustlocalvars(ls, 3); /* start scope for internal variables */
|
||||||
marktobeclosed(fs); /* last control var. must be closed */
|
marktobeclosed(fs); /* last internal var. must be closed */
|
||||||
luaK_checkstack(fs, 3); /* extra space to call generator */
|
luaK_checkstack(fs, 2); /* extra space to call iterator */
|
||||||
forbody(ls, base, line, nvars - 4, 1);
|
forbody(ls, base, line, nvars - 3, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
40
lvm.c
40
lvm.c
@@ -1806,26 +1806,38 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
vmbreak;
|
vmbreak;
|
||||||
}
|
}
|
||||||
vmcase(OP_TFORPREP) {
|
vmcase(OP_TFORPREP) {
|
||||||
|
/* before: 'ra' has the iterator function, 'ra + 1' has the state,
|
||||||
|
'ra + 2' has the initial value for the control variable, and
|
||||||
|
'ra + 3' has the closing variable. This opcode then swaps the
|
||||||
|
control and the closing variables and marks the closing variable
|
||||||
|
as to-be-closed.
|
||||||
|
*/
|
||||||
StkId ra = RA(i);
|
StkId ra = RA(i);
|
||||||
/* create to-be-closed upvalue (if needed) */
|
TValue temp; /* to swap control and closing variables */
|
||||||
halfProtect(luaF_newtbcupval(L, ra + 3));
|
setobj(L, &temp, s2v(ra + 3));
|
||||||
pc += GETARG_Bx(i);
|
setobjs2s(L, ra + 3, ra + 2);
|
||||||
i = *(pc++); /* go to next instruction */
|
setobj2s(L, ra + 2, &temp);
|
||||||
|
/* create to-be-closed upvalue (if closing var. is not nil) */
|
||||||
|
halfProtect(luaF_newtbcupval(L, ra + 2));
|
||||||
|
pc += GETARG_Bx(i); /* go to end of the loop */
|
||||||
|
i = *(pc++); /* fetch next instruction */
|
||||||
lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i));
|
lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i));
|
||||||
goto l_tforcall;
|
goto l_tforcall;
|
||||||
}
|
}
|
||||||
vmcase(OP_TFORCALL) {
|
vmcase(OP_TFORCALL) {
|
||||||
l_tforcall: {
|
l_tforcall: {
|
||||||
StkId ra = RA(i);
|
|
||||||
/* 'ra' has the iterator function, 'ra + 1' has the state,
|
/* 'ra' has the iterator function, 'ra + 1' has the state,
|
||||||
'ra + 2' has the control variable, and 'ra + 3' has the
|
'ra + 2' has the closing variable, and 'ra + 3' has the control
|
||||||
to-be-closed variable. The call will use the stack after
|
variable. The call will use the stack starting at 'ra + 3',
|
||||||
these values (starting at 'ra + 4')
|
so that it preserves the first three values, and the first
|
||||||
|
return will be the new value for the control variable.
|
||||||
*/
|
*/
|
||||||
/* push function, state, and control variable */
|
StkId ra = RA(i);
|
||||||
memcpy(ra + 4, ra, 3 * sizeof(*ra));
|
setobjs2s(L, ra + 5, ra + 3); /* copy the control variable */
|
||||||
L->top.p = ra + 4 + 3;
|
setobjs2s(L, ra + 4, ra + 1); /* copy state */
|
||||||
ProtectNT(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */
|
setobjs2s(L, ra + 3, ra); /* copy function */
|
||||||
|
L->top.p = ra + 3 + 3;
|
||||||
|
ProtectNT(luaD_call(L, ra + 3, 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 */
|
||||||
lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i));
|
lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i));
|
||||||
@@ -1834,10 +1846,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
vmcase(OP_TFORLOOP) {
|
vmcase(OP_TFORLOOP) {
|
||||||
l_tforloop: {
|
l_tforloop: {
|
||||||
StkId ra = RA(i);
|
StkId ra = RA(i);
|
||||||
if (!ttisnil(s2v(ra + 4))) { /* continue loop? */
|
if (!ttisnil(s2v(ra + 3))) /* continue loop? */
|
||||||
setobjs2s(L, ra + 2, ra + 4); /* save control variable */
|
|
||||||
pc -= GETARG_Bx(i); /* jump back */
|
pc -= GETARG_Bx(i); /* jump back */
|
||||||
}
|
|
||||||
vmbreak;
|
vmbreak;
|
||||||
}}
|
}}
|
||||||
vmcase(OP_SETLIST) {
|
vmcase(OP_SETLIST) {
|
||||||
|
|||||||
@@ -427,12 +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
|
||||||
local stvar = 0 -- to-be-closed is 4th state variable in the loop
|
local stvar = 0 -- to-be-closed is 3th state variable in the loop
|
||||||
for i = 1, 1000 do
|
for i = 1, 1000 do
|
||||||
local n, v = debug.getlocal(lv, i)
|
local n, v = debug.getlocal(lv, i)
|
||||||
if n == "(for state)" then
|
if n == "(for state)" then
|
||||||
stvar = stvar + 1
|
stvar = stvar + 1
|
||||||
if stvar == 4 then return v end
|
if stvar == 3 then return v end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user