소스 검색

small peephole optimizations

Roberto Ierusalimschy 7 년 전
부모
커밋
10b8c99bbb
5개의 변경된 파일63개의 추가작업 그리고 48개의 파일을 삭제
  1. 53 38
      lcode.c
  2. 2 1
      lcode.h
  3. 2 2
      lparser.c
  4. 1 2
      lparser.h
  5. 5 5
      lvm.c

+ 53 - 38
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;
+    }
+  }
+}

+ 2 - 1
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

+ 2 - 2
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);

+ 1 - 2
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' */

+ 5 - 5
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... */