aboutsummaryrefslogtreecommitdiff
path: root/lvm.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lvm.c107
1 files changed, 60 insertions, 47 deletions
diff --git a/lvm.c b/lvm.c
index 9b71ff31..e4c026fd 100644
--- a/lvm.c
+++ b/lvm.c
@@ -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*/
208static int forprep (lua_State *L, StkId ra) { 213static 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*/
268static int floatforloop (StkId ra) { 272static 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*/
368static int l_strcmp (const TString *ts1, const TString *ts2) { 371static 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) {