diff options
Diffstat (limited to '')
-rw-r--r-- | lvm.c | 107 |
1 files changed, 60 insertions, 47 deletions
@@ -93,7 +93,9 @@ static int l_strton (const TValue *obj, TValue *result) { | |||
93 | return 0; | 93 | return 0; |
94 | else { | 94 | else { |
95 | TString *st = tsvalue(obj); | 95 | TString *st = tsvalue(obj); |
96 | return (luaO_str2num(getstr(st), result) == tsslen(st) + 1); | 96 | size_t stlen; |
97 | const char *s = getlstr(st, stlen); | ||
98 | return (luaO_str2num(s, result) == stlen + 1); | ||
97 | } | 99 | } |
98 | } | 100 | } |
99 | 101 | ||
@@ -198,12 +200,15 @@ static int forlimit (lua_State *L, lua_Integer init, const TValue *lim, | |||
198 | 200 | ||
199 | /* | 201 | /* |
200 | ** Prepare a numerical for loop (opcode OP_FORPREP). | 202 | ** Prepare a numerical for loop (opcode OP_FORPREP). |
203 | ** Before execution, stack is as follows: | ||
204 | ** ra : initial value | ||
205 | ** ra + 1 : limit | ||
206 | ** ra + 2 : step | ||
201 | ** Return true to skip the loop. Otherwise, | 207 | ** Return true to skip the loop. Otherwise, |
202 | ** after preparation, stack will be as follows: | 208 | ** after preparation, stack will be as follows: |
203 | ** ra : internal index (safe copy of the control variable) | 209 | ** ra : loop counter (integer loops) or limit (float loops) |
204 | ** ra + 1 : loop counter (integer loops) or limit (float loops) | 210 | ** ra + 1 : step |
205 | ** ra + 2 : step | 211 | ** ra + 2 : control variable |
206 | ** ra + 3 : control variable | ||
207 | */ | 212 | */ |
208 | static int forprep (lua_State *L, StkId ra) { | 213 | static int forprep (lua_State *L, StkId ra) { |
209 | TValue *pinit = s2v(ra); | 214 | TValue *pinit = s2v(ra); |
@@ -215,7 +220,6 @@ static int forprep (lua_State *L, StkId ra) { | |||
215 | lua_Integer limit; | 220 | lua_Integer limit; |
216 | if (step == 0) | 221 | if (step == 0) |
217 | luaG_runerror(L, "'for' step is zero"); | 222 | luaG_runerror(L, "'for' step is zero"); |
218 | setivalue(s2v(ra + 3), init); /* control variable */ | ||
219 | if (forlimit(L, init, plimit, &limit, step)) | 223 | if (forlimit(L, init, plimit, &limit, step)) |
220 | return 1; /* skip the loop */ | 224 | return 1; /* skip the loop */ |
221 | else { /* prepare loop counter */ | 225 | else { /* prepare loop counter */ |
@@ -230,9 +234,10 @@ static int forprep (lua_State *L, StkId ra) { | |||
230 | /* 'step+1' avoids negating 'mininteger' */ | 234 | /* 'step+1' avoids negating 'mininteger' */ |
231 | count /= l_castS2U(-(step + 1)) + 1u; | 235 | count /= l_castS2U(-(step + 1)) + 1u; |
232 | } | 236 | } |
233 | /* store the counter in place of the limit (which won't be | 237 | /* use 'chgivalue' for places that for sure had integers */ |
234 | needed anymore) */ | 238 | chgivalue(s2v(ra), l_castU2S(count)); /* change init to count */ |
235 | setivalue(plimit, l_castU2S(count)); | 239 | setivalue(s2v(ra + 1), step); /* change limit to step */ |
240 | chgivalue(s2v(ra + 2), init); /* change step to init */ | ||
236 | } | 241 | } |
237 | } | 242 | } |
238 | else { /* try making all values floats */ | 243 | else { /* try making all values floats */ |
@@ -249,11 +254,10 @@ static int forprep (lua_State *L, StkId ra) { | |||
249 | : luai_numlt(init, limit)) | 254 | : luai_numlt(init, limit)) |
250 | return 1; /* skip the loop */ | 255 | return 1; /* skip the loop */ |
251 | else { | 256 | else { |
252 | /* make sure internal values are all floats */ | 257 | /* make sure all values are floats */ |
253 | setfltvalue(plimit, limit); | 258 | setfltvalue(s2v(ra), limit); |
254 | setfltvalue(pstep, step); | 259 | setfltvalue(s2v(ra + 1), step); |
255 | setfltvalue(s2v(ra), init); /* internal index */ | 260 | setfltvalue(s2v(ra + 2), init); /* control variable */ |
256 | setfltvalue(s2v(ra + 3), init); /* control variable */ | ||
257 | } | 261 | } |
258 | } | 262 | } |
259 | return 0; | 263 | return 0; |
@@ -266,14 +270,13 @@ static int forprep (lua_State *L, StkId ra) { | |||
266 | ** written online with opcode OP_FORLOOP, for performance.) | 270 | ** written online with opcode OP_FORLOOP, for performance.) |
267 | */ | 271 | */ |
268 | static int floatforloop (StkId ra) { | 272 | static int floatforloop (StkId ra) { |
269 | lua_Number step = fltvalue(s2v(ra + 2)); | 273 | lua_Number step = fltvalue(s2v(ra + 1)); |
270 | lua_Number limit = fltvalue(s2v(ra + 1)); | 274 | lua_Number limit = fltvalue(s2v(ra)); |
271 | lua_Number idx = fltvalue(s2v(ra)); /* internal index */ | 275 | lua_Number idx = fltvalue(s2v(ra + 2)); /* control variable */ |
272 | idx = luai_numadd(L, idx, step); /* increment index */ | 276 | idx = luai_numadd(L, idx, step); /* increment index */ |
273 | if (luai_numlt(0, step) ? luai_numle(idx, limit) | 277 | if (luai_numlt(0, step) ? luai_numle(idx, limit) |
274 | : luai_numle(limit, idx)) { | 278 | : luai_numle(limit, idx)) { |
275 | chgfltvalue(s2v(ra), idx); /* update internal index */ | 279 | chgfltvalue(s2v(ra + 2), idx); /* update control variable */ |
276 | setfltvalue(s2v(ra + 3), idx); /* and control variable */ | ||
277 | return 1; /* jump back */ | 280 | return 1; /* jump back */ |
278 | } | 281 | } |
279 | else | 282 | else |
@@ -366,10 +369,10 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key, | |||
366 | ** have different lengths. | 369 | ** have different lengths. |
367 | */ | 370 | */ |
368 | static int l_strcmp (const TString *ts1, const TString *ts2) { | 371 | static int l_strcmp (const TString *ts1, const TString *ts2) { |
369 | const char *s1 = getstr(ts1); | 372 | size_t rl1; /* real length */ |
370 | size_t rl1 = tsslen(ts1); /* real length */ | 373 | const char *s1 = getlstr(ts1, rl1); |
371 | const char *s2 = getstr(ts2); | 374 | size_t rl2; |
372 | size_t rl2 = tsslen(ts2); | 375 | const char *s2 = getlstr(ts2, rl2); |
373 | for (;;) { /* for each segment */ | 376 | for (;;) { /* for each segment */ |
374 | int temp = strcoll(s1, s2); | 377 | int temp = strcoll(s1, s2); |
375 | if (temp != 0) /* not equal? */ | 378 | if (temp != 0) /* not equal? */ |
@@ -619,8 +622,9 @@ static void copy2buff (StkId top, int n, char *buff) { | |||
619 | size_t tl = 0; /* size already copied */ | 622 | size_t tl = 0; /* size already copied */ |
620 | do { | 623 | do { |
621 | TString *st = tsvalue(s2v(top - n)); | 624 | TString *st = tsvalue(s2v(top - n)); |
622 | size_t l = tsslen(st); /* length of string being copied */ | 625 | size_t l; /* length of string being copied */ |
623 | memcpy(buff + tl, getstr(st), l * sizeof(char)); | 626 | const char *s = getlstr(st, l); |
627 | memcpy(buff + tl, s, l * sizeof(char)); | ||
624 | tl += l; | 628 | tl += l; |
625 | } while (--n > 0); | 629 | } while (--n > 0); |
626 | } | 630 | } |
@@ -1766,15 +1770,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1766 | } | 1770 | } |
1767 | vmcase(OP_FORLOOP) { | 1771 | vmcase(OP_FORLOOP) { |
1768 | StkId ra = RA(i); | 1772 | StkId ra = RA(i); |
1769 | if (ttisinteger(s2v(ra + 2))) { /* integer loop? */ | 1773 | if (ttisinteger(s2v(ra + 1))) { /* integer loop? */ |
1770 | lua_Unsigned count = l_castS2U(ivalue(s2v(ra + 1))); | 1774 | lua_Unsigned count = l_castS2U(ivalue(s2v(ra))); |
1771 | if (count > 0) { /* still more iterations? */ | 1775 | if (count > 0) { /* still more iterations? */ |
1772 | lua_Integer step = ivalue(s2v(ra + 2)); | 1776 | lua_Integer step = ivalue(s2v(ra + 1)); |
1773 | lua_Integer idx = ivalue(s2v(ra)); /* internal index */ | 1777 | lua_Integer idx = ivalue(s2v(ra + 2)); /* control variable */ |
1774 | chgivalue(s2v(ra + 1), count - 1); /* update counter */ | 1778 | chgivalue(s2v(ra), count - 1); /* update counter */ |
1775 | idx = intop(+, idx, step); /* add step to index */ | 1779 | idx = intop(+, idx, step); /* add step to index */ |
1776 | chgivalue(s2v(ra), idx); /* update internal index */ | 1780 | chgivalue(s2v(ra + 2), idx); /* update control variable */ |
1777 | setivalue(s2v(ra + 3), idx); /* and control variable */ | ||
1778 | pc -= GETARG_Bx(i); /* jump back */ | 1781 | pc -= GETARG_Bx(i); /* jump back */ |
1779 | } | 1782 | } |
1780 | } | 1783 | } |
@@ -1791,26 +1794,38 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1791 | vmbreak; | 1794 | vmbreak; |
1792 | } | 1795 | } |
1793 | vmcase(OP_TFORPREP) { | 1796 | vmcase(OP_TFORPREP) { |
1797 | /* before: 'ra' has the iterator function, 'ra + 1' has the state, | ||
1798 | 'ra + 2' has the initial value for the control variable, and | ||
1799 | 'ra + 3' has the closing variable. This opcode then swaps the | ||
1800 | control and the closing variables and marks the closing variable | ||
1801 | as to-be-closed. | ||
1802 | */ | ||
1794 | StkId ra = RA(i); | 1803 | StkId ra = RA(i); |
1795 | /* create to-be-closed upvalue (if needed) */ | 1804 | TValue temp; /* to swap control and closing variables */ |
1796 | halfProtect(luaF_newtbcupval(L, ra + 3)); | 1805 | setobj(L, &temp, s2v(ra + 3)); |
1797 | pc += GETARG_Bx(i); | 1806 | setobjs2s(L, ra + 3, ra + 2); |
1798 | i = *(pc++); /* go to next instruction */ | 1807 | setobj2s(L, ra + 2, &temp); |
1808 | /* create to-be-closed upvalue (if closing var. is not nil) */ | ||
1809 | halfProtect(luaF_newtbcupval(L, ra + 2)); | ||
1810 | pc += GETARG_Bx(i); /* go to end of the loop */ | ||
1811 | i = *(pc++); /* fetch next instruction */ | ||
1799 | lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i)); | 1812 | lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i)); |
1800 | goto l_tforcall; | 1813 | goto l_tforcall; |
1801 | } | 1814 | } |
1802 | vmcase(OP_TFORCALL) { | 1815 | vmcase(OP_TFORCALL) { |
1803 | l_tforcall: { | 1816 | l_tforcall: { |
1804 | StkId ra = RA(i); | ||
1805 | /* 'ra' has the iterator function, 'ra + 1' has the state, | 1817 | /* 'ra' has the iterator function, 'ra + 1' has the state, |
1806 | 'ra + 2' has the control variable, and 'ra + 3' has the | 1818 | 'ra + 2' has the closing variable, and 'ra + 3' has the control |
1807 | to-be-closed variable. The call will use the stack after | 1819 | variable. The call will use the stack starting at 'ra + 3', |
1808 | these values (starting at 'ra + 4') | 1820 | so that it preserves the first three values, and the first |
1821 | return will be the new value for the control variable. | ||
1809 | */ | 1822 | */ |
1810 | /* push function, state, and control variable */ | 1823 | StkId ra = RA(i); |
1811 | memcpy(ra + 4, ra, 3 * sizeof(*ra)); | 1824 | setobjs2s(L, ra + 5, ra + 3); /* copy the control variable */ |
1812 | L->top.p = ra + 4 + 3; | 1825 | setobjs2s(L, ra + 4, ra + 1); /* copy state */ |
1813 | ProtectNT(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */ | 1826 | setobjs2s(L, ra + 3, ra); /* copy function */ |
1827 | L->top.p = ra + 3 + 3; | ||
1828 | ProtectNT(luaD_call(L, ra + 3, GETARG_C(i))); /* do the call */ | ||
1814 | updatestack(ci); /* stack may have changed */ | 1829 | updatestack(ci); /* stack may have changed */ |
1815 | i = *(pc++); /* go to next instruction */ | 1830 | i = *(pc++); /* go to next instruction */ |
1816 | lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i)); | 1831 | lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i)); |
@@ -1819,10 +1834,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1819 | vmcase(OP_TFORLOOP) { | 1834 | vmcase(OP_TFORLOOP) { |
1820 | l_tforloop: { | 1835 | l_tforloop: { |
1821 | StkId ra = RA(i); | 1836 | StkId ra = RA(i); |
1822 | if (!ttisnil(s2v(ra + 4))) { /* continue loop? */ | 1837 | if (!ttisnil(s2v(ra + 3))) /* continue loop? */ |
1823 | setobjs2s(L, ra + 2, ra + 4); /* save control variable */ | ||
1824 | pc -= GETARG_Bx(i); /* jump back */ | 1838 | pc -= GETARG_Bx(i); /* jump back */ |
1825 | } | ||
1826 | vmbreak; | 1839 | vmbreak; |
1827 | }} | 1840 | }} |
1828 | vmcase(OP_SETLIST) { | 1841 | vmcase(OP_SETLIST) { |