From d615e78e08201906e2f1dfc054b080fbbf7db428 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Thu, 6 Apr 2000 14:36:52 -0300 Subject: [PATCH] new optimization: jumps to jumps --- lcode.c | 22 ++++++++++++++++++---- lparser.c | 36 ++++++++++++++++++------------------ lparser.h | 3 ++- 3 files changed, 38 insertions(+), 23 deletions(-) diff --git a/lcode.c b/lcode.c index de4c3623..750def9a 100644 --- a/lcode.c +++ b/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); } diff --git a/lparser.c b/lparser.c index 1bb0c0cc..3fbffb05 100644 --- a/lparser.c +++ b/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)); diff --git a/lparser.h b/lparser.h index 64214861..edfa2a06 100644 --- a/lparser.h +++ b/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 */