xref: /illumos-gate/usr/src/uts/common/fs/zfs/lua/lvm.c (revision dfc11533)
1*dfc11533SChris Williamson /*
2*dfc11533SChris Williamson ** $Id: lvm.c,v 2.155.1.1 2013/04/12 18:48:47 roberto Exp $
3*dfc11533SChris Williamson ** Lua virtual machine
4*dfc11533SChris Williamson ** See Copyright Notice in lua.h
5*dfc11533SChris Williamson */
6*dfc11533SChris Williamson 
7*dfc11533SChris Williamson 
8*dfc11533SChris Williamson #include <sys/zfs_context.h>
9*dfc11533SChris Williamson 
10*dfc11533SChris Williamson #define	strcoll(l,r) (strcmp((l),(r)))
11*dfc11533SChris Williamson 
12*dfc11533SChris Williamson #define lvm_c
13*dfc11533SChris Williamson #define LUA_CORE
14*dfc11533SChris Williamson 
15*dfc11533SChris Williamson #include "lua.h"
16*dfc11533SChris Williamson 
17*dfc11533SChris Williamson #include "ldebug.h"
18*dfc11533SChris Williamson #include "ldo.h"
19*dfc11533SChris Williamson #include "lfunc.h"
20*dfc11533SChris Williamson #include "lgc.h"
21*dfc11533SChris Williamson #include "lobject.h"
22*dfc11533SChris Williamson #include "lopcodes.h"
23*dfc11533SChris Williamson #include "lstate.h"
24*dfc11533SChris Williamson #include "lstring.h"
25*dfc11533SChris Williamson #include "ltable.h"
26*dfc11533SChris Williamson #include "ltm.h"
27*dfc11533SChris Williamson #include "lvm.h"
28*dfc11533SChris Williamson 
29*dfc11533SChris Williamson 
30*dfc11533SChris Williamson 
31*dfc11533SChris Williamson /* limit for table tag-method chains (to avoid loops) */
32*dfc11533SChris Williamson #define MAXTAGLOOP	100
33*dfc11533SChris Williamson 
34*dfc11533SChris Williamson 
luaV_tonumber(const TValue * obj,TValue * n)35*dfc11533SChris Williamson const TValue *luaV_tonumber (const TValue *obj, TValue *n) {
36*dfc11533SChris Williamson   lua_Number num;
37*dfc11533SChris Williamson   if (ttisnumber(obj)) return obj;
38*dfc11533SChris Williamson   if (ttisstring(obj) && luaO_str2d(svalue(obj), tsvalue(obj)->len, &num)) {
39*dfc11533SChris Williamson     setnvalue(n, num);
40*dfc11533SChris Williamson     return n;
41*dfc11533SChris Williamson   }
42*dfc11533SChris Williamson   else
43*dfc11533SChris Williamson     return NULL;
44*dfc11533SChris Williamson }
45*dfc11533SChris Williamson 
46*dfc11533SChris Williamson 
luaV_tostring(lua_State * L,StkId obj)47*dfc11533SChris Williamson int luaV_tostring (lua_State *L, StkId obj) {
48*dfc11533SChris Williamson   if (!ttisnumber(obj))
49*dfc11533SChris Williamson     return 0;
50*dfc11533SChris Williamson   else {
51*dfc11533SChris Williamson     char s[LUAI_MAXNUMBER2STR];
52*dfc11533SChris Williamson     lua_Number n = nvalue(obj);
53*dfc11533SChris Williamson     int l = lua_number2str(s, n);
54*dfc11533SChris Williamson     setsvalue2s(L, obj, luaS_newlstr(L, s, l));
55*dfc11533SChris Williamson     return 1;
56*dfc11533SChris Williamson   }
57*dfc11533SChris Williamson }
58*dfc11533SChris Williamson 
59*dfc11533SChris Williamson 
traceexec(lua_State * L)60*dfc11533SChris Williamson static void traceexec (lua_State *L) {
61*dfc11533SChris Williamson   CallInfo *ci = L->ci;
62*dfc11533SChris Williamson   lu_byte mask = L->hookmask;
63*dfc11533SChris Williamson   int counthook = ((mask & LUA_MASKCOUNT) && L->hookcount == 0);
64*dfc11533SChris Williamson   if (counthook)
65*dfc11533SChris Williamson     resethookcount(L);  /* reset count */
66*dfc11533SChris Williamson   if (ci->callstatus & CIST_HOOKYIELD) {  /* called hook last time? */
67*dfc11533SChris Williamson     ci->callstatus &= ~CIST_HOOKYIELD;  /* erase mark */
68*dfc11533SChris Williamson     return;  /* do not call hook again (VM yielded, so it did not move) */
69*dfc11533SChris Williamson   }
70*dfc11533SChris Williamson   if (counthook)
71*dfc11533SChris Williamson     luaD_hook(L, LUA_HOOKCOUNT, -1);  /* call count hook */
72*dfc11533SChris Williamson   if (mask & LUA_MASKLINE) {
73*dfc11533SChris Williamson     Proto *p = ci_func(ci)->p;
74*dfc11533SChris Williamson     int npc = pcRel(ci->u.l.savedpc, p);
75*dfc11533SChris Williamson     int newline = getfuncline(p, npc);
76*dfc11533SChris Williamson     if (npc == 0 ||  /* call linehook when enter a new function, */
77*dfc11533SChris Williamson         ci->u.l.savedpc <= L->oldpc ||  /* when jump back (loop), or when */
78*dfc11533SChris Williamson         newline != getfuncline(p, pcRel(L->oldpc, p)))  /* enter a new line */
79*dfc11533SChris Williamson       luaD_hook(L, LUA_HOOKLINE, newline);  /* call line hook */
80*dfc11533SChris Williamson   }
81*dfc11533SChris Williamson   L->oldpc = ci->u.l.savedpc;
82*dfc11533SChris Williamson   if (L->status == LUA_YIELD) {  /* did hook yield? */
83*dfc11533SChris Williamson     if (counthook)
84*dfc11533SChris Williamson       L->hookcount = 1;  /* undo decrement to zero */
85*dfc11533SChris Williamson     ci->u.l.savedpc--;  /* undo increment (resume will increment it again) */
86*dfc11533SChris Williamson     ci->callstatus |= CIST_HOOKYIELD;  /* mark that it yielded */
87*dfc11533SChris Williamson     ci->func = L->top - 1;  /* protect stack below results */
88*dfc11533SChris Williamson     luaD_throw(L, LUA_YIELD);
89*dfc11533SChris Williamson   }
90*dfc11533SChris Williamson }
91*dfc11533SChris Williamson 
92*dfc11533SChris Williamson 
callTM(lua_State * L,const TValue * f,const TValue * p1,const TValue * p2,TValue * p3,int hasres)93*dfc11533SChris Williamson static void callTM (lua_State *L, const TValue *f, const TValue *p1,
94*dfc11533SChris Williamson                     const TValue *p2, TValue *p3, int hasres) {
95*dfc11533SChris Williamson   ptrdiff_t result = savestack(L, p3);
96*dfc11533SChris Williamson   setobj2s(L, L->top++, f);  /* push function */
97*dfc11533SChris Williamson   setobj2s(L, L->top++, p1);  /* 1st argument */
98*dfc11533SChris Williamson   setobj2s(L, L->top++, p2);  /* 2nd argument */
99*dfc11533SChris Williamson   if (!hasres)  /* no result? 'p3' is third argument */
100*dfc11533SChris Williamson     setobj2s(L, L->top++, p3);  /* 3rd argument */
101*dfc11533SChris Williamson   /* metamethod may yield only when called from Lua code */
102*dfc11533SChris Williamson   luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci));
103*dfc11533SChris Williamson   if (hasres) {  /* if has result, move it to its place */
104*dfc11533SChris Williamson     p3 = restorestack(L, result);
105*dfc11533SChris Williamson     setobjs2s(L, p3, --L->top);
106*dfc11533SChris Williamson   }
107*dfc11533SChris Williamson }
108*dfc11533SChris Williamson 
109*dfc11533SChris Williamson 
luaV_gettable(lua_State * L,const TValue * t,TValue * key,StkId val)110*dfc11533SChris Williamson void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
111*dfc11533SChris Williamson   int loop;
112*dfc11533SChris Williamson   for (loop = 0; loop < MAXTAGLOOP; loop++) {
113*dfc11533SChris Williamson     const TValue *tm;
114*dfc11533SChris Williamson     if (ttistable(t)) {  /* `t' is a table? */
115*dfc11533SChris Williamson       Table *h = hvalue(t);
116*dfc11533SChris Williamson       const TValue *res = luaH_get(h, key); /* do a primitive get */
117*dfc11533SChris Williamson       if (!ttisnil(res) ||  /* result is not nil? */
118*dfc11533SChris Williamson           (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
119*dfc11533SChris Williamson         setobj2s(L, val, res);
120*dfc11533SChris Williamson         return;
121*dfc11533SChris Williamson       }
122*dfc11533SChris Williamson       /* else will try the tag method */
123*dfc11533SChris Williamson     }
124*dfc11533SChris Williamson     else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
125*dfc11533SChris Williamson       luaG_typeerror(L, t, "index");
126*dfc11533SChris Williamson     if (ttisfunction(tm)) {
127*dfc11533SChris Williamson       callTM(L, tm, t, key, val, 1);
128*dfc11533SChris Williamson       return;
129*dfc11533SChris Williamson     }
130*dfc11533SChris Williamson     t = tm;  /* else repeat with 'tm' */
131*dfc11533SChris Williamson   }
132*dfc11533SChris Williamson   luaG_runerror(L, "loop in gettable");
133*dfc11533SChris Williamson }
134*dfc11533SChris Williamson 
135*dfc11533SChris Williamson 
luaV_settable(lua_State * L,const TValue * t,TValue * key,StkId val)136*dfc11533SChris Williamson void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
137*dfc11533SChris Williamson   int loop;
138*dfc11533SChris Williamson   for (loop = 0; loop < MAXTAGLOOP; loop++) {
139*dfc11533SChris Williamson     const TValue *tm;
140*dfc11533SChris Williamson     if (ttistable(t)) {  /* `t' is a table? */
141*dfc11533SChris Williamson       Table *h = hvalue(t);
142*dfc11533SChris Williamson       TValue *oldval = cast(TValue *, luaH_get(h, key));
143*dfc11533SChris Williamson       /* if previous value is not nil, there must be a previous entry
144*dfc11533SChris Williamson          in the table; moreover, a metamethod has no relevance */
145*dfc11533SChris Williamson       if (!ttisnil(oldval) ||
146*dfc11533SChris Williamson          /* previous value is nil; must check the metamethod */
147*dfc11533SChris Williamson          ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL &&
148*dfc11533SChris Williamson          /* no metamethod; is there a previous entry in the table? */
149*dfc11533SChris Williamson          (oldval != luaO_nilobject ||
150*dfc11533SChris Williamson          /* no previous entry; must create one. (The next test is
151*dfc11533SChris Williamson             always true; we only need the assignment.) */
152*dfc11533SChris Williamson          (oldval = luaH_newkey(L, h, key), 1)))) {
153*dfc11533SChris Williamson         /* no metamethod and (now) there is an entry with given key */
154*dfc11533SChris Williamson         setobj2t(L, oldval, val);  /* assign new value to that entry */
155*dfc11533SChris Williamson         invalidateTMcache(h);
156*dfc11533SChris Williamson         luaC_barrierback(L, obj2gco(h), val);
157*dfc11533SChris Williamson         return;
158*dfc11533SChris Williamson       }
159*dfc11533SChris Williamson       /* else will try the metamethod */
160*dfc11533SChris Williamson     }
161*dfc11533SChris Williamson     else  /* not a table; check metamethod */
162*dfc11533SChris Williamson       if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
163*dfc11533SChris Williamson         luaG_typeerror(L, t, "index");
164*dfc11533SChris Williamson     /* there is a metamethod */
165*dfc11533SChris Williamson     if (ttisfunction(tm)) {
166*dfc11533SChris Williamson       callTM(L, tm, t, key, val, 0);
167*dfc11533SChris Williamson       return;
168*dfc11533SChris Williamson     }
169*dfc11533SChris Williamson     t = tm;  /* else repeat with 'tm' */
170*dfc11533SChris Williamson   }
171*dfc11533SChris Williamson   luaG_runerror(L, "loop in settable");
172*dfc11533SChris Williamson }
173*dfc11533SChris Williamson 
174*dfc11533SChris Williamson 
call_binTM(lua_State * L,const TValue * p1,const TValue * p2,StkId res,TMS event)175*dfc11533SChris Williamson static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2,
176*dfc11533SChris Williamson                        StkId res, TMS event) {
177*dfc11533SChris Williamson   const TValue *tm = luaT_gettmbyobj(L, p1, event);  /* try first operand */
178*dfc11533SChris Williamson   if (ttisnil(tm))
179*dfc11533SChris Williamson     tm = luaT_gettmbyobj(L, p2, event);  /* try second operand */
180*dfc11533SChris Williamson   if (ttisnil(tm)) return 0;
181*dfc11533SChris Williamson   callTM(L, tm, p1, p2, res, 1);
182*dfc11533SChris Williamson   return 1;
183*dfc11533SChris Williamson }
184*dfc11533SChris Williamson 
185*dfc11533SChris Williamson 
get_equalTM(lua_State * L,Table * mt1,Table * mt2,TMS event)186*dfc11533SChris Williamson static const TValue *get_equalTM (lua_State *L, Table *mt1, Table *mt2,
187*dfc11533SChris Williamson                                   TMS event) {
188*dfc11533SChris Williamson   const TValue *tm1 = fasttm(L, mt1, event);
189*dfc11533SChris Williamson   const TValue *tm2;
190*dfc11533SChris Williamson   if (tm1 == NULL) return NULL;  /* no metamethod */
191*dfc11533SChris Williamson   if (mt1 == mt2) return tm1;  /* same metatables => same metamethods */
192*dfc11533SChris Williamson   tm2 = fasttm(L, mt2, event);
193*dfc11533SChris Williamson   if (tm2 == NULL) return NULL;  /* no metamethod */
194*dfc11533SChris Williamson   if (luaV_rawequalobj(tm1, tm2))  /* same metamethods? */
195*dfc11533SChris Williamson     return tm1;
196*dfc11533SChris Williamson   return NULL;
197*dfc11533SChris Williamson }
198*dfc11533SChris Williamson 
199*dfc11533SChris Williamson 
call_orderTM(lua_State * L,const TValue * p1,const TValue * p2,TMS event)200*dfc11533SChris Williamson static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2,
201*dfc11533SChris Williamson                          TMS event) {
202*dfc11533SChris Williamson   if (!call_binTM(L, p1, p2, L->top, event))
203*dfc11533SChris Williamson     return -1;  /* no metamethod */
204*dfc11533SChris Williamson   else
205*dfc11533SChris Williamson     return !l_isfalse(L->top);
206*dfc11533SChris Williamson }
207*dfc11533SChris Williamson 
208*dfc11533SChris Williamson 
l_strcmp(const TString * ls,const TString * rs)209*dfc11533SChris Williamson static int l_strcmp (const TString *ls, const TString *rs) {
210*dfc11533SChris Williamson   const char *l = getstr(ls);
211*dfc11533SChris Williamson   size_t ll = ls->tsv.len;
212*dfc11533SChris Williamson   const char *r = getstr(rs);
213*dfc11533SChris Williamson   size_t lr = rs->tsv.len;
214*dfc11533SChris Williamson   for (;;) {
215*dfc11533SChris Williamson     int temp = strcoll(l, r);
216*dfc11533SChris Williamson     if (temp != 0) return temp;
217*dfc11533SChris Williamson     else {  /* strings are equal up to a `\0' */
218*dfc11533SChris Williamson       size_t len = strlen(l);  /* index of first `\0' in both strings */
219*dfc11533SChris Williamson       if (len == lr)  /* r is finished? */
220*dfc11533SChris Williamson         return (len == ll) ? 0 : 1;
221*dfc11533SChris Williamson       else if (len == ll)  /* l is finished? */
222*dfc11533SChris Williamson         return -1;  /* l is smaller than r (because r is not finished) */
223*dfc11533SChris Williamson       /* both strings longer than `len'; go on comparing (after the `\0') */
224*dfc11533SChris Williamson       len++;
225*dfc11533SChris Williamson       l += len; ll -= len; r += len; lr -= len;
226*dfc11533SChris Williamson     }
227*dfc11533SChris Williamson   }
228*dfc11533SChris Williamson }
229*dfc11533SChris Williamson 
230*dfc11533SChris Williamson 
luaV_lessthan(lua_State * L,const TValue * l,const TValue * r)231*dfc11533SChris Williamson int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
232*dfc11533SChris Williamson   int res;
233*dfc11533SChris Williamson   if (ttisnumber(l) && ttisnumber(r))
234*dfc11533SChris Williamson     return luai_numlt(L, nvalue(l), nvalue(r));
235*dfc11533SChris Williamson   else if (ttisstring(l) && ttisstring(r))
236*dfc11533SChris Williamson     return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
237*dfc11533SChris Williamson   else if ((res = call_orderTM(L, l, r, TM_LT)) < 0)
238*dfc11533SChris Williamson     luaG_ordererror(L, l, r);
239*dfc11533SChris Williamson   return res;
240*dfc11533SChris Williamson }
241*dfc11533SChris Williamson 
242*dfc11533SChris Williamson 
luaV_lessequal(lua_State * L,const TValue * l,const TValue * r)243*dfc11533SChris Williamson int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {
244*dfc11533SChris Williamson   int res;
245*dfc11533SChris Williamson   if (ttisnumber(l) && ttisnumber(r))
246*dfc11533SChris Williamson     return luai_numle(L, nvalue(l), nvalue(r));
247*dfc11533SChris Williamson   else if (ttisstring(l) && ttisstring(r))
248*dfc11533SChris Williamson     return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
249*dfc11533SChris Williamson   else if ((res = call_orderTM(L, l, r, TM_LE)) >= 0)  /* first try `le' */
250*dfc11533SChris Williamson     return res;
251*dfc11533SChris Williamson   else if ((res = call_orderTM(L, r, l, TM_LT)) < 0)  /* else try `lt' */
252*dfc11533SChris Williamson     luaG_ordererror(L, l, r);
253*dfc11533SChris Williamson   return !res;
254*dfc11533SChris Williamson }
255*dfc11533SChris Williamson 
256*dfc11533SChris Williamson 
257*dfc11533SChris Williamson /*
258*dfc11533SChris Williamson ** equality of Lua values. L == NULL means raw equality (no metamethods)
259*dfc11533SChris Williamson */
luaV_equalobj_(lua_State * L,const TValue * t1,const TValue * t2)260*dfc11533SChris Williamson int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2) {
261*dfc11533SChris Williamson   const TValue *tm;
262*dfc11533SChris Williamson   lua_assert(ttisequal(t1, t2));
263*dfc11533SChris Williamson   switch (ttype(t1)) {
264*dfc11533SChris Williamson     case LUA_TNIL: return 1;
265*dfc11533SChris Williamson     case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));
266*dfc11533SChris Williamson     case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2);  /* true must be 1 !! */
267*dfc11533SChris Williamson     case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
268*dfc11533SChris Williamson     case LUA_TLCF: return fvalue(t1) == fvalue(t2);
269*dfc11533SChris Williamson     case LUA_TSHRSTR: return eqshrstr(rawtsvalue(t1), rawtsvalue(t2));
270*dfc11533SChris Williamson     case LUA_TLNGSTR: return luaS_eqlngstr(rawtsvalue(t1), rawtsvalue(t2));
271*dfc11533SChris Williamson     case LUA_TUSERDATA: {
272*dfc11533SChris Williamson       if (uvalue(t1) == uvalue(t2)) return 1;
273*dfc11533SChris Williamson       else if (L == NULL) return 0;
274*dfc11533SChris Williamson       tm = get_equalTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, TM_EQ);
275*dfc11533SChris Williamson       break;  /* will try TM */
276*dfc11533SChris Williamson     }
277*dfc11533SChris Williamson     case LUA_TTABLE: {
278*dfc11533SChris Williamson       if (hvalue(t1) == hvalue(t2)) return 1;
279*dfc11533SChris Williamson       else if (L == NULL) return 0;
280*dfc11533SChris Williamson       tm = get_equalTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
281*dfc11533SChris Williamson       break;  /* will try TM */
282*dfc11533SChris Williamson     }
283*dfc11533SChris Williamson     default:
284*dfc11533SChris Williamson       lua_assert(iscollectable(t1));
285*dfc11533SChris Williamson       return gcvalue(t1) == gcvalue(t2);
286*dfc11533SChris Williamson   }
287*dfc11533SChris Williamson   if (tm == NULL) return 0;  /* no TM? */
288*dfc11533SChris Williamson   callTM(L, tm, t1, t2, L->top, 1);  /* call TM */
289*dfc11533SChris Williamson   return !l_isfalse(L->top);
290*dfc11533SChris Williamson }
291*dfc11533SChris Williamson 
292*dfc11533SChris Williamson 
luaV_concat(lua_State * L,int total)293*dfc11533SChris Williamson void luaV_concat (lua_State *L, int total) {
294*dfc11533SChris Williamson   lua_assert(total >= 2);
295*dfc11533SChris Williamson   do {
296*dfc11533SChris Williamson     StkId top = L->top;
297*dfc11533SChris Williamson     int n = 2;  /* number of elements handled in this pass (at least 2) */
298*dfc11533SChris Williamson     if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {
299*dfc11533SChris Williamson       if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
300*dfc11533SChris Williamson         luaG_concaterror(L, top-2, top-1);
301*dfc11533SChris Williamson     }
302*dfc11533SChris Williamson     else if (tsvalue(top-1)->len == 0)  /* second operand is empty? */
303*dfc11533SChris Williamson       (void)tostring(L, top - 2);  /* result is first operand */
304*dfc11533SChris Williamson     else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) {
305*dfc11533SChris Williamson       setobjs2s(L, top - 2, top - 1);  /* result is second op. */
306*dfc11533SChris Williamson     }
307*dfc11533SChris Williamson     else {
308*dfc11533SChris Williamson       /* at least two non-empty string values; get as many as possible */
309*dfc11533SChris Williamson       size_t tl = tsvalue(top-1)->len;
310*dfc11533SChris Williamson       char *buffer;
311*dfc11533SChris Williamson       int i;
312*dfc11533SChris Williamson       /* collect total length */
313*dfc11533SChris Williamson       for (i = 1; i < total && tostring(L, top-i-1); i++) {
314*dfc11533SChris Williamson         size_t l = tsvalue(top-i-1)->len;
315*dfc11533SChris Williamson         if (l >= (MAX_SIZET/sizeof(char)) - tl)
316*dfc11533SChris Williamson           luaG_runerror(L, "string length overflow");
317*dfc11533SChris Williamson         tl += l;
318*dfc11533SChris Williamson       }
319*dfc11533SChris Williamson       buffer = luaZ_openspace(L, &G(L)->buff, tl);
320*dfc11533SChris Williamson       tl = 0;
321*dfc11533SChris Williamson       n = i;
322*dfc11533SChris Williamson       do {  /* concat all strings */
323*dfc11533SChris Williamson         size_t l = tsvalue(top-i)->len;
324*dfc11533SChris Williamson         memcpy(buffer+tl, svalue(top-i), l * sizeof(char));
325*dfc11533SChris Williamson         tl += l;
326*dfc11533SChris Williamson       } while (--i > 0);
327*dfc11533SChris Williamson       setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));
328*dfc11533SChris Williamson     }
329*dfc11533SChris Williamson     total -= n-1;  /* got 'n' strings to create 1 new */
330*dfc11533SChris Williamson     L->top -= n-1;  /* popped 'n' strings and pushed one */
331*dfc11533SChris Williamson   } while (total > 1);  /* repeat until only 1 result left */
332*dfc11533SChris Williamson }
333*dfc11533SChris Williamson 
334*dfc11533SChris Williamson 
luaV_objlen(lua_State * L,StkId ra,const TValue * rb)335*dfc11533SChris Williamson void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
336*dfc11533SChris Williamson   const TValue *tm;
337*dfc11533SChris Williamson   switch (ttypenv(rb)) {
338*dfc11533SChris Williamson     case LUA_TTABLE: {
339*dfc11533SChris Williamson       Table *h = hvalue(rb);
340*dfc11533SChris Williamson       tm = fasttm(L, h->metatable, TM_LEN);
341*dfc11533SChris Williamson       if (tm) break;  /* metamethod? break switch to call it */
342*dfc11533SChris Williamson       setnvalue(ra, cast_num(luaH_getn(h)));  /* else primitive len */
343*dfc11533SChris Williamson       return;
344*dfc11533SChris Williamson     }
345*dfc11533SChris Williamson     case LUA_TSTRING: {
346*dfc11533SChris Williamson       setnvalue(ra, cast_num(tsvalue(rb)->len));
347*dfc11533SChris Williamson       return;
348*dfc11533SChris Williamson     }
349*dfc11533SChris Williamson     default: {  /* try metamethod */
350*dfc11533SChris Williamson       tm = luaT_gettmbyobj(L, rb, TM_LEN);
351*dfc11533SChris Williamson       if (ttisnil(tm))  /* no metamethod? */
352*dfc11533SChris Williamson         luaG_typeerror(L, rb, "get length of");
353*dfc11533SChris Williamson       break;
354*dfc11533SChris Williamson     }
355*dfc11533SChris Williamson   }
356*dfc11533SChris Williamson   callTM(L, tm, rb, rb, ra, 1);
357*dfc11533SChris Williamson }
358*dfc11533SChris Williamson 
359*dfc11533SChris Williamson /*
360*dfc11533SChris Williamson  * luaV_div and luaV_mod patched in from Lua 5.3.2 in order to properly handle
361*dfc11533SChris Williamson  * div/mod by zero (instead of crashing, which is the default behavior in
362*dfc11533SChris Williamson  * Lua 5.2)
363*dfc11533SChris Williamson  */
364*dfc11533SChris Williamson 
365*dfc11533SChris Williamson /*
366*dfc11533SChris Williamson ** Integer division; return 'm // n', that is, floor(m/n).
367*dfc11533SChris Williamson ** C division truncates its result (rounds towards zero).
368*dfc11533SChris Williamson ** 'floor(q) == trunc(q)' when 'q >= 0' or when 'q' is integer,
369*dfc11533SChris Williamson ** otherwise 'floor(q) == trunc(q) - 1'.
370*dfc11533SChris Williamson */
luaV_div(lua_State * L,lua_Number m,lua_Number n)371*dfc11533SChris Williamson static lua_Number luaV_div (lua_State *L, lua_Number m, lua_Number n) {
372*dfc11533SChris Williamson   if ((lua_Unsigned)(n) + 1u <= 1u) {  /* special cases: -1 or 0 */
373*dfc11533SChris Williamson     if (n == 0)
374*dfc11533SChris Williamson       luaG_runerror(L, "attempt to divide by zero");
375*dfc11533SChris Williamson     return (0 - m);   /* n==-1; avoid overflow with 0x80000...//-1 */
376*dfc11533SChris Williamson   }
377*dfc11533SChris Williamson   else {
378*dfc11533SChris Williamson     lua_Number q = m / n;  /* perform C division */
379*dfc11533SChris Williamson     if ((m ^ n) < 0 && m % n != 0)  /* 'm/n' would be negative non-integer? */
380*dfc11533SChris Williamson       q -= 1;  /* correct result for different rounding */
381*dfc11533SChris Williamson     return q;
382*dfc11533SChris Williamson   }
383*dfc11533SChris Williamson }
384*dfc11533SChris Williamson 
385*dfc11533SChris Williamson 
386*dfc11533SChris Williamson /*
387*dfc11533SChris Williamson ** Integer modulus; return 'm % n'. (Assume that C '%' with
388*dfc11533SChris Williamson ** negative operands follows C99 behavior. See previous comment
389*dfc11533SChris Williamson ** about luaV_div.)
390*dfc11533SChris Williamson */
luaV_mod(lua_State * L,lua_Number m,lua_Number n)391*dfc11533SChris Williamson static lua_Number luaV_mod (lua_State *L, lua_Number m, lua_Number n) {
392*dfc11533SChris Williamson   if ((lua_Unsigned)(n) + 1u <= 1u) {  /* special cases: -1 or 0 */
393*dfc11533SChris Williamson     if (n == 0)
394*dfc11533SChris Williamson       luaG_runerror(L, "attempt to perform 'n%%0'");
395*dfc11533SChris Williamson     return 0;   /* m % -1 == 0; avoid overflow with 0x80000...%-1 */
396*dfc11533SChris Williamson   }
397*dfc11533SChris Williamson   else {
398*dfc11533SChris Williamson     lua_Number r = m % n;
399*dfc11533SChris Williamson     if (r != 0 && (m ^ n) < 0)  /* 'm/n' would be non-integer negative? */
400*dfc11533SChris Williamson       r += n;  /* correct result for different rounding */
401*dfc11533SChris Williamson     return r;
402*dfc11533SChris Williamson   }
403*dfc11533SChris Williamson }
404*dfc11533SChris Williamson 
405*dfc11533SChris Williamson /*
406*dfc11533SChris Williamson  * End patch from 5.3.2
407*dfc11533SChris Williamson  */
408*dfc11533SChris Williamson 
luaV_arith(lua_State * L,StkId ra,const TValue * rb,const TValue * rc,TMS op)409*dfc11533SChris Williamson void luaV_arith (lua_State *L, StkId ra, const TValue *rb,
410*dfc11533SChris Williamson                  const TValue *rc, TMS op) {
411*dfc11533SChris Williamson   TValue tempb, tempc;
412*dfc11533SChris Williamson   const TValue *b, *c;
413*dfc11533SChris Williamson   if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
414*dfc11533SChris Williamson       (c = luaV_tonumber(rc, &tempc)) != NULL) {
415*dfc11533SChris Williamson     /*
416*dfc11533SChris Williamson      * Patched: if dividing or modding, use patched functions from 5.3
417*dfc11533SChris Williamson      */
418*dfc11533SChris Williamson     lua_Number res;
419*dfc11533SChris Williamson     int lop = op - TM_ADD + LUA_OPADD;
420*dfc11533SChris Williamson     if (lop == LUA_OPDIV) {
421*dfc11533SChris Williamson       res = luaV_div(L, nvalue(b), nvalue(c));
422*dfc11533SChris Williamson     } else if (lop == LUA_OPMOD) {
423*dfc11533SChris Williamson       res = luaV_mod(L, nvalue(b), nvalue(c));
424*dfc11533SChris Williamson     } else {
425*dfc11533SChris Williamson       res = luaO_arith(op - TM_ADD + LUA_OPADD, nvalue(b), nvalue(c));
426*dfc11533SChris Williamson     }
427*dfc11533SChris Williamson     setnvalue(ra, res);
428*dfc11533SChris Williamson   }
429*dfc11533SChris Williamson   else if (!call_binTM(L, rb, rc, ra, op))
430*dfc11533SChris Williamson     luaG_aritherror(L, rb, rc);
431*dfc11533SChris Williamson }
432*dfc11533SChris Williamson 
433*dfc11533SChris Williamson 
434*dfc11533SChris Williamson /*
435*dfc11533SChris Williamson ** check whether cached closure in prototype 'p' may be reused, that is,
436*dfc11533SChris Williamson ** whether there is a cached closure with the same upvalues needed by
437*dfc11533SChris Williamson ** new closure to be created.
438*dfc11533SChris Williamson */
getcached(Proto * p,UpVal ** encup,StkId base)439*dfc11533SChris Williamson static Closure *getcached (Proto *p, UpVal **encup, StkId base) {
440*dfc11533SChris Williamson   Closure *c = p->cache;
441*dfc11533SChris Williamson   if (c != NULL) {  /* is there a cached closure? */
442*dfc11533SChris Williamson     int nup = p->sizeupvalues;
443*dfc11533SChris Williamson     Upvaldesc *uv = p->upvalues;
444*dfc11533SChris Williamson     int i;
445*dfc11533SChris Williamson     for (i = 0; i < nup; i++) {  /* check whether it has right upvalues */
446*dfc11533SChris Williamson       TValue *v = uv[i].instack ? base + uv[i].idx : encup[uv[i].idx]->v;
447*dfc11533SChris Williamson       if (c->l.upvals[i]->v != v)
448*dfc11533SChris Williamson         return NULL;  /* wrong upvalue; cannot reuse closure */
449*dfc11533SChris Williamson     }
450*dfc11533SChris Williamson   }
451*dfc11533SChris Williamson   return c;  /* return cached closure (or NULL if no cached closure) */
452*dfc11533SChris Williamson }
453*dfc11533SChris Williamson 
454*dfc11533SChris Williamson 
455*dfc11533SChris Williamson /*
456*dfc11533SChris Williamson ** create a new Lua closure, push it in the stack, and initialize
457*dfc11533SChris Williamson ** its upvalues. Note that the call to 'luaC_barrierproto' must come
458*dfc11533SChris Williamson ** before the assignment to 'p->cache', as the function needs the
459*dfc11533SChris Williamson ** original value of that field.
460*dfc11533SChris Williamson */
pushclosure(lua_State * L,Proto * p,UpVal ** encup,StkId base,StkId ra)461*dfc11533SChris Williamson static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base,
462*dfc11533SChris Williamson                          StkId ra) {
463*dfc11533SChris Williamson   int nup = p->sizeupvalues;
464*dfc11533SChris Williamson   Upvaldesc *uv = p->upvalues;
465*dfc11533SChris Williamson   int i;
466*dfc11533SChris Williamson   Closure *ncl = luaF_newLclosure(L, nup);
467*dfc11533SChris Williamson   ncl->l.p = p;
468*dfc11533SChris Williamson   setclLvalue(L, ra, ncl);  /* anchor new closure in stack */
469*dfc11533SChris Williamson   for (i = 0; i < nup; i++) {  /* fill in its upvalues */
470*dfc11533SChris Williamson     if (uv[i].instack)  /* upvalue refers to local variable? */
471*dfc11533SChris Williamson       ncl->l.upvals[i] = luaF_findupval(L, base + uv[i].idx);
472*dfc11533SChris Williamson     else  /* get upvalue from enclosing function */
473*dfc11533SChris Williamson       ncl->l.upvals[i] = encup[uv[i].idx];
474*dfc11533SChris Williamson   }
475*dfc11533SChris Williamson   luaC_barrierproto(L, p, ncl);
476*dfc11533SChris Williamson   p->cache = ncl;  /* save it on cache for reuse */
477*dfc11533SChris Williamson }
478*dfc11533SChris Williamson 
479*dfc11533SChris Williamson 
480*dfc11533SChris Williamson /*
481*dfc11533SChris Williamson ** finish execution of an opcode interrupted by an yield
482*dfc11533SChris Williamson */
luaV_finishOp(lua_State * L)483*dfc11533SChris Williamson void luaV_finishOp (lua_State *L) {
484*dfc11533SChris Williamson   CallInfo *ci = L->ci;
485*dfc11533SChris Williamson   StkId base = ci->u.l.base;
486*dfc11533SChris Williamson   Instruction inst = *(ci->u.l.savedpc - 1);  /* interrupted instruction */
487*dfc11533SChris Williamson   OpCode op = GET_OPCODE(inst);
488*dfc11533SChris Williamson   switch (op) {  /* finish its execution */
489*dfc11533SChris Williamson     case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV:
490*dfc11533SChris Williamson     case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN:
491*dfc11533SChris Williamson     case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: {
492*dfc11533SChris Williamson       setobjs2s(L, base + GETARG_A(inst), --L->top);
493*dfc11533SChris Williamson       break;
494*dfc11533SChris Williamson     }
495*dfc11533SChris Williamson     case OP_LE: case OP_LT: case OP_EQ: {
496*dfc11533SChris Williamson       int res = !l_isfalse(L->top - 1);
497*dfc11533SChris Williamson       L->top--;
498*dfc11533SChris Williamson       /* metamethod should not be called when operand is K */
499*dfc11533SChris Williamson       lua_assert(!ISK(GETARG_B(inst)));
500*dfc11533SChris Williamson       if (op == OP_LE &&  /* "<=" using "<" instead? */
501*dfc11533SChris Williamson           ttisnil(luaT_gettmbyobj(L, base + GETARG_B(inst), TM_LE)))
502*dfc11533SChris Williamson         res = !res;  /* invert result */
503*dfc11533SChris Williamson       lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP);
504*dfc11533SChris Williamson       if (res != GETARG_A(inst))  /* condition failed? */
505*dfc11533SChris Williamson         ci->u.l.savedpc++;  /* skip jump instruction */
506*dfc11533SChris Williamson       break;
507*dfc11533SChris Williamson     }
508*dfc11533SChris Williamson     case OP_CONCAT: {
509*dfc11533SChris Williamson       StkId top = L->top - 1;  /* top when 'call_binTM' was called */
510*dfc11533SChris Williamson       int b = GETARG_B(inst);      /* first element to concatenate */
511*dfc11533SChris Williamson       int total = cast_int(top - 1 - (base + b));  /* yet to concatenate */
512*dfc11533SChris Williamson       setobj2s(L, top - 2, top);  /* put TM result in proper position */
513*dfc11533SChris Williamson       if (total > 1) {  /* are there elements to concat? */
514*dfc11533SChris Williamson         L->top = top - 1;  /* top is one after last element (at top-2) */
515*dfc11533SChris Williamson         luaV_concat(L, total);  /* concat them (may yield again) */
516*dfc11533SChris Williamson       }
517*dfc11533SChris Williamson       /* move final result to final position */
518*dfc11533SChris Williamson       setobj2s(L, ci->u.l.base + GETARG_A(inst), L->top - 1);
519*dfc11533SChris Williamson       L->top = ci->top;  /* restore top */
520*dfc11533SChris Williamson       break;
521*dfc11533SChris Williamson     }
522*dfc11533SChris Williamson     case OP_TFORCALL: {
523*dfc11533SChris Williamson       lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP);
524*dfc11533SChris Williamson       L->top = ci->top;  /* correct top */
525*dfc11533SChris Williamson       break;
526*dfc11533SChris Williamson     }
527*dfc11533SChris Williamson     case OP_CALL: {
528*dfc11533SChris Williamson       if (GETARG_C(inst) - 1 >= 0)  /* nresults >= 0? */
529*dfc11533SChris Williamson         L->top = ci->top;  /* adjust results */
530*dfc11533SChris Williamson       break;
531*dfc11533SChris Williamson     }
532*dfc11533SChris Williamson     case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE:
533*dfc11533SChris Williamson       break;
534*dfc11533SChris Williamson     default: lua_assert(0);
535*dfc11533SChris Williamson   }
536*dfc11533SChris Williamson }
537*dfc11533SChris Williamson 
538*dfc11533SChris Williamson 
539*dfc11533SChris Williamson 
540*dfc11533SChris Williamson /*
541*dfc11533SChris Williamson ** some macros for common tasks in `luaV_execute'
542*dfc11533SChris Williamson */
543*dfc11533SChris Williamson 
544*dfc11533SChris Williamson #if !defined luai_runtimecheck
545*dfc11533SChris Williamson #define luai_runtimecheck(L, c)		/* void */
546*dfc11533SChris Williamson #endif
547*dfc11533SChris Williamson 
548*dfc11533SChris Williamson 
549*dfc11533SChris Williamson #define RA(i)	(base+GETARG_A(i))
550*dfc11533SChris Williamson /* to be used after possible stack reallocation */
551*dfc11533SChris Williamson #define RB(i)	check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))
552*dfc11533SChris Williamson #define RC(i)	check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))
553*dfc11533SChris Williamson #define RKB(i)	check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \
554*dfc11533SChris Williamson 	ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i))
555*dfc11533SChris Williamson #define RKC(i)	check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \
556*dfc11533SChris Williamson 	ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i))
557*dfc11533SChris Williamson #define KBx(i)  \
558*dfc11533SChris Williamson   (k + (GETARG_Bx(i) != 0 ? GETARG_Bx(i) - 1 : GETARG_Ax(*ci->u.l.savedpc++)))
559*dfc11533SChris Williamson 
560*dfc11533SChris Williamson 
561*dfc11533SChris Williamson /* execute a jump instruction */
562*dfc11533SChris Williamson #define dojump(ci,i,e) \
563*dfc11533SChris Williamson   { int a = GETARG_A(i); \
564*dfc11533SChris Williamson     if (a > 0) luaF_close(L, ci->u.l.base + a - 1); \
565*dfc11533SChris Williamson     ci->u.l.savedpc += GETARG_sBx(i) + e; }
566*dfc11533SChris Williamson 
567*dfc11533SChris Williamson /* for test instructions, execute the jump instruction that follows it */
568*dfc11533SChris Williamson #define donextjump(ci)	{ i = *ci->u.l.savedpc; dojump(ci, i, 1); }
569*dfc11533SChris Williamson 
570*dfc11533SChris Williamson 
571*dfc11533SChris Williamson #define Protect(x)	{ {x;}; base = ci->u.l.base; }
572*dfc11533SChris Williamson 
573*dfc11533SChris Williamson #define checkGC(L,c)  \
574*dfc11533SChris Williamson   Protect( luaC_condGC(L,{L->top = (c);  /* limit of live values */ \
575*dfc11533SChris Williamson                           luaC_step(L); \
576*dfc11533SChris Williamson                           L->top = ci->top;})  /* restore top */ \
577*dfc11533SChris Williamson            luai_threadyield(L); )
578*dfc11533SChris Williamson 
579*dfc11533SChris Williamson 
580*dfc11533SChris Williamson #define arith_op(op,tm) { \
581*dfc11533SChris Williamson         TValue *rb = RKB(i); \
582*dfc11533SChris Williamson         TValue *rc = RKC(i); \
583*dfc11533SChris Williamson         if (ttisnumber(rb) && ttisnumber(rc)) { \
584*dfc11533SChris Williamson           lua_Number nb = nvalue(rb), nc = nvalue(rc); \
585*dfc11533SChris Williamson           setnvalue(ra, op(L, nb, nc)); \
586*dfc11533SChris Williamson         } \
587*dfc11533SChris Williamson         else { Protect(luaV_arith(L, ra, rb, rc, tm)); } }
588*dfc11533SChris Williamson 
589*dfc11533SChris Williamson 
590*dfc11533SChris Williamson #define vmdispatch(o)	switch(o)
591*dfc11533SChris Williamson #define vmcase(l,b)	case l: {b}  break;
592*dfc11533SChris Williamson #define vmcasenb(l,b)	case l: {b}		/* nb = no break */
593*dfc11533SChris Williamson 
luaV_execute(lua_State * L)594*dfc11533SChris Williamson void luaV_execute (lua_State *L) {
595*dfc11533SChris Williamson   CallInfo *ci = L->ci;
596*dfc11533SChris Williamson   LClosure *cl;
597*dfc11533SChris Williamson   TValue *k;
598*dfc11533SChris Williamson   StkId base;
599*dfc11533SChris Williamson  newframe:  /* reentry point when frame changes (call/return) */
600*dfc11533SChris Williamson   lua_assert(ci == L->ci);
601*dfc11533SChris Williamson   cl = clLvalue(ci->func);
602*dfc11533SChris Williamson   k = cl->p->k;
603*dfc11533SChris Williamson   base = ci->u.l.base;
604*dfc11533SChris Williamson   /* main loop of interpreter */
605*dfc11533SChris Williamson   for (;;) {
606*dfc11533SChris Williamson     Instruction i = *(ci->u.l.savedpc++);
607*dfc11533SChris Williamson     StkId ra;
608*dfc11533SChris Williamson     if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
609*dfc11533SChris Williamson         (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
610*dfc11533SChris Williamson       Protect(traceexec(L));
611*dfc11533SChris Williamson     }
612*dfc11533SChris Williamson     /* WARNING: several calls may realloc the stack and invalidate `ra' */
613*dfc11533SChris Williamson     ra = RA(i);
614*dfc11533SChris Williamson     lua_assert(base == ci->u.l.base);
615*dfc11533SChris Williamson     lua_assert(base <= L->top && L->top < L->stack + L->stacksize);
616*dfc11533SChris Williamson     vmdispatch (GET_OPCODE(i)) {
617*dfc11533SChris Williamson       vmcase(OP_MOVE,
618*dfc11533SChris Williamson         setobjs2s(L, ra, RB(i));
619*dfc11533SChris Williamson       )
620