diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2011-02-01 16:03:10 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2011-02-01 16:03:10 -0200 |
commit | dd547c55c85ba48f481836ba76ecdfe69960bcd0 (patch) | |
tree | d75d864ae35fc5bafacf3c206eaa20885b03a3d1 | |
parent | f6bd8b1147d58c35e73225b4adc5499c11d2bf0f (diff) | |
download | lua-dd547c55c85ba48f481836ba76ecdfe69960bcd0.tar.gz lua-dd547c55c85ba48f481836ba76ecdfe69960bcd0.tar.bz2 lua-dd547c55c85ba48f481836ba76ecdfe69960bcd0.zip |
new scheme to close upvalues in 'break'; jump instructions may
do the close, avoiding the need for a OP_CLOSE instruction
-rw-r--r-- | lcode.c | 15 | ||||
-rw-r--r-- | lcode.h | 3 | ||||
-rw-r--r-- | lopcodes.h | 7 | ||||
-rw-r--r-- | lparser.c | 8 | ||||
-rw-r--r-- | lvm.c | 29 |
5 files changed, 41 insertions, 21 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 2.49 2010/07/07 16:27:29 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 2.50 2011/01/31 14:28:41 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 | */ |
@@ -171,6 +171,19 @@ void luaK_patchlist (FuncState *fs, int list, int target) { | |||
171 | } | 171 | } |
172 | 172 | ||
173 | 173 | ||
174 | LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level) { | ||
175 | level++; /* argument is +1 to reserve 0 as non-op */ | ||
176 | while (list != NO_JUMP) { | ||
177 | int next = getjump(fs, list); | ||
178 | lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP && | ||
179 | (GETARG_A(fs->f->code[list]) == 0 || | ||
180 | GETARG_A(fs->f->code[list]) >= level)); | ||
181 | SETARG_A(fs->f->code[list], level); | ||
182 | list = next; | ||
183 | } | ||
184 | } | ||
185 | |||
186 | |||
174 | void luaK_patchtohere (FuncState *fs, int list) { | 187 | void luaK_patchtohere (FuncState *fs, int list) { |
175 | luaK_getlabel(fs); | 188 | luaK_getlabel(fs); |
176 | luaK_concat(fs, &fs->jpc, list); | 189 | luaK_concat(fs, &fs->jpc, list); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.h,v 1.54 2010/04/17 12:46:32 roberto Exp roberto $ | 2 | ** $Id: lcode.h,v 1.55 2010/07/02 20:42:40 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 | */ |
@@ -71,6 +71,7 @@ LUAI_FUNC int luaK_jump (FuncState *fs); | |||
71 | LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); | 71 | LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); |
72 | LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); | 72 | LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); |
73 | LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); | 73 | LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); |
74 | LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level); | ||
74 | LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); | 75 | LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); |
75 | LUAI_FUNC int luaK_getlabel (FuncState *fs); | 76 | LUAI_FUNC int luaK_getlabel (FuncState *fs); |
76 | LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line); | 77 | LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.h,v 1.136 2010/10/13 16:45:54 roberto Exp roberto $ | 2 | ** $Id: lopcodes.h,v 1.137 2010/10/25 12:24:55 roberto Exp roberto $ |
3 | ** Opcodes for Lua virtual machine | 3 | ** Opcodes for Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -195,8 +195,7 @@ OP_LEN,/* A B R(A) := length of R(B) */ | |||
195 | 195 | ||
196 | OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ | 196 | OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ |
197 | 197 | ||
198 | OP_JMP,/* sBx pc+=sBx */ | 198 | OP_JMP,/* A sBx pc+=sBx; if (A) close all upvalues >= R(A) + 1 */ |
199 | |||
200 | OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ | 199 | OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ |
201 | OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ | 200 | OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ |
202 | OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ | 201 | OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ |
@@ -217,7 +216,7 @@ OP_TFORLOOP,/* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx }*/ | |||
217 | 216 | ||
218 | OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */ | 217 | OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */ |
219 | 218 | ||
220 | OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/ | 219 | OP_CLOSE,/* A close all upvalues >= R(A) */ |
221 | OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx]) */ | 220 | OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx]) */ |
222 | 221 | ||
223 | OP_VARARG,/* A B R(A), R(A+1), ..., R(A+B-2) = vararg */ | 222 | OP_VARARG,/* A B R(A), R(A+1), ..., R(A+B-2) = vararg */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 2.94 2010/12/17 12:03:41 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 2.95 2011/01/26 16:30:02 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 | */ |
@@ -245,7 +245,7 @@ static int searchvar (FuncState *fs, TString *n) { | |||
245 | 245 | ||
246 | /* | 246 | /* |
247 | Mark block where variable at given level was defined | 247 | Mark block where variable at given level was defined |
248 | (to emit OP_CLOSE later). | 248 | (to emit close instructions later). |
249 | */ | 249 | */ |
250 | static void markupval (FuncState *fs, int level) { | 250 | static void markupval (FuncState *fs, int level) { |
251 | BlockCnt *bl = fs->bl; | 251 | BlockCnt *bl = fs->bl; |
@@ -1053,9 +1053,9 @@ static void breakstat (LexState *ls) { | |||
1053 | } | 1053 | } |
1054 | if (!bl) | 1054 | if (!bl) |
1055 | luaX_syntaxerror(ls, "no loop to break"); | 1055 | luaX_syntaxerror(ls, "no loop to break"); |
1056 | if (upval) | ||
1057 | luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); | ||
1058 | luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); | 1056 | luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); |
1057 | if (upval) | ||
1058 | luaK_patchclose(fs, bl->breaklist, bl->nactvar); | ||
1059 | } | 1059 | } |
1060 | 1060 | ||
1061 | 1061 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.126 2010/12/06 21:08:36 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.127 2010/12/17 12:05:37 roberto Exp roberto $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -466,7 +466,14 @@ void luaV_finishOp (lua_State *L) { | |||
466 | (k + (GETARG_Bx(i) != 0 ? GETARG_Bx(i) - 1 : GETARG_Ax(*ci->u.l.savedpc++))) | 466 | (k + (GETARG_Bx(i) != 0 ? GETARG_Bx(i) - 1 : GETARG_Ax(*ci->u.l.savedpc++))) |
467 | 467 | ||
468 | 468 | ||
469 | #define dojump(i) (ci->u.l.savedpc += (i)) | 469 | /* execute a jump instruction */ |
470 | #define dojump(ci,i) \ | ||
471 | { int a = GETARG_A(i); \ | ||
472 | if (a > 0) luaF_close(L, ci->u.l.base + a - 1); \ | ||
473 | ci->u.l.savedpc += GETARG_sBx(i); } | ||
474 | |||
475 | /* for test instructions, execute the jump instruction that follows it */ | ||
476 | #define donextjump(ci) dojump(ci, *ci->u.l.savedpc) | ||
470 | 477 | ||
471 | 478 | ||
472 | #define Protect(x) { {x;}; base = ci->u.l.base; } | 479 | #define Protect(x) { {x;}; base = ci->u.l.base; } |
@@ -620,41 +627,41 @@ void luaV_execute (lua_State *L) { | |||
620 | L->top = ci->top; /* restore top */ | 627 | L->top = ci->top; /* restore top */ |
621 | ) | 628 | ) |
622 | vmcase(OP_JMP, | 629 | vmcase(OP_JMP, |
623 | dojump(GETARG_sBx(i)); | 630 | dojump(ci, i); |
624 | ) | 631 | ) |
625 | vmcase(OP_EQ, | 632 | vmcase(OP_EQ, |
626 | TValue *rb = RKB(i); | 633 | TValue *rb = RKB(i); |
627 | TValue *rc = RKC(i); | 634 | TValue *rc = RKC(i); |
628 | Protect( | 635 | Protect( |
629 | if (equalobj(L, rb, rc) == GETARG_A(i)) | 636 | if (equalobj(L, rb, rc) == GETARG_A(i)) |
630 | dojump(GETARG_sBx(*ci->u.l.savedpc)); | 637 | donextjump(ci); |
631 | ) | 638 | ) |
632 | ci->u.l.savedpc++; | 639 | ci->u.l.savedpc++; |
633 | ) | 640 | ) |
634 | vmcase(OP_LT, | 641 | vmcase(OP_LT, |
635 | Protect( | 642 | Protect( |
636 | if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) | 643 | if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) |
637 | dojump(GETARG_sBx(*ci->u.l.savedpc)); | 644 | donextjump(ci); |
638 | ) | 645 | ) |
639 | ci->u.l.savedpc++; | 646 | ci->u.l.savedpc++; |
640 | ) | 647 | ) |
641 | vmcase(OP_LE, | 648 | vmcase(OP_LE, |
642 | Protect( | 649 | Protect( |
643 | if (luaV_lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) | 650 | if (luaV_lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) |
644 | dojump(GETARG_sBx(*ci->u.l.savedpc)); | 651 | donextjump(ci); |
645 | ) | 652 | ) |
646 | ci->u.l.savedpc++; | 653 | ci->u.l.savedpc++; |
647 | ) | 654 | ) |
648 | vmcase(OP_TEST, | 655 | vmcase(OP_TEST, |
649 | if (GETARG_C(i) ? !l_isfalse(ra) : l_isfalse(ra)) | 656 | if (GETARG_C(i) ? !l_isfalse(ra) : l_isfalse(ra)) |
650 | dojump(GETARG_sBx(*ci->u.l.savedpc)); | 657 | donextjump(ci); |
651 | ci->u.l.savedpc++; | 658 | ci->u.l.savedpc++; |
652 | ) | 659 | ) |
653 | vmcase(OP_TESTSET, | 660 | vmcase(OP_TESTSET, |
654 | TValue *rb = RB(i); | 661 | TValue *rb = RB(i); |
655 | if (GETARG_C(i) ? !l_isfalse(rb) : l_isfalse(rb)) { | 662 | if (GETARG_C(i) ? !l_isfalse(rb) : l_isfalse(rb)) { |
656 | setobjs2s(L, ra, rb); | 663 | setobjs2s(L, ra, rb); |
657 | dojump(GETARG_sBx(*ci->u.l.savedpc)); | 664 | donextjump(ci); |
658 | } | 665 | } |
659 | ci->u.l.savedpc++; | 666 | ci->u.l.savedpc++; |
660 | ) | 667 | ) |
@@ -722,7 +729,7 @@ void luaV_execute (lua_State *L) { | |||
722 | lua_Number limit = nvalue(ra+1); | 729 | lua_Number limit = nvalue(ra+1); |
723 | if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit) | 730 | if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit) |
724 | : luai_numle(L, limit, idx)) { | 731 | : luai_numle(L, limit, idx)) { |
725 | dojump(GETARG_sBx(i)); /* jump back */ | 732 | ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ |
726 | setnvalue(ra, idx); /* update internal index... */ | 733 | setnvalue(ra, idx); /* update internal index... */ |
727 | setnvalue(ra+3, idx); /* ...and external index */ | 734 | setnvalue(ra+3, idx); /* ...and external index */ |
728 | } | 735 | } |
@@ -738,7 +745,7 @@ void luaV_execute (lua_State *L) { | |||
738 | else if (!tonumber(pstep, ra+2)) | 745 | else if (!tonumber(pstep, ra+2)) |
739 | luaG_runerror(L, LUA_QL("for") " step must be a number"); | 746 | luaG_runerror(L, LUA_QL("for") " step must be a number"); |
740 | setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep))); | 747 | setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep))); |
741 | dojump(GETARG_sBx(i)); | 748 | ci->u.l.savedpc += GETARG_sBx(i); |
742 | ) | 749 | ) |
743 | vmcase(OP_TFORCALL, | 750 | vmcase(OP_TFORCALL, |
744 | StkId cb = ra + 3; /* call base */ | 751 | StkId cb = ra + 3; /* call base */ |
@@ -757,7 +764,7 @@ void luaV_execute (lua_State *L) { | |||
757 | l_tforloop: | 764 | l_tforloop: |
758 | if (!ttisnil(ra + 1)) { /* continue loop? */ | 765 | if (!ttisnil(ra + 1)) { /* continue loop? */ |
759 | setobjs2s(L, ra, ra + 1); /* save control variable */ | 766 | setobjs2s(L, ra, ra + 1); /* save control variable */ |
760 | dojump(GETARG_sBx(i)); /* jump back */ | 767 | ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ |
761 | } | 768 | } |
762 | ) | 769 | ) |
763 | vmcase(OP_SETLIST, | 770 | vmcase(OP_SETLIST, |