diff options
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 40 |
1 files changed, 25 insertions, 15 deletions
@@ -1806,26 +1806,38 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1806 | vmbreak; | 1806 | vmbreak; |
1807 | } | 1807 | } |
1808 | vmcase(OP_TFORPREP) { | 1808 | vmcase(OP_TFORPREP) { |
1809 | /* before: 'ra' has the iterator function, 'ra + 1' has the state, | ||
1810 | 'ra + 2' has the initial value for the control variable, and | ||
1811 | 'ra + 3' has the closing variable. This opcode then swaps the | ||
1812 | control and the closing variables and marks the closing variable | ||
1813 | as to-be-closed. | ||
1814 | */ | ||
1809 | StkId ra = RA(i); | 1815 | StkId ra = RA(i); |
1810 | /* create to-be-closed upvalue (if needed) */ | 1816 | TValue temp; /* to swap control and closing variables */ |
1811 | halfProtect(luaF_newtbcupval(L, ra + 3)); | 1817 | setobj(L, &temp, s2v(ra + 3)); |
1812 | pc += GETARG_Bx(i); | 1818 | setobjs2s(L, ra + 3, ra + 2); |
1813 | i = *(pc++); /* go to next instruction */ | 1819 | setobj2s(L, ra + 2, &temp); |
1820 | /* create to-be-closed upvalue (if closing var. is not nil) */ | ||
1821 | halfProtect(luaF_newtbcupval(L, ra + 2)); | ||
1822 | pc += GETARG_Bx(i); /* go to end of the loop */ | ||
1823 | i = *(pc++); /* fetch next instruction */ | ||
1814 | lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i)); | 1824 | lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i)); |
1815 | goto l_tforcall; | 1825 | goto l_tforcall; |
1816 | } | 1826 | } |
1817 | vmcase(OP_TFORCALL) { | 1827 | vmcase(OP_TFORCALL) { |
1818 | l_tforcall: { | 1828 | l_tforcall: { |
1819 | StkId ra = RA(i); | ||
1820 | /* 'ra' has the iterator function, 'ra + 1' has the state, | 1829 | /* 'ra' has the iterator function, 'ra + 1' has the state, |
1821 | 'ra + 2' has the control variable, and 'ra + 3' has the | 1830 | 'ra + 2' has the closing variable, and 'ra + 3' has the control |
1822 | to-be-closed variable. The call will use the stack after | 1831 | variable. The call will use the stack starting at 'ra + 3', |
1823 | these values (starting at 'ra + 4') | 1832 | so that it preserves the first three values, and the first |
1833 | return will be the new value for the control variable. | ||
1824 | */ | 1834 | */ |
1825 | /* push function, state, and control variable */ | 1835 | StkId ra = RA(i); |
1826 | memcpy(ra + 4, ra, 3 * sizeof(*ra)); | 1836 | setobjs2s(L, ra + 5, ra + 3); /* copy the control variable */ |
1827 | L->top.p = ra + 4 + 3; | 1837 | setobjs2s(L, ra + 4, ra + 1); /* copy state */ |
1828 | ProtectNT(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */ | 1838 | setobjs2s(L, ra + 3, ra); /* copy function */ |
1839 | L->top.p = ra + 3 + 3; | ||
1840 | ProtectNT(luaD_call(L, ra + 3, GETARG_C(i))); /* do the call */ | ||
1829 | updatestack(ci); /* stack may have changed */ | 1841 | updatestack(ci); /* stack may have changed */ |
1830 | i = *(pc++); /* go to next instruction */ | 1842 | i = *(pc++); /* go to next instruction */ |
1831 | lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i)); | 1843 | lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i)); |
@@ -1834,10 +1846,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1834 | vmcase(OP_TFORLOOP) { | 1846 | vmcase(OP_TFORLOOP) { |
1835 | l_tforloop: { | 1847 | l_tforloop: { |
1836 | StkId ra = RA(i); | 1848 | StkId ra = RA(i); |
1837 | if (!ttisnil(s2v(ra + 4))) { /* continue loop? */ | 1849 | if (!ttisnil(s2v(ra + 3))) /* continue loop? */ |
1838 | setobjs2s(L, ra + 2, ra + 4); /* save control variable */ | ||
1839 | pc -= GETARG_Bx(i); /* jump back */ | 1850 | pc -= GETARG_Bx(i); /* jump back */ |
1840 | } | ||
1841 | vmbreak; | 1851 | vmbreak; |
1842 | }} | 1852 | }} |
1843 | vmcase(OP_SETLIST) { | 1853 | vmcase(OP_SETLIST) { |