diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-05-10 14:02:32 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-05-10 14:02:32 -0300 |
commit | b487975344ee90c0410e79e1af08461bdbc0f3da (patch) | |
tree | 4ae1c9f12afe1edbcc0c8de22abdac4b19e2844d /lparser.c | |
parent | 94e5545806515bc830982dedc4966bd2756a023e (diff) | |
download | lua-b487975344ee90c0410e79e1af08461bdbc0f3da.tar.gz lua-b487975344ee90c0410e79e1af08461bdbc0f3da.tar.bz2 lua-b487975344ee90c0410e79e1af08461bdbc0f3da.zip |
optimization for `while' (first version)
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 47 |
1 files changed, 43 insertions, 4 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 1.178 2002/04/24 20:07:46 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.179 2002/05/07 17:36:56 roberto Exp roberto $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -946,22 +946,61 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { | |||
946 | static void cond (LexState *ls, expdesc *v) { | 946 | static void cond (LexState *ls, expdesc *v) { |
947 | /* cond -> exp */ | 947 | /* cond -> exp */ |
948 | expr(ls, v); /* read condition */ | 948 | expr(ls, v); /* read condition */ |
949 | if (v->k == VNIL) v->k = VFALSE; /* `falses' are all equal here */ | ||
949 | luaK_goiftrue(ls->fs, v); | 950 | luaK_goiftrue(ls->fs, v); |
951 | luaK_patchtohere(ls->fs, v->t); | ||
950 | } | 952 | } |
951 | 953 | ||
952 | 954 | ||
955 | /* | ||
956 | ** The while statement optimizes its code by coding the condition | ||
957 | ** after its body (and thus avoiding one jump in the loop). | ||
958 | */ | ||
959 | |||
960 | /* | ||
961 | ** maximum size of expressions for optimizing `while' code | ||
962 | */ | ||
963 | #ifndef MAXEXPWHILE | ||
964 | #define MAXEXPWHILE 100 | ||
965 | #endif | ||
966 | |||
967 | /* | ||
968 | ** the call `luaK_goiffalse' may grow the size of an expression by | ||
969 | ** at most this: | ||
970 | */ | ||
971 | #define EXTRAEXP 5 | ||
972 | |||
953 | static void whilestat (LexState *ls, int line) { | 973 | static void whilestat (LexState *ls, int line) { |
954 | /* whilestat -> WHILE cond DO block END */ | 974 | /* whilestat -> WHILE cond DO block END */ |
975 | Instruction codeexp[MAXEXPWHILE + EXTRAEXP]; | ||
976 | int lineexp = 0; | ||
977 | int i; | ||
978 | int sizeexp; | ||
955 | FuncState *fs = ls->fs; | 979 | FuncState *fs = ls->fs; |
956 | int while_init = luaK_getlabel(fs); | 980 | int while_init = luaK_getlabel(fs); |
957 | expdesc v; | 981 | expdesc v; |
958 | BlockCnt bl; | 982 | BlockCnt bl; |
959 | enterblock(fs, &bl, 1); | ||
960 | next(ls); | 983 | next(ls); |
961 | cond(ls, &v); | 984 | expr(ls, &v); |
985 | if (v.k == VK) v.k = VTRUE; /* `trues' are all equal here */ | ||
986 | lineexp = ls->linenumber; | ||
987 | luaK_goiffalse(fs, &v); | ||
988 | sizeexp = fs->pc - while_init; | ||
989 | if (sizeexp > MAXEXPWHILE) | ||
990 | luaX_syntaxerror(ls, "while condition too complex"); | ||
991 | fs->pc = while_init; /* remove `exp' code */ | ||
992 | luaK_getlabel(fs); | ||
993 | for (i = 0; i < sizeexp; i++) /* save `exp' code */ | ||
994 | codeexp[i] = fs->f->code[while_init + i]; | ||
995 | luaK_jump(fs); | ||
996 | enterblock(fs, &bl, 1); | ||
962 | check(ls, TK_DO); | 997 | check(ls, TK_DO); |
963 | block(ls); | 998 | block(ls); |
964 | luaK_patchlist(fs, luaK_jump(fs), while_init); | 999 | luaK_patchtohere(fs, while_init); /* initial jump jumps to here */ |
1000 | luaK_moveexp(&v, fs->pc - while_init); /* correct pointers */ | ||
1001 | for (i=0; i<sizeexp; i++) | ||
1002 | luaK_code(fs, codeexp[i], lineexp); | ||
1003 | luaK_patchlist(fs, v.t, while_init+1); | ||
965 | luaK_patchtohere(fs, v.f); | 1004 | luaK_patchtohere(fs, v.f); |
966 | check_match(ls, TK_END, TK_WHILE, line); | 1005 | check_match(ls, TK_END, TK_WHILE, line); |
967 | leaveblock(fs); | 1006 | leaveblock(fs); |