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-github-80d9b09f351c7a9be557116e9c79ae11e9b3f032.tar.gz |
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 @@ /* -** $Id: lcode.c,v 2.120 2017/06/27 11:35:31 roberto Exp roberto $ +** $Id: lcode.c,v 2.121 2017/06/29 15:06:44 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -272,20 +272,51 @@ void luaK_patchlist (FuncState *fs, int list, int target) { /* -** Path all jumps in 'list' to close upvalues up to given 'level' -** (The assertion checks that jumps either were closing nothing -** or were closing higher levels, from inner blocks.) +** Check whether some jump in given list needs a close instruction. */ -void luaK_patchclose (FuncState *fs, int list, int level) { - level++; /* argument is +1 to reserve 0 as non-op */ +int luaK_needclose (FuncState *fs, int list) { for (; list != NO_JUMP; list = getjump(fs, list)) { - lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP && - (GETARG_A(fs->f->code[list]) == 0 || - GETARG_A(fs->f->code[list]) >= level)); - SETARG_A(fs->f->code[list], level); + if (GETARG_A(fs->f->code[list])) /* needs close? */ + return 1; + } + return 0; +} + + +/* +** Correct a jump list to jump to 'target'. If 'hasclose' is true, +** 'target' contains an OP_CLOSE instruction (see first assert). +** Only jumps with the A arg true need that close; other jumps +** avoid it jumping to the next instruction. +*/ +void luaK_patchgoto (FuncState *fs, int list, int target, int hasclose) { + lua_assert(!hasclose || GET_OPCODE(fs->f->code[target]) == OP_CLOSE); + while (list != NO_JUMP) { + int next = getjump(fs, list); + lua_assert(!GETARG_A(fs->f->code[list]) || hasclose); + patchtestreg(fs, list, NO_REG); /* do not generate values */ + if (!hasclose || GETARG_A(fs->f->code[list])) + fixjump(fs, list, target); + else /* there is a CLOSE instruction but jump does not need it */ + fixjump(fs, list, target + 1); /* avoid CLOSE instruction */ + list = next; } } + +/* +** Mark (using the A arg) all jumps in 'list' to close upvalues. Mark +** will instruct 'luaK_patchgoto' to make these jumps go to OP_CLOSE +** instructions. +*/ +void luaK_patchclose (FuncState *fs, int list) { + for (; list != NO_JUMP; list = getjump(fs, list)) { + lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP); + SETARG_A(fs->f->code[list], 1); + } +} + + #if !defined(MAXIWTHABS) #define MAXIWTHABS 120 #endif |