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*dfc11533SChris Williamson       vmcase(OP_LOADK,
621*dfc11533SChris Williamson         TValue *rb = k + GETARG_Bx(i);
622*dfc11533SChris Williamson         setobj2s(L, ra, rb);
623*dfc11533SChris Williamson       )
624*dfc11533SChris Williamson       vmcase(OP_LOADKX,
625*dfc11533SChris Williamson         TValue *rb;
626*dfc11533SChris Williamson         lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG);
627*dfc11533SChris Williamson         rb = k + GETARG_Ax(*ci->u.l.savedpc++);
628*dfc11533SChris Williamson         setobj2s(L, ra, rb);
629*dfc11533SChris Williamson       )
630*dfc11533SChris Williamson       vmcase(OP_LOADBOOL,
631*dfc11533SChris Williamson         setbvalue(ra, GETARG_B(i));
632*dfc11533SChris Williamson         if (GETARG_C(i)) ci->u.l.savedpc++;  /* skip next instruction (if C) */
633*dfc11533SChris Williamson       )
634*dfc11533SChris Williamson       vmcase(OP_LOADNIL,
635*dfc11533SChris Williamson         int b = GETARG_B(i);
636*dfc11533SChris Williamson         do {
637*dfc11533SChris Williamson           setnilvalue(ra++);
638*dfc11533SChris Williamson         } while (b--);
639*dfc11533SChris Williamson       )
640*dfc11533SChris Williamson       vmcase(OP_GETUPVAL,
641*dfc11533SChris Williamson         int b = GETARG_B(i);
642*dfc11533SChris Williamson         setobj2s(L, ra, cl->upvals[b]->v);
643*dfc11533SChris Williamson       )
644*dfc11533SChris Williamson       vmcase(OP_GETTABUP,
645*dfc11533SChris Williamson         int b = GETARG_B(i);
646*dfc11533SChris Williamson         Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra));
647*dfc11533SChris Williamson       )
648*dfc11533SChris Williamson       vmcase(OP_GETTABLE,
649*dfc11533SChris Williamson         Protect(luaV_gettable(L, RB(i), RKC(i), ra));
650*dfc11533SChris Williamson       )
651*dfc11533SChris Williamson       vmcase(OP_SETTABUP,
652*dfc11533SChris Williamson         int a = GETARG_A(i);
653*dfc11533SChris Williamson         Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i)));
654*dfc11533SChris Williamson       )
655*dfc11533SChris Williamson       vmcase(OP_SETUPVAL,
656*dfc11533SChris Williamson         UpVal *uv = cl->upvals[GETARG_B(i)];
657*dfc11533SChris Williamson         setobj(L, uv->v, ra);
658*dfc11533SChris Williamson         luaC_barrier(L, uv, ra);
659*dfc11533SChris Williamson       )
660*dfc11533SChris Williamson       vmcase(OP_SETTABLE,
661*dfc11533SChris Williamson         Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
662*dfc11533SChris Williamson       )
663*dfc11533SChris Williamson       vmcase(OP_NEWTABLE,
664*dfc11533SChris Williamson         int b = GETARG_B(i);
665*dfc11533SChris Williamson         int c = GETARG_C(i);
666*dfc11533SChris Williamson         Table *t = luaH_new(L);
667*dfc11533SChris Williamson         sethvalue(L, ra, t);
668*dfc11533SChris Williamson         if (b != 0 || c != 0)
669*dfc11533SChris Williamson           luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c));
670*dfc11533SChris Williamson         checkGC(L, ra + 1);
671*dfc11533SChris Williamson       )
672*dfc11533SChris Williamson       vmcase(OP_SELF,
673*dfc11533SChris Williamson         StkId rb = RB(i);
674*dfc11533SChris Williamson         setobjs2s(L, ra+1, rb);
675*dfc11533SChris Williamson         Protect(luaV_gettable(L, rb, RKC(i), ra));
676*dfc11533SChris Williamson       )
677*dfc11533SChris Williamson       vmcase(OP_ADD,
678*dfc11533SChris Williamson         arith_op(luai_numadd, TM_ADD);
679*dfc11533SChris Williamson       )
680*dfc11533SChris Williamson       vmcase(OP_SUB,
681*dfc11533SChris Williamson         arith_op(luai_numsub, TM_SUB);
682*dfc11533SChris Williamson       )
683*dfc11533SChris Williamson       vmcase(OP_MUL,
684*dfc11533SChris Williamson         arith_op(luai_nummul, TM_MUL);
685*dfc11533SChris Williamson       )
686*dfc11533SChris Williamson       /*
687*dfc11533SChris Williamson        * Patched: use luaV_* instead of luai_* to handle div/mod by 0
688*dfc11533SChris Williamson        */
689*dfc11533SChris Williamson       vmcase(OP_DIV,
690*dfc11533SChris Williamson         arith_op(luaV_div, TM_DIV);
691*dfc11533SChris Williamson       )
692*dfc11533SChris Williamson       vmcase(OP_MOD,
693*dfc11533SChris Williamson         arith_op(luaV_mod, TM_MOD);
694*dfc11533SChris Williamson       )
695*dfc11533SChris Williamson       vmcase(OP_POW,
696*dfc11533SChris Williamson         arith_op(luai_numpow, TM_POW);
697*dfc11533SChris Williamson       )
698*dfc11533SChris Williamson       vmcase(OP_UNM,
699*dfc11533SChris Williamson         TValue *rb = RB(i);
700*dfc11533SChris Williamson         if (ttisnumber(rb)) {
701*dfc11533SChris Williamson           lua_Number nb = nvalue(rb);
702*dfc11533SChris Williamson           setnvalue(ra, luai_numunm(L, nb));
703*dfc11533SChris Williamson         }
704*dfc11533SChris Williamson         else {
705*dfc11533SChris Williamson           Protect(luaV_arith(L, ra, rb, rb, TM_UNM));
706*dfc11533SChris Williamson         }
707*dfc11533SChris Williamson       )
708*dfc11533SChris Williamson       vmcase(OP_NOT,
709*dfc11533SChris Williamson         TValue *rb = RB(i);
710*dfc11533SChris Williamson         int res = l_isfalse(rb);  /* next assignment may change this value */
711*dfc11533SChris Williamson         setbvalue(ra, res);
712*dfc11533SChris Williamson       )
713*dfc11533SChris Williamson       vmcase(OP_LEN,
714*dfc11533SChris Williamson         Protect(luaV_objlen(L, ra, RB(i)));
715*dfc11533SChris Williamson       )
716*dfc11533SChris Williamson       vmcase(OP_CONCAT,
717*dfc11533SChris Williamson         int b = GETARG_B(i);
718*dfc11533SChris Williamson         int c = GETARG_C(i);
719*dfc11533SChris Williamson         StkId rb;
720*dfc11533SChris Williamson         L->top = base + c + 1;  /* mark the end of concat operands */
721*dfc11533SChris Williamson         Protect(luaV_concat(L, c - b + 1));
722*dfc11533SChris Williamson         ra = RA(i);  /* 'luav_concat' may invoke TMs and move the stack */
723*dfc11533SChris Williamson         rb = b + base;
724*dfc11533SChris Williamson         setobjs2s(L, ra, rb);
725*dfc11533SChris Williamson         checkGC(L, (ra >= rb ? ra + 1 : rb));
726*dfc11533SChris Williamson         L->top = ci->top;  /* restore top */
727*dfc11533SChris Williamson       )
728*dfc11533SChris Williamson       vmcase(OP_JMP,
729*dfc11533SChris Williamson         dojump(ci, i, 0);
730*dfc11533SChris Williamson       )
731*dfc11533SChris Williamson       vmcase(OP_EQ,
732*dfc11533SChris Williamson         TValue *rb = RKB(i);
733*dfc11533SChris Williamson         TValue *rc = RKC(i);
734*dfc11533SChris Williamson         Protect(
735*dfc11533SChris Williamson           if (cast_int(equalobj(L, rb, rc)) != GETARG_A(i))
736*dfc11533SChris Williamson             ci->u.l.savedpc++;
737*dfc11533SChris Williamson           else
738*dfc11533SChris Williamson             donextjump(ci);
739*dfc11533SChris Williamson         )
740*dfc11533SChris Williamson       )
741*dfc11533SChris Williamson       vmcase(OP_LT,
742*dfc11533SChris Williamson         Protect(
743*dfc11533SChris Williamson           if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i))
744*dfc11533SChris Williamson             ci->u.l.savedpc++;
745*dfc11533SChris Williamson           else
746*dfc11533SChris Williamson             donextjump(ci);
747*dfc11533SChris Williamson         )
748*dfc11533SChris Williamson       )
749*dfc11533SChris Williamson       vmcase(OP_LE,
750*dfc11533SChris Williamson         Protect(
751*dfc11533SChris Williamson           if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i))
752*dfc11533SChris Williamson             ci->u.l.savedpc++;
753*dfc11533SChris Williamson           else
754*dfc11533SChris Williamson             donextjump(ci);
755*dfc11533SChris Williamson         )
756*dfc11533SChris Williamson       )
757*dfc11533SChris Williamson       vmcase(OP_TEST,
758*dfc11533SChris Williamson         if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra))
759*dfc11533SChris Williamson             ci->u.l.savedpc++;
760*dfc11533SChris Williamson           else
761*dfc11533SChris Williamson           donextjump(ci);
762*dfc11533SChris Williamson       )
763*dfc11533SChris Williamson       vmcase(OP_TESTSET,
764*dfc11533SChris Williamson         TValue *rb = RB(i);
765*dfc11533SChris Williamson         if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb))
766*dfc11533SChris Williamson           ci->u.l.savedpc++;
767*dfc11533SChris Williamson         else {
768*dfc11533SChris Williamson           setobjs2s(L, ra, rb);
769*dfc11533SChris Williamson           donextjump(ci);
770*dfc11533SChris Williamson         }
771*dfc11533SChris Williamson       )
772*dfc11533SChris Williamson       vmcase(OP_CALL,
773*dfc11533SChris Williamson         int b = GETARG_B(i);
774*dfc11533SChris Williamson         int nresults = GETARG_C(i) - 1;
775*dfc11533SChris Williamson         if (b != 0) L->top = ra+b;  /* else previous instruction set top */
776*dfc11533SChris Williamson         if (luaD_precall(L, ra, nresults)) {  /* C function? */
777*dfc11533SChris Williamson           if (nresults >= 0) L->top = ci->top;  /* adjust results */
778*dfc11533SChris Williamson           base = ci->u.l.base;
779*dfc11533SChris Williamson         }
780*dfc11533SChris Williamson         else {  /* Lua function */
781*dfc11533SChris Williamson           ci = L->ci;
782*dfc11533SChris Williamson           ci->callstatus |= CIST_REENTRY;
783*dfc11533SChris Williamson           goto newframe;  /* restart luaV_execute over new Lua function */
784*dfc11533SChris Williamson         }
785*dfc11533SChris Williamson       )
786*dfc11533SChris Williamson       vmcase(OP_TAILCALL,
787*dfc11533SChris Williamson         int b = GETARG_B(i);
788*dfc11533SChris Williamson         if (b != 0) L->top = ra+b;  /* else previous instruction set top */
789*dfc11533SChris Williamson         lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
790*dfc11533SChris Williamson         if (luaD_precall(L, ra, LUA_MULTRET))  /* C function? */
791*dfc11533SChris Williamson           base = ci->u.l.base;
792*dfc11533SChris Williamson         else {
793*dfc11533SChris Williamson           /* tail call: put called frame (n) in place of caller one (o) */
794*dfc11533SChris Williamson           CallInfo *nci = L->ci;  /* called frame */
795*dfc11533SChris Williamson           CallInfo *oci = nci->previous;  /* caller frame */
796*dfc11533SChris Williamson           StkId nfunc = nci->func;  /* called function */
797*dfc11533SChris Williamson           StkId ofunc = oci->func;  /* caller function */
798*dfc11533SChris Williamson           /* last stack slot filled by 'precall' */
799*dfc11533SChris Williamson           StkId lim = nci->u.l.base + getproto(nfunc)->numparams;
800*dfc11533SChris Williamson           int aux;
801*dfc11533SChris Williamson           /* close all upvalues from previous call */
802*dfc11533SChris Williamson           if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base);
803*dfc11533SChris Williamson           /* move new frame into old one */
804*dfc11533SChris Williamson           for (aux = 0; nfunc + aux < lim; aux++)
805*dfc11533SChris Williamson             setobjs2s(L, ofunc + aux, nfunc + aux);
806*dfc11533SChris Williamson           oci->u.l.base = ofunc + (nci->u.l.base - nfunc);  /* correct base */
807*dfc11533SChris Williamson           oci->top = L->top = ofunc + (L->top - nfunc);  /* correct top */
808*dfc11533SChris Williamson           oci->u.l.savedpc = nci->u.l.savedpc;
809*dfc11533SChris Williamson           oci->callstatus |= CIST_TAIL;  /* function was tail called */
810*dfc11533SChris Williamson           ci = L->ci = oci;  /* remove new frame */
811*dfc11533SChris Williamson           lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize);
812*dfc11533SChris Williamson           goto newframe;  /* restart luaV_execute over new Lua function */
813*dfc11533SChris Williamson         }
814*dfc11533SChris Williamson       )
815*dfc11533SChris Williamson       vmcasenb(OP_RETURN,
816*dfc11533SChris Williamson         int b = GETARG_B(i);
817*dfc11533SChris Williamson         if (b != 0) L->top = ra+b-1;
818*dfc11533SChris Williamson         if (cl->p->sizep > 0) luaF_close(L, base);
819*dfc11533SChris Williamson         b = luaD_poscall(L, ra);
820*dfc11533SChris Williamson         if (!(ci->callstatus & CIST_REENTRY))  /* 'ci' still the called one */
821*dfc11533SChris Williamson           return;  /* external invocation: return */
822*dfc11533SChris Williamson         else {  /* invocation via reentry: continue execution */
823*dfc11533SChris Williamson           ci = L->ci;
824*dfc11533SChris Williamson           if (b) L->top = ci->top;
825*dfc11533SChris Williamson           lua_assert(isLua(ci));
826*dfc11533SChris Williamson           lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL);
827*dfc11533SChris Williamson           goto newframe;  /* restart luaV_execute over new Lua function */
828*dfc11533SChris Williamson         }
829*dfc11533SChris Williamson       )
830*dfc11533SChris Williamson       vmcase(OP_FORLOOP,
831*dfc11533SChris Williamson         lua_Number step = nvalue(ra+2);
832*dfc11533SChris Williamson         lua_Number idx = luai_numadd(L, nvalue(ra), step); /* increment index */
833*dfc11533SChris Williamson         lua_Number limit = nvalue(ra+1);
834*dfc11533SChris Williamson         if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit)
835*dfc11533SChris Williamson                                    : luai_numle(L, limit, idx)) {
836*dfc11533SChris Williamson           ci->u.l.savedpc += GETARG_sBx(i);  /* jump back */
837*dfc11533SChris Williamson           setnvalue(ra, idx);  /* update internal index... */
838*dfc11533SChris Williamson           setnvalue(ra+3, idx);  /* ...and external index */
839*dfc11533SChris Williamson         }
840*dfc11533SChris Williamson       )
841*dfc11533SChris Williamson       vmcase(OP_FORPREP,
842*dfc11533SChris Williamson         const TValue *init = ra;
843*dfc11533SChris Williamson         const TValue *plimit = ra+1;
844*dfc11533SChris Williamson         const TValue *pstep = ra+2;
845*dfc11533SChris Williamson         if (!tonumber(init, ra))
846*dfc11533SChris Williamson           luaG_runerror(L, LUA_QL("for") " initial value must be a number");
847*dfc11533SChris Williamson         else if (!tonumber(plimit, ra+1))
848*dfc11533SChris Williamson           luaG_runerror(L, LUA_QL("for") " limit must be a number");
849*dfc11533SChris Williamson         else if (!tonumber(pstep, ra+2))
850*dfc11533SChris Williamson           luaG_runerror(L, LUA_QL("for") " step must be a number");
851*dfc11533SChris Williamson         setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep)));
852*dfc11533SChris Williamson         ci->u.l.savedpc += GETARG_sBx(i);
853*dfc11533SChris Williamson       )
854*dfc11533SChris Williamson       vmcasenb(OP_TFORCALL,
855*dfc11533SChris Williamson         StkId cb = ra + 3;  /* call base */
856*dfc11533SChris Williamson         setobjs2s(L, cb+2, ra+2);
857*dfc11533SChris Williamson         setobjs2s(L, cb+1, ra+1);
858*dfc11533SChris Williamson         setobjs2s(L, cb, ra);
859*dfc11533SChris Williamson         L->top = cb + 3;  /* func. + 2 args (state and index) */
860*dfc11533SChris Williamson         Protect(luaD_call(L, cb, GETARG_C(i), 1));
861*dfc11533SChris Williamson         L->top = ci->top;
862*dfc11533SChris Williamson         i = *(ci->u.l.savedpc++);  /* go to next instruction */
863*dfc11533SChris Williamson         ra = RA(i);
864*dfc11533SChris Williamson         lua_assert(GET_OPCODE(i) == OP_TFORLOOP);
865*dfc11533SChris Williamson         goto l_tforloop;
866*dfc11533SChris Williamson       )
867*dfc11533SChris Williamson       vmcase(OP_TFORLOOP,
868*dfc11533SChris Williamson         l_tforloop:
869*dfc11533SChris Williamson         if (!ttisnil(ra + 1)) {  /* continue loop? */
870*dfc11533SChris Williamson           setobjs2s(L, ra, ra + 1);  /* save control variable */
871*dfc11533SChris Williamson            ci->u.l.savedpc += GETARG_sBx(i);  /* jump back */
872*dfc11533SChris Williamson         }
873*dfc11533SChris Williamson       )
874*dfc11533SChris Williamson       vmcase(OP_SETLIST,
875*dfc11533SChris Williamson         int n = GETARG_B(i);
876*dfc11533SChris Williamson         int c = GETARG_C(i);
877*dfc11533SChris Williamson         int last;
878*dfc11533SChris Williamson         Table *h;
879*dfc11533SChris Williamson         if (n == 0) n = cast_int(L->top - ra) - 1;
880*dfc11533SChris Williamson         if (c == 0) {
881*dfc11533SChris Williamson           lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG);
882*dfc11533SChris Williamson           c = GETARG_Ax(*ci->u.l.savedpc++);
883*dfc11533SChris Williamson         }
884*dfc11533SChris Williamson         luai_runtimecheck(L, ttistable(ra));
885*dfc11533SChris Williamson         h = hvalue(ra);
886*dfc11533SChris Williamson         last = ((c-1)*LFIELDS_PER_FLUSH) + n;
887*dfc11533SChris Williamson         if (last > h->sizearray)  /* needs more space? */
888*dfc11533SChris Williamson           luaH_resizearray(L, h, last);  /* pre-allocate it at once */
889*dfc11533SChris Williamson         for (; n > 0; n--) {
890*dfc11533SChris Williamson           TValue *val = ra+n;
891*dfc11533SChris Williamson           luaH_setint(L, h, last--, val);
892*dfc11533SChris Williamson           luaC_barrierback(L, obj2gco(h), val);
893*dfc11533SChris Williamson         }
894*dfc11533SChris Williamson         L->top = ci->top;  /* correct top (in case of previous open call) */
895*dfc11533SChris Williamson       )
896*dfc11533SChris Williamson       vmcase(OP_CLOSURE,
897*dfc11533SChris Williamson         Proto *p = cl->p->p[GETARG_Bx(i)];
898*dfc11533SChris Williamson         Closure *ncl = getcached(p, cl->upvals, base);  /* cached closure */
899*dfc11533SChris Williamson         if (ncl == NULL)  /* no match? */
900*dfc11533SChris Williamson           pushclosure(L, p, cl->upvals, base, ra);  /* create a new one */
901*dfc11533SChris Williamson         else
902*dfc11533SChris Williamson           setclLvalue(L, ra, ncl);  /* push cashed closure */
903*dfc11533SChris Williamson         checkGC(L, ra + 1);
904*dfc11533SChris Williamson       )
905*dfc11533SChris Williamson       vmcase(OP_VARARG,
906*dfc11533SChris Williamson         int b = GETARG_B(i) - 1;
907*dfc11533SChris Williamson         int j;
908*dfc11533SChris Williamson         int n = cast_int(base - ci->func) - cl->p->numparams - 1;
909*dfc11533SChris Williamson         if (b < 0) {  /* B == 0? */
910*dfc11533SChris Williamson           b = n;  /* get all var. arguments */
911*dfc11533SChris Williamson           Protect(luaD_checkstack(L, n));
912*dfc11533SChris Williamson           ra = RA(i);  /* previous call may change the stack */
913*dfc11533SChris Williamson           L->top = ra + n;
914*dfc11533SChris Williamson         }
915*dfc11533SChris Williamson         for (j = 0; j < b; j++) {
916*dfc11533SChris Williamson           if (j < n) {
917*dfc11533SChris Williamson             setobjs2s(L, ra + j, base - n + j);
918*dfc11533SChris Williamson           }
919*dfc11533SChris Williamson           else {
920*dfc11533SChris Williamson             setnilvalue(ra + j);
921*dfc11533SChris Williamson           }
922*dfc11533SChris Williamson         }
923*dfc11533SChris Williamson       )
924*dfc11533SChris Williamson       vmcase(OP_EXTRAARG,
925*dfc11533SChris Williamson         lua_assert(0);
926*dfc11533SChris Williamson       )
927*dfc11533SChris Williamson     }
928*dfc11533SChris Williamson   }
929*dfc11533SChris Williamson }
930*dfc11533SChris Williamson 
931