aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-12-18 15:53:50 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-12-18 15:53:50 -0200
commitd388c165ef79cb9c668e28fa92242ffbc0430e54 (patch)
treec10d2aee1d049d9c430ac9bebe810e9e733a8acb
parentab07005568a399f2e97996677472d9e6e69c9f4f (diff)
downloadlua-d388c165ef79cb9c668e28fa92242ffbc0430e54.tar.gz
lua-d388c165ef79cb9c668e28fa92242ffbc0430e54.tar.bz2
lua-d388c165ef79cb9c668e28fa92242ffbc0430e54.zip
new opcodes 'FORLOOP1'/'FORPREP1' for "basic for" (integer variable
with increment of 1)
-rw-r--r--lopcodes.c6
-rw-r--r--lopcodes.h6
-rw-r--r--lparser.c51
-rw-r--r--lvm.c28
4 files changed, 73 insertions, 18 deletions
diff --git a/lopcodes.c b/lopcodes.c
index 1d246384..f5896ba0 100644
--- a/lopcodes.c
+++ b/lopcodes.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lopcodes.c,v 1.72 2017/12/04 17:41:30 roberto Exp roberto $ 2** $Id: lopcodes.c,v 1.73 2017/12/13 18:32:09 roberto Exp roberto $
3** Opcodes for Lua virtual machine 3** Opcodes for Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -82,6 +82,8 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
82 "RETURN", 82 "RETURN",
83 "RETURN0", 83 "RETURN0",
84 "RETURN1", 84 "RETURN1",
85 "FORLOOP1",
86 "FORPREP1",
85 "FORLOOP", 87 "FORLOOP",
86 "FORPREP", 88 "FORPREP",
87 "TFORCALL", 89 "TFORCALL",
@@ -160,6 +162,8 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
160 ,opmode(0, 0, iABC) /* OP_RETURN */ 162 ,opmode(0, 0, iABC) /* OP_RETURN */
161 ,opmode(0, 0, iABC) /* OP_RETURN0 */ 163 ,opmode(0, 0, iABC) /* OP_RETURN0 */
162 ,opmode(0, 0, iABC) /* OP_RETURN1 */ 164 ,opmode(0, 0, iABC) /* OP_RETURN1 */
165 ,opmode(0, 1, iABx) /* OP_FORLOOP1 */
166 ,opmode(0, 1, iABx) /* OP_FORPREP1 */
163 ,opmode(0, 1, iABx) /* OP_FORLOOP */ 167 ,opmode(0, 1, iABx) /* OP_FORLOOP */
164 ,opmode(0, 1, iABx) /* OP_FORPREP */ 168 ,opmode(0, 1, iABx) /* OP_FORPREP */
165 ,opmode(0, 0, iABC) /* OP_TFORCALL */ 169 ,opmode(0, 0, iABC) /* OP_TFORCALL */
diff --git a/lopcodes.h b/lopcodes.h
index c3269dff..ec880703 100644
--- a/lopcodes.h
+++ b/lopcodes.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lopcodes.h,v 1.178 2017/12/15 18:35:22 roberto Exp roberto $ 2** $Id: lopcodes.h,v 1.179 2017/12/15 18:53:48 roberto Exp roberto $
3** Opcodes for Lua virtual machine 3** Opcodes for Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -267,6 +267,10 @@ OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */
267OP_RETURN0,/* return */ 267OP_RETURN0,/* return */
268OP_RETURN1,/* A return R(A) */ 268OP_RETURN1,/* A return R(A) */
269 269
270OP_FORLOOP1,/* A Bx R(A)++;
271 if R(A) <= R(A+1) then { pc-=Bx; R(A+3)=R(A) } */
272OP_FORPREP1,/* A Bx R(A)--; pc+=Bx */
273
270OP_FORLOOP,/* A Bx R(A)+=R(A+2); 274OP_FORLOOP,/* A Bx R(A)+=R(A+2);
271 if R(A) <?= R(A+1) then { pc-=Bx; R(A+3)=R(A) } */ 275 if R(A) <?= R(A+1) then { pc-=Bx; R(A+3)=R(A) } */
272OP_FORPREP,/* A Bx R(A)-=R(A+2); pc+=Bx */ 276OP_FORPREP,/* A Bx R(A)-=R(A+2); pc+=Bx */
diff --git a/lparser.c b/lparser.c
index 8f25eec3..6317a788 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lparser.c,v 2.172 2017/12/15 13:07:10 roberto Exp roberto $ 2** $Id: lparser.c,v 2.173 2017/12/18 12:33:54 roberto Exp roberto $
3** Lua Parser 3** Lua Parser
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -1313,11 +1313,20 @@ static void repeatstat (LexState *ls, int line) {
1313} 1313}
1314 1314
1315 1315
1316static void exp1 (LexState *ls) { 1316/*
1317** Read an expression and generate code to put its results in next
1318** stack slot. Return true if expression is a constant integer and,
1319** if 'i' is not-zero, its value is equal to 'i'.
1320**
1321*/
1322static int exp1 (LexState *ls, int i) {
1317 expdesc e; 1323 expdesc e;
1324 int res;
1318 expr(ls, &e); 1325 expr(ls, &e);
1326 res = luaK_isKint(&e) && (i == 0 || i == e.u.ival);
1319 luaK_exp2nextreg(ls->fs, &e); 1327 luaK_exp2nextreg(ls->fs, &e);
1320 lua_assert(e.k == VNONRELOC); 1328 lua_assert(e.k == VNONRELOC);
1329 return res;
1321} 1330}
1322 1331
1323 1332
@@ -1337,29 +1346,37 @@ static void fixforjump (FuncState *fs, int pc, int dest, int back) {
1337} 1346}
1338 1347
1339 1348
1340static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { 1349/*
1350** Generate code for a 'for' loop. 'kind' can be zero (a common for
1351** loop), one (a basic for loop, with integer values and increment of
1352** 1), or two (a generic for loop).
1353*/
1354static void forbody (LexState *ls, int base, int line, int nvars, int kind) {
1341 /* forbody -> DO block */ 1355 /* forbody -> DO block */
1342 BlockCnt bl; 1356 BlockCnt bl;
1343 FuncState *fs = ls->fs; 1357 FuncState *fs = ls->fs;
1344 int prep, endfor; 1358 int prep, endfor;
1345 adjustlocalvars(ls, 3); /* control variables */ 1359 adjustlocalvars(ls, 3); /* control variables */
1346 checknext(ls, TK_DO); 1360 checknext(ls, TK_DO);
1347 prep = isnum ? luaK_codeABx(fs, OP_FORPREP, base, 0) : luaK_jump(fs); 1361 prep = (kind == 0) ? luaK_codeABx(fs, OP_FORPREP, base, 0)
1362 : (kind == 1) ? luaK_codeABx(fs, OP_FORPREP1, base, 0)
1363 : luaK_jump(fs);
1348 enterblock(fs, &bl, 0); /* scope for declared variables */ 1364 enterblock(fs, &bl, 0); /* scope for declared variables */
1349 adjustlocalvars(ls, nvars); 1365 adjustlocalvars(ls, nvars);
1350 luaK_reserveregs(fs, nvars); 1366 luaK_reserveregs(fs, nvars);
1351 block(ls); 1367 block(ls);
1352 leaveblock(fs); /* end of scope for declared variables */ 1368 leaveblock(fs); /* end of scope for declared variables */
1353 if (isnum) { /* numeric for? */ 1369 if (kind == 2) { /* generic for? */
1354 fixforjump(fs, prep, luaK_getlabel(fs), 0);
1355 endfor = luaK_codeABx(fs, OP_FORLOOP, base, 0);
1356 }
1357 else { /* generic for */
1358 luaK_patchtohere(fs, prep); 1370 luaK_patchtohere(fs, prep);
1359 luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); 1371 luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars);
1360 luaK_fixline(fs, line); 1372 luaK_fixline(fs, line);
1361 endfor = luaK_codeABx(fs, OP_TFORLOOP, base + 2, 0); 1373 endfor = luaK_codeABx(fs, OP_TFORLOOP, base + 2, 0);
1362 } 1374 }
1375 else {
1376 fixforjump(fs, prep, luaK_getlabel(fs), 0);
1377 endfor = (kind == 0) ? luaK_codeABx(fs, OP_FORLOOP, base, 0)
1378 : luaK_codeABx(fs, OP_FORLOOP1, base, 0);
1379 }
1363 fixforjump(fs, endfor, prep + 1, 1); 1380 fixforjump(fs, endfor, prep + 1, 1);
1364 luaK_fixline(fs, line); 1381 luaK_fixline(fs, line);
1365} 1382}
@@ -1369,21 +1386,25 @@ static void fornum (LexState *ls, TString *varname, int line) {
1369 /* fornum -> NAME = exp,exp[,exp] forbody */ 1386 /* fornum -> NAME = exp,exp[,exp] forbody */
1370 FuncState *fs = ls->fs; 1387 FuncState *fs = ls->fs;
1371 int base = fs->freereg; 1388 int base = fs->freereg;
1389 int basicfor = 1; /* true if it is a "basic" 'for' (integer + 1) */
1372 new_localvarliteral(ls, "(for index)"); 1390 new_localvarliteral(ls, "(for index)");
1373 new_localvarliteral(ls, "(for limit)"); 1391 new_localvarliteral(ls, "(for limit)");
1374 new_localvarliteral(ls, "(for step)"); 1392 new_localvarliteral(ls, "(for step)");
1375 new_localvar(ls, varname); 1393 new_localvar(ls, varname);
1376 checknext(ls, '='); 1394 checknext(ls, '=');
1377 exp1(ls); /* initial value */ 1395 if (!exp1(ls, 0)) /* initial value not an integer? */
1396 basicfor = 0; /* not a basic 'for' */
1378 checknext(ls, ','); 1397 checknext(ls, ',');
1379 exp1(ls); /* limit */ 1398 exp1(ls, 0); /* limit */
1380 if (testnext(ls, ',')) 1399 if (testnext(ls, ',')) {
1381 exp1(ls); /* optional step */ 1400 if (!exp1(ls, 1)) /* optional step not 1? */
1401 basicfor = 0; /* not a basic 'for' */
1402 }
1382 else { /* default step = 1 */ 1403 else { /* default step = 1 */
1383 luaK_int(fs, fs->freereg, 1); 1404 luaK_int(fs, fs->freereg, 1);
1384 luaK_reserveregs(fs, 1); 1405 luaK_reserveregs(fs, 1);
1385 } 1406 }
1386 forbody(ls, base, line, 1, 1); 1407 forbody(ls, base, line, 1, basicfor);
1387} 1408}
1388 1409
1389 1410
@@ -1408,7 +1429,7 @@ static void forlist (LexState *ls, TString *indexname) {
1408 line = ls->linenumber; 1429 line = ls->linenumber;
1409 adjust_assign(ls, 3, explist(ls, &e), &e); 1430 adjust_assign(ls, 3, explist(ls, &e), &e);
1410 luaK_checkstack(fs, 3); /* extra space to call generator */ 1431 luaK_checkstack(fs, 3); /* extra space to call generator */
1411 forbody(ls, base, line, nvars - 3, 0); 1432 forbody(ls, base, line, nvars - 3, 2);
1412} 1433}
1413 1434
1414 1435
diff --git a/lvm.c b/lvm.c
index 90fd1060..22d37bbb 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 2.324 2017/12/04 17:41:30 roberto Exp roberto $ 2** $Id: lvm.c,v 2.326 2017/12/18 17:49:31 roberto Exp $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -1564,6 +1564,32 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1564 } 1564 }
1565 return; 1565 return;
1566 } 1566 }
1567 vmcase(OP_FORLOOP1) {
1568 lua_Integer idx = intop(+, ivalue(vra), 1); /* increment index */
1569 lua_Integer limit = ivalue(s2v(ra + 1));
1570 if (idx <= limit) {
1571 pc -= GETARG_Bx(i); /* jump back */
1572 chgivalue(vra, idx); /* update internal index... */
1573 setivalue(s2v(ra + 3), idx); /* ...and external index */
1574 }
1575 updatetrap(ci);
1576 vmbreak;
1577 }
1578 vmcase(OP_FORPREP1) {
1579 TValue *init = vra;
1580 TValue *plimit = s2v(ra + 1);
1581 lua_Integer ilimit, initv;
1582 int stopnow;
1583 if (!forlimit(plimit, &ilimit, 1, &stopnow)) {
1584 savepc(L); /* for the error message */
1585 luaG_runerror(L, "'for' limit must be a number");
1586 }
1587 initv = (stopnow ? 0 : ivalue(init));
1588 setivalue(plimit, ilimit);
1589 setivalue(init, intop(-, initv, 1));
1590 pc += GETARG_Bx(i);
1591 vmbreak;
1592 }
1567 vmcase(OP_FORLOOP) { 1593 vmcase(OP_FORLOOP) {
1568 if (ttisinteger(vra)) { /* integer loop? */ 1594 if (ttisinteger(vra)) { /* integer loop? */
1569 lua_Integer step = ivalue(s2v(ra + 2)); 1595 lua_Integer step = ivalue(s2v(ra + 2));