diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-10-26 10:38:50 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-10-26 10:38:50 -0300 |
commit | 6e9b719694bffb8de711f182d405ec37d32ae0b1 (patch) | |
tree | 943fcd9aacd2f7845acfd955e1bb0a9607576fa4 | |
parent | 34840301b529686ce8168828b140a478a5d44b53 (diff) | |
download | lua-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.h | 1 | ||||
-rw-r--r-- | lopcodes.c | 1 | ||||
-rw-r--r-- | lopcodes.h | 1 | ||||
-rw-r--r-- | lopnames.h | 1 | ||||
-rw-r--r-- | lparser.c | 16 | ||||
-rw-r--r-- | lvm.c | 4 |
6 files changed, 14 insertions, 10 deletions
@@ -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, |
@@ -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 */ |
@@ -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) } */ |
283 | OP_FORPREP,/* A Bx R(A)-=R(A+2); pc+=Bx */ | 283 | OP_FORPREP,/* A Bx R(A)-=R(A+2); pc+=Bx */ |
284 | 284 | ||
285 | OP_TFORPREP,/* A Bx create upvalue A; pc+=Bx */ | ||
285 | OP_TFORCALL,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */ | 286 | OP_TFORCALL,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */ |
286 | OP_TFORLOOP,/* A Bx if R(A+1) ~= nil then { R(A)=R(A+1); pc -= Bx } */ | 287 | OP_TFORLOOP,/* A Bx if R(A+1) ~= nil then { R(A)=R(A+1); pc -= Bx } */ |
287 | 288 | ||
@@ -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", |
@@ -1350,30 +1350,26 @@ static void fixforjump (FuncState *fs, int pc, int dest, int back) { | |||
1350 | */ | 1350 | */ |
1351 | static void forbody (LexState *ls, int base, int line, int nvars, int kind) { | 1351 | static 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 | } |
@@ -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); |