|
@@ -55,7 +55,7 @@
|
|
|
*/
|
|
|
|
|
|
/* number of bits in the mantissa of a float */
|
|
|
-#define NBM (l_mathlim(MANT_DIG))
|
|
|
+#define NBM (l_floatatt(MANT_DIG))
|
|
|
|
|
|
/*
|
|
|
** Check whether some integers may not fit in a float, testing whether
|
|
@@ -80,6 +80,21 @@
|
|
|
#endif
|
|
|
|
|
|
|
|
|
+/*
|
|
|
+** Try to convert a value from string to a number value.
|
|
|
+** If the value is not a string or is a string not representing
|
|
|
+** a valid numeral (or if coercions from strings to numbers
|
|
|
+** are disabled via macro 'cvt2num'), do not modify 'result'
|
|
|
+** and return 0.
|
|
|
+*/
|
|
|
+static int l_strton (const TValue *obj, TValue *result) {
|
|
|
+ lua_assert(obj != result);
|
|
|
+ if (!cvt2num(obj)) /* is object not a string? */
|
|
|
+ return 0;
|
|
|
+ else
|
|
|
+ return (luaO_str2num(svalue(obj), result) == vslen(obj) + 1);
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
/*
|
|
|
** 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) {
|
|
|
*n = cast_num(ivalue(obj));
|
|
|
return 1;
|
|
|
}
|
|
|
- else if (cvt2num(obj) && /* string coercible to number? */
|
|
|
- luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) {
|
|
|
+ else if (l_strton(obj, &v)) { /* string coercible to number? */
|
|
|
*n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */
|
|
|
return 1;
|
|
|
}
|
|
@@ -102,16 +116,13 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) {
|
|
|
|
|
|
|
|
|
/*
|
|
|
-** try to convert a float to an integer, rounding according to 'mode':
|
|
|
-** mode == 0: accepts only integral values
|
|
|
-** mode == 1: takes the floor of the number
|
|
|
-** mode == 2: takes the ceil of the number
|
|
|
+** try to convert a float to an integer, rounding according to 'mode'.
|
|
|
*/
|
|
|
-int luaV_flttointeger (lua_Number n, lua_Integer *p, int mode) {
|
|
|
+int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode) {
|
|
|
lua_Number f = l_floor(n);
|
|
|
if (n != f) { /* not an integral value? */
|
|
|
- if (mode == 0) return 0; /* fails if mode demands integral value */
|
|
|
- else if (mode > 1) /* needs ceil? */
|
|
|
+ if (mode == F2Ieq) return 0; /* fails if mode demands integral value */
|
|
|
+ else if (mode == F2Iceil) /* needs ceil? */
|
|
|
f += 1; /* convert floor to ceil (remember: n != f) */
|
|
|
}
|
|
|
return lua_numbertointeger(f, p);
|
|
@@ -123,7 +134,7 @@ int luaV_flttointeger (lua_Number n, lua_Integer *p, int mode) {
|
|
|
** without string coercion.
|
|
|
** ("Fast track" handled by macro 'tointegerns'.)
|
|
|
*/
|
|
|
-int luaV_tointegerns (const TValue *obj, lua_Integer *p, int mode) {
|
|
|
+int luaV_tointegerns (const TValue *obj, lua_Integer *p, F2Imod mode) {
|
|
|
if (ttisfloat(obj))
|
|
|
return luaV_flttointeger(fltvalue(obj), p, mode);
|
|
|
else if (ttisinteger(obj)) {
|
|
@@ -138,33 +149,33 @@ int luaV_tointegerns (const TValue *obj, lua_Integer *p, int mode) {
|
|
|
/*
|
|
|
** try to convert a value to an integer.
|
|
|
*/
|
|
|
-int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) {
|
|
|
+int luaV_tointeger (const TValue *obj, lua_Integer *p, F2Imod mode) {
|
|
|
TValue v;
|
|
|
- if (cvt2num(obj) && luaO_str2num(svalue(obj), &v) == vslen(obj) + 1)
|
|
|
- obj = &v; /* change string to its corresponding number */
|
|
|
+ if (l_strton(obj, &v)) /* does 'obj' point to a numerical string? */
|
|
|
+ obj = &v; /* change it to point to its corresponding number */
|
|
|
return luaV_tointegerns(obj, p, mode);
|
|
|
}
|
|
|
|
|
|
|
|
|
/*
|
|
|
** Try to convert a 'for' limit to an integer, preserving the semantics
|
|
|
-** of the loop. (The following explanation assumes a positive step;
|
|
|
-** it is valid for negative steps mutatis mutandis.)
|
|
|
-** Return true if the loop must not run.
|
|
|
+** of the loop. Return true if the loop must not run; otherwise, '*p'
|
|
|
+** gets the integer limit.
|
|
|
+** (The following explanation assumes a positive step; it is valid for
|
|
|
+** negative steps mutatis mutandis.)
|
|
|
** If the limit is an integer or can be converted to an integer,
|
|
|
** rounding down, that is the limit.
|
|
|
** Otherwise, check whether the limit can be converted to a float. If
|
|
|
** the float is too large, clip it to LUA_MAXINTEGER. If the float
|
|
|
** is too negative, the loop should not run, because any initial
|
|
|
-** integer value is greater than such limit; so, it returns true to
|
|
|
-** signal that.
|
|
|
-** (For this latter case, no integer limit would be correct; even a
|
|
|
-** limit of LUA_MININTEGER would run the loop once for an initial
|
|
|
-** value equal to LUA_MININTEGER.)
|
|
|
+** integer value is greater than such limit; so, the function returns
|
|
|
+** true to signal that. (For this latter case, no integer limit would be
|
|
|
+** correct; even a limit of LUA_MININTEGER would run the loop once for
|
|
|
+** an initial value equal to LUA_MININTEGER.)
|
|
|
*/
|
|
|
static int forlimit (lua_State *L, lua_Integer init, const TValue *lim,
|
|
|
lua_Integer *p, lua_Integer step) {
|
|
|
- if (!luaV_tointeger(lim, p, (step < 0 ? 2 : 1))) {
|
|
|
+ if (!luaV_tointeger(lim, p, (step < 0 ? F2Iceil : F2Ifloor))) {
|
|
|
/* not coercible to in integer */
|
|
|
lua_Number flim; /* try to convert to float */
|
|
|
if (!tonumber(lim, &flim)) /* cannot convert to float? */
|
|
@@ -183,6 +194,91 @@ static int forlimit (lua_State *L, lua_Integer init, const TValue *lim,
|
|
|
}
|
|
|
|
|
|
|
|
|
+/*
|
|
|
+** Prepare a numerical for loop (opcode OP_FORPREP).
|
|
|
+** Return true to skip the loop. Otherwise,
|
|
|
+** after preparation, stack will be as follows:
|
|
|
+** ra : internal index (safe copy of the control variable)
|
|
|
+** ra + 1 : loop counter (integer loops) or limit (float loops)
|
|
|
+** ra + 2 : step
|
|
|
+** ra + 3 : control variable
|
|
|
+*/
|
|
|
+static int forprep (lua_State *L, StkId ra) {
|
|
|
+ TValue *pinit = s2v(ra);
|
|
|
+ TValue *plimit = s2v(ra + 1);
|
|
|
+ TValue *pstep = s2v(ra + 2);
|
|
|
+ if (ttisinteger(pinit) && ttisinteger(pstep)) { /* integer loop? */
|
|
|
+ lua_Integer init = ivalue(pinit);
|
|
|
+ lua_Integer step = ivalue(pstep);
|
|
|
+ lua_Integer limit;
|
|
|
+ if (step == 0)
|
|
|
+ luaG_runerror(L, "'for' step is zero");
|
|
|
+ setivalue(s2v(ra + 3), init); /* control variable */
|
|
|
+ if (forlimit(L, init, plimit, &limit, step))
|
|
|
+ return 1; /* skip the loop */
|
|
|
+ else { /* prepare loop counter */
|
|
|
+ lua_Unsigned count;
|
|
|
+ if (step > 0) { /* ascending loop? */
|
|
|
+ count = l_castS2U(limit) - l_castS2U(init);
|
|
|
+ if (step != 1) /* avoid division in the too common case */
|
|
|
+ count /= l_castS2U(step);
|
|
|
+ }
|
|
|
+ else { /* step < 0; descending loop */
|
|
|
+ count = l_castS2U(init) - l_castS2U(limit);
|
|
|
+ /* 'step+1' avoids negating 'mininteger' */
|
|
|
+ count /= l_castS2U(-(step + 1)) + 1u;
|
|
|
+ }
|
|
|
+ /* store the counter in place of the limit (which won't be
|
|
|
+ needed anymore) */
|
|
|
+ setivalue(plimit, l_castU2S(count));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else { /* try making all values floats */
|
|
|
+ lua_Number init; lua_Number limit; lua_Number step;
|
|
|
+ if (l_unlikely(!tonumber(plimit, &limit)))
|
|
|
+ luaG_forerror(L, plimit, "limit");
|
|
|
+ if (l_unlikely(!tonumber(pstep, &step)))
|
|
|
+ luaG_forerror(L, pstep, "step");
|
|
|
+ if (l_unlikely(!tonumber(pinit, &init)))
|
|
|
+ luaG_forerror(L, pinit, "initial value");
|
|
|
+ if (step == 0)
|
|
|
+ luaG_runerror(L, "'for' step is zero");
|
|
|
+ if (luai_numlt(0, step) ? luai_numlt(limit, init)
|
|
|
+ : luai_numlt(init, limit))
|
|
|
+ return 1; /* skip the loop */
|
|
|
+ else {
|
|
|
+ /* make sure internal values are all floats */
|
|
|
+ setfltvalue(plimit, limit);
|
|
|
+ setfltvalue(pstep, step);
|
|
|
+ setfltvalue(s2v(ra), init); /* internal index */
|
|
|
+ setfltvalue(s2v(ra + 3), init); /* control variable */
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+** Execute a step of a float numerical for loop, returning
|
|
|
+** true iff the loop must continue. (The integer case is
|
|
|
+** written online with opcode OP_FORLOOP, for performance.)
|
|
|
+*/
|
|
|
+static int floatforloop (StkId ra) {
|
|
|
+ lua_Number step = fltvalue(s2v(ra + 2));
|
|
|
+ lua_Number limit = fltvalue(s2v(ra + 1));
|
|
|
+ lua_Number idx = fltvalue(s2v(ra)); /* internal index */
|
|
|
+ idx = luai_numadd(L, idx, step); /* increment index */
|
|
|
+ if (luai_numlt(0, step) ? luai_numle(idx, limit)
|
|
|
+ : luai_numle(limit, idx)) {
|
|
|
+ chgfltvalue(s2v(ra), idx); /* update internal index */
|
|
|
+ setfltvalue(s2v(ra + 3), idx); /* and control variable */
|
|
|
+ return 1; /* jump back */
|
|
|
+ }
|
|
|
+ else
|
|
|
+ return 0; /* finish the loop */
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
/*
|
|
|
** Finish the table access 'val = t[key]'.
|
|
|
** if 'slot' is NULL, 't' is not a table; otherwise, 'slot' points to
|
|
@@ -196,7 +292,7 @@ void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
|
|
|
if (slot == NULL) { /* 't' is not a table? */
|
|
|
lua_assert(!ttistable(t));
|
|
|
tm = luaT_gettmbyobj(L, t, TM_INDEX);
|
|
|
- if (unlikely(notm(tm)))
|
|
|
+ if (l_unlikely(notm(tm)))
|
|
|
luaG_typeerror(L, t, "index"); /* no metamethod */
|
|
|
/* else will try the metamethod */
|
|
|
}
|
|
@@ -241,10 +337,7 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
|
|
|
lua_assert(isempty(slot)); /* slot must be empty */
|
|
|
tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */
|
|
|
if (tm == NULL) { /* no metamethod? */
|
|
|
- if (isabstkey(slot)) /* no previous entry? */
|
|
|
- slot = luaH_newkey(L, h, key); /* create one */
|
|
|
- /* no metamethod and (now) there is an entry with given key */
|
|
|
- setobj2t(L, cast(TValue *, slot), val); /* set its new value */
|
|
|
+ luaH_finishset(L, h, key, slot, val); /* set new value */
|
|
|
invalidateTMcache(h);
|
|
|
luaC_barrierback(L, obj2gco(h), val);
|
|
|
return;
|
|
@@ -253,7 +346,7 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
|
|
|
}
|
|
|
else { /* not a table; check metamethod */
|
|
|
tm = luaT_gettmbyobj(L, t, TM_NEWINDEX);
|
|
|
- if (unlikely(notm(tm)))
|
|
|
+ if (l_unlikely(notm(tm)))
|
|
|
luaG_typeerror(L, t, "index");
|
|
|
}
|
|
|
/* try the metamethod */
|
|
@@ -318,7 +411,7 @@ static int LTintfloat (lua_Integer i, lua_Number f) {
|
|
|
return luai_numlt(cast_num(i), f); /* compare them as floats */
|
|
|
else { /* i < f <=> i < ceil(f) */
|
|
|
lua_Integer fi;
|
|
|
- if (luaV_flttointeger(f, &fi, 2)) /* fi = ceil(f) */
|
|
|
+ if (luaV_flttointeger(f, &fi, F2Iceil)) /* fi = ceil(f) */
|
|
|
return i < fi; /* compare them as integers */
|
|
|
else /* 'f' is either greater or less than all integers */
|
|
|
return f > 0; /* greater? */
|
|
@@ -335,7 +428,7 @@ static int LEintfloat (lua_Integer i, lua_Number f) {
|
|
|
return luai_numle(cast_num(i), f); /* compare them as floats */
|
|
|
else { /* i <= f <=> i <= floor(f) */
|
|
|
lua_Integer fi;
|
|
|
- if (luaV_flttointeger(f, &fi, 1)) /* fi = floor(f) */
|
|
|
+ if (luaV_flttointeger(f, &fi, F2Ifloor)) /* fi = floor(f) */
|
|
|
return i <= fi; /* compare them as integers */
|
|
|
else /* 'f' is either greater or less than all integers */
|
|
|
return f > 0; /* greater? */
|
|
@@ -352,7 +445,7 @@ static int LTfloatint (lua_Number f, lua_Integer i) {
|
|
|
return luai_numlt(f, cast_num(i)); /* compare them as floats */
|
|
|
else { /* f < i <=> floor(f) < i */
|
|
|
lua_Integer fi;
|
|
|
- if (luaV_flttointeger(f, &fi, 1)) /* fi = floor(f) */
|
|
|
+ if (luaV_flttointeger(f, &fi, F2Ifloor)) /* fi = floor(f) */
|
|
|
return fi < i; /* compare them as integers */
|
|
|
else /* 'f' is either greater or less than all integers */
|
|
|
return f < 0; /* less? */
|
|
@@ -369,7 +462,7 @@ static int LEfloatint (lua_Number f, lua_Integer i) {
|
|
|
return luai_numle(f, cast_num(i)); /* compare them as floats */
|
|
|
else { /* f <= i <=> ceil(f) <= i */
|
|
|
lua_Integer fi;
|
|
|
- if (luaV_flttointeger(f, &fi, 2)) /* fi = ceil(f) */
|
|
|
+ if (luaV_flttointeger(f, &fi, F2Iceil)) /* fi = ceil(f) */
|
|
|
return fi <= i; /* compare them as integers */
|
|
|
else /* 'f' is either greater or less than all integers */
|
|
|
return f < 0; /* less? */
|
|
@@ -445,11 +538,6 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
|
|
|
|
|
|
/*
|
|
|
** return 'l <= r' for non-numbers.
|
|
|
-** If it needs a metamethod and there is no '__le', try '__lt', based
|
|
|
-** on l <= r iff !(r < l) (assuming a total order). If the metamethod
|
|
|
-** yields during this substitution, the continuation has to know about
|
|
|
-** it (to negate the result of r<l); bit CIST_LEQ in the call status
|
|
|
-** keeps that information.
|
|
|
*/
|
|
|
static int lessequalothers (lua_State *L, const TValue *l, const TValue *r) {
|
|
|
lua_assert(!ttisnumber(l) || !ttisnumber(r));
|
|
@@ -480,21 +568,25 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
|
|
|
if (ttype(t1) != ttype(t2) || ttype(t1) != LUA_TNUMBER)
|
|
|
return 0; /* only numbers can be equal with different variants */
|
|
|
else { /* two numbers with different variants */
|
|
|
- lua_Integer i1, i2; /* compare them as integers */
|
|
|
- return (tointegerns(t1, &i1) && tointegerns(t2, &i2) && i1 == i2);
|
|
|
+ /* One of them is an integer. If the other does not have an
|
|
|
+ integer value, they cannot be equal; otherwise, compare their
|
|
|
+ integer values. */
|
|
|
+ lua_Integer i1, i2;
|
|
|
+ return (luaV_tointegerns(t1, &i1, F2Ieq) &&
|
|
|
+ luaV_tointegerns(t2, &i2, F2Ieq) &&
|
|
|
+ i1 == i2);
|
|
|
}
|
|
|
}
|
|
|
/* values have same type and same variant */
|
|
|
switch (ttypetag(t1)) {
|
|
|
- case LUA_TNIL: return 1;
|
|
|
- case LUA_TNUMINT: return (ivalue(t1) == ivalue(t2));
|
|
|
- case LUA_TNUMFLT: return luai_numeq(fltvalue(t1), fltvalue(t2));
|
|
|
- case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1! */
|
|
|
- case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
|
|
|
- case LUA_TLCF: return fvalue(t1) == fvalue(t2);
|
|
|
- case LUA_TSHRSTR: return eqshrstr(tsvalue(t1), tsvalue(t2));
|
|
|
- case LUA_TLNGSTR: return luaS_eqlngstr(tsvalue(t1), tsvalue(t2));
|
|
|
- case LUA_TUSERDATA: {
|
|
|
+ case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE: return 1;
|
|
|
+ case LUA_VNUMINT: return (ivalue(t1) == ivalue(t2));
|
|
|
+ case LUA_VNUMFLT: return luai_numeq(fltvalue(t1), fltvalue(t2));
|
|
|
+ case LUA_VLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
|
|
|
+ case LUA_VLCF: return fvalue(t1) == fvalue(t2);
|
|
|
+ case LUA_VSHRSTR: return eqshrstr(tsvalue(t1), tsvalue(t2));
|
|
|
+ case LUA_VLNGSTR: return luaS_eqlngstr(tsvalue(t1), tsvalue(t2));
|
|
|
+ case LUA_VUSERDATA: {
|
|
|
if (uvalue(t1) == uvalue(t2)) return 1;
|
|
|
else if (L == NULL) return 0;
|
|
|
tm = fasttm(L, uvalue(t1)->metatable, TM_EQ);
|
|
@@ -502,7 +594,7 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
|
|
|
tm = fasttm(L, uvalue(t2)->metatable, TM_EQ);
|
|
|
break; /* will try TM */
|
|
|
}
|
|
|
- case LUA_TTABLE: {
|
|
|
+ case LUA_VTABLE: {
|
|
|
if (hvalue(t1) == hvalue(t2)) return 1;
|
|
|
else if (L == NULL) return 0;
|
|
|
tm = fasttm(L, hvalue(t1)->metatable, TM_EQ);
|
|
@@ -544,7 +636,8 @@ static void copy2buff (StkId top, int n, char *buff) {
|
|
|
** from 'L->top - total' up to 'L->top - 1'.
|
|
|
*/
|
|
|
void luaV_concat (lua_State *L, int total) {
|
|
|
- lua_assert(total >= 2);
|
|
|
+ if (total == 1)
|
|
|
+ return; /* "all" values already concatenated */
|
|
|
do {
|
|
|
StkId top = L->top;
|
|
|
int n = 2; /* number of elements handled in this pass (at least 2) */
|
|
@@ -563,7 +656,7 @@ void luaV_concat (lua_State *L, int total) {
|
|
|
/* collect total length and number of strings */
|
|
|
for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) {
|
|
|
size_t l = vslen(s2v(top - n - 1));
|
|
|
- if (unlikely(l >= (MAX_SIZE/sizeof(char)) - tl))
|
|
|
+ if (l_unlikely(l >= (MAX_SIZE/sizeof(char)) - tl))
|
|
|
luaG_runerror(L, "string length overflow");
|
|
|
tl += l;
|
|
|
}
|
|
@@ -590,24 +683,24 @@ void luaV_concat (lua_State *L, int total) {
|
|
|
void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
|
|
|
const TValue *tm;
|
|
|
switch (ttypetag(rb)) {
|
|
|
- case LUA_TTABLE: {
|
|
|
+ case LUA_VTABLE: {
|
|
|
Table *h = hvalue(rb);
|
|
|
tm = fasttm(L, h->metatable, TM_LEN);
|
|
|
if (tm) break; /* metamethod? break switch to call it */
|
|
|
setivalue(s2v(ra), luaH_getn(h)); /* else primitive len */
|
|
|
return;
|
|
|
}
|
|
|
- case LUA_TSHRSTR: {
|
|
|
+ case LUA_VSHRSTR: {
|
|
|
setivalue(s2v(ra), tsvalue(rb)->shrlen);
|
|
|
return;
|
|
|
}
|
|
|
- case LUA_TLNGSTR: {
|
|
|
+ case LUA_VLNGSTR: {
|
|
|
setivalue(s2v(ra), tsvalue(rb)->u.lnglen);
|
|
|
return;
|
|
|
}
|
|
|
default: { /* try metamethod */
|
|
|
tm = luaT_gettmbyobj(L, rb, TM_LEN);
|
|
|
- if (unlikely(notm(tm))) /* no metamethod? */
|
|
|
+ if (l_unlikely(notm(tm))) /* no metamethod? */
|
|
|
luaG_typeerror(L, rb, "get length of");
|
|
|
break;
|
|
|
}
|
|
@@ -623,7 +716,7 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
|
|
|
** otherwise 'floor(q) == trunc(q) - 1'.
|
|
|
*/
|
|
|
lua_Integer luaV_idiv (lua_State *L, lua_Integer m, lua_Integer n) {
|
|
|
- if (unlikely(l_castS2U(n) + 1u <= 1u)) { /* special cases: -1 or 0 */
|
|
|
+ if (l_unlikely(l_castS2U(n) + 1u <= 1u)) { /* special cases: -1 or 0 */
|
|
|
if (n == 0)
|
|
|
luaG_runerror(L, "attempt to divide by zero");
|
|
|
return intop(-, 0, m); /* n==-1; avoid overflow with 0x80000...//-1 */
|
|
@@ -643,7 +736,7 @@ lua_Integer luaV_idiv (lua_State *L, lua_Integer m, lua_Integer n) {
|
|
|
** about luaV_idiv.)
|
|
|
*/
|
|
|
lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) {
|
|
|
- if (unlikely(l_castS2U(n) + 1u <= 1u)) { /* special cases: -1 or 0 */
|
|
|
+ if (l_unlikely(l_castS2U(n) + 1u <= 1u)) { /* special cases: -1 or 0 */
|
|
|
if (n == 0)
|
|
|
luaG_runerror(L, "attempt to perform 'n%%0'");
|
|
|
return 0; /* m % -1 == 0; avoid overflow with 0x80000...%-1 */
|
|
@@ -750,10 +843,12 @@ void luaV_finishOp (lua_State *L) {
|
|
|
int a = GETARG_A(inst); /* first element to concatenate */
|
|
|
int total = cast_int(top - 1 - (base + a)); /* yet to concatenate */
|
|
|
setobjs2s(L, top - 2, top); /* put TM result in proper position */
|
|
|
- if (total > 1) { /* are there elements to concat? */
|
|
|
- L->top = top - 1; /* top is one after last element (at top-2) */
|
|
|
- luaV_concat(L, total); /* concat them (may yield again) */
|
|
|
- }
|
|
|
+ L->top = top - 1; /* top is one after last element (at top-2) */
|
|
|
+ luaV_concat(L, total); /* concat them (may yield again) */
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case OP_CLOSE: case OP_RETURN: { /* yielded closing variables */
|
|
|
+ ci->u.l.savedpc--; /* repeat instruction to close other vars. */
|
|
|
break;
|
|
|
}
|
|
|
default: {
|
|
@@ -788,39 +883,22 @@ void luaV_finishOp (lua_State *L) {
|
|
|
#define l_gei(a,b) (a >= b)
|
|
|
|
|
|
|
|
|
-/*
|
|
|
-** Auxiliary macro for arithmetic operations over floats and others
|
|
|
-** with immediate operand. 'fop' is the float operation; 'tm' is the
|
|
|
-** corresponding metamethod; 'flip' is true if operands were flipped.
|
|
|
-*/
|
|
|
-#define op_arithfI_aux(L,v1,imm,fop,tm,flip) { \
|
|
|
- lua_Number nb; \
|
|
|
- if (tonumberns(v1, nb)) { \
|
|
|
- lua_Number fimm = cast_num(imm); \
|
|
|
- pc++; setfltvalue(s2v(ra), fop(L, nb, fimm)); \
|
|
|
- }}
|
|
|
-
|
|
|
-
|
|
|
-/*
|
|
|
-** Arithmetic operations over floats and others with immediate operand.
|
|
|
-*/
|
|
|
-#define op_arithfI(L,fop,tm) { \
|
|
|
- TValue *v1 = vRB(i); \
|
|
|
- int imm = GETARG_sC(i); \
|
|
|
- op_arithfI_aux(L, v1, imm, fop, tm, 0); }
|
|
|
-
|
|
|
/*
|
|
|
** Arithmetic operations with immediate operands. 'iop' is the integer
|
|
|
-** operation.
|
|
|
+** operation, 'fop' is the float operation.
|
|
|
*/
|
|
|
-#define op_arithI(L,iop,fop,tm,flip) { \
|
|
|
+#define op_arithI(L,iop,fop) { \
|
|
|
TValue *v1 = vRB(i); \
|
|
|
int imm = GETARG_sC(i); \
|
|
|
if (ttisinteger(v1)) { \
|
|
|
lua_Integer iv1 = ivalue(v1); \
|
|
|
pc++; setivalue(s2v(ra), iop(L, iv1, imm)); \
|
|
|
} \
|
|
|
- else op_arithfI_aux(L, v1, imm, fop, tm, flip); }
|
|
|
+ else if (ttisfloat(v1)) { \
|
|
|
+ lua_Number nb = fltvalue(v1); \
|
|
|
+ lua_Number fimm = cast_num(imm); \
|
|
|
+ pc++; setfltvalue(s2v(ra), fop(L, nb, fimm)); \
|
|
|
+ }}
|
|
|
|
|
|
|
|
|
/*
|
|
@@ -844,11 +922,18 @@ void luaV_finishOp (lua_State *L) {
|
|
|
|
|
|
|
|
|
/*
|
|
|
-** Arithmetic operations with register operands.
|
|
|
+** Arithmetic operations with K operands for floats.
|
|
|
*/
|
|
|
-#define op_arith(L,iop,fop) { \
|
|
|
+#define op_arithfK(L,fop) { \
|
|
|
TValue *v1 = vRB(i); \
|
|
|
- TValue *v2 = vRC(i); \
|
|
|
+ TValue *v2 = KC(i); lua_assert(ttisnumber(v2)); \
|
|
|
+ op_arithf_aux(L, v1, v2, fop); }
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+** Arithmetic operations over integers and floats.
|
|
|
+*/
|
|
|
+#define op_arith_aux(L,v1,v2,iop,fop) { \
|
|
|
if (ttisinteger(v1) && ttisinteger(v2)) { \
|
|
|
lua_Integer i1 = ivalue(v1); lua_Integer i2 = ivalue(v2); \
|
|
|
pc++; setivalue(s2v(ra), iop(L, i1, i2)); \
|
|
@@ -857,32 +942,21 @@ void luaV_finishOp (lua_State *L) {
|
|
|
|
|
|
|
|
|
/*
|
|
|
-** Arithmetic operations with K operands.
|
|
|
+** Arithmetic operations with register operands.
|
|
|
*/
|
|
|
-#define op_arithK(L,iop,fop,flip) { \
|
|
|
+#define op_arith(L,iop,fop) { \
|
|
|
TValue *v1 = vRB(i); \
|
|
|
- TValue *v2 = KC(i); \
|
|
|
- if (ttisinteger(v1) && ttisinteger(v2)) { \
|
|
|
- lua_Integer i1 = ivalue(v1); lua_Integer i2 = ivalue(v2); \
|
|
|
- pc++; setivalue(s2v(ra), iop(L, i1, i2)); \
|
|
|
- } \
|
|
|
- else { \
|
|
|
- lua_Number n1; lua_Number n2; \
|
|
|
- if (tonumberns(v1, n1) && tonumberns(v2, n2)) { \
|
|
|
- pc++; setfltvalue(s2v(ra), fop(L, n1, n2)); \
|
|
|
- }}}
|
|
|
+ TValue *v2 = vRC(i); \
|
|
|
+ op_arith_aux(L, v1, v2, iop, fop); }
|
|
|
|
|
|
|
|
|
/*
|
|
|
-** Arithmetic operations with K operands for floats.
|
|
|
+** Arithmetic operations with K operands.
|
|
|
*/
|
|
|
-#define op_arithfK(L,fop) { \
|
|
|
+#define op_arithK(L,iop,fop) { \
|
|
|
TValue *v1 = vRB(i); \
|
|
|
- TValue *v2 = KC(i); \
|
|
|
- lua_Number n1; lua_Number n2; \
|
|
|
- if (tonumberns(v1, n1) && tonumberns(v2, n2)) { \
|
|
|
- pc++; setfltvalue(s2v(ra), fop(L, n1, n2)); \
|
|
|
- }}
|
|
|
+ TValue *v2 = KC(i); lua_assert(ttisnumber(v2)); \
|
|
|
+ op_arith_aux(L, v1, v2, iop, fop); }
|
|
|
|
|
|
|
|
|
/*
|
|
@@ -911,9 +985,11 @@ void luaV_finishOp (lua_State *L) {
|
|
|
|
|
|
|
|
|
/*
|
|
|
-** Order operations with register operands.
|
|
|
+** Order operations with register operands. 'opn' actually works
|
|
|
+** for all numbers, but the fast track improves performance for
|
|
|
+** integers.
|
|
|
*/
|
|
|
-#define op_order(L,opi,opf,other) { \
|
|
|
+#define op_order(L,opi,opn,other) { \
|
|
|
int cond; \
|
|
|
TValue *rb = vRB(i); \
|
|
|
if (ttisinteger(s2v(ra)) && ttisinteger(rb)) { \
|
|
@@ -922,14 +998,15 @@ void luaV_finishOp (lua_State *L) {
|
|
|
cond = opi(ia, ib); \
|
|
|
} \
|
|
|
else if (ttisnumber(s2v(ra)) && ttisnumber(rb)) \
|
|
|
- cond = opf(s2v(ra), rb); \
|
|
|
+ cond = opn(s2v(ra), rb); \
|
|
|
else \
|
|
|
Protect(cond = other(L, s2v(ra), rb)); \
|
|
|
docondjump(); }
|
|
|
|
|
|
|
|
|
/*
|
|
|
-** Order operations with immediate operand.
|
|
|
+** Order operations with immediate operand. (Immediate operand is
|
|
|
+** always small enough to have an exact representation as a float.)
|
|
|
*/
|
|
|
#define op_orderI(L,opi,opf,inv,tm) { \
|
|
|
int cond; \
|
|
@@ -977,7 +1054,8 @@ void luaV_finishOp (lua_State *L) {
|
|
|
#define updatebase(ci) (base = ci->func + 1)
|
|
|
|
|
|
|
|
|
-#define updatestack(ci) { if (trap) { updatebase(ci); ra = RA(i); } }
|
|
|
+#define updatestack(ci) \
|
|
|
+ { if (l_unlikely(trap)) { updatebase(ci); ra = RA(i); } }
|
|
|
|
|
|
|
|
|
/*
|
|
@@ -1021,25 +1099,21 @@ void luaV_finishOp (lua_State *L) {
|
|
|
#define ProtectNT(exp) (savepc(L), (exp), updatetrap(ci))
|
|
|
|
|
|
/*
|
|
|
-** Protect code that will finish the loop (returns) or can only raise
|
|
|
-** errors. (That is, it will not return to the interpreter main loop
|
|
|
-** after changing the stack or hooks.)
|
|
|
+** Protect code that can only raise errors. (That is, it cannnot change
|
|
|
+** the stack or hooks.)
|
|
|
*/
|
|
|
#define halfProtect(exp) (savestate(L,ci), (exp))
|
|
|
|
|
|
-/* idem, but without changing the stack */
|
|
|
-#define halfProtectNT(exp) (savepc(L), (exp))
|
|
|
-
|
|
|
-
|
|
|
+/* 'c' is the limit of live values in the stack */
|
|
|
#define checkGC(L,c) \
|
|
|
- { luaC_condGC(L, L->top = (c), /* limit of live values */ \
|
|
|
+ { luaC_condGC(L, (savepc(L), L->top = (c)), \
|
|
|
updatetrap(ci)); \
|
|
|
luai_threadyield(L); }
|
|
|
|
|
|
|
|
|
/* fetch an instruction and prepare its execution */
|
|
|
#define vmfetch() { \
|
|
|
- if (trap) { /* stack reallocation or hooks? */ \
|
|
|
+ if (l_unlikely(trap)) { /* stack reallocation or hooks? */ \
|
|
|
trap = luaG_traceexec(L, pc); /* handle hooks */ \
|
|
|
updatebase(ci); /* correct stack */ \
|
|
|
} \
|
|
@@ -1061,17 +1135,20 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|
|
#if LUA_USE_JUMPTABLE
|
|
|
#include "ljumptab.h"
|
|
|
#endif
|
|
|
- tailcall:
|
|
|
+ startfunc:
|
|
|
trap = L->hookmask;
|
|
|
+ returning: /* trap already set */
|
|
|
cl = clLvalue(s2v(ci->func));
|
|
|
k = cl->p->k;
|
|
|
pc = ci->u.l.savedpc;
|
|
|
- if (trap) {
|
|
|
- if (cl->p->is_vararg)
|
|
|
- trap = 0; /* hooks will start after VARARGPREP instruction */
|
|
|
- else if (pc == cl->p->code) /* first instruction (not resuming)? */
|
|
|
- luaD_hookcall(L, ci);
|
|
|
- ci->u.l.trap = 1; /* there may be other hooks */
|
|
|
+ if (l_unlikely(trap)) {
|
|
|
+ if (pc == cl->p->code) { /* first instruction (not resuming)? */
|
|
|
+ if (cl->p->is_vararg)
|
|
|
+ trap = 0; /* hooks will start after VARARGPREP instruction */
|
|
|
+ else /* check 'call' hook */
|
|
|
+ luaD_hookcall(L, ci);
|
|
|
+ }
|
|
|
+ ci->u.l.trap = 1; /* assume trap is on, for now */
|
|
|
}
|
|
|
base = ci->func + 1;
|
|
|
/* main loop of interpreter */
|
|
@@ -1079,10 +1156,12 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|
|
Instruction i; /* instruction being executed */
|
|
|
StkId ra; /* instruction's A register */
|
|
|
vmfetch();
|
|
|
+// low-level line tracing for debugging Lua
|
|
|
+// printf("line: %d\n", luaG_getfuncline(cl->p, pcRel(pc, cl->p)));
|
|
|
lua_assert(base == ci->func + 1);
|
|
|
- lua_assert(base <= L->top && L->top < L->stack + L->stacksize);
|
|
|
+ lua_assert(base <= L->top && L->top < L->stack_last);
|
|
|
/* invalidate top for instructions not expecting it */
|
|
|
- lua_assert(isIT(i) || (L->top = base));
|
|
|
+ lua_assert(isIT(i) || (cast_void(L->top = base), 1));
|
|
|
vmdispatch (GET_OPCODE(i)) {
|
|
|
vmcase(OP_MOVE) {
|
|
|
setobjs2s(L, ra, RB(i));
|
|
@@ -1109,9 +1188,17 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|
|
setobj2s(L, ra, rb);
|
|
|
vmbreak;
|
|
|
}
|
|
|
- vmcase(OP_LOADBOOL) {
|
|
|
- setbvalue(s2v(ra), GETARG_B(i));
|
|
|
- if (GETARG_C(i)) pc++; /* skip next instruction (if C) */
|
|
|
+ vmcase(OP_LOADFALSE) {
|
|
|
+ setbfvalue(s2v(ra));
|
|
|
+ vmbreak;
|
|
|
+ }
|
|
|
+ vmcase(OP_LFALSESKIP) {
|
|
|
+ setbfvalue(s2v(ra));
|
|
|
+ pc++; /* skip next instruction */
|
|
|
+ vmbreak;
|
|
|
+ }
|
|
|
+ vmcase(OP_LOADTRUE) {
|
|
|
+ setbtvalue(s2v(ra));
|
|
|
vmbreak;
|
|
|
}
|
|
|
vmcase(OP_LOADNIL) {
|
|
@@ -1243,8 +1330,9 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|
|
Table *t;
|
|
|
if (b > 0)
|
|
|
b = 1 << (b - 1); /* size is 2^(b - 1) */
|
|
|
- if (TESTARG_k(i))
|
|
|
- c += GETARG_Ax(*pc) * (MAXARG_C + 1);
|
|
|
+ lua_assert((!TESTARG_k(i)) == (GETARG_Ax(*pc) == 0));
|
|
|
+ if (TESTARG_k(i)) /* non-zero extra argument? */
|
|
|
+ c += GETARG_Ax(*pc) * (MAXARG_C + 1); /* add it to size */
|
|
|
pc++; /* skip extra argument */
|
|
|
L->top = ra + 1; /* correct top in case of emergency GC */
|
|
|
t = luaH_new(L); /* memory allocation */
|
|
@@ -1268,23 +1356,23 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|
|
vmbreak;
|
|
|
}
|
|
|
vmcase(OP_ADDI) {
|
|
|
- op_arithI(L, l_addi, luai_numadd, TM_ADD, GETARG_k(i));
|
|
|
+ op_arithI(L, l_addi, luai_numadd);
|
|
|
vmbreak;
|
|
|
}
|
|
|
vmcase(OP_ADDK) {
|
|
|
- op_arithK(L, l_addi, luai_numadd, GETARG_k(i));
|
|
|
+ op_arithK(L, l_addi, luai_numadd);
|
|
|
vmbreak;
|
|
|
}
|
|
|
vmcase(OP_SUBK) {
|
|
|
- op_arithK(L, l_subi, luai_numsub, 0);
|
|
|
+ op_arithK(L, l_subi, luai_numsub);
|
|
|
vmbreak;
|
|
|
}
|
|
|
vmcase(OP_MULK) {
|
|
|
- op_arithK(L, l_muli, luai_nummul, GETARG_k(i));
|
|
|
+ op_arithK(L, l_muli, luai_nummul);
|
|
|
vmbreak;
|
|
|
}
|
|
|
vmcase(OP_MODK) {
|
|
|
- op_arithK(L, luaV_mod, luaV_modf, 0);
|
|
|
+ op_arithK(L, luaV_mod, luaV_modf);
|
|
|
vmbreak;
|
|
|
}
|
|
|
vmcase(OP_POWK) {
|
|
@@ -1296,7 +1384,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|
|
vmbreak;
|
|
|
}
|
|
|
vmcase(OP_IDIVK) {
|
|
|
- op_arithK(L, luaV_idiv, luai_numidiv, 0);
|
|
|
+ op_arithK(L, luaV_idiv, luai_numidiv);
|
|
|
vmbreak;
|
|
|
}
|
|
|
vmcase(OP_BANDK) {
|
|
@@ -1430,8 +1518,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|
|
}
|
|
|
vmcase(OP_NOT) {
|
|
|
TValue *rb = vRB(i);
|
|
|
- int nrb = l_isfalse(rb); /* next assignment may change this value */
|
|
|
- setbvalue(s2v(ra), nrb);
|
|
|
+ if (l_isfalse(rb))
|
|
|
+ setbtvalue(s2v(ra));
|
|
|
+ else
|
|
|
+ setbfvalue(s2v(ra));
|
|
|
vmbreak;
|
|
|
}
|
|
|
vmcase(OP_LEN) {
|
|
@@ -1446,7 +1536,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|
|
vmbreak;
|
|
|
}
|
|
|
vmcase(OP_CLOSE) {
|
|
|
- Protect(luaF_close(L, ra, LUA_OK));
|
|
|
+ Protect(luaF_close(L, ra, LUA_OK, 1));
|
|
|
vmbreak;
|
|
|
}
|
|
|
vmcase(OP_TBC) {
|
|
@@ -1476,7 +1566,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|
|
vmcase(OP_EQK) {
|
|
|
TValue *rb = KB(i);
|
|
|
/* basic types do not use '__eq'; we can use raw equality */
|
|
|
- int cond = luaV_equalobj(NULL, s2v(ra), rb);
|
|
|
+ int cond = luaV_rawequalobj(s2v(ra), rb);
|
|
|
docondjump();
|
|
|
vmbreak;
|
|
|
}
|
|
@@ -1524,49 +1614,54 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|
|
vmbreak;
|
|
|
}
|
|
|
vmcase(OP_CALL) {
|
|
|
+ CallInfo *newci;
|
|
|
int b = GETARG_B(i);
|
|
|
int nresults = GETARG_C(i) - 1;
|
|
|
if (b != 0) /* fixed number of arguments? */
|
|
|
L->top = ra + b; /* top signals number of arguments */
|
|
|
/* else previous instruction set top */
|
|
|
- ProtectNT(luaD_call(L, ra, nresults));
|
|
|
+ savepc(L); /* in case of errors */
|
|
|
+ if ((newci = luaD_precall(L, ra, nresults)) == NULL)
|
|
|
+ updatetrap(ci); /* C call; nothing else to be done */
|
|
|
+ else { /* Lua call: run function in this same C frame */
|
|
|
+ ci = newci;
|
|
|
+ ci->callstatus = 0; /* call re-uses 'luaV_execute' */
|
|
|
+ goto startfunc;
|
|
|
+ }
|
|
|
vmbreak;
|
|
|
}
|
|
|
vmcase(OP_TAILCALL) {
|
|
|
int b = GETARG_B(i); /* number of arguments + 1 (function) */
|
|
|
int nparams1 = GETARG_C(i);
|
|
|
- /* delat is virtual 'func' - real 'func' (vararg functions) */
|
|
|
+ /* delta is virtual 'func' - real 'func' (vararg functions) */
|
|
|
int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0;
|
|
|
if (b != 0)
|
|
|
L->top = ra + b;
|
|
|
else /* previous instruction set top */
|
|
|
b = cast_int(L->top - ra);
|
|
|
- savepc(ci); /* some calls here can raise errors */
|
|
|
+ savepc(ci); /* several calls here can raise errors */
|
|
|
if (TESTARG_k(i)) {
|
|
|
- /* close upvalues from current call; the compiler ensures
|
|
|
- that there are no to-be-closed variables here, so this
|
|
|
- call cannot change the stack */
|
|
|
- luaF_close(L, base, NOCLOSINGMETH);
|
|
|
+ luaF_closeupval(L, base); /* close upvalues from current call */
|
|
|
+ lua_assert(L->tbclist < base); /* no pending tbc variables */
|
|
|
lua_assert(base == ci->func + 1);
|
|
|
}
|
|
|
- if (!ttisfunction(s2v(ra))) { /* not a function? */
|
|
|
+ while (!ttisfunction(s2v(ra))) { /* not a function? */
|
|
|
luaD_tryfuncTM(L, ra); /* try '__call' metamethod */
|
|
|
b++; /* there is now one extra argument */
|
|
|
+ checkstackGCp(L, 1, ra);
|
|
|
}
|
|
|
if (!ttisLclosure(s2v(ra))) { /* C function? */
|
|
|
- luaD_call(L, ra, LUA_MULTRET); /* call it */
|
|
|
+ luaD_precall(L, ra, LUA_MULTRET); /* call it */
|
|
|
updatetrap(ci);
|
|
|
updatestack(ci); /* stack may have been relocated */
|
|
|
- ci->func -= delta;
|
|
|
- luaD_poscall(L, ci, cast_int(L->top - ra));
|
|
|
- return;
|
|
|
+ ci->func -= delta; /* restore 'func' (if vararg) */
|
|
|
+ luaD_poscall(L, ci, cast_int(L->top - ra)); /* finish caller */
|
|
|
+ updatetrap(ci); /* 'luaD_poscall' can change hooks */
|
|
|
+ goto ret; /* caller returns after the tail call */
|
|
|
}
|
|
|
- else { /* Lua tail call */
|
|
|
- ci->func -= delta;
|
|
|
- luaD_pretailcall(L, ci, ra, b); /* prepare call frame */
|
|
|
- goto tailcall;
|
|
|
- }
|
|
|
- vmbreak;
|
|
|
+ ci->func -= delta; /* restore 'func' (if vararg) */
|
|
|
+ luaD_pretailcall(L, ci, ra, b); /* prepare call frame */
|
|
|
+ goto startfunc; /* execute the callee */
|
|
|
}
|
|
|
vmcase(OP_RETURN) {
|
|
|
int n = GETARG_B(i) - 1; /* number of results */
|
|
@@ -1577,7 +1672,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|
|
if (TESTARG_k(i)) { /* may there be open upvalues? */
|
|
|
if (L->top < ci->top)
|
|
|
L->top = ci->top;
|
|
|
- luaF_close(L, base, LUA_OK);
|
|
|
+ luaF_close(L, base, CLOSEKTOP, 1);
|
|
|
updatetrap(ci);
|
|
|
updatestack(ci);
|
|
|
}
|
|
@@ -1585,26 +1680,31 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|
|
ci->func -= ci->u.l.nextraargs + nparams1;
|
|
|
L->top = ra + n; /* set call for 'luaD_poscall' */
|
|
|
luaD_poscall(L, ci, n);
|
|
|
- return;
|
|
|
+ updatetrap(ci); /* 'luaD_poscall' can change hooks */
|
|
|
+ goto ret;
|
|
|
}
|
|
|
vmcase(OP_RETURN0) {
|
|
|
- if (L->hookmask) {
|
|
|
+ if (l_unlikely(L->hookmask)) {
|
|
|
L->top = ra;
|
|
|
- halfProtectNT(luaD_poscall(L, ci, 0)); /* no hurry... */
|
|
|
+ savepc(ci);
|
|
|
+ luaD_poscall(L, ci, 0); /* no hurry... */
|
|
|
+ trap = 1;
|
|
|
}
|
|
|
else { /* do the 'poscall' here */
|
|
|
- int nres = ci->nresults;
|
|
|
+ int nres;
|
|
|
L->ci = ci->previous; /* back to caller */
|
|
|
L->top = base - 1;
|
|
|
- while (nres-- > 0)
|
|
|
+ for (nres = ci->nresults; l_unlikely(nres > 0); nres--)
|
|
|
setnilvalue(s2v(L->top++)); /* all results are nil */
|
|
|
}
|
|
|
- return;
|
|
|
+ goto ret;
|
|
|
}
|
|
|
vmcase(OP_RETURN1) {
|
|
|
- if (L->hookmask) {
|
|
|
+ if (l_unlikely(L->hookmask)) {
|
|
|
L->top = ra + 1;
|
|
|
- halfProtectNT(luaD_poscall(L, ci, 1)); /* no hurry... */
|
|
|
+ savepc(ci);
|
|
|
+ luaD_poscall(L, ci, 1); /* no hurry... */
|
|
|
+ trap = 1;
|
|
|
}
|
|
|
else { /* do the 'poscall' here */
|
|
|
int nres = ci->nresults;
|
|
@@ -1614,11 +1714,17 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|
|
else {
|
|
|
setobjs2s(L, base - 1, ra); /* at least this result */
|
|
|
L->top = base;
|
|
|
- while (--nres > 0) /* complete missing results */
|
|
|
- setnilvalue(s2v(L->top++));
|
|
|
+ for (; l_unlikely(nres > 1); nres--)
|
|
|
+ setnilvalue(s2v(L->top++)); /* complete missing results */
|
|
|
}
|
|
|
}
|
|
|
- return;
|
|
|
+ ret: /* return from a Lua function */
|
|
|
+ if (ci->callstatus & CIST_FRESH)
|
|
|
+ return; /* end this frame */
|
|
|
+ else {
|
|
|
+ ci = ci->previous;
|
|
|
+ goto returning; /* continue running caller in this frame */
|
|
|
+ }
|
|
|
}
|
|
|
vmcase(OP_FORLOOP) {
|
|
|
if (ttisinteger(s2v(ra + 2))) { /* integer loop? */
|
|
@@ -1633,73 +1739,15 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|
|
pc -= GETARG_Bx(i); /* jump back */
|
|
|
}
|
|
|
}
|
|
|
- else { /* floating loop */
|
|
|
- lua_Number step = fltvalue(s2v(ra + 2));
|
|
|
- lua_Number limit = fltvalue(s2v(ra + 1));
|
|
|
- lua_Number idx = fltvalue(s2v(ra));
|
|
|
- idx = luai_numadd(L, idx, step); /* increment index */
|
|
|
- if (luai_numlt(0, step) ? luai_numle(idx, limit)
|
|
|
- : luai_numle(limit, idx)) {
|
|
|
- chgfltvalue(s2v(ra), idx); /* update internal index */
|
|
|
- setfltvalue(s2v(ra + 3), idx); /* and control variable */
|
|
|
- pc -= GETARG_Bx(i); /* jump back */
|
|
|
- }
|
|
|
- }
|
|
|
+ else if (floatforloop(ra)) /* float loop */
|
|
|
+ pc -= GETARG_Bx(i); /* jump back */
|
|
|
updatetrap(ci); /* allows a signal to break the loop */
|
|
|
vmbreak;
|
|
|
}
|
|
|
vmcase(OP_FORPREP) {
|
|
|
- TValue *pinit = s2v(ra);
|
|
|
- TValue *plimit = s2v(ra + 1);
|
|
|
- TValue *pstep = s2v(ra + 2);
|
|
|
savestate(L, ci); /* in case of errors */
|
|
|
- if (ttisinteger(pinit) && ttisinteger(pstep)) { /* integer loop? */
|
|
|
- lua_Integer init = ivalue(pinit);
|
|
|
- lua_Integer step = ivalue(pstep);
|
|
|
- lua_Integer limit;
|
|
|
- if (step == 0)
|
|
|
- luaG_runerror(L, "'for' step is zero");
|
|
|
- setivalue(s2v(ra + 3), init); /* control variable */
|
|
|
- if (forlimit(L, init, plimit, &limit, step))
|
|
|
- pc += GETARG_Bx(i) + 1; /* skip the loop */
|
|
|
- else { /* prepare loop counter */
|
|
|
- lua_Unsigned count;
|
|
|
- if (step > 0) { /* ascending loop? */
|
|
|
- count = l_castS2U(limit) - l_castS2U(init);
|
|
|
- if (step != 1) /* avoid division in the too common case */
|
|
|
- count /= l_castS2U(step);
|
|
|
- }
|
|
|
- else { /* step < 0; descending loop */
|
|
|
- count = l_castS2U(init) - l_castS2U(limit);
|
|
|
- /* 'step+1' avoids negating 'mininteger' */
|
|
|
- count /= l_castS2U(-(step + 1)) + 1u;
|
|
|
- }
|
|
|
- /* store the counter in place of the limit (which won't be
|
|
|
- needed anymore */
|
|
|
- setivalue(plimit, l_castU2S(count));
|
|
|
- }
|
|
|
- }
|
|
|
- else { /* try making all values floats */
|
|
|
- lua_Number init; lua_Number limit; lua_Number step;
|
|
|
- if (unlikely(!tonumber(plimit, &limit)))
|
|
|
- luaG_forerror(L, plimit, "limit");
|
|
|
- if (unlikely(!tonumber(pstep, &step)))
|
|
|
- luaG_forerror(L, pstep, "step");
|
|
|
- if (unlikely(!tonumber(pinit, &init)))
|
|
|
- luaG_forerror(L, pinit, "initial value");
|
|
|
- if (step == 0)
|
|
|
- luaG_runerror(L, "'for' step is zero");
|
|
|
- if (luai_numlt(0, step) ? luai_numlt(limit, init)
|
|
|
- : luai_numlt(init, limit))
|
|
|
- pc += GETARG_Bx(i) + 1; /* skip the loop */
|
|
|
- else {
|
|
|
- /* make sure internal values are all float */
|
|
|
- setfltvalue(plimit, limit);
|
|
|
- setfltvalue(pstep, step);
|
|
|
- setfltvalue(s2v(ra), init); /* internal index */
|
|
|
- setfltvalue(s2v(ra + 3), init); /* control variable */
|
|
|
- }
|
|
|
- }
|
|
|
+ if (forprep(L, ra))
|
|
|
+ pc += GETARG_Bx(i) + 1; /* skip the loop */
|
|
|
vmbreak;
|
|
|
}
|
|
|
vmcase(OP_TFORPREP) {
|
|
@@ -1769,11 +1817,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|
|
vmbreak;
|
|
|
}
|
|
|
vmcase(OP_VARARGPREP) {
|
|
|
- luaT_adjustvarargs(L, GETARG_A(i), ci, cl->p);
|
|
|
- updatetrap(ci);
|
|
|
- if (trap) {
|
|
|
+ ProtectNT(luaT_adjustvarargs(L, GETARG_A(i), ci, cl->p));
|
|
|
+ if (l_unlikely(trap)) { /* previous "Protect" updated trap */
|
|
|
luaD_hookcall(L, ci);
|
|
|
- L->oldpc = pc + 1; /* next opcode will be seen as a "new" line */
|
|
|
+ L->oldpc = 1; /* next opcode will be seen as a "new" line */
|
|
|
}
|
|
|
updatebase(ci); /* function has new base after adjustment */
|
|
|
vmbreak;
|