From 80d9b09f351c7a9be557116e9c79ae11e9b3f032 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy <roberto@inf.puc-rio.br> Date: Wed, 13 Sep 2017 16:50:08 -0300 Subject: 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) --- lcode.c | 51 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 10 deletions(-) (limited to 'lcode.c') diff --git a/lcode.c b/lcode.c index 169c439d..1edf08aa 100644 --- a/lcode.c +++ b/lcode.c @@ -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 -- cgit v1.2.3-55-g6feb