aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-10-26 10:38:50 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-10-26 10:38:50 -0300
commit6e9b719694bffb8de711f182d405ec37d32ae0b1 (patch)
tree943fcd9aacd2f7845acfd955e1bb0a9607576fa4
parent34840301b529686ce8168828b140a478a5d44b53 (diff)
downloadlua-6e9b719694bffb8de711f182d405ec37d32ae0b1.tar.gz
lua-6e9b719694bffb8de711f182d405ec37d32ae0b1.tar.bz2
lua-6e9b719694bffb8de711f182d405ec37d32ae0b1.zip
More uniformity in code generation for 'for' loops
Added new instruction 'OP_TFORPREP' to prepare a generic for loop. Currently it is equivalent to a jump (but with a format 'iABx', similar to other for-loop preparing instructions), but soon it will be the place to create upvalues for closing loop states.
-rw-r--r--ljumptab.h1
-rw-r--r--lopcodes.c1
-rw-r--r--lopcodes.h1
-rw-r--r--lopnames.h1
-rw-r--r--lparser.c16
-rw-r--r--lvm.c4
6 files changed, 14 insertions, 10 deletions
diff --git a/ljumptab.h b/ljumptab.h
index da4cf7b7..6767e95b 100644
--- a/ljumptab.h
+++ b/ljumptab.h
@@ -96,6 +96,7 @@ static void *disptab[] = {
96&&L_OP_FORPREP1, 96&&L_OP_FORPREP1,
97&&L_OP_FORLOOP, 97&&L_OP_FORLOOP,
98&&L_OP_FORPREP, 98&&L_OP_FORPREP,
99&&L_OP_TFORPREP,
99&&L_OP_TFORCALL, 100&&L_OP_TFORCALL,
100&&L_OP_TFORLOOP, 101&&L_OP_TFORLOOP,
101&&L_OP_SETLIST, 102&&L_OP_SETLIST,
diff --git a/lopcodes.c b/lopcodes.c
index f6915beb..11a73c29 100644
--- a/lopcodes.c
+++ b/lopcodes.c
@@ -90,6 +90,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
90 ,opmode(0, 0, 0, 1, iABx) /* OP_FORPREP1 */ 90 ,opmode(0, 0, 0, 1, iABx) /* OP_FORPREP1 */
91 ,opmode(0, 0, 0, 1, iABx) /* OP_FORLOOP */ 91 ,opmode(0, 0, 0, 1, iABx) /* OP_FORLOOP */
92 ,opmode(0, 0, 0, 1, iABx) /* OP_FORPREP */ 92 ,opmode(0, 0, 0, 1, iABx) /* OP_FORPREP */
93 ,opmode(0, 0, 0, 0, iABx) /* OP_TFORPREP */
93 ,opmode(0, 0, 0, 0, iABC) /* OP_TFORCALL */ 94 ,opmode(0, 0, 0, 0, iABC) /* OP_TFORCALL */
94 ,opmode(0, 0, 0, 1, iABx) /* OP_TFORLOOP */ 95 ,opmode(0, 0, 0, 1, iABx) /* OP_TFORLOOP */
95 ,opmode(0, 1, 0, 0, iABC) /* OP_SETLIST */ 96 ,opmode(0, 1, 0, 0, iABC) /* OP_SETLIST */
diff --git a/lopcodes.h b/lopcodes.h
index 4d144000..4797d7c3 100644
--- a/lopcodes.h
+++ b/lopcodes.h
@@ -282,6 +282,7 @@ OP_FORLOOP,/* A Bx R(A)+=R(A+2);
282 if R(A) <?= R(A+1) then { pc-=Bx; R(A+3)=R(A) } */ 282 if R(A) <?= R(A+1) then { pc-=Bx; R(A+3)=R(A) } */
283OP_FORPREP,/* A Bx R(A)-=R(A+2); pc+=Bx */ 283OP_FORPREP,/* A Bx R(A)-=R(A+2); pc+=Bx */
284 284
285OP_TFORPREP,/* A Bx create upvalue A; pc+=Bx */
285OP_TFORCALL,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */ 286OP_TFORCALL,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */
286OP_TFORLOOP,/* A Bx if R(A+1) ~= nil then { R(A)=R(A+1); pc -= Bx } */ 287OP_TFORLOOP,/* A Bx if R(A+1) ~= nil then { R(A)=R(A+1); pc -= Bx } */
287 288
diff --git a/lopnames.h b/lopnames.h
index 304d3b6c..b2c4fe21 100644
--- a/lopnames.h
+++ b/lopnames.h
@@ -81,6 +81,7 @@ static const char *const opnames[] = {
81 "FORPREP1", 81 "FORPREP1",
82 "FORLOOP", 82 "FORLOOP",
83 "FORPREP", 83 "FORPREP",
84 "TFORPREP",
84 "TFORCALL", 85 "TFORCALL",
85 "TFORLOOP", 86 "TFORLOOP",
86 "SETLIST", 87 "SETLIST",
diff --git a/lparser.c b/lparser.c
index c0c40eae..c3dc6362 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1350,30 +1350,26 @@ static void fixforjump (FuncState *fs, int pc, int dest, int back) {
1350*/ 1350*/
1351static void forbody (LexState *ls, int base, int line, int nvars, int kind) { 1351static void forbody (LexState *ls, int base, int line, int nvars, int kind) {
1352 /* forbody -> DO block */ 1352 /* forbody -> DO block */
1353 static OpCode forprep[3] = {OP_FORPREP, OP_FORPREP1, OP_TFORPREP};
1354 static OpCode forloop[3] = {OP_FORLOOP, OP_FORLOOP1, OP_TFORLOOP};
1353 BlockCnt bl; 1355 BlockCnt bl;
1354 FuncState *fs = ls->fs; 1356 FuncState *fs = ls->fs;
1355 int prep, endfor; 1357 int prep, endfor;
1356 adjustlocalvars(ls, 3); /* control variables */ 1358 adjustlocalvars(ls, 3); /* control variables */
1357 checknext(ls, TK_DO); 1359 checknext(ls, TK_DO);
1358 prep = (kind == 0) ? luaK_codeABx(fs, OP_FORPREP, base, 0) 1360 prep = luaK_codeABx(fs, forprep[kind], base, 0);
1359 : (kind == 1) ? luaK_codeABx(fs, OP_FORPREP1, base, 0)
1360 : luaK_jump(fs);
1361 enterblock(fs, &bl, 0); /* scope for declared variables */ 1361 enterblock(fs, &bl, 0); /* scope for declared variables */
1362 adjustlocalvars(ls, nvars); 1362 adjustlocalvars(ls, nvars);
1363 luaK_reserveregs(fs, nvars); 1363 luaK_reserveregs(fs, nvars);
1364 block(ls); 1364 block(ls);
1365 leaveblock(fs); /* end of scope for declared variables */ 1365 leaveblock(fs); /* end of scope for declared variables */
1366 fixforjump(fs, prep, luaK_getlabel(fs), 0);
1366 if (kind == 2) { /* generic for? */ 1367 if (kind == 2) { /* generic for? */
1367 luaK_patchtohere(fs, prep);
1368 luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); 1368 luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars);
1369 luaK_fixline(fs, line); 1369 luaK_fixline(fs, line);
1370 endfor = luaK_codeABx(fs, OP_TFORLOOP, base + 2, 0); 1370 base += 2; /* base for 'OP_TFORLOOP' (skips function and state) */
1371 }
1372 else {
1373 fixforjump(fs, prep, luaK_getlabel(fs), 0);
1374 endfor = (kind == 0) ? luaK_codeABx(fs, OP_FORLOOP, base, 0)
1375 : luaK_codeABx(fs, OP_FORLOOP1, base, 0);
1376 } 1371 }
1372 endfor = luaK_codeABx(fs, forloop[kind], base, 0);
1377 fixforjump(fs, endfor, prep + 1, 1); 1373 fixforjump(fs, endfor, prep + 1, 1);
1378 luaK_fixline(fs, line); 1374 luaK_fixline(fs, line);
1379} 1375}
diff --git a/lvm.c b/lvm.c
index 2a1ee175..35a58089 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1744,6 +1744,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1744 pc += GETARG_Bx(i); 1744 pc += GETARG_Bx(i);
1745 vmbreak; 1745 vmbreak;
1746 } 1746 }
1747 vmcase(OP_TFORPREP) {
1748 pc += GETARG_Bx(i);
1749 vmbreak;
1750 }
1747 vmcase(OP_TFORCALL) { 1751 vmcase(OP_TFORCALL) {
1748 StkId cb = ra + 3; /* call base */ 1752 StkId cb = ra + 3; /* call base */
1749 setobjs2s(L, cb+2, ra+2); 1753 setobjs2s(L, cb+2, ra+2);