aboutsummaryrefslogtreecommitdiff
path: root/lcode.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-09-13 16:50:08 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-09-13 16:50:08 -0300
commit80d9b09f351c7a9be557116e9c79ae11e9b3f032 (patch)
treea6ae7cce019e85c2f79987035c77d4e4213d07a9 /lcode.c
parent029d269f4d1afd0e9ea0f889eb3e65a7f0fab0f9 (diff)
downloadlua-80d9b09f351c7a9be557116e9c79ae11e9b3f032.tar.gz
lua-80d9b09f351c7a9be557116e9c79ae11e9b3f032.tar.bz2
lua-80d9b09f351c7a9be557116e9c79ae11e9b3f032.zip
jumps do not close upvalues (to be faster and simpler);
explicit instruction to close upvalues; command 'break' not handled like a 'goto' (to optimize removal of uneeded 'close' instructions)
Diffstat (limited to 'lcode.c')
-rw-r--r--lcode.c51
1 files changed, 41 insertions, 10 deletions
diff --git a/lcode.c b/lcode.c
index 169c439d..1edf08aa 100644
--- a/lcode.c
+++ b/lcode.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lcode.c,v 2.120 2017/06/27 11:35:31 roberto Exp roberto $ 2** $Id: lcode.c,v 2.121 2017/06/29 15:06:44 roberto Exp roberto $
3** Code generator for Lua 3** Code generator for Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -272,20 +272,51 @@ void luaK_patchlist (FuncState *fs, int list, int target) {
272 272
273 273
274/* 274/*
275** Path all jumps in 'list' to close upvalues up to given 'level' 275** Check whether some jump in given list needs a close instruction.
276** (The assertion checks that jumps either were closing nothing
277** or were closing higher levels, from inner blocks.)
278*/ 276*/
279void luaK_patchclose (FuncState *fs, int list, int level) { 277int luaK_needclose (FuncState *fs, int list) {
280 level++; /* argument is +1 to reserve 0 as non-op */
281 for (; list != NO_JUMP; list = getjump(fs, list)) { 278 for (; list != NO_JUMP; list = getjump(fs, list)) {
282 lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP && 279 if (GETARG_A(fs->f->code[list])) /* needs close? */
283 (GETARG_A(fs->f->code[list]) == 0 || 280 return 1;
284 GETARG_A(fs->f->code[list]) >= level)); 281 }
285 SETARG_A(fs->f->code[list], level); 282 return 0;
283}
284
285
286/*
287** Correct a jump list to jump to 'target'. If 'hasclose' is true,
288** 'target' contains an OP_CLOSE instruction (see first assert).
289** Only jumps with the A arg true need that close; other jumps
290** avoid it jumping to the next instruction.
291*/
292void luaK_patchgoto (FuncState *fs, int list, int target, int hasclose) {
293 lua_assert(!hasclose || GET_OPCODE(fs->f->code[target]) == OP_CLOSE);
294 while (list != NO_JUMP) {
295 int next = getjump(fs, list);
296 lua_assert(!GETARG_A(fs->f->code[list]) || hasclose);
297 patchtestreg(fs, list, NO_REG); /* do not generate values */
298 if (!hasclose || GETARG_A(fs->f->code[list]))
299 fixjump(fs, list, target);
300 else /* there is a CLOSE instruction but jump does not need it */
301 fixjump(fs, list, target + 1); /* avoid CLOSE instruction */
302 list = next;
286 } 303 }
287} 304}
288 305
306
307/*
308** Mark (using the A arg) all jumps in 'list' to close upvalues. Mark
309** will instruct 'luaK_patchgoto' to make these jumps go to OP_CLOSE
310** instructions.
311*/
312void luaK_patchclose (FuncState *fs, int list) {
313 for (; list != NO_JUMP; list = getjump(fs, list)) {
314 lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP);
315 SETARG_A(fs->f->code[list], 1);
316 }
317}
318
319
289#if !defined(MAXIWTHABS) 320#if !defined(MAXIWTHABS)
290#define MAXIWTHABS 120 321#define MAXIWTHABS 120
291#endif 322#endif