aboutsummaryrefslogtreecommitdiff
path: root/lvm.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lvm.c90
1 files changed, 50 insertions, 40 deletions
diff --git a/lvm.c b/lvm.c
index 4d71cfff..256d689f 100644
--- a/lvm.c
+++ b/lvm.c
@@ -198,12 +198,15 @@ static int forlimit (lua_State *L, lua_Integer init, const TValue *lim,
198 198
199/* 199/*
200** Prepare a numerical for loop (opcode OP_FORPREP). 200** Prepare a numerical for loop (opcode OP_FORPREP).
201** Before execution, stack is as follows:
202** ra : initial value
203** ra + 1 : limit
204** ra + 2 : step
201** Return true to skip the loop. Otherwise, 205** Return true to skip the loop. Otherwise,
202** after preparation, stack will be as follows: 206** after preparation, stack will be as follows:
203** ra : internal index (safe copy of the control variable) 207** ra : loop counter (integer loops) or limit (float loops)
204** ra + 1 : loop counter (integer loops) or limit (float loops) 208** ra + 1 : step
205** ra + 2 : step 209** ra + 2 : control variable
206** ra + 3 : control variable
207*/ 210*/
208static int forprep (lua_State *L, StkId ra) { 211static int forprep (lua_State *L, StkId ra) {
209 TValue *pinit = s2v(ra); 212 TValue *pinit = s2v(ra);
@@ -215,7 +218,6 @@ static int forprep (lua_State *L, StkId ra) {
215 lua_Integer limit; 218 lua_Integer limit;
216 if (step == 0) 219 if (step == 0)
217 luaG_runerror(L, "'for' step is zero"); 220 luaG_runerror(L, "'for' step is zero");
218 setivalue(s2v(ra + 3), init); /* control variable */
219 if (forlimit(L, init, plimit, &limit, step)) 221 if (forlimit(L, init, plimit, &limit, step))
220 return 1; /* skip the loop */ 222 return 1; /* skip the loop */
221 else { /* prepare loop counter */ 223 else { /* prepare loop counter */
@@ -230,9 +232,10 @@ static int forprep (lua_State *L, StkId ra) {
230 /* 'step+1' avoids negating 'mininteger' */ 232 /* 'step+1' avoids negating 'mininteger' */
231 count /= l_castS2U(-(step + 1)) + 1u; 233 count /= l_castS2U(-(step + 1)) + 1u;
232 } 234 }
233 /* store the counter in place of the limit (which won't be 235 /* use 'chgivalue' for places that for sure had integers */
234 needed anymore) */ 236 chgivalue(s2v(ra), l_castU2S(count)); /* change init to count */
235 setivalue(plimit, l_castU2S(count)); 237 setivalue(s2v(ra + 1), step); /* change limit to step */
238 chgivalue(s2v(ra + 2), init); /* change step to init */
236 } 239 }
237 } 240 }
238 else { /* try making all values floats */ 241 else { /* try making all values floats */
@@ -249,11 +252,10 @@ static int forprep (lua_State *L, StkId ra) {
249 : luai_numlt(init, limit)) 252 : luai_numlt(init, limit))
250 return 1; /* skip the loop */ 253 return 1; /* skip the loop */
251 else { 254 else {
252 /* make sure internal values are all floats */ 255 /* make sure all values are floats */
253 setfltvalue(plimit, limit); 256 setfltvalue(s2v(ra), limit);
254 setfltvalue(pstep, step); 257 setfltvalue(s2v(ra + 1), step);
255 setfltvalue(s2v(ra), init); /* internal index */ 258 setfltvalue(s2v(ra + 2), init); /* control variable */
256 setfltvalue(s2v(ra + 3), init); /* control variable */
257 } 259 }
258 } 260 }
259 return 0; 261 return 0;
@@ -266,14 +268,13 @@ static int forprep (lua_State *L, StkId ra) {
266** written online with opcode OP_FORLOOP, for performance.) 268** written online with opcode OP_FORLOOP, for performance.)
267*/ 269*/
268static int floatforloop (StkId ra) { 270static int floatforloop (StkId ra) {
269 lua_Number step = fltvalue(s2v(ra + 2)); 271 lua_Number step = fltvalue(s2v(ra + 1));
270 lua_Number limit = fltvalue(s2v(ra + 1)); 272 lua_Number limit = fltvalue(s2v(ra));
271 lua_Number idx = fltvalue(s2v(ra)); /* internal index */ 273 lua_Number idx = fltvalue(s2v(ra + 2)); /* control variable */
272 idx = luai_numadd(L, idx, step); /* increment index */ 274 idx = luai_numadd(L, idx, step); /* increment index */
273 if (luai_numlt(0, step) ? luai_numle(idx, limit) 275 if (luai_numlt(0, step) ? luai_numle(idx, limit)
274 : luai_numle(limit, idx)) { 276 : luai_numle(limit, idx)) {
275 chgfltvalue(s2v(ra), idx); /* update internal index */ 277 chgfltvalue(s2v(ra + 2), idx); /* update control variable */
276 setfltvalue(s2v(ra + 3), idx); /* and control variable */
277 return 1; /* jump back */ 278 return 1; /* jump back */
278 } 279 }
279 else 280 else
@@ -1783,15 +1784,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1783 } 1784 }
1784 vmcase(OP_FORLOOP) { 1785 vmcase(OP_FORLOOP) {
1785 StkId ra = RA(i); 1786 StkId ra = RA(i);
1786 if (ttisinteger(s2v(ra + 2))) { /* integer loop? */ 1787 if (ttisinteger(s2v(ra + 1))) { /* integer loop? */
1787 lua_Unsigned count = l_castS2U(ivalue(s2v(ra + 1))); 1788 lua_Unsigned count = l_castS2U(ivalue(s2v(ra)));
1788 if (count > 0) { /* still more iterations? */ 1789 if (count > 0) { /* still more iterations? */
1789 lua_Integer step = ivalue(s2v(ra + 2)); 1790 lua_Integer step = ivalue(s2v(ra + 1));
1790 lua_Integer idx = ivalue(s2v(ra)); /* internal index */ 1791 lua_Integer idx = ivalue(s2v(ra + 2)); /* control variable */
1791 chgivalue(s2v(ra + 1), count - 1); /* update counter */ 1792 chgivalue(s2v(ra), count - 1); /* update counter */
1792 idx = intop(+, idx, step); /* add step to index */ 1793 idx = intop(+, idx, step); /* add step to index */
1793 chgivalue(s2v(ra), idx); /* update internal index */ 1794 chgivalue(s2v(ra + 2), idx); /* update control variable */
1794 setivalue(s2v(ra + 3), idx); /* and control variable */
1795 pc -= GETARG_Bx(i); /* jump back */ 1795 pc -= GETARG_Bx(i); /* jump back */
1796 } 1796 }
1797 } 1797 }
@@ -1808,26 +1808,38 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1808 vmbreak; 1808 vmbreak;
1809 } 1809 }
1810 vmcase(OP_TFORPREP) { 1810 vmcase(OP_TFORPREP) {
1811 /* before: 'ra' has the iterator function, 'ra + 1' has the state,
1812 'ra + 2' has the initial value for the control variable, and
1813 'ra + 3' has the closing variable. This opcode then swaps the
1814 control and the closing variables and marks the closing variable
1815 as to-be-closed.
1816 */
1811 StkId ra = RA(i); 1817 StkId ra = RA(i);
1812 /* create to-be-closed upvalue (if needed) */ 1818 TValue temp; /* to swap control and closing variables */
1813 halfProtect(luaF_newtbcupval(L, ra + 3)); 1819 setobj(L, &temp, s2v(ra + 3));
1814 pc += GETARG_Bx(i); 1820 setobjs2s(L, ra + 3, ra + 2);
1815 i = *(pc++); /* go to next instruction */ 1821 setobj2s(L, ra + 2, &temp);
1822 /* create to-be-closed upvalue (if closing var. is not nil) */
1823 halfProtect(luaF_newtbcupval(L, ra + 2));
1824 pc += GETARG_Bx(i); /* go to end of the loop */
1825 i = *(pc++); /* fetch next instruction */
1816 lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i)); 1826 lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i));
1817 goto l_tforcall; 1827 goto l_tforcall;
1818 } 1828 }
1819 vmcase(OP_TFORCALL) { 1829 vmcase(OP_TFORCALL) {
1820 l_tforcall: { 1830 l_tforcall: {
1821 StkId ra = RA(i);
1822 /* 'ra' has the iterator function, 'ra + 1' has the state, 1831 /* 'ra' has the iterator function, 'ra + 1' has the state,
1823 'ra + 2' has the control variable, and 'ra + 3' has the 1832 'ra + 2' has the closing variable, and 'ra + 3' has the control
1824 to-be-closed variable. The call will use the stack after 1833 variable. The call will use the stack starting at 'ra + 3',
1825 these values (starting at 'ra + 4') 1834 so that it preserves the first three values, and the first
1835 return will be the new value for the control variable.
1826 */ 1836 */
1827 /* push function, state, and control variable */ 1837 StkId ra = RA(i);
1828 memcpy(ra + 4, ra, 3 * sizeof(*ra)); 1838 setobjs2s(L, ra + 5, ra + 3); /* copy the control variable */
1829 L->top.p = ra + 4 + 3; 1839 setobjs2s(L, ra + 4, ra + 1); /* copy state */
1830 ProtectNT(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */ 1840 setobjs2s(L, ra + 3, ra); /* copy function */
1841 L->top.p = ra + 3 + 3;
1842 ProtectNT(luaD_call(L, ra + 3, GETARG_C(i))); /* do the call */
1831 updatestack(ci); /* stack may have changed */ 1843 updatestack(ci); /* stack may have changed */
1832 i = *(pc++); /* go to next instruction */ 1844 i = *(pc++); /* go to next instruction */
1833 lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i)); 1845 lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i));
@@ -1836,10 +1848,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1836 vmcase(OP_TFORLOOP) { 1848 vmcase(OP_TFORLOOP) {
1837 l_tforloop: { 1849 l_tforloop: {
1838 StkId ra = RA(i); 1850 StkId ra = RA(i);
1839 if (!ttisnil(s2v(ra + 4))) { /* continue loop? */ 1851 if (!ttisnil(s2v(ra + 3))) /* continue loop? */
1840 setobjs2s(L, ra + 2, ra + 4); /* save control variable */
1841 pc -= GETARG_Bx(i); /* jump back */ 1852 pc -= GETARG_Bx(i); /* jump back */
1842 }
1843 vmbreak; 1853 vmbreak;
1844 }} 1854 }}
1845 vmcase(OP_SETLIST) { 1855 vmcase(OP_SETLIST) {