2
0
Эх сурвалжийг харах

new optimization: jumps to jumps

Roberto Ierusalimschy 25 жил өмнө
parent
commit
d615e78e08
3 өөрчлөгдсөн 38 нэмэгдсэн , 23 устгасан
  1. 18 4
      lcode.c
  2. 18 18
      lparser.c
  3. 2 1
      lparser.h

+ 18 - 4
lcode.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 1.19 2000/04/04 20:48:44 roberto Exp roberto $
+** $Id: lcode.c,v 1.20 2000/04/05 17:51:58 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -171,7 +171,12 @@ static void luaK_neq (FuncState *fs) {
 
 
 int luaK_jump (FuncState *fs) {
-  return luaK_S(fs, OP_JMP, NO_JUMP, 0);
+  int j = luaK_S(fs, OP_JMP, NO_JUMP, 0);
+  if (j == fs->lasttarget) {  /* possible jumps to this jump? */
+    luaK_concat(fs, &j, fs->jlt);  /* keep them on hold */
+    fs->jlt = NO_JUMP;
+  }
+  return j;
 }
 
 
@@ -220,11 +225,17 @@ static int luaK_getjump (FuncState *fs, int pc) {
 
 
 /*
+** discharge list of jumps to last target.
 ** returns current `pc' and marks it as a jump target (to avoid wrong
 ** optimizations with consecutive instructions not in the same basic block).
 */
 int luaK_getlabel (FuncState *fs) {
-  fs->lasttarget = fs->pc;
+  if (fs->pc != fs->lasttarget) {
+    int lasttarget = fs->lasttarget;
+    fs->lasttarget = fs->pc;
+    luaK_patchlist(fs, fs->jlt, lasttarget);  /* discharge old list `jlt' */
+    fs->jlt = NO_JUMP;  /* nobody jumps to this new label (till now) */
+  }
   return fs->pc;
 }
 
@@ -394,7 +405,10 @@ static void luaK_patchlistaux (FuncState *fs, int list, int target,
 
 
 void luaK_patchlist (FuncState *fs, int list, int target) {
-  luaK_patchlistaux(fs, list, target, OP_END, 0);
+  if (target == fs->lasttarget)  /* same target that list `jlt'? */
+    luaK_concat(fs, &fs->jlt, list);  /* delay fixing */
+  else
+    luaK_patchlistaux(fs, list, target, OP_END, 0);
 }
 
 

+ 18 - 18
lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 1.75 2000/04/03 13:44:55 roberto Exp roberto $
+** $Id: lparser.c,v 1.76 2000/04/05 17:51:58 roberto Exp roberto $
 ** LL(1) Parser and code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -71,20 +71,6 @@ static void error_unexpected (LexState *ls) {
 }
 
 
-static void error_unmatched (LexState *ls, int what, int who, int where) {
-  if (where == ls->linenumber)
-    error_expected(ls, what);
-  else {
-    char buff[100];
-    char t_what[TOKEN_LEN], t_who[TOKEN_LEN];
-    luaX_token2str(what, t_what);
-    luaX_token2str(who, t_who);
-    sprintf(buff, "`%.20s' expected (to close `%.20s' at line %d)",
-            t_what, t_who, where);
-    luaK_error(ls, buff);
-  }
-}
-
 static void check (LexState *ls, int c) {
   if (ls->token != c)
     error_expected(ls, c);
@@ -121,8 +107,19 @@ static int optional (LexState *ls, int c) {
 
 
 static void check_match (LexState *ls, int what, int who, int where) {
-  if (ls->token != what)
-    error_unmatched(ls, what, who, where);
+  if (ls->token != what) {
+    if (where == ls->linenumber)
+      error_expected(ls, what);
+    else {
+      char buff[100];
+      char t_what[TOKEN_LEN], t_who[TOKEN_LEN];
+      luaX_token2str(what, t_what);
+      luaX_token2str(who, t_who);
+      sprintf(buff, "`%.20s' expected (to close `%.20s' at line %d)",
+              t_what, t_who, where);
+      luaK_error(ls, buff);
+    }
+  }
   next(ls);
 }
 
@@ -363,6 +360,7 @@ static void init_state (LexState *ls, FuncState *fs, TString *source) {
   f->source = source;
   fs->pc = 0;
   fs->lasttarget = 0;
+  fs->jlt = NO_JUMP;
   f->code = NULL;
   f->maxstacksize = 0;
   f->numparams = 0;  /* default for main chunk */
@@ -376,6 +374,7 @@ static void close_func (LexState *ls) {
   FuncState *fs = ls->fs;
   Proto *f = fs->f;
   luaK_0(fs, OP_END, 0);
+  luaK_getlabel(fs);  /* close eventual list of pending jumps */
   luaM_reallocvector(L, f->code, fs->pc, Instruction);
   luaM_reallocvector(L, f->kstr, f->nkstr, TString *);
   luaM_reallocvector(L, f->knum, f->nknum, Number);
@@ -1114,7 +1113,8 @@ static void ret (LexState *ls) {
       Breaklabel *bl = fs->bl;
       int currentlevel = fs->stacklevel;
       if (bl == NULL)
-        luaK_error(ls, "no breakable structure to break");
+        luaK_error(ls, "break not inside while or repeat loop");
+
       setline_and_next(ls);  /* skip BREAK */
       luaK_adjuststack(fs, currentlevel - bl->stacklevel);
       luaK_concat(fs, &bl->breaklist, luaK_jump(fs));

+ 2 - 1
lparser.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.h,v 1.14 2000/03/24 17:26:08 roberto Exp roberto $
+** $Id: lparser.h,v 1.15 2000/04/05 17:51:58 roberto Exp roberto $
 ** LL(1) Parser and code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -43,6 +43,7 @@ typedef struct FuncState {
   struct lua_State *L;  /* copy of the Lua state */
   int pc;  /* next position to code */
   int lasttarget;   /* `pc' of last `jump target' */
+  int jlt;  /* list of jumps to `lasttarged' */
   int stacklevel;  /* number of values on activation register */
   int nlocalvar;  /* number of active local variables */
   int nupvalues;  /* number of upvalues */