Path: blob/main/sys/contrib/openzfs/module/lua/lvm.c
48383 views
// SPDX-License-Identifier: MIT1/*2** $Id: lvm.c,v 2.155.1.1 2013/04/12 18:48:47 roberto Exp $3** Lua virtual machine4** See Copyright Notice in lua.h5*/678#define lvm_c9#define LUA_CORE1011#include <sys/lua/lua.h>1213#include "ldebug.h"14#include "ldo.h"15#include "lfunc.h"16#include "lgc.h"17#include "lobject.h"18#include "lopcodes.h"19#include "lstate.h"20#include "lstring.h"21#include "ltable.h"22#include "ltm.h"23#include "lvm.h"2425#ifdef _KERNEL26#define strcoll(l,r) (strcmp((l),(r)))27#endif2829/* limit for table tag-method chains (to avoid loops) */30#define MAXTAGLOOP 100313233const TValue *luaV_tonumber (const TValue *obj, TValue *n) {34lua_Number num;35if (ttisnumber(obj)) return obj;36if (ttisstring(obj) && luaO_str2d(svalue(obj), tsvalue(obj)->len, &num)) {37setnvalue(n, num);38return n;39}40else41return NULL;42}434445int luaV_tostring (lua_State *L, StkId obj) {46if (!ttisnumber(obj))47return 0;48else {49char s[LUAI_MAXNUMBER2STR];50lua_Number n = nvalue(obj);51int l = lua_number2str(s, n);52setsvalue2s(L, obj, luaS_newlstr(L, s, l));53return 1;54}55}565758static void traceexec (lua_State *L) {59CallInfo *ci = L->ci;60lu_byte mask = L->hookmask;61int counthook = ((mask & LUA_MASKCOUNT) && L->hookcount == 0);62if (counthook)63resethookcount(L); /* reset count */64if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */65ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */66return; /* do not call hook again (VM yielded, so it did not move) */67}68if (counthook)69luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */70if (mask & LUA_MASKLINE) {71Proto *p = ci_func(ci)->p;72int npc = pcRel(ci->u.l.savedpc, p);73int newline = getfuncline(p, npc);74if (npc == 0 || /* call linehook when enter a new function, */75ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */76newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */77luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */78}79L->oldpc = ci->u.l.savedpc;80if (L->status == LUA_YIELD) { /* did hook yield? */81if (counthook)82L->hookcount = 1; /* undo decrement to zero */83ci->u.l.savedpc--; /* undo increment (resume will increment it again) */84ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */85ci->func = L->top - 1; /* protect stack below results */86luaD_throw(L, LUA_YIELD);87}88}899091static void callTM (lua_State *L, const TValue *f, const TValue *p1,92const TValue *p2, TValue *p3, int hasres) {93if (L == NULL) return;9495ptrdiff_t result = savestack(L, p3);96setobj2s(L, L->top++, f); /* push function */97setobj2s(L, L->top++, p1); /* 1st argument */98setobj2s(L, L->top++, p2); /* 2nd argument */99if (!hasres) /* no result? 'p3' is third argument */100setobj2s(L, L->top++, p3); /* 3rd argument */101/* metamethod may yield only when called from Lua code */102luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci));103if (hasres) { /* if has result, move it to its place */104p3 = restorestack(L, result);105setobjs2s(L, p3, --L->top);106}107}108109110void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {111int loop;112for (loop = 0; loop < MAXTAGLOOP; loop++) {113const TValue *tm;114if (ttistable(t)) { /* `t' is a table? */115Table *h = hvalue(t);116const TValue *res = luaH_get(h, key); /* do a primitive get */117if (!ttisnil(res) || /* result is not nil? */118(tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */119setobj2s(L, val, res);120return;121}122/* else will try the tag method */123}124else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))125luaG_typeerror(L, t, "index");126if (ttisfunction(tm)) {127callTM(L, tm, t, key, val, 1);128return;129}130t = tm; /* else repeat with 'tm' */131}132luaG_runerror(L, "loop in gettable");133}134135136void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {137int loop;138for (loop = 0; loop < MAXTAGLOOP; loop++) {139const TValue *tm;140if (ttistable(t)) { /* `t' is a table? */141Table *h = hvalue(t);142TValue *oldval = cast(TValue *, luaH_get(h, key));143/* if previous value is not nil, there must be a previous entry144in the table; moreover, a metamethod has no relevance */145if (!ttisnil(oldval) ||146/* previous value is nil; must check the metamethod */147((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL &&148/* no metamethod; is there a previous entry in the table? */149(oldval != luaO_nilobject ||150/* no previous entry; must create one. (The next test is151always true; we only need the assignment.) */152(oldval = luaH_newkey(L, h, key), 1)))) {153/* no metamethod and (now) there is an entry with given key */154setobj2t(L, oldval, val); /* assign new value to that entry */155invalidateTMcache(h);156luaC_barrierback(L, obj2gco(h), val);157return;158}159/* else will try the metamethod */160}161else /* not a table; check metamethod */162if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))163luaG_typeerror(L, t, "index");164/* there is a metamethod */165if (ttisfunction(tm)) {166callTM(L, tm, t, key, val, 0);167return;168}169t = tm; /* else repeat with 'tm' */170}171luaG_runerror(L, "loop in settable");172}173174175static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2,176StkId res, TMS event) {177const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */178if (ttisnil(tm))179tm = luaT_gettmbyobj(L, p2, event); /* try second operand */180if (ttisnil(tm)) return 0;181callTM(L, tm, p1, p2, res, 1);182return 1;183}184185186static const TValue *get_equalTM (lua_State *L, Table *mt1, Table *mt2,187TMS event) {188const TValue *tm1 = fasttm(L, mt1, event);189const TValue *tm2;190if (tm1 == NULL) return NULL; /* no metamethod */191if (mt1 == mt2) return tm1; /* same metatables => same metamethods */192tm2 = fasttm(L, mt2, event);193if (tm2 == NULL) return NULL; /* no metamethod */194if (luaV_rawequalobj(tm1, tm2)) /* same metamethods? */195return tm1;196return NULL;197}198199200static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2,201TMS event) {202if (!call_binTM(L, p1, p2, L->top, event))203return -1; /* no metamethod */204else205return !l_isfalse(L->top);206}207208209static int l_strcmp (const TString *ls, const TString *rs) {210const char *l = getstr(ls);211size_t ll = ls->tsv.len;212const char *r = getstr(rs);213size_t lr = rs->tsv.len;214for (;;) {215int temp = strcoll(l, r);216if (temp != 0) return temp;217else { /* strings are equal up to a `\0' */218size_t len = strlen(l); /* index of first `\0' in both strings */219if (len == lr) /* r is finished? */220return (len == ll) ? 0 : 1;221else if (len == ll) /* l is finished? */222return -1; /* l is smaller than r (because r is not finished) */223/* both strings longer than `len'; go on comparing (after the `\0') */224len++;225l += len; ll -= len; r += len; lr -= len;226}227}228}229230231int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {232int res;233if (ttisnumber(l) && ttisnumber(r))234return luai_numlt(L, nvalue(l), nvalue(r));235else if (ttisstring(l) && ttisstring(r))236return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;237else if ((res = call_orderTM(L, l, r, TM_LT)) < 0)238luaG_ordererror(L, l, r);239return res;240}241242243int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {244int res;245if (ttisnumber(l) && ttisnumber(r))246return luai_numle(L, nvalue(l), nvalue(r));247else if (ttisstring(l) && ttisstring(r))248return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;249else if ((res = call_orderTM(L, l, r, TM_LE)) >= 0) /* first try `le' */250return res;251else if ((res = call_orderTM(L, r, l, TM_LT)) < 0) /* else try `lt' */252luaG_ordererror(L, l, r);253return !res;254}255256257/*258** equality of Lua values. L == NULL means raw equality (no metamethods)259*/260int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2) {261const TValue *tm;262lua_assert(ttisequal(t1, t2));263switch (ttype(t1)) {264case LUA_TNIL: return 1;265case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));266case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */267case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);268case LUA_TLCF: return fvalue(t1) == fvalue(t2);269case LUA_TSHRSTR: return eqshrstr(rawtsvalue(t1), rawtsvalue(t2));270case LUA_TLNGSTR: return luaS_eqlngstr(rawtsvalue(t1), rawtsvalue(t2));271case LUA_TUSERDATA: {272if (uvalue(t1) == uvalue(t2)) return 1;273else if (L == NULL) return 0;274tm = get_equalTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, TM_EQ);275break; /* will try TM */276}277case LUA_TTABLE: {278if (hvalue(t1) == hvalue(t2)) return 1;279else if (L == NULL) return 0;280tm = get_equalTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);281break; /* will try TM */282}283default:284lua_assert(iscollectable(t1));285return gcvalue(t1) == gcvalue(t2);286}287if (tm == NULL || L == NULL) return 0; /* no TM? */288callTM(L, tm, t1, t2, L->top, 1); /* call TM */289return !l_isfalse(L->top);290}291292293void luaV_concat (lua_State *L, int total) {294lua_assert(total >= 2);295do {296StkId top = L->top;297int n = 2; /* number of elements handled in this pass (at least 2) */298if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {299if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))300luaG_concaterror(L, top-2, top-1);301}302else if (tsvalue(top-1)->len == 0) /* second operand is empty? */303(void)tostring(L, top - 2); /* result is first operand */304else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) {305setobjs2s(L, top - 2, top - 1); /* result is second op. */306}307else {308/* at least two non-empty string values; get as many as possible */309size_t tl = tsvalue(top-1)->len;310char *buffer;311int i;312/* collect total length */313for (i = 1; i < total && tostring(L, top-i-1); i++) {314size_t l = tsvalue(top-i-1)->len;315if (l >= (MAX_SIZET/sizeof(char)) - tl)316luaG_runerror(L, "string length overflow");317tl += l;318}319buffer = luaZ_openspace(L, &G(L)->buff, tl);320tl = 0;321n = i;322do { /* concat all strings */323size_t l = tsvalue(top-i)->len;324memcpy(buffer+tl, svalue(top-i), l * sizeof(char));325tl += l;326} while (--i > 0);327setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));328}329total -= n-1; /* got 'n' strings to create 1 new */330L->top -= n-1; /* popped 'n' strings and pushed one */331} while (total > 1); /* repeat until only 1 result left */332}333334335void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {336const TValue *tm;337switch (ttypenv(rb)) {338case LUA_TTABLE: {339Table *h = hvalue(rb);340tm = fasttm(L, h->metatable, TM_LEN);341if (tm) break; /* metamethod? break switch to call it */342setnvalue(ra, cast_num(luaH_getn(h))); /* else primitive len */343return;344}345case LUA_TSTRING: {346setnvalue(ra, cast_num(tsvalue(rb)->len));347return;348}349default: { /* try metamethod */350tm = luaT_gettmbyobj(L, rb, TM_LEN);351if (ttisnil(tm)) /* no metamethod? */352luaG_typeerror(L, rb, "get length of");353break;354}355}356callTM(L, tm, rb, rb, ra, 1);357}358359/*360* luaV_div and luaV_mod patched in from Lua 5.3.2 in order to properly handle361* div/mod by zero (instead of crashing, which is the default behavior in362* Lua 5.2)363*/364365/*366** Integer division; return 'm // n', that is, floor(m/n).367** C division truncates its result (rounds towards zero).368** 'floor(q) == trunc(q)' when 'q >= 0' or when 'q' is integer,369** otherwise 'floor(q) == trunc(q) - 1'.370*/371static lua_Number luaV_div (lua_State *L, lua_Number m, lua_Number n) {372if ((lua_Unsigned)(n) + 1u <= 1u) { /* special cases: -1 or 0 */373if (n == 0)374luaG_runerror(L, "attempt to divide by zero");375return (0 - m); /* n==-1; avoid overflow with 0x80000...//-1 */376}377else {378lua_Number q = m / n; /* perform C division */379if ((m ^ n) < 0 && m % n != 0) /* 'm/n' would be negative non-integer? */380q -= 1; /* correct result for different rounding */381return q;382}383}384385386/*387** Integer modulus; return 'm % n'. (Assume that C '%' with388** negative operands follows C99 behavior. See previous comment389** about luaV_div.)390*/391static lua_Number luaV_mod (lua_State *L, lua_Number m, lua_Number n) {392if ((lua_Unsigned)(n) + 1u <= 1u) { /* special cases: -1 or 0 */393if (n == 0)394luaG_runerror(L, "attempt to perform 'n%%0'");395return 0; /* m % -1 == 0; avoid overflow with 0x80000...%-1 */396}397else {398lua_Number r = m % n;399if (r != 0 && (m ^ n) < 0) /* 'm/n' would be non-integer negative? */400r += n; /* correct result for different rounding */401return r;402}403}404405/*406* End patch from 5.3.2407*/408409void luaV_arith (lua_State *L, StkId ra, const TValue *rb,410const TValue *rc, TMS op) {411TValue tempb, tempc;412const TValue *b, *c;413if ((b = luaV_tonumber(rb, &tempb)) != NULL &&414(c = luaV_tonumber(rc, &tempc)) != NULL) {415/*416* Patched: if dividing or modding, use patched functions from 5.3417*/418lua_Number res;419int lop = op - TM_ADD + LUA_OPADD;420if (lop == LUA_OPDIV) {421res = luaV_div(L, nvalue(b), nvalue(c));422} else if (lop == LUA_OPMOD) {423res = luaV_mod(L, nvalue(b), nvalue(c));424} else {425res = luaO_arith(op - TM_ADD + LUA_OPADD, nvalue(b), nvalue(c));426}427setnvalue(ra, res);428}429else if (!call_binTM(L, rb, rc, ra, op))430luaG_aritherror(L, rb, rc);431}432433434/*435** check whether cached closure in prototype 'p' may be reused, that is,436** whether there is a cached closure with the same upvalues needed by437** new closure to be created.438*/439static Closure *getcached (Proto *p, UpVal **encup, StkId base) {440Closure *c = p->cache;441if (c != NULL) { /* is there a cached closure? */442int nup = p->sizeupvalues;443Upvaldesc *uv = p->upvalues;444int i;445for (i = 0; i < nup; i++) { /* check whether it has right upvalues */446TValue *v = uv[i].instack ? base + uv[i].idx : encup[uv[i].idx]->v;447if (c->l.upvals[i]->v != v)448return NULL; /* wrong upvalue; cannot reuse closure */449}450}451return c; /* return cached closure (or NULL if no cached closure) */452}453454455/*456** create a new Lua closure, push it in the stack, and initialize457** its upvalues. Note that the call to 'luaC_barrierproto' must come458** before the assignment to 'p->cache', as the function needs the459** original value of that field.460*/461static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base,462StkId ra) {463int nup = p->sizeupvalues;464Upvaldesc *uv = p->upvalues;465int i;466Closure *ncl = luaF_newLclosure(L, nup);467ncl->l.p = p;468setclLvalue(L, ra, ncl); /* anchor new closure in stack */469for (i = 0; i < nup; i++) { /* fill in its upvalues */470if (uv[i].instack) /* upvalue refers to local variable? */471ncl->l.upvals[i] = luaF_findupval(L, base + uv[i].idx);472else /* get upvalue from enclosing function */473ncl->l.upvals[i] = encup[uv[i].idx];474}475luaC_barrierproto(L, p, ncl);476p->cache = ncl; /* save it on cache for reuse */477}478479480/*481** finish execution of an opcode interrupted by an yield482*/483void luaV_finishOp (lua_State *L) {484CallInfo *ci = L->ci;485StkId base = ci->u.l.base;486Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */487OpCode op = GET_OPCODE(inst);488switch (op) { /* finish its execution */489case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV:490case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN:491case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: {492setobjs2s(L, base + GETARG_A(inst), --L->top);493break;494}495case OP_LE: case OP_LT: case OP_EQ: {496int res = !l_isfalse(L->top - 1);497L->top--;498/* metamethod should not be called when operand is K */499lua_assert(!ISK(GETARG_B(inst)));500if (op == OP_LE && /* "<=" using "<" instead? */501ttisnil(luaT_gettmbyobj(L, base + GETARG_B(inst), TM_LE)))502res = !res; /* invert result */503lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP);504if (res != GETARG_A(inst)) /* condition failed? */505ci->u.l.savedpc++; /* skip jump instruction */506break;507}508case OP_CONCAT: {509StkId top = L->top - 1; /* top when 'call_binTM' was called */510int b = GETARG_B(inst); /* first element to concatenate */511int total = cast_int(top - 1 - (base + b)); /* yet to concatenate */512setobj2s(L, top - 2, top); /* put TM result in proper position */513if (total > 1) { /* are there elements to concat? */514L->top = top - 1; /* top is one after last element (at top-2) */515luaV_concat(L, total); /* concat them (may yield again) */516}517/* move final result to final position */518setobj2s(L, ci->u.l.base + GETARG_A(inst), L->top - 1);519L->top = ci->top; /* restore top */520break;521}522case OP_TFORCALL: {523lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP);524L->top = ci->top; /* correct top */525break;526}527case OP_CALL: {528if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */529L->top = ci->top; /* adjust results */530break;531}532case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE:533break;534default: lua_assert(0);535}536}537538539540/*541** some macros for common tasks in `luaV_execute'542*/543544#if !defined luai_runtimecheck545#define luai_runtimecheck(L, c) /* void */546#endif547548549#define RA(i) (base+GETARG_A(i))550/* to be used after possible stack reallocation */551#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))552#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))553#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \554ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i))555#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \556ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i))557#define KBx(i) \558(k + (GETARG_Bx(i) != 0 ? GETARG_Bx(i) - 1 : GETARG_Ax(*ci->u.l.savedpc++)))559560561/* execute a jump instruction */562#define dojump(ci,i,e) \563{ int a = GETARG_A(i); \564if (a > 0) luaF_close(L, ci->u.l.base + a - 1); \565ci->u.l.savedpc += GETARG_sBx(i) + e; }566567/* for test instructions, execute the jump instruction that follows it */568#define donextjump(ci) { i = *ci->u.l.savedpc; dojump(ci, i, 1); }569570571#define Protect(x) { {x;} base = ci->u.l.base; }572573#define checkGC(L,c) \574Protect( luaC_condGC(L,{L->top = (c); /* limit of live values */ \575luaC_step(L); \576L->top = ci->top;}) /* restore top */ \577luai_threadyield(L); )578579580#define arith_op(op,tm) { \581TValue *rb = RKB(i); \582TValue *rc = RKC(i); \583if (ttisnumber(rb) && ttisnumber(rc)) { \584lua_Number nb = nvalue(rb), nc = nvalue(rc); \585setnvalue(ra, op(L, nb, nc)); \586} \587else { Protect(luaV_arith(L, ra, rb, rc, tm)); } }588589590#define vmdispatch(o) switch(o)591#define vmcase(l,b) case l: {b} break;592#define vmcasenb(l,b) case l: {b} /* nb = no break */593594void luaV_execute (lua_State *L) {595CallInfo *ci = L->ci;596LClosure *cl;597TValue *k;598StkId base;599newframe: /* reentry point when frame changes (call/return) */600lua_assert(ci == L->ci);601cl = clLvalue(ci->func);602k = cl->p->k;603base = ci->u.l.base;604/* main loop of interpreter */605for (;;) {606Instruction i = *(ci->u.l.savedpc++);607StkId ra;608if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&609(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {610Protect(traceexec(L));611}612/* WARNING: several calls may realloc the stack and invalidate `ra' */613ra = RA(i);614lua_assert(base == ci->u.l.base);615lua_assert(base <= L->top && L->top < L->stack + L->stacksize);616vmdispatch (GET_OPCODE(i)) {617vmcase(OP_MOVE,618setobjs2s(L, ra, RB(i));619)620vmcase(OP_LOADK,621TValue *rb = k + GETARG_Bx(i);622setobj2s(L, ra, rb);623)624vmcase(OP_LOADKX,625TValue *rb;626lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG);627rb = k + GETARG_Ax(*ci->u.l.savedpc++);628setobj2s(L, ra, rb);629)630vmcase(OP_LOADBOOL,631setbvalue(ra, GETARG_B(i));632if (GETARG_C(i)) ci->u.l.savedpc++; /* skip next instruction (if C) */633)634vmcase(OP_LOADNIL,635int b = GETARG_B(i);636do {637setnilvalue(ra++);638} while (b--);639)640vmcase(OP_GETUPVAL,641int b = GETARG_B(i);642setobj2s(L, ra, cl->upvals[b]->v);643)644vmcase(OP_GETTABUP,645int b = GETARG_B(i);646Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra));647)648vmcase(OP_GETTABLE,649Protect(luaV_gettable(L, RB(i), RKC(i), ra));650)651vmcase(OP_SETTABUP,652int a = GETARG_A(i);653Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i)));654)655vmcase(OP_SETUPVAL,656UpVal *uv = cl->upvals[GETARG_B(i)];657setobj(L, uv->v, ra);658luaC_barrier(L, uv, ra);659)660vmcase(OP_SETTABLE,661Protect(luaV_settable(L, ra, RKB(i), RKC(i)));662)663vmcase(OP_NEWTABLE,664int b = GETARG_B(i);665int c = GETARG_C(i);666Table *t = luaH_new(L);667sethvalue(L, ra, t);668if (b != 0 || c != 0)669luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c));670checkGC(L, ra + 1);671)672vmcase(OP_SELF,673StkId rb = RB(i);674setobjs2s(L, ra+1, rb);675Protect(luaV_gettable(L, rb, RKC(i), ra));676)677vmcase(OP_ADD,678arith_op(luai_numadd, TM_ADD);679)680vmcase(OP_SUB,681arith_op(luai_numsub, TM_SUB);682)683vmcase(OP_MUL,684arith_op(luai_nummul, TM_MUL);685)686/*687* Patched: use luaV_* instead of luai_* to handle div/mod by 0688*/689vmcase(OP_DIV,690arith_op(luaV_div, TM_DIV);691)692vmcase(OP_MOD,693arith_op(luaV_mod, TM_MOD);694)695vmcase(OP_POW,696arith_op(luai_numpow, TM_POW);697)698vmcase(OP_UNM,699TValue *rb = RB(i);700if (ttisnumber(rb)) {701lua_Number nb = nvalue(rb);702setnvalue(ra, luai_numunm(L, nb));703}704else {705Protect(luaV_arith(L, ra, rb, rb, TM_UNM));706}707)708vmcase(OP_NOT,709TValue *rb = RB(i);710int res = l_isfalse(rb); /* next assignment may change this value */711setbvalue(ra, res);712)713vmcase(OP_LEN,714Protect(luaV_objlen(L, ra, RB(i)));715)716vmcase(OP_CONCAT,717int b = GETARG_B(i);718int c = GETARG_C(i);719StkId rb;720L->top = base + c + 1; /* mark the end of concat operands */721Protect(luaV_concat(L, c - b + 1));722ra = RA(i); /* 'luav_concat' may invoke TMs and move the stack */723rb = b + base;724setobjs2s(L, ra, rb);725checkGC(L, (ra >= rb ? ra + 1 : rb));726L->top = ci->top; /* restore top */727)728vmcase(OP_JMP,729dojump(ci, i, 0);730)731vmcase(OP_EQ,732TValue *rb = RKB(i);733TValue *rc = RKC(i);734Protect(735if (cast_int(equalobj(L, rb, rc)) != GETARG_A(i))736ci->u.l.savedpc++;737else738donextjump(ci);739)740)741vmcase(OP_LT,742Protect(743if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i))744ci->u.l.savedpc++;745else746donextjump(ci);747)748)749vmcase(OP_LE,750Protect(751if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i))752ci->u.l.savedpc++;753else754donextjump(ci);755)756)757vmcase(OP_TEST,758if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra))759ci->u.l.savedpc++;760else761donextjump(ci);762)763vmcase(OP_TESTSET,764TValue *rb = RB(i);765if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb))766ci->u.l.savedpc++;767else {768setobjs2s(L, ra, rb);769donextjump(ci);770}771)772vmcase(OP_CALL,773int b = GETARG_B(i);774int nresults = GETARG_C(i) - 1;775if (b != 0) L->top = ra+b; /* else previous instruction set top */776if (luaD_precall(L, ra, nresults)) { /* C function? */777if (nresults >= 0) L->top = ci->top; /* adjust results */778base = ci->u.l.base;779}780else { /* Lua function */781ci = L->ci;782ci->callstatus |= CIST_REENTRY;783goto newframe; /* restart luaV_execute over new Lua function */784}785)786vmcase(OP_TAILCALL,787int b = GETARG_B(i);788if (b != 0) L->top = ra+b; /* else previous instruction set top */789lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);790if (luaD_precall(L, ra, LUA_MULTRET)) /* C function? */791base = ci->u.l.base;792else {793/* tail call: put called frame (n) in place of caller one (o) */794CallInfo *nci = L->ci; /* called frame */795CallInfo *oci = nci->previous; /* caller frame */796StkId nfunc = nci->func; /* called function */797StkId ofunc = oci->func; /* caller function */798/* last stack slot filled by 'precall' */799StkId lim = nci->u.l.base + getproto(nfunc)->numparams;800int aux;801/* close all upvalues from previous call */802if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base);803/* move new frame into old one */804for (aux = 0; nfunc + aux < lim; aux++)805setobjs2s(L, ofunc + aux, nfunc + aux);806oci->u.l.base = ofunc + (nci->u.l.base - nfunc); /* correct base */807oci->top = L->top = ofunc + (L->top - nfunc); /* correct top */808oci->u.l.savedpc = nci->u.l.savedpc;809oci->callstatus |= CIST_TAIL; /* function was tail called */810ci = L->ci = oci; /* remove new frame */811lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize);812goto newframe; /* restart luaV_execute over new Lua function */813}814)815vmcasenb(OP_RETURN,816int b = GETARG_B(i);817if (b != 0) L->top = ra+b-1;818if (cl->p->sizep > 0) luaF_close(L, base);819b = luaD_poscall(L, ra);820if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */821return; /* external invocation: return */822else { /* invocation via reentry: continue execution */823ci = L->ci;824if (b) L->top = ci->top;825lua_assert(isLua(ci));826lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL);827goto newframe; /* restart luaV_execute over new Lua function */828}829)830vmcase(OP_FORLOOP,831lua_Number step = nvalue(ra+2);832lua_Number idx = luai_numadd(L, nvalue(ra), step); /* increment index */833lua_Number limit = nvalue(ra+1);834if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit)835: luai_numle(L, limit, idx)) {836ci->u.l.savedpc += GETARG_sBx(i); /* jump back */837setnvalue(ra, idx); /* update internal index... */838setnvalue(ra+3, idx); /* ...and external index */839}840)841vmcase(OP_FORPREP,842const TValue *init = ra;843const TValue *plimit = ra+1;844const TValue *pstep = ra+2;845if (!tonumber(init, ra))846luaG_runerror(L, LUA_QL("for") " initial value must be a number");847else if (!tonumber(plimit, ra+1))848luaG_runerror(L, LUA_QL("for") " limit must be a number");849else if (!tonumber(pstep, ra+2))850luaG_runerror(L, LUA_QL("for") " step must be a number");851setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep)));852ci->u.l.savedpc += GETARG_sBx(i);853)854vmcasenb(OP_TFORCALL,855StkId cb = ra + 3; /* call base */856setobjs2s(L, cb+2, ra+2);857setobjs2s(L, cb+1, ra+1);858setobjs2s(L, cb, ra);859L->top = cb + 3; /* func. + 2 args (state and index) */860Protect(luaD_call(L, cb, GETARG_C(i), 1));861L->top = ci->top;862i = *(ci->u.l.savedpc++); /* go to next instruction */863ra = RA(i);864lua_assert(GET_OPCODE(i) == OP_TFORLOOP);865goto l_tforloop;866)867vmcase(OP_TFORLOOP,868l_tforloop:869if (!ttisnil(ra + 1)) { /* continue loop? */870setobjs2s(L, ra, ra + 1); /* save control variable */871ci->u.l.savedpc += GETARG_sBx(i); /* jump back */872}873)874vmcase(OP_SETLIST,875int n = GETARG_B(i);876int c = GETARG_C(i);877int last;878Table *h;879if (n == 0) n = cast_int(L->top - ra) - 1;880if (c == 0) {881lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG);882c = GETARG_Ax(*ci->u.l.savedpc++);883}884luai_runtimecheck(L, ttistable(ra));885h = hvalue(ra);886last = ((c-1)*LFIELDS_PER_FLUSH) + n;887if (last > h->sizearray) /* needs more space? */888luaH_resizearray(L, h, last); /* pre-allocate it at once */889for (; n > 0; n--) {890TValue *val = ra+n;891luaH_setint(L, h, last--, val);892luaC_barrierback(L, obj2gco(h), val);893}894L->top = ci->top; /* correct top (in case of previous open call) */895)896vmcase(OP_CLOSURE,897Proto *p = cl->p->p[GETARG_Bx(i)];898Closure *ncl = getcached(p, cl->upvals, base); /* cached closure */899if (ncl == NULL) /* no match? */900pushclosure(L, p, cl->upvals, base, ra); /* create a new one */901else902setclLvalue(L, ra, ncl); /* push cashed closure */903checkGC(L, ra + 1);904)905vmcase(OP_VARARG,906int b = GETARG_B(i) - 1;907int j;908int n = cast_int(base - ci->func) - cl->p->numparams - 1;909if (b < 0) { /* B == 0? */910b = n; /* get all var. arguments */911Protect(luaD_checkstack(L, n));912ra = RA(i); /* previous call may change the stack */913L->top = ra + n;914}915for (j = 0; j < b; j++) {916if (j < n) {917setobjs2s(L, ra + j, base - n + j);918}919else {920setnilvalue(ra + j);921}922}923)924vmcase(OP_EXTRAARG,925lua_assert(0);926)927}928}929}930931932