aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-05-10 14:02:32 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-05-10 14:02:32 -0300
commitb487975344ee90c0410e79e1af08461bdbc0f3da (patch)
tree4ae1c9f12afe1edbcc0c8de22abdac4b19e2844d
parent94e5545806515bc830982dedc4966bd2756a023e (diff)
downloadlua-b487975344ee90c0410e79e1af08461bdbc0f3da.tar.gz
lua-b487975344ee90c0410e79e1af08461bdbc0f3da.tar.bz2
lua-b487975344ee90c0410e79e1af08461bdbc0f3da.zip
optimization for `while' (first version)
-rw-r--r--lcode.c27
-rw-r--r--lcode.h5
-rw-r--r--lparser.c47
3 files changed, 64 insertions, 15 deletions
diff --git a/lcode.c b/lcode.c
index 6d463311..f72bcdb3 100644
--- a/lcode.c
+++ b/lcode.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lcode.c,v 1.99 2002/05/07 17:36:56 roberto Exp roberto $ 2** $Id: lcode.c,v 1.100 2002/05/09 14:14:34 roberto Exp roberto $
3** Code generator for Lua 3** Code generator for Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -39,6 +39,13 @@ void luaK_nil (FuncState *fs, int from, int n) {
39} 39}
40 40
41 41
42void luaK_moveexp (expdesc *e, int offset) {
43 if (e->t != NO_JUMP) e->t += offset;
44 if (e->f != NO_JUMP) e->f += offset;
45 if (e->k == VRELOCABLE || e->k == VJMP) e->info += offset;
46}
47
48
42int luaK_jump (FuncState *fs) { 49int luaK_jump (FuncState *fs) {
43 int j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); 50 int j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP);
44 if (j == fs->lasttarget) { /* possible jumps to this jump? */ 51 if (j == fs->lasttarget) { /* possible jumps to this jump? */
@@ -515,12 +522,10 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) {
515 } 522 }
516 } 523 }
517 luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ 524 luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */
518 luaK_patchtohere(fs, e->t);
519 e->t = NO_JUMP;
520} 525}
521 526
522 527
523static void luaK_goiffalse (FuncState *fs, expdesc *e) { 528void luaK_goiffalse (FuncState *fs, expdesc *e) {
524 int pc; /* pc of last jump */ 529 int pc; /* pc of last jump */
525 luaK_dischargevars(fs, e); 530 luaK_dischargevars(fs, e);
526 switch (e->k) { 531 switch (e->k) {
@@ -542,8 +547,6 @@ static void luaK_goiffalse (FuncState *fs, expdesc *e) {
542 } 547 }
543 } 548 }
544 luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ 549 luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */
545 luaK_patchtohere(fs, e->f);
546 e->f = NO_JUMP;
547} 550}
548 551
549 552
@@ -607,10 +610,14 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
607 switch (op) { 610 switch (op) {
608 case OPR_AND: { 611 case OPR_AND: {
609 luaK_goiftrue(fs, v); 612 luaK_goiftrue(fs, v);
613 luaK_patchtohere(fs, v->t);
614 v->t = NO_JUMP;
610 break; 615 break;
611 } 616 }
612 case OPR_OR: { 617 case OPR_OR: {
613 luaK_goiffalse(fs, v); 618 luaK_goiffalse(fs, v);
619 luaK_patchtohere(fs, v->f);
620 v->f = NO_JUMP;
614 break; 621 break;
615 } 622 }
616 case OPR_CONCAT: { 623 case OPR_CONCAT: {
@@ -727,7 +734,7 @@ void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {
727} 734}
728 735
729 736
730static int luaK_code (FuncState *fs, Instruction i) { 737int luaK_code (FuncState *fs, Instruction i, int line) {
731 Proto *f = fs->f; 738 Proto *f = fs->f;
732 int oldsize = f->sizecode; 739 int oldsize = f->sizecode;
733 /* put new instruction in code array */ 740 /* put new instruction in code array */
@@ -736,19 +743,19 @@ static int luaK_code (FuncState *fs, Instruction i) {
736 f->code[fs->pc] = i; 743 f->code[fs->pc] = i;
737 if (f->sizecode != oldsize) 744 if (f->sizecode != oldsize)
738 luaM_reallocvector(fs->L, f->lineinfo, oldsize, f->sizecode, int); 745 luaM_reallocvector(fs->L, f->lineinfo, oldsize, f->sizecode, int);
739 f->lineinfo[fs->pc] = fs->ls->lastline; 746 f->lineinfo[fs->pc] = line;
740 return fs->pc++; 747 return fs->pc++;
741} 748}
742 749
743 750
744int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { 751int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {
745 lua_assert(getOpMode(o) == iABC); 752 lua_assert(getOpMode(o) == iABC);
746 return luaK_code(fs, CREATE_ABC(o, a, b, c)); 753 return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline);
747} 754}
748 755
749 756
750int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { 757int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
751 lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); 758 lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
752 return luaK_code(fs, CREATE_ABx(o, a, bc)); 759 return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline);
753} 760}
754 761
diff --git a/lcode.h b/lcode.h
index 472b4ebc..7d46ca43 100644
--- a/lcode.h
+++ b/lcode.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lcode.h,v 1.32 2002/04/24 20:07:46 roberto Exp roberto $ 2** $Id: lcode.h,v 1.33 2002/05/07 17:36:56 roberto Exp roberto $
3** Code generator for Lua 3** Code generator for Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -41,6 +41,7 @@ typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_NOUNOPR } UnOpr;
41 41
42#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) 42#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)
43 43
44int luaK_code (FuncState *fs, Instruction i, int line);
44int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); 45int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
45int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); 46int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);
46void luaK_nil (FuncState *fs, int from, int n); 47void luaK_nil (FuncState *fs, int from, int n);
@@ -54,7 +55,9 @@ void luaK_exp2val (FuncState *fs, expdesc *e);
54int luaK_exp2RK (FuncState *fs, expdesc *e); 55int luaK_exp2RK (FuncState *fs, expdesc *e);
55void luaK_self (FuncState *fs, expdesc *e, expdesc *key); 56void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
56void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); 57void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
58void luaK_moveexp (expdesc *e, int offset);
57void luaK_goiftrue (FuncState *fs, expdesc *e); 59void luaK_goiftrue (FuncState *fs, expdesc *e);
60void luaK_goiffalse (FuncState *fs, expdesc *e);
58void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); 61void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
59void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults); 62void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults);
60int luaK_jump (FuncState *fs); 63int luaK_jump (FuncState *fs);
diff --git a/lparser.c b/lparser.c
index b6e500b8..eaf0bc8a 100644
--- a/lparser.c
+++ b/lparser.c
@@ -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) {
946static void cond (LexState *ls, expdesc *v) { 946static 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
953static void whilestat (LexState *ls, int line) { 973static 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);