diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-09-13 16:50:08 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-09-13 16:50:08 -0300 |
commit | 80d9b09f351c7a9be557116e9c79ae11e9b3f032 (patch) | |
tree | a6ae7cce019e85c2f79987035c77d4e4213d07a9 /lcode.c | |
parent | 029d269f4d1afd0e9ea0f889eb3e65a7f0fab0f9 (diff) | |
download | lua-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.c | 51 |
1 files changed, 41 insertions, 10 deletions
@@ -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 | */ |
279 | void luaK_patchclose (FuncState *fs, int list, int level) { | 277 | int 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 | */ | ||
292 | void 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 | */ | ||
312 | void 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 |