summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-12-04 16:51:53 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-12-04 16:51:53 -0300
commit81f2401c6dc6afc819787a0b651f9e4be241e942 (patch)
tree0d7a253bee771ad300702c45e332409d398d521a
parent508a705c1c08d883473199d6ba019d186c28b9df (diff)
downloadlua-81f2401c6dc6afc819787a0b651f9e4be241e942.tar.gz
lua-81f2401c6dc6afc819787a0b651f9e4be241e942.tar.bz2
lua-81f2401c6dc6afc819787a0b651f9e4be241e942.zip
Code reorganization for opcodes OP_FORPREP and OP_FORLOOP
Parts of the code for opcodes OP_FORPREP and OP_FORLOOP were moved to functions outside the interpreter loop.
-rw-r--r--lvm.c191
1 files changed, 116 insertions, 75 deletions
diff --git a/lvm.c b/lvm.c
index 93cb8bc8..dc479f0a 100644
--- a/lvm.c
+++ b/lvm.c
@@ -80,6 +80,21 @@
80#endif 80#endif
81 81
82 82
83/*
84** Try to convert a value from string to a number value.
85** If the value is not a string or is a string not representing
86** a valid numeral (or if coercions from strings to numbers
87** are disabled via macro 'cvt2num'), do not modify 'result'
88** and return 0.
89*/
90static int l_strton (const TValue *obj, TValue *result) {
91 lua_assert(obj != result);
92 if (!cvt2num(obj)) /* is object not a string? */
93 return 0;
94 else
95 return (luaO_str2num(svalue(obj), result) == vslen(obj) + 1);
96}
97
83 98
84/* 99/*
85** Try to convert a value to a float. The float case is already handled 100** Try to convert a value to a float. The float case is already handled
@@ -91,8 +106,7 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) {
91 *n = cast_num(ivalue(obj)); 106 *n = cast_num(ivalue(obj));
92 return 1; 107 return 1;
93 } 108 }
94 else if (cvt2num(obj) && /* string coercible to number? */ 109 else if (l_strton(obj, &v)) { /* string coercible to number? */
95 luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) {
96 *n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */ 110 *n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */
97 return 1; 111 return 1;
98 } 112 }
@@ -111,7 +125,7 @@ int luaV_flttointeger (lua_Number n, lua_Integer *p, int mode) {
111 lua_Number f = l_floor(n); 125 lua_Number f = l_floor(n);
112 if (n != f) { /* not an integral value? */ 126 if (n != f) { /* not an integral value? */
113 if (mode == 0) return 0; /* fails if mode demands integral value */ 127 if (mode == 0) return 0; /* fails if mode demands integral value */
114 else if (mode > 1) /* needs ceil? */ 128 else if (mode == 2) /* needs ceil? */
115 f += 1; /* convert floor to ceil (remember: n != f) */ 129 f += 1; /* convert floor to ceil (remember: n != f) */
116 } 130 }
117 return lua_numbertointeger(f, p); 131 return lua_numbertointeger(f, p);
@@ -140,27 +154,27 @@ int luaV_tointegerns (const TValue *obj, lua_Integer *p, int mode) {
140*/ 154*/
141int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) { 155int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) {
142 TValue v; 156 TValue v;
143 if (cvt2num(obj) && luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) 157 if (l_strton(obj, &v)) /* does 'obj' point to a numerical string? */
144 obj = &v; /* change string to its corresponding number */ 158 obj = &v; /* change it to point to its corresponding number */
145 return luaV_tointegerns(obj, p, mode); 159 return luaV_tointegerns(obj, p, mode);
146} 160}
147 161
148 162
149/* 163/*
150** Try to convert a 'for' limit to an integer, preserving the semantics 164** Try to convert a 'for' limit to an integer, preserving the semantics
151** of the loop. (The following explanation assumes a positive step; 165** of the loop. Return true if the loop must not run; otherwise, '*p'
152** it is valid for negative steps mutatis mutandis.) 166** gets the integer limit.
153** Return true if the loop must not run. 167** (The following explanation assumes a positive step; it is valid for
168** negative steps mutatis mutandis.)
154** If the limit is an integer or can be converted to an integer, 169** If the limit is an integer or can be converted to an integer,
155** rounding down, that is the limit. 170** rounding down, that is the limit.
156** Otherwise, check whether the limit can be converted to a float. If 171** Otherwise, check whether the limit can be converted to a float. If
157** the float is too large, clip it to LUA_MAXINTEGER. If the float 172** the float is too large, clip it to LUA_MAXINTEGER. If the float
158** is too negative, the loop should not run, because any initial 173** is too negative, the loop should not run, because any initial
159** integer value is greater than such limit; so, it returns true to 174** integer value is greater than such limit; so, the function returns
160** signal that. 175** true to signal that. (For this latter case, no integer limit would be
161** (For this latter case, no integer limit would be correct; even a 176** correct; even a limit of LUA_MININTEGER would run the loop once for
162** limit of LUA_MININTEGER would run the loop once for an initial 177** an initial value equal to LUA_MININTEGER.)
163** value equal to LUA_MININTEGER.)
164*/ 178*/
165static int forlimit (lua_State *L, lua_Integer init, const TValue *lim, 179static int forlimit (lua_State *L, lua_Integer init, const TValue *lim,
166 lua_Integer *p, lua_Integer step) { 180 lua_Integer *p, lua_Integer step) {
@@ -184,6 +198,91 @@ static int forlimit (lua_State *L, lua_Integer init, const TValue *lim,
184 198
185 199
186/* 200/*
201** Prepare a numerical for loop (opcode OP_FORPREP).
202** Return true to skip the loop. Otherwise,
203** after preparation, stack will be as follows:
204** ra : internal index (safe copy of the control variable)
205** ra + 1 : loop counter (integer loops) or limit (float loops)
206** ra + 2 : step
207** ra + 3 : control variable
208*/
209static int forprep (lua_State *L, StkId ra) {
210 TValue *pinit = s2v(ra);
211 TValue *plimit = s2v(ra + 1);
212 TValue *pstep = s2v(ra + 2);
213 if (ttisinteger(pinit) && ttisinteger(pstep)) { /* integer loop? */
214 lua_Integer init = ivalue(pinit);
215 lua_Integer step = ivalue(pstep);
216 lua_Integer limit;
217 if (step == 0)
218 luaG_runerror(L, "'for' step is zero");
219 setivalue(s2v(ra + 3), init); /* control variable */
220 if (forlimit(L, init, plimit, &limit, step))
221 return 1; /* skip the loop */
222 else { /* prepare loop counter */
223 lua_Unsigned count;
224 if (step > 0) { /* ascending loop? */
225 count = l_castS2U(limit) - l_castS2U(init);
226 if (step != 1) /* avoid division in the too common case */
227 count /= l_castS2U(step);
228 }
229 else { /* step < 0; descending loop */
230 count = l_castS2U(init) - l_castS2U(limit);
231 /* 'step+1' avoids negating 'mininteger' */
232 count /= l_castS2U(-(step + 1)) + 1u;
233 }
234 /* store the counter in place of the limit (which won't be
235 needed anymore */
236 setivalue(plimit, l_castU2S(count));
237 }
238 }
239 else { /* try making all values floats */
240 lua_Number init; lua_Number limit; lua_Number step;
241 if (unlikely(!tonumber(plimit, &limit)))
242 luaG_forerror(L, plimit, "limit");
243 if (unlikely(!tonumber(pstep, &step)))
244 luaG_forerror(L, pstep, "step");
245 if (unlikely(!tonumber(pinit, &init)))
246 luaG_forerror(L, pinit, "initial value");
247 if (step == 0)
248 luaG_runerror(L, "'for' step is zero");
249 if (luai_numlt(0, step) ? luai_numlt(limit, init)
250 : luai_numlt(init, limit))
251 return 1; /* skip the loop */
252 else {
253 /* make sure internal values are all floats */
254 setfltvalue(plimit, limit);
255 setfltvalue(pstep, step);
256 setfltvalue(s2v(ra), init); /* internal index */
257 setfltvalue(s2v(ra + 3), init); /* control variable */
258 }
259 }
260 return 0;
261}
262
263
264/*
265** Execute a step of a float numerical for loop, returning
266** true iff the loop must continue. (The integer case is
267** written online with opcode OP_FORLOOP, for performance.)
268*/
269static int floatforloop (StkId ra) {
270 lua_Number step = fltvalue(s2v(ra + 2));
271 lua_Number limit = fltvalue(s2v(ra + 1));
272 lua_Number idx = fltvalue(s2v(ra)); /* internal index */
273 idx = luai_numadd(L, idx, step); /* increment index */
274 if (luai_numlt(0, step) ? luai_numle(idx, limit)
275 : luai_numle(limit, idx)) {
276 chgfltvalue(s2v(ra), idx); /* update internal index */
277 setfltvalue(s2v(ra + 3), idx); /* and control variable */
278 return 1; /* jump back */
279 }
280 else
281 return 0; /* finish the loop */
282}
283
284
285/*
187** Finish the table access 'val = t[key]'. 286** Finish the table access 'val = t[key]'.
188** if 'slot' is NULL, 't' is not a table; otherwise, 'slot' points to 287** if 'slot' is NULL, 't' is not a table; otherwise, 'slot' points to
189** t[k] entry (which must be empty). 288** t[k] entry (which must be empty).
@@ -1631,73 +1730,15 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1631 pc -= GETARG_Bx(i); /* jump back */ 1730 pc -= GETARG_Bx(i); /* jump back */
1632 } 1731 }
1633 } 1732 }
1634 else { /* floating loop */ 1733 else if (floatforloop(ra)) /* float loop */
1635 lua_Number step = fltvalue(s2v(ra + 2)); 1734 pc -= GETARG_Bx(i); /* jump back */
1636 lua_Number limit = fltvalue(s2v(ra + 1));
1637 lua_Number idx = fltvalue(s2v(ra));
1638 idx = luai_numadd(L, idx, step); /* increment index */
1639 if (luai_numlt(0, step) ? luai_numle(idx, limit)
1640 : luai_numle(limit, idx)) {
1641 chgfltvalue(s2v(ra), idx); /* update internal index */
1642 setfltvalue(s2v(ra + 3), idx); /* and control variable */
1643 pc -= GETARG_Bx(i); /* jump back */
1644 }
1645 }
1646 updatetrap(ci); /* allows a signal to break the loop */ 1735 updatetrap(ci); /* allows a signal to break the loop */
1647 vmbreak; 1736 vmbreak;
1648 } 1737 }
1649 vmcase(OP_FORPREP) { 1738 vmcase(OP_FORPREP) {
1650 TValue *pinit = s2v(ra);
1651 TValue *plimit = s2v(ra + 1);
1652 TValue *pstep = s2v(ra + 2);
1653 savestate(L, ci); /* in case of errors */ 1739 savestate(L, ci); /* in case of errors */
1654 if (ttisinteger(pinit) && ttisinteger(pstep)) { /* integer loop? */ 1740 if (forprep(L, ra))
1655 lua_Integer init = ivalue(pinit); 1741 pc += GETARG_Bx(i) + 1; /* skip the loop */
1656 lua_Integer step = ivalue(pstep);
1657 lua_Integer limit;
1658 if (step == 0)
1659 luaG_runerror(L, "'for' step is zero");
1660 setivalue(s2v(ra + 3), init); /* control variable */
1661 if (forlimit(L, init, plimit, &limit, step))
1662 pc += GETARG_Bx(i) + 1; /* skip the loop */
1663 else { /* prepare loop counter */
1664 lua_Unsigned count;
1665 if (step > 0) { /* ascending loop? */
1666 count = l_castS2U(limit) - l_castS2U(init);
1667 if (step != 1) /* avoid division in the too common case */
1668 count /= l_castS2U(step);
1669 }
1670 else { /* step < 0; descending loop */
1671 count = l_castS2U(init) - l_castS2U(limit);
1672 /* 'step+1' avoids negating 'mininteger' */
1673 count /= l_castS2U(-(step + 1)) + 1u;
1674 }
1675 /* store the counter in place of the limit (which won't be
1676 needed anymore */
1677 setivalue(plimit, l_castU2S(count));
1678 }
1679 }
1680 else { /* try making all values floats */
1681 lua_Number init; lua_Number limit; lua_Number step;
1682 if (unlikely(!tonumber(plimit, &limit)))
1683 luaG_forerror(L, plimit, "limit");
1684 if (unlikely(!tonumber(pstep, &step)))
1685 luaG_forerror(L, pstep, "step");
1686 if (unlikely(!tonumber(pinit, &init)))
1687 luaG_forerror(L, pinit, "initial value");
1688 if (step == 0)
1689 luaG_runerror(L, "'for' step is zero");
1690 if (luai_numlt(0, step) ? luai_numlt(limit, init)
1691 : luai_numlt(init, limit))
1692 pc += GETARG_Bx(i) + 1; /* skip the loop */
1693 else {
1694 /* make sure internal values are all float */
1695 setfltvalue(plimit, limit);
1696 setfltvalue(pstep, step);
1697 setfltvalue(s2v(ra), init); /* internal index */
1698 setfltvalue(s2v(ra + 3), init); /* control variable */
1699 }
1700 }
1701 vmbreak; 1742 vmbreak;
1702 } 1743 }
1703 vmcase(OP_TFORPREP) { 1744 vmcase(OP_TFORPREP) {