diff options
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 41 |
1 files changed, 28 insertions, 13 deletions
@@ -866,7 +866,8 @@ void luaV_finishOp (lua_State *L) { | |||
866 | #define ProtectNT(exp) (savepc(L), (exp), updatetrap(ci)) | 866 | #define ProtectNT(exp) (savepc(L), (exp), updatetrap(ci)) |
867 | 867 | ||
868 | /* | 868 | /* |
869 | ** Protect code that will finish the loop (returns). | 869 | ** Protect code that will finish the loop (returns) or can only raise |
870 | ** errors. | ||
870 | */ | 871 | */ |
871 | #define halfProtect(exp) (savepc(L), (exp)) | 872 | #define halfProtect(exp) (savepc(L), (exp)) |
872 | 873 | ||
@@ -1457,7 +1458,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1457 | vmbreak; | 1458 | vmbreak; |
1458 | } | 1459 | } |
1459 | vmcase(OP_TBC) { | 1460 | vmcase(OP_TBC) { |
1460 | luaF_newtbcupval(L, ra); /* create new to-be-closed upvalue */ | 1461 | /* create new to-be-closed upvalue */ |
1462 | halfProtect(luaF_newtbcupval(L, ra)); | ||
1461 | vmbreak; | 1463 | vmbreak; |
1462 | } | 1464 | } |
1463 | vmcase(OP_JMP) { | 1465 | vmcase(OP_JMP) { |
@@ -1745,21 +1747,34 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1745 | vmbreak; | 1747 | vmbreak; |
1746 | } | 1748 | } |
1747 | vmcase(OP_TFORPREP) { | 1749 | vmcase(OP_TFORPREP) { |
1750 | /* is 'state' a function or has a '__close' metamethod? */ | ||
1751 | if (ttisfunction(s2v(ra + 1)) || | ||
1752 | !ttisnil(luaT_gettmbyobj(L, s2v(ra + 1), TM_CLOSE))) { | ||
1753 | /* create to-be-closed upvalue for it */ | ||
1754 | halfProtect(luaF_newtbcupval(L, ra + 1)); | ||
1755 | } | ||
1748 | pc += GETARG_Bx(i); | 1756 | pc += GETARG_Bx(i); |
1749 | vmbreak; | 1757 | i = *(pc++); /* go to next instruction */ |
1758 | lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i)); | ||
1759 | goto l_tforcall; | ||
1750 | } | 1760 | } |
1751 | vmcase(OP_TFORCALL) { | 1761 | vmcase(OP_TFORCALL) { |
1752 | StkId cb = ra + 3; /* call base */ | 1762 | l_tforcall: |
1753 | setobjs2s(L, cb+2, ra+2); | 1763 | /* 'ra' has the iterator function, 'ra + 1' has the state, |
1754 | setobjs2s(L, cb+1, ra+1); | 1764 | and 'ra + 2' has the control variable. The call will use |
1755 | setobjs2s(L, cb, ra); | 1765 | the stack after these values (starting at 'ra + 3') |
1756 | L->top = cb + 3; /* func. + 2 args (state and index) */ | 1766 | */ |
1757 | Protect(luaD_call(L, cb, GETARG_C(i))); | 1767 | /* push function, state, and control variable */ |
1758 | if (trap) /* keep 'base' correct for next instruction */ | 1768 | memcpy(ra + 3, ra, 3 * sizeof(*ra)); |
1759 | updatebase(ci); | 1769 | L->top = ra + 6; |
1770 | Protect(luaD_call(L, ra + 3, GETARG_C(i))); /* do the call */ | ||
1771 | if (trap) { /* stack may have changed? */ | ||
1772 | updatebase(ci); /* keep 'base' correct */ | ||
1773 | ra = RA(i); /* keep 'ra' correct for next instruction */ | ||
1774 | } | ||
1760 | i = *(pc++); /* go to next instruction */ | 1775 | i = *(pc++); /* go to next instruction */ |
1761 | ra = RA(i); /* get its 'ra' */ | 1776 | ra += 2; /* adjust for next instruction */ |
1762 | lua_assert(GET_OPCODE(i) == OP_TFORLOOP); | 1777 | lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i)); |
1763 | goto l_tforloop; | 1778 | goto l_tforloop; |
1764 | } | 1779 | } |
1765 | vmcase(OP_TFORLOOP) { | 1780 | vmcase(OP_TFORLOOP) { |