From 10b8c99bbbb5405f5fb37513645421b8e3c3ba43 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Thu, 30 Nov 2017 11:29:18 -0200 Subject: small peephole optimizations --- lcode.c | 91 +++++++++++++++++++++++++++++++++++++-------------------------- lcode.h | 3 ++- lparser.c | 4 +-- lparser.h | 3 +-- lvm.c | 10 +++---- 5 files changed, 63 insertions(+), 48 deletions(-) diff --git a/lcode.c b/lcode.c index 8f9fa408..d1585193 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.138 2017/11/28 15:26:15 roberto Exp roberto $ +** $Id: lcode.c,v 2.140 2017/11/30 13:17:06 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -134,17 +134,10 @@ void luaK_concat (FuncState *fs, int *l1, int l2) { /* ** Create a jump instruction and return its position, so its destination -** can be fixed later (with 'fixjump'). If there are jumps to -** this position (kept in 'jpc'), link them all together so that -** 'patchlistaux' will fix all them directly to the final destination. +** can be fixed later (with 'fixjump'). */ int luaK_jump (FuncState *fs) { - int jpc = fs->jpc; /* save list of jumps to here */ - int j; - fs->jpc = NO_JUMP; /* no more jumps to here */ - j = codesJ(fs, OP_JMP, NO_JUMP, 0); - luaK_concat(fs, &j, jpc); /* keep them on hold */ - return j; + return codesJ(fs, OP_JMP, NO_JUMP, 0); } @@ -249,39 +242,20 @@ static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, } -/* -** Ensure all pending jumps to current position are fixed (jumping -** to current position with no values) and reset list of pending -** jumps -*/ -static void dischargejpc (FuncState *fs) { - patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); - fs->jpc = NO_JUMP; -} - - -/* -** Add elements in 'list' to list of pending jumps to "here" -** (current position) -*/ -void luaK_patchtohere (FuncState *fs, int list) { - luaK_getlabel(fs); /* mark "here" as a jump target */ - luaK_concat(fs, &fs->jpc, list); -} - - /* ** Path all jumps in 'list' to jump to 'target'. ** (The assert means that we cannot fix a jump to a forward address ** because we only know addresses once code is generated.) */ void luaK_patchlist (FuncState *fs, int list, int target) { - if (target == fs->pc) /* 'target' is current position? */ - luaK_patchtohere(fs, list); /* add list to pending jumps */ - else { - lua_assert(target < fs->pc); - patchlistaux(fs, list, target, NO_REG, target); - } + lua_assert(target <= fs->pc); + patchlistaux(fs, list, target, NO_REG, target); +} + + +void luaK_patchtohere (FuncState *fs, int list) { + int hr = luaK_getlabel(fs); /* mark "here" as a jump target */ + luaK_patchlist(fs, list, hr); } @@ -365,7 +339,6 @@ static void savelineinfo (FuncState *fs, Proto *f, int pc, int line) { */ static int luaK_code (FuncState *fs, Instruction i) { Proto *f = fs->f; - dischargejpc(fs); /* 'pc' will change */ /* put new instruction in code array */ luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, MAX_INT, "opcodes"); @@ -1537,3 +1510,45 @@ void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { fs->freereg = base + 1; /* free registers with list values */ } + +/* +** return the final target of a jump (skipping jumps to jumps) +*/ +static int finaltarget (Instruction *code, int i) { + int count; + for (count = 0; count < 100; count++) { /* avoid infinite loops */ + Instruction pc = code[i]; + if (GET_OPCODE(pc) != OP_JMP) + break; + else + i += GETARG_sJ(pc) + 1; + } + return i; +} + + +/* +** Do a final pass over the code of a function, doing small peephole +** optimizations and adjustments. +*/ +void luaK_finish (FuncState *fs) { + int i; + Proto *p = fs->f; + for (i = 0; i < fs->pc; i++) { + Instruction *pc = &p->code[i]; + switch (GET_OPCODE(*pc)) { + case OP_RETURN: case OP_RETURN0: case OP_RETURN1: + case OP_TAILCALL: { + if (p->sizep > 0) + SETARG_k(*pc, 1); /* signal that they must close upvalues */ + break; + } + case OP_JMP: { + int target = finaltarget(p->code, i); + fixjump(fs, i, target); + break; + } + default: break; + } + } +} diff --git a/lcode.h b/lcode.h index 1c3229d9..a1fd735d 100644 --- a/lcode.h +++ b/lcode.h @@ -1,5 +1,5 @@ /* -** $Id: lcode.h,v 1.67 2017/09/28 16:53:29 roberto Exp roberto $ +** $Id: lcode.h,v 1.68 2017/10/04 21:56:32 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -88,6 +88,7 @@ LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2, int line); LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); +LUAI_FUNC void luaK_finish (FuncState *fs); #endif diff --git a/lparser.c b/lparser.c index 3eb83fba..1d46c6f2 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.167 2017/10/04 21:53:03 roberto Exp roberto $ +** $Id: lparser.c,v 2.168 2017/11/23 16:35:54 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -547,7 +547,6 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { fs->previousline = f->linedefined; fs->iwthabs = 0; fs->lasttarget = 0; - fs->jpc = NO_JUMP; fs->freereg = 0; fs->nk = 0; fs->nabslineinfo = 0; @@ -569,6 +568,7 @@ static void close_func (LexState *ls) { Proto *f = fs->f; luaK_ret(fs, 0, 0); /* final return */ leaveblock(fs); + luaK_finish(fs); luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); f->sizecode = fs->pc; luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, ls_byte); diff --git a/lparser.h b/lparser.h index 3ab6065d..4d342d32 100644 --- a/lparser.h +++ b/lparser.h @@ -1,5 +1,5 @@ /* -** $Id: lparser.h,v 1.77 2017/04/28 20:57:45 roberto Exp roberto $ +** $Id: lparser.h,v 1.78 2017/06/27 11:35:31 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -124,7 +124,6 @@ typedef struct FuncState { int pc; /* next position to code (equivalent to 'ncode') */ int lasttarget; /* 'label' of last 'jump label' */ int previousline; /* last line that was saved in 'lineinfo' */ - int jpc; /* list of pending jumps to 'pc' */ int nk; /* number of elements in 'k' */ int np; /* number of elements in 'p' */ int nabslineinfo; /* number of elements in 'abslineinfo' */ diff --git a/lvm.c b/lvm.c index 16e4fde0..0ba78b3d 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.321 2017/11/29 13:02:17 roberto Exp roberto $ +** $Id: lvm.c,v 2.322 2017/11/29 16:57:36 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -1453,7 +1453,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { /* next instruction will do the return */ } else { /* tail call */ - if (cl->p->sizep > 0) /* close upvalues from previous call */ + if (TESTARG_k(i)) /* close upvalues from previous call */ luaF_close(L, ci->func + 1); luaD_pretailcall(L, ci, ra, b); /* prepare call frame */ goto tailcall; @@ -1462,7 +1462,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { } vmcase(OP_RETURN) { int b = GETARG_B(i); - if (cl->p->sizep > 0) + if (TESTARG_k(i)) luaF_close(L, base); halfProtect( luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))) @@ -1470,7 +1470,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { return; } vmcase(OP_RETURN0) { - if (cl->p->sizep > 0) + if (TESTARG_k(i)) luaF_close(L, base); if (L->hookmask) halfProtect(luaD_poscall(L, ci, ra, 0)); /* no hurry... */ @@ -1484,7 +1484,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { return; } vmcase(OP_RETURN1) { - if (cl->p->sizep > 0) + if (TESTARG_k(i)) luaF_close(L, base); if (L->hookmask) halfProtect(luaD_poscall(L, ci, ra, 1)); /* no hurry... */ -- cgit v1.2.3-55-g6feb